pcie/types/config/
pci_bridge.rs1use core::{fmt::Debug, ops::Deref};
2
3use bit_field::BitField;
4use pci_types::{ConfigRegionAccess, PciPciBridgeHeader};
5use rdif_pcie::ConfigAccess;
6
7use super::PciHeaderBase;
8
9pub struct PciPciBridge {
10 base: Option<PciHeaderBase>,
11 header: Option<PciPciBridgeHeader>,
12 is_root: bool,
13}
14
15impl PciPciBridge {
16 pub(crate) fn root() -> Self {
17 Self {
18 base: None,
19 header: None,
20 is_root: true,
21 }
22 }
23
24 pub(crate) fn new(base: PciHeaderBase) -> Self {
25 let header = PciPciBridgeHeader::from_header(base.header(), &base.root)
26 .expect("PciPciBridgeHeader::from_header failed");
27
28 Self {
29 base: Some(base),
30 header: Some(header),
31 is_root: false,
32 }
33 }
34
35 fn header(&self) -> &PciPciBridgeHeader {
36 self.header.as_ref().expect("Not a root bridge")
37 }
38
39 fn access(&self) -> &ConfigAccess {
40 &self.base.as_ref().expect("Not a root bridge").root
41 }
42
43 pub fn primary_bus_number(&self) -> u8 {
44 if self.is_root {
45 return 0;
46 }
47 self.header().primary_bus_number(self.access())
48 }
49
50 pub fn secondary_bus_number(&self) -> u8 {
51 if self.is_root {
52 return 0;
53 }
54 self.header().secondary_bus_number(self.access())
55 }
56
57 pub fn subordinate_bus_number(&self) -> u8 {
58 if self.is_root {
59 return 0;
60 }
61 self.header().subordinate_bus_number(self.access())
62 }
63
64 pub fn update_bus_number<F>(&mut self, f: F)
65 where
66 F: FnOnce(BusNumber) -> BusNumber,
67 {
68 if self.is_root {
69 return;
70 }
71 let address = self.base.as_ref().unwrap().address();
72 let mut data = unsafe { self.access().read(address, 0x18) };
73 let new_bus = f(BusNumber {
74 primary: data.get_bits(0..8) as u8,
75 secondary: data.get_bits(8..16) as u8,
76 subordinate: data.get_bits(16..24) as u8,
77 });
78 data.set_bits(16..24, new_bus.subordinate.into());
79 data.set_bits(8..16, new_bus.secondary.into());
80 data.set_bits(0..8, new_bus.primary.into());
81 unsafe {
82 self.access().write(address, 0x18, data);
83 }
84 }
85}
86
87pub struct BusNumber {
88 pub primary: u8,
89 pub secondary: u8,
90 pub subordinate: u8,
91}
92
93impl Deref for PciPciBridge {
94 type Target = PciHeaderBase;
95
96 fn deref(&self) -> &Self::Target {
97 self.base.as_ref().expect("Not a root bridge")
98 }
99}
100
101impl Debug for PciPciBridge {
102 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 f.debug_struct("PciPciBridge")
104 .field("base", &self.base.as_ref().expect("Not a root bridge"))
105 .field("primary_bus", &self.primary_bus_number())
106 .field("secondary_bus", &self.secondary_bus_number())
107 .field("subordinate_bus", &self.subordinate_bus_number())
108 .finish()
109 }
110}