2023-09-02 17:06:39 +08:00

75 lines
1.9 KiB
Rust

use crate::sync::Mutex;
use acpi::PlatformInfo;
use log::info;
use spin::Once;
use x86::apic::ioapic::IoApic;
use crate::arch::x86::kernel::acpi::ACPI_TABLES;
pub struct IoApicWrapper {
io_apic: IoApic,
}
impl IoApicWrapper {
fn new(io_apic: IoApic) -> Self {
Self { io_apic }
}
pub fn disable_all(&mut self) {
self.io_apic.disable_all()
}
pub fn enable(&mut self, irq: u8, cpunum: u8) {
self.io_apic.enable(irq, cpunum);
}
pub fn id(&mut self) -> u8 {
self.io_apic.id()
}
pub fn version(&mut self) -> u8 {
self.io_apic.version()
}
pub fn supported_interrupts(&mut self) -> u8 {
self.io_apic.supported_interrupts()
}
}
/// # Safety: The pointer inside the IoApic will not change
unsafe impl Send for IoApicWrapper {}
/// # Safety: The pointer inside the IoApic will not change
unsafe impl Sync for IoApicWrapper {}
pub static IO_APIC: Once<Mutex<IoApicWrapper>> = Once::new();
pub fn init() {
let c = ACPI_TABLES.get().unwrap().lock();
let platform_info = PlatformInfo::new(&*c).unwrap();
let ioapic_address = match platform_info.interrupt_model {
acpi::InterruptModel::Unknown => panic!("not found APIC in ACPI Table"),
acpi::InterruptModel::Apic(apic) => {
apic.io_apics
.iter()
.next()
.expect("There must be at least one IO APIC")
.address
}
_ => {
panic!("Unknown interrupt model")
}
};
let mut io_apic = unsafe { IoApic::new(crate::vm::paddr_to_vaddr(ioapic_address as usize)) };
let id = io_apic.id();
let version = io_apic.version();
let max_redirection_entry = io_apic.supported_interrupts();
info!(
"IOAPIC id: {}, version:{}, max_redirection_entry:{}",
id, version, max_redirection_entry
);
IO_APIC.call_once(|| Mutex::new(IoApicWrapper::new(io_apic)));
}