use alloc::collections::btree_map::BTreeMap; use libk::error::Error; use crate::device::{PciInterrupt, PciInterruptRoute}; #[derive(Debug)] pub enum PciInterruptMap { Fixed(BTreeMap), #[cfg(any(target_arch = "x86_64", rust_analyzer))] Acpi(alloc::string::String), Legacy, } impl PciInterruptMap { pub fn map_interrupt(&self, interrupt: &PciInterrupt) -> Result { match self { Self::Fixed(map) => map.get(interrupt).cloned().ok_or(Error::DoesNotExist), #[cfg(any(target_arch = "x86_64", rust_analyzer))] Self::Acpi(aml_object_name) => { use device_api::interrupt::{IrqLevel, IrqOptions, IrqTrigger}; use crate::device::PciInterruptPin; let aml_pin = match interrupt.pin { PciInterruptPin::A => ygg_driver_acpi::PciPin::IntA, PciInterruptPin::B => ygg_driver_acpi::PciPin::IntB, PciInterruptPin::C => ygg_driver_acpi::PciPin::IntC, PciInterruptPin::D => ygg_driver_acpi::PciPin::IntD, }; let aml_route = ygg_driver_acpi::get_pci_route( aml_object_name.as_str(), interrupt.address.device as u16, interrupt.address.function as u16, aml_pin, ) .or_else(|| { ygg_driver_acpi::get_pci_route( aml_object_name.as_str(), interrupt.address.device as u16, 0xFFFF, aml_pin, ) }) .ok_or(Error::DoesNotExist)?; let trigger = match aml_route.trigger { ygg_driver_acpi::InterruptTrigger::Edge => IrqTrigger::Edge, ygg_driver_acpi::InterruptTrigger::Level => IrqTrigger::Level, }; let level = match aml_route.polarity { ygg_driver_acpi::InterruptPolarity::ActiveLow => IrqLevel::ActiveLow, ygg_driver_acpi::InterruptPolarity::ActiveHigh => IrqLevel::ActiveHigh, }; Ok(PciInterruptRoute { options: IrqOptions { trigger, level }, number: aml_route.irq, }) } Self::Legacy => todo!(), } } }