Protect PIC & IOAPIC with Mutex

master
WangRunji 7 years ago
parent bb51547c12
commit 2028eadbfe

@ -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
}
}

@ -1,3 +1,5 @@
pub use self::ioapic::IOAPIC;
mod lapic;
mod ioapic;

@ -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);
}

@ -3,4 +3,5 @@ pub mod acpi;
pub mod apic;
pub mod mp;
pub mod serial;
pub mod pic;
pub mod pic;
pub mod console;

@ -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();

Loading…
Cancel
Save