mod ioapic_regs;
use ioapic_regs::*;
mod irq_entry;
pub use irq_entry::{IrqFlags, IrqMode, RedirectionTableEntry};
#[derive(Debug)]
pub struct IoApic {
regs: IoApicRegisters,
}
impl IoApic {
pub unsafe fn new(base_addr: u64) -> Self {
IoApic {
regs: IoApicRegisters::new(base_addr),
}
}
pub unsafe fn init(&mut self, offset: u8) {
let end = self.max_table_entry() + 1;
for i in 0..end {
self.regs.set(irq_entry::lo(i), u32::from(i + offset));
self.regs.write(irq_entry::hi(i), 0);
}
}
pub unsafe fn id(&mut self) -> u8 {
((self.regs.read(ID) >> 24) & 0xf) as u8
}
pub unsafe fn set_id(&mut self, id: u8) {
self.regs.write(ID, u32::from(id) << 24);
}
pub unsafe fn version(&mut self) -> u8 {
(self.regs.read(VERSION) & 0xff) as u8
}
pub unsafe fn max_table_entry(&mut self) -> u8 {
((self.regs.read(VERSION) >> 16) & 0xff) as u8
}
pub unsafe fn arbitration_id(&mut self) -> u8 {
((self.regs.read(ARBITRATION) >> 24) & 0xf) as u8
}
pub unsafe fn set_arbitration_id(&mut self, id: u8) {
self.regs.write(ARBITRATION, u32::from(id) << 24);
}
pub unsafe fn table_entry(&mut self, irq: u8) -> RedirectionTableEntry {
let lo = irq_entry::lo(irq);
let hi = irq_entry::hi(irq);
RedirectionTableEntry::from_raw(self.regs.read(lo), self.regs.read(hi))
}
pub unsafe fn set_table_entry(
&mut self,
irq: u8,
entry: RedirectionTableEntry,
) {
let lo = irq_entry::lo(irq);
let hi = irq_entry::hi(irq);
let (lo_value, hi_value) = entry.into_raw();
self.regs.write(lo, lo_value);
self.regs.write(hi, hi_value);
}
pub unsafe fn enable_irq(&mut self, irq: u8) {
self.regs.clear(irq_entry::lo(irq), IrqFlags::MASKED.bits());
}
pub unsafe fn disable_irq(&mut self, irq: u8) {
self.regs.set(irq_entry::lo(irq), IrqFlags::MASKED.bits());
}
}