1use crate::ChipsetDevice;
7use crate::io::IoError;
8use crate::io::IoResult;
9use inspect::Inspect;
10use inspect::InspectMut;
11use mesh::MeshPayload;
12use zerocopy::IntoBytes;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Inspect, MeshPayload)]
16pub struct PciConfigByteEnable(u8);
17
18impl PciConfigByteEnable {
19 pub const FULL: Self = Self(0b1111);
21
22 pub const BYTE0: Self = Self(0b0001);
24 pub const BYTE1: Self = Self(0b0010);
26 pub const BYTE2: Self = Self(0b0100);
28 pub const BYTE3: Self = Self(0b1000);
30 pub const LOW_WORD: Self = Self(0b0011);
32 pub const HIGH_WORD: Self = Self(0b1100);
34
35 pub const fn new(bits: u8) -> Option<Self> {
37 if bits != 0 && bits <= 0xf {
38 Some(Self(bits))
39 } else {
40 None
41 }
42 }
43
44 pub const fn from_offset_len(offset: u16, len: usize) -> Result<Self, IoError> {
46 let lane = (offset & 0x3) as u8;
47 match len {
48 1 => Ok(Self(1 << lane)),
49 2 if lane & 1 == 0 && lane <= 2 => Ok(Self(0x3 << lane)),
50 4 if lane == 0 => Ok(Self::FULL),
51 2 | 4 => Err(IoError::UnalignedAccess),
52 _ => Err(IoError::InvalidAccessSize),
53 }
54 }
55
56 pub const fn to_byte_offset_len(self) -> (u16, usize) {
58 (self.0.trailing_zeros() as u16, self.0.count_ones() as usize)
59 }
60
61 pub const fn bits(self) -> u8 {
63 self.0
64 }
65
66 pub const fn is_full(self) -> bool {
68 self.0 == 0xf
69 }
70
71 pub const fn mask(self) -> u32 {
73 let mut mask = 0;
74 let mut lane = 0;
75 while lane < 4 {
76 if self.0 & (1 << lane) != 0 {
77 mask |= 0xff << (lane * 8);
78 }
79 lane += 1;
80 }
81 mask
82 }
83
84 pub const fn merge(self, current_value: u32, write_value: u32) -> u32 {
86 let mask = self.mask();
87 (current_value & !mask) | (write_value & mask)
88 }
89
90 pub const fn extract(self, value: u32) -> u32 {
92 value & self.mask()
93 }
94
95 pub const fn restrict(self, byte_enable: PciConfigByteEnable) -> Option<Self> {
98 Self::new(self.0 & byte_enable.0)
99 }
100
101 pub const fn exclude(self, byte_enable: PciConfigByteEnable) -> Option<Self> {
104 Self::new(self.0 & !byte_enable.0)
105 }
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Inspect)]
110pub struct ByteEnabledDwordWrite {
111 value: u32,
112 byte_enable: PciConfigByteEnable,
113}
114
115impl ByteEnabledDwordWrite {
116 pub const fn new(value: u32, byte_enable: PciConfigByteEnable) -> Self {
118 Self {
119 value: byte_enable.merge(0, value),
120 byte_enable,
121 }
122 }
123
124 pub const fn with_all_bytes_enabled(value: u32) -> Self {
126 Self::new(value, PciConfigByteEnable::FULL)
127 }
128
129 pub fn from_intercept_buffer(byte_enable: PciConfigByteEnable, buffer: &[u8]) -> Self {
131 let mut temp: u32 = 0;
132 let (byte_offset, len) = byte_enable.to_byte_offset_len();
133 assert!(len <= buffer.len());
134 let byte_offset = byte_offset as usize;
135 temp.as_mut_bytes()[byte_offset..byte_offset + len].copy_from_slice(buffer);
136 Self::new(temp, byte_enable)
137 }
138
139 pub fn as_valid_byte_slice(&self) -> &[u8] {
141 let (byte_offset, len) = self.byte_enable.to_byte_offset_len();
142 let byte_offset = byte_offset as usize;
143 &self.value.as_bytes()[byte_offset..byte_offset + len]
144 }
145
146 pub const fn is_full(self) -> bool {
148 self.byte_enable.is_full()
149 }
150
151 pub const fn byte_enable(&self) -> PciConfigByteEnable {
153 self.byte_enable
154 }
155
156 pub const fn valid_mask(self) -> u32 {
158 self.byte_enable.mask()
159 }
160
161 pub const fn merge(self, current_value: u32) -> u32 {
163 self.byte_enable.merge(current_value, self.value)
164 }
165
166 pub const fn merge_into(self, current_value: &mut u32) {
168 *current_value = self.merge(*current_value);
169 }
170
171 pub const fn merge_low(self, current_value: u16) -> u16 {
173 self.byte_enable.merge(current_value as u32, self.value) as u16
174 }
175
176 pub const fn merge_high(self, current_value: u16) -> u16 {
178 let shifted = (current_value as u32) << 16;
179 let merged = self.byte_enable.merge(shifted, self.value);
180 (merged >> 16) as u16
181 }
182
183 pub const fn extract(self) -> u32 {
185 self.byte_enable.extract(self.value)
186 }
187
188 pub const fn extract_low(self) -> u16 {
190 self.extract() as u16
191 }
192
193 pub const fn extract_high(self) -> u16 {
195 (self.extract() >> 16) as u16
196 }
197}
198
199#[derive(Debug, InspectMut)]
201pub struct ByteEnabledDwordRead<'a> {
202 value: &'a mut u32,
203 byte_enable: PciConfigByteEnable,
204}
205
206impl<'a> ByteEnabledDwordRead<'a> {
207 pub const fn new(value: &'a mut u32, byte_enable: PciConfigByteEnable) -> Self {
209 Self { value, byte_enable }
210 }
211
212 pub const fn with_all_bytes_enabled(value: &'a mut u32) -> Self {
214 Self::new(value, PciConfigByteEnable::FULL)
215 }
216
217 pub const fn byte_enable(&self) -> PciConfigByteEnable {
219 self.byte_enable
220 }
221
222 pub fn fill_intercept_buffer(self, buffer: &mut [u8]) {
224 let src = self.into_valid_byte_slice();
225 buffer.copy_from_slice(src);
226 }
227
228 pub fn into_valid_byte_slice(self) -> &'a mut [u8] {
230 let (byte_offset, len) = self.byte_enable.to_byte_offset_len();
231 let byte_offset = byte_offset as usize;
232 &mut self.value.as_mut_bytes()[byte_offset..byte_offset + len]
233 }
234
235 pub const fn valid_mask(&self) -> u32 {
237 self.byte_enable.mask()
238 }
239
240 pub fn set(&mut self, value: u32) {
242 *self.value = self.byte_enable.merge(*self.value, value);
243 }
244
245 pub fn set_low_high(&mut self, low: u16, high: u16) {
247 *self.value = self
248 .byte_enable
249 .merge(*self.value, (high as u32) << 16 | (low as u32));
250 }
251
252 pub fn set_bytes(&mut self, byte0: u8, byte1: u8, byte2: u8, byte3: u8) {
254 *self.value = self.byte_enable.merge(
255 *self.value,
256 (byte3 as u32) << 24 | (byte2 as u32) << 16 | (byte1 as u32) << 8 | (byte0 as u32),
257 );
258 }
259
260 pub const fn extract(&self) -> u32 {
262 self.byte_enable.extract(*self.value)
263 }
264
265 pub const fn extract_low(self) -> u16 {
267 self.extract() as u16
268 }
269
270 pub const fn extract_high(self) -> u16 {
272 (self.extract() >> 16) as u16
273 }
274
275 pub fn reborrow(&mut self) -> ByteEnabledDwordRead<'_> {
277 self.restrict(PciConfigByteEnable::FULL).unwrap()
278 }
279
280 pub fn restrict(
282 &mut self,
283 byte_enable: PciConfigByteEnable,
284 ) -> Option<ByteEnabledDwordRead<'_>> {
285 let byte_enable = self.byte_enable.restrict(byte_enable)?;
286 Some(ByteEnabledDwordRead::new(&mut *self.value, byte_enable))
287 }
288
289 pub fn exclude(
291 &mut self,
292 byte_enable: PciConfigByteEnable,
293 ) -> Option<ByteEnabledDwordRead<'_>> {
294 let byte_enable = self.byte_enable.exclude(byte_enable)?;
295 Some(ByteEnabledDwordRead::new(&mut *self.value, byte_enable))
296 }
297}
298
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Inspect)]
301pub struct PciConfigAddress {
302 pub bus: u8,
304 pub devfn: u8,
306 dword_number: u16,
308}
309
310impl PciConfigAddress {
311 pub const fn new(bus: u8, devfn: u8, dword_number: u16) -> Option<Self> {
313 if dword_number >= 1024 {
314 return None;
315 }
316 Some(Self {
317 bus,
318 devfn,
319 dword_number,
320 })
321 }
322
323 pub const fn device(self) -> u8 {
325 self.devfn >> 3
326 }
327
328 pub const fn function(self) -> u8 {
330 self.devfn & 0x7
331 }
332
333 pub const fn byte_offset(self) -> u16 {
335 self.dword_number * 4
336 }
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq, Inspect)]
341pub enum PciConfigAccessType {
342 Type0,
345 Type1,
348}
349
350pub trait PciConfigSpace: ChipsetDevice {
352 fn pci_cfg_read(&mut self, byte_offset: u16, value: ByteEnabledDwordRead<'_>) -> IoResult;
362
363 fn pci_cfg_write(&mut self, byte_offset: u16, value: ByteEnabledDwordWrite) -> IoResult;
373
374 fn pci_cfg_read_with_routing(
390 &mut self,
391 access_type: PciConfigAccessType,
392 address: PciConfigAddress,
393 mut value: ByteEnabledDwordRead<'_>,
394 ) -> IoResult {
395 match (access_type, address.devfn) {
396 (PciConfigAccessType::Type0, 0) => self.pci_cfg_read(address.byte_offset(), value),
397 _ => {
398 value.set(!0);
399 IoResult::Ok
400 }
401 }
402 }
403
404 fn pci_cfg_write_with_routing(
419 &mut self,
420 access_type: PciConfigAccessType,
421 address: PciConfigAddress,
422 value: ByteEnabledDwordWrite,
423 ) -> IoResult {
424 match (access_type, address.devfn) {
425 (PciConfigAccessType::Type0, 0) => self.pci_cfg_write(address.byte_offset(), value),
426 _ => IoResult::Ok,
427 }
428 }
429
430 fn suggested_bdf(&mut self) -> Option<(u8, u8, u8)> {
458 None
459 }
460}
461
462#[cfg(test)]
463mod tests {
464 use super::*;
465
466 #[test]
467 fn byte_enable_from_offset_len_rejects_invalid_accesses() {
468 assert_eq!(
469 PciConfigByteEnable::from_offset_len(0, 1).unwrap().bits(),
470 0b0001
471 );
472 assert_eq!(
473 PciConfigByteEnable::from_offset_len(1, 1).unwrap().bits(),
474 0b0010
475 );
476 assert_eq!(
477 PciConfigByteEnable::from_offset_len(2, 1).unwrap().bits(),
478 0b0100
479 );
480 assert_eq!(
481 PciConfigByteEnable::from_offset_len(3, 1).unwrap().bits(),
482 0b1000
483 );
484 assert_eq!(
485 PciConfigByteEnable::from_offset_len(0, 2).unwrap().bits(),
486 0b0011
487 );
488 assert_eq!(
489 PciConfigByteEnable::from_offset_len(2, 2).unwrap().bits(),
490 0b1100
491 );
492 assert_eq!(
493 PciConfigByteEnable::from_offset_len(0, 4).unwrap().bits(),
494 0b1111
495 );
496
497 assert!(matches!(
498 PciConfigByteEnable::from_offset_len(1, 2),
499 Err(IoError::UnalignedAccess)
500 ));
501 assert!(matches!(
502 PciConfigByteEnable::from_offset_len(3, 2),
503 Err(IoError::UnalignedAccess)
504 ));
505 assert!(matches!(
506 PciConfigByteEnable::from_offset_len(1, 4),
507 Err(IoError::UnalignedAccess)
508 ));
509 assert!(matches!(
510 PciConfigByteEnable::from_offset_len(0, 3),
511 Err(IoError::InvalidAccessSize)
512 ));
513 }
514
515 #[test]
516 fn byte_enable_masks_and_merges_lanes() {
517 let byte_enable = PciConfigByteEnable::from_offset_len(1, 1).unwrap();
518 assert_eq!(byte_enable.bits(), 0b0010);
519 assert_eq!(byte_enable.mask(), 0x0000_ff00);
520 assert_eq!(byte_enable.extract(0x1234_5678), 0x0000_5600);
521 assert_eq!(byte_enable.merge(0xaaaa_aaaa, 0x1234_5678), 0xaaaa_56aa);
522
523 let byte_enable = PciConfigByteEnable::from_offset_len(2, 2).unwrap();
524 assert_eq!(byte_enable.bits(), 0b1100);
525 assert_eq!(byte_enable.mask(), 0xffff_0000);
526 assert_eq!(byte_enable.extract(0x1234_5678), 0x1234_0000);
527 assert_eq!(byte_enable.merge(0xaaaa_aaaa, 0x1234_5678), 0x1234_aaaa);
528
529 let byte_enable = PciConfigByteEnable::from_offset_len(0, 4).unwrap();
530 assert_eq!(byte_enable.bits(), 0b1111);
531 assert_eq!(byte_enable.mask(), 0xffff_ffff);
532 assert_eq!(byte_enable.extract(0x1234_5678), 0x1234_5678);
533 assert_eq!(byte_enable.merge(0xaaaa_aaaa, 0x1234_5678), 0x1234_5678);
534 }
535
536 #[test]
537 fn byte_enabled_intercept_buffers_copy_selected_lanes() {
538 let write = ByteEnabledDwordWrite::from_intercept_buffer(
539 PciConfigByteEnable::HIGH_WORD,
540 &[0x22, 0x11],
541 );
542 assert_eq!(write.extract(), 0x1122_0000);
543 assert_eq!(write.merge(0xaabb_ccdd), 0x1122_ccdd);
544
545 let mut value = 0x5566_7788;
546 let read = ByteEnabledDwordRead::new(&mut value, PciConfigByteEnable::HIGH_WORD);
547 let mut buffer = [0; 2];
548 read.fill_intercept_buffer(&mut buffer);
549 assert_eq!(buffer, [0x66, 0x55]);
550 }
551
552 #[test]
553 fn config_request_decodes_bdf() {
554 let address = PciConfigAddress::new(0x12, 0x1d, 0x40).unwrap();
555
556 assert_eq!(address.bus, 0x12);
557 assert_eq!(address.devfn, 0x1d);
558 assert_eq!(address.device(), 3);
559 assert_eq!(address.function(), 5);
560 assert_eq!(address.byte_offset(), 0x100);
561 }
562}