diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index bbd5121720..1db0b12cc1 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -153,12 +153,13 @@ pub unsafe fn init(already_supplied_rsdp: Option<*const u8>) { } } - //TODO: support this on any arch - #[cfg(target_arch = "aarch64")] - spcr::Spcr::init(); // TODO: Enumerate processors in userspace, and then provide an ACPI-independent interface // to initialize enumerated processors to userspace? Madt::init(); + //TODO: support this on any arch + // SPCR must be initialized after MADT for interrupt controllers + #[cfg(target_arch = "aarch64")] + spcr::Spcr::init(); // TODO: Let userspace setup HPET, and then provide an interface to specify which timer to // use? Hpet::init(); diff --git a/src/acpi/spcr.rs b/src/acpi/spcr.rs index cad4a90a69..d35eecf18d 100644 --- a/src/acpi/spcr.rs +++ b/src/acpi/spcr.rs @@ -8,6 +8,12 @@ use crate::{ memory::{map_device_memory, PhysicalAddress, PAGE_SIZE}, }; +const INTERRUPT_TYPE_8259: u8 = 1 << 0; +const INTERRUPT_TYPE_APIC: u8 = 1 << 1; +const INTERRUPT_TYPE_SAPIC: u8 = 1 << 2; +const INTERRUPT_TYPE_GIC: u8 = 1 << 3; +const INTERRUPT_TYPE_PLIC: u8 = 1 << 4; + #[derive(Clone, Copy, Debug)] #[repr(C, packed)] pub struct Spcr { @@ -78,7 +84,14 @@ impl Spcr { ) }; let serial_port = uart_pl011::SerialPort::new(virt.data(), false); - *COM1.lock() = SerialKind::Pl011(serial_port) + *COM1.lock() = SerialKind::Pl011(serial_port); + //TODO: enable IRQ on more platforms and interrupt types + if (spcr.interrupt_type & INTERRUPT_TYPE_GIC) == INTERRUPT_TYPE_GIC { + #[cfg(target_arch = "aarch64")] + unsafe { + crate::device::serial::init_acpi(spcr.gsiv); + } + } } else { warn!( "SPCR unsuppoted address for PL011 {:#x?}", diff --git a/src/arch/aarch64/device/serial.rs b/src/arch/aarch64/device/serial.rs index e57901ff32..604b8ba5f5 100644 --- a/src/arch/aarch64/device/serial.rs +++ b/src/arch/aarch64/device/serial.rs @@ -88,3 +88,12 @@ pub unsafe fn init(fdt: &Fdt) { COM1.lock().enable_irq(); } } + +pub unsafe fn init_acpi(irq: u32) { + //TODO: what should chip index be? + let virq = IRQ_CHIP.irq_chip_list.chips[0].ic.irq_to_virq(irq).unwrap(); + info!("serial_port virq = {}", virq); + register_irq(virq as u32, Box::new(Com1Irq {})); + IRQ_CHIP.irq_enable(virq as u32); + COM1.lock().enable_irq(); +} \ No newline at end of file