devices/pci/pcie/
pcie_device.rs1use std::sync::Arc;
6
7use resources::SystemAllocator;
8use sync::Mutex;
9use zerocopy::FromBytes;
10use zerocopy::Immutable;
11use zerocopy::IntoBytes;
12use zerocopy::KnownLayout;
13
14use crate::pci::pci_configuration::PciCapConfig;
15use crate::pci::pci_configuration::PciCapConfigWriteResult;
16use crate::pci::pci_configuration::PciCapabilityID;
17use crate::pci::pcie::pci_bridge::PciBridgeBusRange;
18use crate::pci::pcie::*;
19use crate::pci::MsiConfig;
20use crate::pci::PciAddress;
21use crate::pci::PciCapability;
22use crate::pci::PciDeviceError;
23
24pub trait PcieDevice: Send {
25 fn get_device_id(&self) -> u16;
26 fn debug_label(&self) -> String;
27 fn preferred_address(&self) -> Option<PciAddress> {
28 None
29 }
30 fn allocate_address(
31 &mut self,
32 resources: &mut SystemAllocator,
33 ) -> std::result::Result<PciAddress, PciDeviceError>;
34 fn read_config(&self, reg_idx: usize, data: &mut u32);
35 fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
36 fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>);
37 fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>);
38 fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>;
39 fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
40 None
41 }
42 fn get_removed_devices(&self) -> Vec<PciAddress>;
43
44 fn hotplug_implemented(&self) -> bool;
48
49 fn hotplugged(&self) -> bool;
51
52 fn get_bridge_window_size(&self) -> (u64, u64);
55}
56
57#[repr(C)]
58#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
59pub struct PcieCap {
60 _cap_vndr: u8,
61 _cap_next: u8,
62 pcie_cap: u16,
63 dev_cap: u32,
64 dev_control: u16,
65 dev_status: u16,
66 link_cap: u32,
67 link_control: u16,
68 link_status: u16,
69 slot_cap: u32,
70 slot_control: u16,
71 slot_status: u16,
72 root_control: u16,
73 root_cap: u16,
74 root_status: u32,
75 dev_cap_2: u32,
76 dev_control_2: u16,
77 dev_status_2: u16,
78 link_cap_2: u32,
79 link_control_2: u16,
80 link_status_2: u16,
81 slot_cap_2: u32,
82 slot_control_2: u16,
83 slot_status_2: u16,
84}
85
86impl PciCapability for PcieCap {
87 fn bytes(&self) -> &[u8] {
88 self.as_bytes()
89 }
90
91 fn id(&self) -> PciCapabilityID {
92 PciCapabilityID::PciExpress
93 }
94
95 fn writable_bits(&self) -> Vec<u32> {
96 vec![
97 0u32,
98 0,
99 0xf_ffff,
100 0,
101 0x3000_0fff,
102 0,
103 0x11f_1fff,
104 0x1f,
105 0,
106 0,
107 0,
108 0,
109 0,
110 0,
111 0,
112 ]
113 }
114}
115
116impl PcieCap {
117 pub fn new(device_type: PcieDevicePortType, slot: bool, irq_num: u16) -> Self {
118 let mut pcie_cap = PCIE_CAP_VERSION;
119 pcie_cap |= (device_type as u16) << PCIE_TYPE_SHIFT;
120 if slot {
121 pcie_cap |= 1 << PCIE_CAP_SLOT_SHIFT;
122 }
123 pcie_cap |= irq_num << PCIE_CAP_IRQ_NUM_SHIFT;
124
125 let dev_cap = PCIE_DEVCAP_RBER;
126 let link_cap = (PCIE_LINK_X1 | PCIE_LINK_2_5GT) as u32;
127 let link_status = PCIE_LINK_X1 | PCIE_LINK_2_5GT;
128
129 let mut slot_cap: u32 = 0;
130 let mut slot_control: u16 = 0;
131 if slot {
132 slot_cap = PCIE_SLTCAP_ABP
133 | PCIE_SLTCAP_AIP
134 | PCIE_SLTCAP_PIP
135 | PCIE_SLTCAP_HPS
136 | PCIE_SLTCAP_HPC;
137 slot_control = PCIE_SLTCTL_PIC_OFF | PCIE_SLTCTL_AIC_OFF;
138 }
139
140 PcieCap {
141 _cap_vndr: 0,
142 _cap_next: 0,
143 pcie_cap,
144 dev_cap,
145 dev_control: 0,
146 dev_status: 0,
147 link_cap,
148 link_control: 0,
149 link_status,
150 slot_cap,
151 slot_control,
152 slot_status: 0,
153 root_control: 0,
154 root_cap: 0,
155 root_status: 0,
156 dev_cap_2: 0,
157 dev_control_2: 0,
158 dev_status_2: 0,
159 link_cap_2: 0,
160 link_control_2: 0,
161 link_status_2: 0,
162 slot_cap_2: 0,
163 slot_control_2: 0,
164 slot_status_2: 0,
165 }
166 }
167}