1pub mod caps;
6pub mod ext_caps;
7
8use std::io;
9
10use crate::config::caps::PciCapabilities;
11use crate::config::ext_caps::PciExtendedCapabilities;
12use crate::regions::structured::{PciRegisterRo, PciRegisterRw};
13use crate::{pci_bit_field, pci_struct};
14
15pci_struct! {
18 pub struct PciConfig<'a> {
23 vendor_id @ 0x00 : PciRegisterRo<'a, u16>,
24 device_id @ 0x02 : PciRegisterRo<'a, u16>,
25 command @ 0x04 : PciCommand<'a>,
26 status @ 0x06 : PciStatus<'a>,
27 revision_id @ 0x08 : PciRegisterRo<'a, u8>,
28 class_code @ 0x09 : PciClassCode<'a>,
29 cache_line_size @ 0x0c : PciRegisterRw<'a, u8>,
30 latency_timer @ 0x0d : PciRegisterRo<'a, u8>,
31 header_type @ 0x0e : PciHeaderType<'a>,
32 bist @ 0x0f : PciBist<'a>,
33 cardbus_cis_pointer @ 0x28 : PciRegisterRo<'a, u32>,
34 subsystem_vendor_id @ 0x2c : PciRegisterRo<'a, u16>,
35 subsystem_id @ 0x2e : PciRegisterRo<'a, u16>,
36 interrupt_line @ 0x3c : PciRegisterRw<'a, u8>,
37 interrupt_pin @ 0x3d : PciRegisterRo<'a, u8>,
38 min_gnt @ 0x3e : PciRegisterRo<'a, u8>,
39 max_lat @ 0x3f : PciRegisterRo<'a, u8>,
40 }
41}
42
43impl<'a> PciConfig<'a> {
44 pub fn capabilities(&self) -> io::Result<PciCapabilities<'a>> {
48 PciCapabilities::backed_by(*self)
49 }
50
51 pub fn extended_capabilities(&self) -> io::Result<PciExtendedCapabilities<'a>> {
55 PciExtendedCapabilities::backed_by(*self)
56 }
57}
58
59pci_bit_field! {
62 pub struct PciCommand<'a> : RW u16 {
63 io_space_enable @ 0 : RW,
64 memory_space_enable @ 1 : RW,
65 bus_master_enable @ 2 : RW,
66 special_cycle_enable @ 3 : RO,
67 memory_write_and_invalidate @ 4 : RO,
68 vga_palette_snoop @ 5 : RO,
69 parity_error_response @ 6 : RW,
70 idsel_stepping_wait_cycle_control @ 7 : RO,
71 serr_enable @ 8 : RW,
72 fast_back_to_back_transactions_enable @ 9 : RO,
73 interrupt_disable @ 10 : RW1C,
74 __ @ 11--15 : RsvdP,
75 }
76}
77
78pci_bit_field! {
81 pub struct PciStatus<'a> : RW u16 {
82 immediate_readiness @ 0 : RO,
83 __ @ 1--2 : RsvdZ,
84 interrupt_status @ 3 : RO,
85 capabilities_list @ 4 : RO,
86 mhz_66_capable @ 5 : RO,
87 __ @ 6 : RsvdZ,
88 fast_back_to_back_transactions_capable @ 7 : RO,
89 master_data_parity_error @ 8 : RW1C,
90 devsel_timing @ 9--10 : RO u8,
91 signaled_target_abort @ 11 : RW1C,
92 received_target_abort @ 12 : RW1C,
93 received_master_abort @ 13 : RW1C,
94 signaled_system_error @ 14 : RW1C,
95 detected_parity_error @ 15 : RW1C,
96 }
97}
98
99pci_struct! {
102 pub struct PciClassCode<'a> : 0x03 {
103 base_class_code @ 0x00 : PciRegisterRo<'a, u8>,
104 sub_class_code @ 0x01 : PciRegisterRo<'a, u8>,
105 programming_interface @ 0x02 : PciRegisterRo<'a, u8>,
106 }
107}
108
109pci_bit_field! {
112 pub struct PciHeaderType<'a> : RO u8 {
113 header_layout @ 0--6 : RO u8,
114 multi_function_device @ 7 : RO,
115 }
116}
117
118pci_bit_field! {
121 pub struct PciBist<'a> : RW u8 {
122 completion_code @ 0--3 : RO u8,
123 __ @ 4--5 : RsvdP,
124 start_bist @ 6 : RW,
125 bist_capable @ 7 : RO,
126 }
127}
128
129#[cfg(test)]
132mod tests {
133 use crate::backends::mock::MockPciDevice;
134 use crate::config::caps::Capability;
135 use crate::config::ext_caps::ExtendedCapability;
136 use crate::device::PciDevice;
137
138 #[test]
139 fn test_lifetimes() {
140 let device: &dyn PciDevice = &MockPciDevice;
141
142 let value_1 = device.config().command().io_space_enable();
143 let value_2 = device
144 .config()
145 .capabilities()
146 .unwrap()
147 .iter()
148 .next()
149 .unwrap()
150 .header()
151 .capability_id();
152
153 value_1.read().unwrap();
154 value_2.read().unwrap();
155 value_1.read().unwrap();
156 }
157
158 #[test]
159 fn test_capabilities() {
160 let device: &dyn PciDevice = &MockPciDevice;
161
162 let cap_ids: Vec<_> = device
163 .config()
164 .capabilities()
165 .unwrap()
166 .iter()
167 .map(|cap| cap.header().capability_id().read().unwrap())
168 .collect();
169
170 assert_eq!(cap_ids, vec![0x01, 0x05, 0x10, 0x11]);
171 }
172
173 #[test]
174 fn test_extended_capabilities() {
175 let device: &dyn PciDevice = &MockPciDevice;
176
177 let ext_cap_ids: Vec<_> = device
178 .config()
179 .extended_capabilities()
180 .unwrap()
181 .iter()
182 .map(|cap| cap.header().capability_id().read().unwrap())
183 .collect();
184
185 assert_eq!(
186 ext_cap_ids,
187 vec![0x0001, 0x0003, 0x0004, 0x0019, 0x0018, 0x001e]
188 );
189 }
190}
191
192