56 lines
2.1 KiB
Rust
56 lines
2.1 KiB
Rust
use alloc::collections::btree_map::BTreeMap;
|
|
use libk::error::Error;
|
|
|
|
use crate::device::{PciInterrupt, PciInterruptRoute};
|
|
|
|
#[derive(Debug)]
|
|
pub enum PciInterruptMap {
|
|
Fixed(BTreeMap<PciInterrupt, PciInterruptRoute>),
|
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
|
Acpi(alloc::string::String),
|
|
Legacy,
|
|
}
|
|
|
|
impl PciInterruptMap {
|
|
pub fn map_interrupt(&self, interrupt: &PciInterrupt) -> Result<PciInterruptRoute, Error> {
|
|
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,
|
|
)
|
|
.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!(),
|
|
}
|
|
}
|
|
}
|