Improve IOAPIC mod

master
WangRunji 7 years ago
parent 15b1687ac6
commit bb51547c12

@ -6,41 +6,44 @@
use core::ptr::{Unique}; use core::ptr::{Unique};
use syscall::io::{Io, Mmio}; use syscall::io::{Io, Mmio};
use bit_field::BitField;
use consts::irq::T_IRQ0;
pub unsafe fn init(ioapic_id: u8) pub unsafe fn init(ioapic_id: u8)
{ {
let ioapic = IOAPIC.as_mut(); let ioapic = IOAPIC.as_mut();
let maxintr = (ioapic.read(REG_VER) >> 16) & 0xFF; assert!(ioapic.id() == ioapic_id, "ioapicinit: id isn't equal to ioapicid; not a MP");
let id = (ioapic.read(REG_ID) >> 24) as u8;
assert!(id == ioapic_id, "ioapicinit: id isn't equal to ioapicid; not a MP");
// Mark all interrupts edge-triggered, active high, disabled, // Mark all interrupts edge-triggered, active high, disabled,
// and not routed to any CPUs. // and not routed to any CPUs.
for i in 0 .. maxintr+1 { for i in 0.. ioapic.maxintr() + 1 {
ioapic.write(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i)); ioapic.write_irq(i, DISABLED, 0);
ioapic.write(REG_TABLE+2*i+1, 0);
} }
} }
const IOAPIC_ADDRESS : u32 = 0xFEC00000; // Default physical address of IO APIC const IOAPIC_ADDRESS : u32 = 0xFEC00000; // Default physical address of IO APIC
const REG_ID : u32 = 0x00; // Register index: ID const REG_ID : u8 = 0x00; // Register index: ID
const REG_VER : u32 = 0x01; // Register index: version const REG_VER : u8 = 0x01; // Register index: version
const REG_TABLE : u32 = 0x10; // Redirection table base const REG_TABLE : u8 = 0x10; // Redirection table base
// The redirection table starts at REG_TABLE and uses // The redirection table starts at REG_TABLE and uses
// two registers to configure each interrupt. // two registers to configure each interrupt.
// The first (low) register in a pair contains configuration bits. // The first (low) register in a pair contains configuration bits.
// The second (high) register contains a bitmask telling which // The second (high) register contains a bitmask telling which
// CPUs can serve that interrupt. // CPUs can serve that interrupt.
const INT_DISABLED : u32 = 0x00010000; // Interrupt disabled
const INT_LEVEL : u32 = 0x00008000; // Level-triggered (vs edge-)
const INT_ACTIVELOW : u32 = 0x00002000; // Active low (vs high)
const INT_LOGICAL : u32 = 0x00000800; // Destination is CPU id (vs APIC ID)
static mut IOAPIC: Unique<IoApic> = unsafe{ Unique::new_unchecked(IOAPIC_ADDRESS as *mut _) }; bitflags! {
flags RedirectionEntry: u32 {
const DISABLED = 0x00010000, // Interrupt disabled
const LEVEL = 0x00008000, // Level-triggered (vs edge-)
const ACTIVELOW = 0x00002000, // Active low (vs high)
const LOGICAL = 0x00000800, // Destination is CPU id (vs APIC ID)
const NONE = 0x00000000,
}
}
const T_IRQ0: u32 = 32; static mut IOAPIC: Unique<IoApic> = unsafe{ Unique::new_unchecked(IOAPIC_ADDRESS as *mut _) };
// IO APIC MMIO structure: write reg, then read or write data. // IO APIC MMIO structure: write reg, then read or write data.
#[repr(C)] #[repr(C)]
@ -51,22 +54,35 @@ struct IoApic {
} }
impl IoApic { impl IoApic {
unsafe fn read(&mut self, reg: u32) -> u32 unsafe fn read(&mut self, reg: u8) -> u32
{ {
self.reg.write(reg); self.reg.write(reg as u32);
self.data.read() self.data.read()
} }
unsafe fn write(&mut self, reg: u32, data: u32) unsafe fn write(&mut self, reg: u8, data: u32)
{ {
self.reg.write(reg); self.reg.write(reg as u32);
self.data.write(data); self.data.write(data);
} }
unsafe fn enable(&mut self, irq: u32, cpunum: u32) unsafe 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)
{ {
// Mark interrupt edge-triggered, active high, // Mark interrupt edge-triggered, active high,
// enabled, and routed to the given cpunum, // enabled, and routed to the given cpunum,
// which happens to be that cpu's APIC ID. // which happens to be that cpu's APIC ID.
self.write(REG_TABLE+2*irq, T_IRQ0 + irq); self.write_irq(irq, NONE, cpunum);
self.write(REG_TABLE+2*irq+1, cpunum << 24); }
fn id(&mut self) -> u8 {
unsafe{ 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 }
}
fn maxintr(&mut self) -> u8 {
unsafe{ self.read(REG_VER).get_bits(16..24) as u8 }
} }
} }

@ -1 +1,11 @@
pub const MAX_CPU_NUM: usize = 8; pub const MAX_CPU_NUM: usize = 8;
pub mod irq {
pub const T_IRQ0 : u8 = 32; // IRQ 0 corresponds to int T_IRQ
pub const IRQ_TIMER : u8 = 0;
pub const IRQ_KBD : u8 = 1;
pub const IRQ_COM1 : u8 = 4;
pub const IRQ_IDE : u8 = 14;
pub const IRQ_ERROR : u8 = 19;
pub const IRQ_SPURIOUS : u8 = 31;
}

Loading…
Cancel
Save