pcie/types/config/
pci_bridge.rs

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