diff --git a/src/arch/x86_64/driver/apic/ioapic.rs b/src/arch/x86_64/driver/apic/ioapic.rs index 64da4eb..0231ecd 100644 --- a/src/arch/x86_64/driver/apic/ioapic.rs +++ b/src/arch/x86_64/driver/apic/ioapic.rs @@ -4,14 +4,14 @@ /// http://www.intel.com/design/chipsets/datashts/29056601.pdf /// See also picirq.c. -use core::ptr::{Unique}; use syscall::io::{Io, Mmio}; use bit_field::BitField; use consts::irq::T_IRQ0; +use spin::Mutex; -pub unsafe fn init(ioapic_id: u8) +pub fn init(ioapic_id: u8) { - let ioapic = IOAPIC.as_mut(); + let mut ioapic = IOAPIC.lock(); assert!(ioapic.id() == ioapic_id, "ioapicinit: id isn't equal to ioapicid; not a MP"); // Mark all interrupts edge-triggered, active high, disabled, @@ -43,33 +43,42 @@ bitflags! { } } -static mut IOAPIC: Unique<IoApic> = unsafe{ Unique::new_unchecked(IOAPIC_ADDRESS as *mut _) }; +lazy_static! { + pub static ref IOAPIC: Mutex<IoApic> = Mutex::new(unsafe{IoApic::new()}); +} // IO APIC MMIO structure: write reg, then read or write data. #[repr(C)] -struct IoApic { +struct IoApicMmio { reg: Mmio<u32>, pad: [Mmio<u32>; 3], data: Mmio<u32>, } +pub struct IoApic { + mmio: &'static mut IoApicMmio +} + impl IoApic { - unsafe fn read(&mut self, reg: u8) -> u32 + unsafe fn new() -> Self { + IoApic { mmio: &mut *(IOAPIC_ADDRESS as *mut IoApicMmio) } + } + fn read(&mut self, reg: u8) -> u32 { - self.reg.write(reg as u32); - self.data.read() + self.mmio.reg.write(reg as u32); + self.mmio.data.read() } - unsafe fn write(&mut self, reg: u8, data: u32) + fn write(&mut self, reg: u8, data: u32) { - self.reg.write(reg as u32); - self.data.write(data); + self.mmio.reg.write(reg as u32); + self.mmio.data.write(data); } - unsafe fn write_irq(&mut self, irq: u8, flags: RedirectionEntry, dest: u8) + fn write_irq(&mut self, irq: u8, flags: RedirectionEntry, dest: u8) { self.write(REG_TABLE+2*irq, (T_IRQ0 + irq) as u32 | flags.bits()); self.write(REG_TABLE+2*irq+1, (dest as u32) << 24); } - unsafe fn enable(&mut self, irq: u8, cpunum: u8) + pub fn enable(&mut self, irq: u8, cpunum: u8) { // Mark interrupt edge-triggered, active high, // enabled, and routed to the given cpunum, @@ -77,12 +86,12 @@ impl IoApic { self.write_irq(irq, NONE, cpunum); } fn id(&mut self) -> u8 { - unsafe{ self.read(REG_ID).get_bits(24..28) as u8 } + self.read(REG_ID).get_bits(24..28) as u8 } fn version(&mut self) -> u8 { - unsafe{ self.read(REG_VER).get_bits(0..8) as u8 } + self.read(REG_VER).get_bits(0..8) as u8 } fn maxintr(&mut self) -> u8 { - unsafe{ self.read(REG_VER).get_bits(16..24) as u8 } + self.read(REG_VER).get_bits(16..24) as u8 } } \ No newline at end of file diff --git a/src/arch/x86_64/driver/apic/mod.rs b/src/arch/x86_64/driver/apic/mod.rs index fc46842..64ac839 100644 --- a/src/arch/x86_64/driver/apic/mod.rs +++ b/src/arch/x86_64/driver/apic/mod.rs @@ -1,3 +1,5 @@ +pub use self::ioapic::IOAPIC; + mod lapic; mod ioapic; diff --git a/src/arch/x86_64/driver/console.rs b/src/arch/x86_64/driver/console.rs new file mode 100644 index 0000000..c4325dc --- /dev/null +++ b/src/arch/x86_64/driver/console.rs @@ -0,0 +1,6 @@ +pub fn init() { + use consts::irq::IRQ_KBD; + // TODO set irq handler + super::pic::enable_irq(IRQ_KBD); + super::apic::IOAPIC.lock().enable(IRQ_KBD, 0); +} \ No newline at end of file diff --git a/src/arch/x86_64/driver/mod.rs b/src/arch/x86_64/driver/mod.rs index c02bc76..5a93241 100644 --- a/src/arch/x86_64/driver/mod.rs +++ b/src/arch/x86_64/driver/mod.rs @@ -3,4 +3,5 @@ pub mod acpi; pub mod apic; pub mod mp; pub mod serial; -pub mod pic; \ No newline at end of file +pub mod pic; +pub mod console; \ No newline at end of file diff --git a/src/arch/x86_64/driver/pic.rs b/src/arch/x86_64/driver/pic.rs index 3e9c295..4674db5 100644 --- a/src/arch/x86_64/driver/pic.rs +++ b/src/arch/x86_64/driver/pic.rs @@ -1,52 +1,65 @@ use syscall::io::*; +use spin::Mutex; -pub static mut MASTER: Pic = Pic::new(0x20); -pub static mut SLAVE: Pic = Pic::new(0xA0); +static MASTER: Mutex<Pic> = Mutex::new(Pic::new(0x20)); +static SLAVE: Mutex<Pic> = Mutex::new(Pic::new(0xA0)); + +pub fn init() { + let mut master = MASTER.lock(); + let mut slave = SLAVE.lock(); -pub unsafe fn init() { // Start initialization - MASTER.cmd.write(0x11); - SLAVE.cmd.write(0x11); + master.cmd.write(0x11); + slave.cmd.write(0x11); // Set offsets - MASTER.data.write(0x20); - SLAVE.data.write(0x28); + master.data.write(0x20); + slave.data.write(0x28); // Set up cascade - MASTER.data.write(4); - SLAVE.data.write(2); + 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); + master.data.write(1); + slave.data.write(1); // Unmask interrupts - MASTER.data.write(0); - SLAVE.data.write(0); + master.data.write(0); + slave.data.write(0); // Ack remaining interrupts - MASTER.ack(); - SLAVE.ack(); + master.ack(); + slave.ack(); +} + +pub fn enable_irq(irq: u8) +{ + match irq { + _ if irq < 8 => MASTER.lock().mask_set(irq), + _ if irq < 16 => SLAVE.lock().mask_set(irq-8), + _ => panic!("irq not in 0..16"), + } } -pub struct Pic { +struct Pic { cmd: Pio<u8>, data: Pio<u8>, } impl Pic { - pub const fn new(port: u16) -> Pic { + const fn new(port: u16) -> Pic { Pic { cmd: Pio::new(port), data: Pio::new(port + 1), } } - pub fn ack(&mut self) { + fn ack(&mut self) { self.cmd.write(0x20); } - pub fn mask_set(&mut self, irq: u8) { + fn mask_set(&mut self, irq: u8) { assert!(irq < 8); let mut mask = self.data.read(); @@ -54,7 +67,7 @@ impl Pic { self.data.write(mask); } - pub fn mask_clear(&mut self, irq: u8) { + fn mask_clear(&mut self, irq: u8) { assert!(irq < 8); let mut mask = self.data.read();