1use crate::util::is_set;
5use bitfield::bitfield;
6use std::fmt;
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref};
8
9#[repr(C, packed)]
11#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
12pub struct Type00Config {
13 pub vendor_id: u16,
14 pub device_id: u16,
15 pub command: u16,
16 pub status: u16,
17 pub revision_id: u8,
18 pub program_interface: u8,
19 pub sub_class: u8,
20 pub base_class: u8,
21 pub cache_line_size: u8,
22 pub latency_timer: u8,
23 pub header_type: u8,
24 pub bist: u8,
25 pub base_address: [u32; 6],
26 pub cardbus_cis_ptr: u32,
27 pub sub_vendor_id: u16,
28 pub subsystem_id: u16,
29 pub expansion_rom_address: u32,
30 pub capabilities_ptr: u8,
31 pub reserved_0: [u8; 3],
32 pub reserved_1: [u8; 4],
33 pub interrupt_line: u8,
34 pub interrupt_pin: u8,
35 pub min_grant: u8,
36 pub max_latency: u8,
37}
38
39impl Type00Config {
40 pub fn new(config: &[u8]) -> Ref<&[u8], Type00Config> {
41 let (config, _) = Ref::from_prefix(config).unwrap();
42 config
43 }
44}
45
46#[repr(C, packed)]
47#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
48pub struct Type01Config {
49 pub vendor_id: u16,
50 pub device_id: u16,
51 pub command: u16,
52 pub status: u16,
53 pub revision_id: u8,
54 pub program_interface: u8,
55 pub sub_class: u8,
56 pub base_class: u8,
57 pub cache_line_size: u8,
58 pub latency_timer: u8,
59 pub header_type: u8,
60 pub bist: u8,
61 pub base_address: [u32; 2],
62 pub primary_bus_number: u8,
63 pub secondary_bus_number: u8,
64 pub subordinate_bus_number: u8,
65 pub secondary_latency_timer: u8,
66 pub io_base: u8,
67 pub io_limit: u8,
68 pub secondary_status: u16,
69 pub memory_base: u16,
70 pub memory_limit: u16,
71 pub pf_memory_base: u16,
72 pub pf_memory_limit: u16,
73 pub pf_base_upper_32: u32,
74 pub pf_limit_upper_32: u32,
75 pub io_base_upper_16: u16,
76 pub io_limit_upper_16: u16,
77 pub capabilities_ptr: u8,
78 pub reserved_0: [u8; 3],
79 pub expansion_rom_base: u32,
80 pub interrupt_line: u8,
81 pub interrupt_pin: u8,
82 pub bridge_control: u16,
83}
84
85impl Type01Config {
86 pub fn new(config: &[u8]) -> Ref<&[u8], Type01Config> {
87 let (config, _) = Ref::from_prefix(config).unwrap();
88 config
89 }
90}
91
92bitfield! {
95 pub struct CommandRegister(u16);
96 pub io_space, _: 0;
97 pub memory_space, _: 1;
98 pub bus_master_en, _: 2;
99 pub special_cycles, _: 3;
100 pub mem_winv_en, _: 4;
101 pub vga_snoop, _: 5;
102 pub parity_error_response, _: 6;
103 pub serr_en, _: 8;
105 pub fb2b_en, _: 9;
106 pub int_disable, _: 10;
107 }
109
110impl fmt::Display for CommandRegister {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "I/O{} Mem{} BusMaster{} SpecCycle{} MemWINV{} VGASnoop{} ParErr{} SERR{} FastB2B{} DisINTx{}",
113 is_set(self.io_space()),
114 is_set(self.memory_space()),
115 is_set(self.bus_master_en()),
116 is_set(self.special_cycles()),
117 is_set(self.mem_winv_en()),
118 is_set(self.vga_snoop()),
119 is_set(self.parity_error_response()),
120 is_set(self.serr_en()),
121 is_set(self.fb2b_en()),
122 is_set(self.int_disable()))
123 }
124}
125
126bitfield! {
129 pub struct StatusRegister(u16);
130 pub int_status, _: 3;
132 pub has_cap_list, _: 4;
133 pub supports_66mhz, _: 5;
134 pub fb2b, _: 7;
136 pub master_data_parity_error, _: 8;
137 pub devsel_timing, _: 10, 9;
138 pub signaled_target_abort, _: 11;
139 pub received_target_abort, _: 12;
140 pub received_master_abort, _: 13;
141 pub signaled_system_error, _: 14;
142 pub detected_parity_error, _: 15;
143}
144
145impl fmt::Display for StatusRegister {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(f, "Cap{} 66Mhz{} FastB2B{} ParErr{} DEVSEL={} >TAbort{} <TAbort{} MAbort{} >SERR{} <PERR{} INTx{}",
148 is_set(self.has_cap_list()),
149 is_set(self.supports_66mhz()),
150 is_set(self.fb2b()),
151 is_set(self.master_data_parity_error()),
152 match self.devsel_timing() {
153 0 => "fast",
154 1 => "medium",
155 2 => "slow",
156 _ => "<3?>",
157 },
158 is_set(self.signaled_target_abort()),
159 is_set(self.received_target_abort()),
160 is_set(self.received_master_abort()),
161 is_set(self.signaled_system_error()),
162 is_set(self.detected_parity_error()),
163 is_set(self.int_status()))
164 }
165}
166
167bitfield! {
168 pub struct SecondaryStatusRegister(u16);
169 pub supports_66mhz, _: 5;
171 pub fb2b, _: 7;
173 pub master_data_parity_error, _: 8;
174 pub devsel_timing, _: 10, 9;
175 pub signaled_target_abort, _: 11;
176 pub received_target_abort, _: 12;
177 pub received_master_abort, _: 13;
178 pub received_system_error, _: 14;
179 pub detected_parity_error, _: 15;
180}
181
182impl fmt::Display for SecondaryStatusRegister {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 write!(
185 f,
186 "66Mhz{} FastB2B{} ParErr{} DEVSEL={} >TAbort{} <TAbort{} MAbort{} <SERR{} <PERR{}",
187 is_set(self.supports_66mhz()),
188 is_set(self.fb2b()),
189 is_set(self.master_data_parity_error()),
190 match self.devsel_timing() {
191 0 => "fast",
192 1 => "medium",
193 2 => "slow",
194 _ => "<3?>",
195 },
196 is_set(self.signaled_target_abort()),
197 is_set(self.received_target_abort()),
198 is_set(self.received_master_abort()),
199 is_set(self.received_system_error()),
200 is_set(self.detected_parity_error())
201 )
202 }
203}
204
205bitfield! {
206 pub struct BridgeControlRegister(u16);
207 pub parity_error_response_en, _: 0;
208 pub serr_en, _: 1;
209 pub isa_en, _: 2;
210 pub vga_en, _: 3;
211 pub vga_16bit_decode, _: 4;
212 pub master_mode_abort, _: 5;
213 pub secondary_bus_reset, _: 6;
214 pub fb2b_en, _: 7;
215 pub primary_discard_timer, _: 8;
216 pub secondary_discard_timer, _: 9;
217 pub discard_timer_status, _: 10;
218 pub discard_timer_serr_en, _: 11;
219 }
221
222impl fmt::Display for BridgeControlRegister {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 writeln!(
225 f,
226 "Parity{} SERR{} NoISA{} VGA{} VGA16{} MAbort{} >Reset{} FastB2b{}",
227 is_set(self.parity_error_response_en()),
228 is_set(self.serr_en()),
229 is_set(self.isa_en()),
230 is_set(self.vga_en()),
231 is_set(self.vga_16bit_decode()),
232 is_set(self.master_mode_abort()),
233 is_set(self.secondary_bus_reset()),
234 is_set(self.fb2b_en())
235 )?;
236 write!(
237 f,
238 "\t\tPriDiscTmr{} SecDiscTmr{} DiscTmrStat{} DiscTmrSERREn{}",
239 is_set(self.primary_discard_timer()),
240 is_set(self.secondary_discard_timer()),
241 is_set(self.discard_timer_status()),
242 is_set(self.discard_timer_serr_en())
243 )
244 }
245}