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