1 use alloc::sync::Arc; 2 3 use super::device::PciDevice; 4 const PCI_ANY_ID: u32 = 0xffff_ffff; 5 6 /// # 结构功能 7 /// 该结构用于驱动和设备之间的识别,驱动会有一个支持的设备ID列表,而设备会自带一个ID,如果设备的ID在驱动的支持列表中,则驱动和设备就可以识别了 8 /// 见https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/mod_devicetable.h#43 9 #[derive(Debug, Copy, Clone)] 10 pub struct PciDeviceID { 11 vendor: u32, 12 device_id: u32, 13 subvendor: u32, 14 subdevice: u32, 15 class: u32, 16 class_mask: u32, 17 _driver_data: u64, 18 _override_only: u32, 19 /// 可能有些设备的识别方式比较特殊,那么可以通过设置该字段进行自定义的识别方式,只需要在PciSpecifiedData枚举中加入一个类型即可 20 /// 若该字段不为None,则优先使用special_data进行识别; 21 /// 该字段是为了增加灵活性 22 special_data: Option<PciSpecifiedData>, 23 } 24 25 impl PciDeviceID { 26 #[allow(dead_code)] 27 pub fn set_special(&mut self, data: PciSpecifiedData) { 28 self.special_data = Some(data); 29 } 30 31 pub fn dummpy() -> Self { 32 return Self { 33 vendor: PCI_ANY_ID, 34 device_id: PCI_ANY_ID, 35 subvendor: PCI_ANY_ID, 36 subdevice: PCI_ANY_ID, 37 class: PCI_ANY_ID, 38 class_mask: PCI_ANY_ID, 39 _driver_data: 0, 40 _override_only: PCI_ANY_ID, 41 special_data: None, 42 }; 43 } 44 pub fn match_dev(&self, dev: &Arc<dyn PciDevice>) -> bool { 45 if let Some(d_data) = &dev.dynid().special_data { 46 return d_data.match_dev(self.special_data); 47 } 48 if let Some(s_data) = &self.special_data { 49 return s_data.match_dev(dev.dynid().special_data); 50 } else { 51 let d_id = dev.dynid(); 52 return self.general_match(d_id); 53 } 54 } 55 56 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/pci/pci.h?fi=pci_match_one_device#195 57 pub fn general_match(&self, id: PciDeviceID) -> bool { 58 if (self.vendor == id.vendor() || self.vendor == PCI_ANY_ID) 59 && (self.device_id == id.device_id() || self.device_id == PCI_ANY_ID) 60 && (self.subvendor == id.subvendor() || self.subvendor == PCI_ANY_ID) 61 && (self.subdevice == id.subdevice() || self.subdevice == PCI_ANY_ID) 62 && self.class_check(&id) 63 { 64 return true; 65 } 66 return false; 67 } 68 69 pub fn class_check(&self, id: &Self) -> bool { 70 return (self.class ^ id.class()) & self.class_mask == 0; 71 } 72 73 pub fn vendor(&self) -> u32 { 74 self.vendor 75 } 76 77 pub fn device_id(&self) -> u32 { 78 self.device_id 79 } 80 81 pub fn subvendor(&self) -> u32 { 82 self.subvendor 83 } 84 85 pub fn subdevice(&self) -> u32 { 86 self.subdevice 87 } 88 89 pub fn class(&self) -> u32 { 90 self.class 91 } 92 93 pub fn _class_mask(&self) -> u32 { 94 self.class_mask 95 } 96 } 97 98 #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)] 99 pub enum PciSpecifiedData {} 100 101 impl PciSpecifiedData { 102 pub fn match_dev(&self, data: Option<Self>) -> bool { 103 if let Some(data) = data { 104 return *self == data; 105 } else { 106 return false; 107 } 108 } 109 } 110