xref: /DragonOS/kernel/src/driver/pci/dev_id.rs (revision 1f4877a4c512eb5ad232436128a0c52287b39aaa)
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)]
set_special(&mut self, data: PciSpecifiedData)27     pub fn set_special(&mut self, data: PciSpecifiedData) {
28         self.special_data = Some(data);
29     }
30 
dummpy() -> Self31     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     }
match_dev(&self, dev: &Arc<dyn PciDevice>) -> bool44     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
general_match(&self, id: PciDeviceID) -> bool57     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 
class_check(&self, id: &Self) -> bool69     pub fn class_check(&self, id: &Self) -> bool {
70         return (self.class ^ id.class()) & self.class_mask == 0;
71     }
72 
vendor(&self) -> u3273     pub fn vendor(&self) -> u32 {
74         self.vendor
75     }
76 
device_id(&self) -> u3277     pub fn device_id(&self) -> u32 {
78         self.device_id
79     }
80 
subvendor(&self) -> u3281     pub fn subvendor(&self) -> u32 {
82         self.subvendor
83     }
84 
subdevice(&self) -> u3285     pub fn subdevice(&self) -> u32 {
86         self.subdevice
87     }
88 
class(&self) -> u3289     pub fn class(&self) -> u32 {
90         self.class
91     }
92 
_class_mask(&self) -> u3293     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 {
match_dev(&self, data: Option<Self>) -> bool102     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