pio and x86/pic
This commit is contained in:
parent
6d8c31b42c
commit
c24ac47698
8 changed files with 199 additions and 8 deletions
5
kernel-rs/src/arch/x86/device/mod.rs
Normal file
5
kernel-rs/src/arch/x86/device/mod.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod pic;
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
unsafe { pic::init(); }
|
||||||
|
}
|
||||||
64
kernel-rs/src/arch/x86/device/pic.rs
Normal file
64
kernel-rs/src/arch/x86/device/pic.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use ::io::{Io, Pio};
|
||||||
|
|
||||||
|
pub static mut MASTER: Pic = Pic::new(0x20);
|
||||||
|
pub static mut SLAVE: Pic = Pic::new(0xA0);
|
||||||
|
|
||||||
|
pub unsafe fn init() {
|
||||||
|
// Start initialization
|
||||||
|
MASTER.cmd.write(0x11);
|
||||||
|
SLAVE.cmd.write(0x11);
|
||||||
|
|
||||||
|
// Set offsets
|
||||||
|
MASTER.data.write(0x20);
|
||||||
|
SLAVE.data.write(0x28);
|
||||||
|
|
||||||
|
// Set up cascade
|
||||||
|
MASTER.data.write(4);
|
||||||
|
SLAVE.data.write(2);
|
||||||
|
|
||||||
|
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
||||||
|
MASTER.data.write(1);
|
||||||
|
SLAVE.data.write(1);
|
||||||
|
|
||||||
|
// Unmask interrupts
|
||||||
|
MASTER.data.write(0);
|
||||||
|
SLAVE.data.write(0);
|
||||||
|
|
||||||
|
// Ack remaining interrupts
|
||||||
|
MASTER.ack();
|
||||||
|
SLAVE.ack();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Pic {
|
||||||
|
cmd: Pio<u8>,
|
||||||
|
data: Pio<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pic {
|
||||||
|
pub const fn new(port: u16) -> Pic {
|
||||||
|
Pic {
|
||||||
|
cmd: Pio::new(port),
|
||||||
|
data: Pio::new(port + 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ack(&mut self) {
|
||||||
|
self.cmd.write(0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mask_set(&mut self, irq: u8) {
|
||||||
|
assert!(irq < 8);
|
||||||
|
|
||||||
|
let mut mask = self.data.read();
|
||||||
|
mask |= 1 << irq;
|
||||||
|
self.data.write(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mask_clear(&mut self, irq: u8) {
|
||||||
|
assert!(irq < 8);
|
||||||
|
|
||||||
|
let mut mask = self.data.read();
|
||||||
|
mask &= !(1 << irq);
|
||||||
|
self.data.write(mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,10 @@ use x86::structures::idt::*;
|
||||||
interrupt!(divide_by_zero, {});
|
interrupt!(divide_by_zero, {});
|
||||||
interrupt!(debug, {});
|
interrupt!(debug, {});
|
||||||
interrupt!(non_maskable, {});
|
interrupt!(non_maskable, {});
|
||||||
interrupt!(breakpoint, {});
|
interrupt!(breakpoint, {
|
||||||
|
println!("testing here dont mind me");
|
||||||
|
flush!();
|
||||||
|
});
|
||||||
interrupt!(overflow, {});
|
interrupt!(overflow, {});
|
||||||
interrupt!(bound_range, {});
|
interrupt!(bound_range, {});
|
||||||
interrupt!(invalid_opcode, {});
|
interrupt!(invalid_opcode, {});
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,7 @@ lazy_static! {
|
||||||
idt.virtualization.set_handler_fn(exception::virtualization);
|
idt.virtualization.set_handler_fn(exception::virtualization);
|
||||||
|
|
||||||
// set up IRQs
|
// set up IRQs
|
||||||
idt.interrupts[0].set_handler_fn(irq::keyboard);
|
idt[33].set_handler_fn(irq::keyboard);
|
||||||
idt.interrupts[1].set_handler_fn(irq::keyboard);
|
|
||||||
idt.interrupts[2].set_handler_fn(irq::keyboard);
|
|
||||||
idt
|
idt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ extern crate x86;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod paging;
|
pub mod paging;
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
|
pub mod device;
|
||||||
|
|
||||||
use multiboot2;
|
use multiboot2;
|
||||||
use acpi;
|
use acpi;
|
||||||
|
|
@ -25,6 +26,12 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
|
||||||
// set up physical allocator
|
// set up physical allocator
|
||||||
::memory::init(&boot_info);
|
::memory::init(&boot_info);
|
||||||
|
|
||||||
|
// pic
|
||||||
|
self::device::init();
|
||||||
|
|
||||||
|
// set up interrupts
|
||||||
|
self::interrupt::init();
|
||||||
|
|
||||||
// set up virtual mapping
|
// set up virtual mapping
|
||||||
let mut active_table = self::paging::init(&boot_info);
|
let mut active_table = self::paging::init(&boot_info);
|
||||||
|
|
||||||
|
|
@ -34,8 +41,6 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
|
||||||
// after core has loaded
|
// after core has loaded
|
||||||
::memory::init_noncore();
|
::memory::init_noncore();
|
||||||
|
|
||||||
// set up interrupts
|
|
||||||
self::interrupt::init();
|
|
||||||
|
|
||||||
// primary CPU entry point
|
// primary CPU entry point
|
||||||
::kmain();
|
::kmain();
|
||||||
|
|
|
||||||
26
kernel-rs/src/io/mod.rs
Normal file
26
kernel-rs/src/io/mod.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
mod pio;
|
||||||
|
|
||||||
|
pub use self::pio::*;
|
||||||
|
|
||||||
|
use core::ops::{BitAnd, BitOr, Not};
|
||||||
|
|
||||||
|
pub trait Io {
|
||||||
|
type Value: Copy + PartialEq + BitAnd<Output = Self::Value> + BitOr<Output = Self::Value> + Not<Output = Self::Value>;
|
||||||
|
|
||||||
|
fn read(&self) -> Self::Value;
|
||||||
|
fn write(&mut self, value: Self::Value);
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn readf(&self, flags: Self::Value) -> bool {
|
||||||
|
(self.read() & flags) as Self::Value == flags
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn writef(&mut self, flags: Self::Value, value: bool) {
|
||||||
|
let tmp: Self::Value = match value {
|
||||||
|
true => self.read() | flags,
|
||||||
|
false => self.read() & !flags,
|
||||||
|
};
|
||||||
|
self.write(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
89
kernel-rs/src/io/pio.rs
Normal file
89
kernel-rs/src/io/pio.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Generic PIO
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Pio<T> {
|
||||||
|
port: u16,
|
||||||
|
value: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Pio<T> {
|
||||||
|
/// Create a PIO from a given port
|
||||||
|
pub const fn new(port: u16) -> Self {
|
||||||
|
Pio::<T> {
|
||||||
|
port: port,
|
||||||
|
value: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read/Write for byte PIO
|
||||||
|
impl Io for Pio<u8> {
|
||||||
|
type Value = u8;
|
||||||
|
|
||||||
|
/// Read
|
||||||
|
#[inline(always)]
|
||||||
|
fn read(&self) -> u8 {
|
||||||
|
let value: u8;
|
||||||
|
unsafe {
|
||||||
|
asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write
|
||||||
|
#[inline(always)]
|
||||||
|
fn write(&mut self, value: u8) {
|
||||||
|
unsafe {
|
||||||
|
asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read/Write for word PIO
|
||||||
|
impl Io for Pio<u16> {
|
||||||
|
type Value = u16;
|
||||||
|
|
||||||
|
/// Read
|
||||||
|
#[inline(always)]
|
||||||
|
fn read(&self) -> u16 {
|
||||||
|
let value: u16;
|
||||||
|
unsafe {
|
||||||
|
asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write
|
||||||
|
#[inline(always)]
|
||||||
|
fn write(&mut self, value: u16) {
|
||||||
|
unsafe {
|
||||||
|
asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read/Write for doubleword PIO
|
||||||
|
impl Io for Pio<u32> {
|
||||||
|
type Value = u32;
|
||||||
|
|
||||||
|
/// Read
|
||||||
|
#[inline(always)]
|
||||||
|
fn read(&self) -> u32 {
|
||||||
|
let value: u32;
|
||||||
|
unsafe {
|
||||||
|
asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write
|
||||||
|
#[inline(always)]
|
||||||
|
fn write(&mut self, value: u32) {
|
||||||
|
unsafe {
|
||||||
|
asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,7 @@ pub mod keyboard;
|
||||||
pub mod console;
|
pub mod console;
|
||||||
/// rust wrappers around cpu I/O instructions.
|
/// rust wrappers around cpu I/O instructions.
|
||||||
pub mod cpuio;
|
pub mod cpuio;
|
||||||
|
pub mod io;
|
||||||
/// ACPI self contained module
|
/// ACPI self contained module
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
/// Heap allocators
|
/// Heap allocators
|
||||||
|
|
@ -46,7 +47,9 @@ pub fn kmain() -> ! {
|
||||||
// vga is specific to chipset not cpu
|
// vga is specific to chipset not cpu
|
||||||
vga::init();
|
vga::init();
|
||||||
|
|
||||||
|
// x86::instructions::interrupts::disable();
|
||||||
// x86::instructions::interrupts::int3();
|
// x86::instructions::interrupts::int3();
|
||||||
|
// x86::instructions::interrupts::enable();
|
||||||
|
|
||||||
// fn stack_overflow() { stack_overflow(); }
|
// fn stack_overflow() { stack_overflow(); }
|
||||||
// stack_overflow();
|
// stack_overflow();
|
||||||
|
|
@ -55,8 +58,6 @@ pub fn kmain() -> ! {
|
||||||
// *(0xdead as *mut u32) = 42;
|
// *(0xdead as *mut u32) = 42;
|
||||||
// };
|
// };
|
||||||
|
|
||||||
println!("at main now!");
|
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue