use core::{any::Any, fmt::Debug}; use alloc::sync::Arc; use crate::{ driver::{base::device::Device, pci::pci_irq::PciIrqMsg}, filesystem::sysfs::Attribute, libs::spinlock::SpinLock, }; use super::IrqNumber; #[derive(Clone, Copy)] pub struct MsiMsg { pub address_lo: u32, pub address_hi: u32, pub data: u32, } impl Debug for MsiMsg { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "MsiMsg {{ address_lo: 0x{:x}, address_hi: 0x{:x}, data: 0x{:x} }}", self.address_lo, self.address_hi, self.data ) } } #[allow(dead_code)] impl MsiMsg { /// Create a new MSI message pub const fn new(address: u64, data: u32) -> Self { MsiMsg { address_lo: address as u32, address_hi: (address >> 32) as u32, data, } } /// Create a new MSI message pub const fn new_lo_hi(address_lo: u32, address_hi: u32, data: u32) -> Self { MsiMsg { address_lo, address_hi, data, } } /// Get the address of the MSI message pub const fn address(&self) -> u64 { (self.address_hi as u64) << 32 | self.address_lo as u64 } pub const fn new_zeroed() -> Self { MsiMsg { address_lo: 0, address_hi: 0, data: 0, } } } #[allow(dead_code)] #[derive(Debug)] pub struct MsiDesc { inner: SpinLock, } #[allow(dead_code)] #[derive(Debug)] struct InnerMsiDesc { /// The base interrupt number irq: IrqNumber, /// The number of vectors used nvec_used: u32, /// Pointer to the device which uses this descriptor dev: Option>, /// The last set MSI message cached for reuse msg: MsiMsg, /// Pointer to sysfs device attribute sysfs_attribute: Option<&'static dyn Attribute>, /// Pointer to MSI callback function func: Option<&'static dyn MsiDescFunc>, /// The index of the MSI descriptor index: u32, /// PCI specific msi descriptor data pci_msg: PciIrqMsg, } #[allow(dead_code)] impl MsiDesc { pub const fn new( irq: IrqNumber, nvec_used: u32, dev: Option>, index: u32, pci_msg: PciIrqMsg, ) -> Self { MsiDesc { inner: SpinLock::new(InnerMsiDesc { irq, nvec_used, dev, msg: MsiMsg { address_lo: 0, address_hi: 0, data: 0, }, sysfs_attribute: None, func: None, index, pci_msg, }), } } pub fn set_msg(&self, msg: MsiMsg) { self.inner.lock().msg = msg; } pub fn msg(&self) -> MsiMsg { self.inner.lock().msg } } #[allow(dead_code)] pub trait MsiDescFunc: Debug + Send + Sync { /// Callback that may be called when the MSI message /// address or data changes. fn write_msi_msg(&self, data: Arc); } /// Data parameter for the `MsiDescFunc` callback. pub trait MsiDescFuncData: Send + Sync + Any {}