pcie/types/config/
pci_bridge.rs

1use 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}