1 use core::{any::Any, fmt::Debug}; 2 3 use alloc::sync::Arc; 4 5 use crate::{ 6 driver::{base::device::Device, pci::pci_irq::PciIrqMsg}, 7 filesystem::sysfs::Attribute, 8 libs::spinlock::SpinLock, 9 }; 10 11 use super::IrqNumber; 12 13 #[derive(Clone, Copy)] 14 pub struct MsiMsg { 15 pub address_lo: u32, 16 pub address_hi: u32, 17 pub data: u32, 18 } 19 20 impl Debug for MsiMsg { 21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 22 write!( 23 f, 24 "MsiMsg {{ address_lo: 0x{:x}, address_hi: 0x{:x}, data: 0x{:x} }}", 25 self.address_lo, self.address_hi, self.data 26 ) 27 } 28 } 29 30 #[allow(dead_code)] 31 impl MsiMsg { 32 /// Create a new MSI message 33 pub const fn new(address: u64, data: u32) -> Self { 34 MsiMsg { 35 address_lo: address as u32, 36 address_hi: (address >> 32) as u32, 37 data, 38 } 39 } 40 41 /// Create a new MSI message 42 pub const fn new_lo_hi(address_lo: u32, address_hi: u32, data: u32) -> Self { 43 MsiMsg { 44 address_lo, 45 address_hi, 46 data, 47 } 48 } 49 50 /// Get the address of the MSI message 51 pub const fn address(&self) -> u64 { 52 (self.address_hi as u64) << 32 | self.address_lo as u64 53 } 54 } 55 56 #[allow(dead_code)] 57 #[derive(Debug)] 58 pub struct MsiDesc { 59 inner: SpinLock<InnerMsiDesc>, 60 } 61 62 #[allow(dead_code)] 63 #[derive(Debug)] 64 struct InnerMsiDesc { 65 /// The base interrupt number 66 irq: IrqNumber, 67 /// The number of vectors used 68 nvec_used: u32, 69 /// Pointer to the device which uses this descriptor 70 dev: Option<Arc<dyn Device>>, 71 /// The last set MSI message cached for reuse 72 msg: MsiMsg, 73 /// Pointer to sysfs device attribute 74 sysfs_attribute: Option<&'static dyn Attribute>, 75 /// Pointer to MSI callback function 76 func: Option<&'static dyn MsiDescFunc>, 77 /// The index of the MSI descriptor 78 index: u32, 79 /// PCI specific msi descriptor data 80 pci_msg: PciIrqMsg, 81 } 82 83 #[allow(dead_code)] 84 impl MsiDesc { 85 pub const fn new( 86 irq: IrqNumber, 87 nvec_used: u32, 88 dev: Option<Arc<dyn Device>>, 89 index: u32, 90 pci_msg: PciIrqMsg, 91 ) -> Self { 92 MsiDesc { 93 inner: SpinLock::new(InnerMsiDesc { 94 irq, 95 nvec_used, 96 dev, 97 msg: MsiMsg { 98 address_lo: 0, 99 address_hi: 0, 100 data: 0, 101 }, 102 sysfs_attribute: None, 103 func: None, 104 index, 105 pci_msg, 106 }), 107 } 108 } 109 110 pub fn set_msg(&self, msg: MsiMsg) { 111 self.inner.lock().msg = msg; 112 } 113 114 pub fn msg(&self) -> MsiMsg { 115 self.inner.lock().msg 116 } 117 } 118 119 pub trait MsiDescFunc: Debug + Send + Sync { 120 /// Callback that may be called when the MSI message 121 /// address or data changes. 122 fn write_msi_msg(&self, data: Arc<dyn MsiDescFuncData>); 123 } 124 125 /// Data parameter for the `MsiDescFunc` callback. 126 pub trait MsiDescFuncData: Send + Sync + Any {} 127