Skip to main content

rdrive/probe/pci/
mod.rs

1use alloc::{collections::btree_set::BTreeSet, vec::Vec};
2use core::ops::{Deref, DerefMut};
3
4use ::pcie::*;
5pub use ::pcie::{Endpoint, PciCapability, PciIntxRoute, PcieGeneric};
6use mmio_api::{MapError, MmioOp};
7pub use rdif_pcie::{DriverGeneric, PciAddress, PciMem32, PciMem64, PcieController};
8use spin::{Mutex, Once};
9
10use crate::{
11    Descriptor, Device, PlatformDevice, ProbeError, get_list,
12    probe::OnProbeError,
13    register::{DriverRegister, ProbeKind},
14};
15
16static PCIE: Once<Mutex<Vec<PcieEnumterator>>> = Once::new();
17
18pub type FnOnProbe = fn(ProbePci<'_>) -> Result<(), OnProbeError>;
19
20pub fn new_driver_generic(
21    mmio_base: usize,
22    mmio_size: usize,
23    mmio_op: &'static dyn MmioOp,
24) -> Result<PcieController, MapError> {
25    Ok(PcieController::new(PcieGeneric::new(
26        mmio_base, mmio_size, mmio_op,
27    )?))
28}
29
30fn pcie() -> &'static Mutex<Vec<PcieEnumterator>> {
31    PCIE.call_once(|| {
32        let ctrl_ls = get_list::<PcieController>();
33        let mut vec = Vec::new();
34        for ctrl in ctrl_ls.into_iter() {
35            vec.push(PcieEnumterator {
36                ctrl,
37                probed: BTreeSet::new(),
38            });
39        }
40        Mutex::new(vec)
41    })
42}
43pub(crate) fn probe_with(
44    registers: &[DriverRegister],
45    stop_if_fail: bool,
46) -> Result<(), ProbeError> {
47    let mut pcie_ls = pcie().lock();
48    for ctrl in pcie_ls.iter_mut() {
49        ctrl.probe(registers, stop_if_fail)?;
50    }
51    Ok(())
52}
53
54pub struct EndpointRc(Option<Endpoint>);
55
56impl EndpointRc {
57    fn new(ep: Endpoint) -> Self {
58        Self(Some(ep))
59    }
60
61    pub fn take(&mut self) -> Endpoint {
62        self.0.take().unwrap()
63    }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub struct PciInfo {
68    pub address: PciAddress,
69    pub interrupt_pin: u8,
70    pub interrupt_line: u8,
71    pub intx_route: Option<PciIntxRoute>,
72}
73
74impl PciInfo {
75    fn from_endpoint(endpoint: &EndpointRc, intx_route: Option<PciIntxRoute>) -> Self {
76        Self {
77            address: endpoint.address(),
78            interrupt_pin: endpoint.interrupt_pin(),
79            interrupt_line: endpoint.interrupt_line(),
80            intx_route,
81        }
82    }
83}
84
85pub struct ProbePci<'a> {
86    info: PciInfo,
87    endpoint: &'a mut EndpointRc,
88    platform: PlatformDevice,
89}
90
91impl<'a> ProbePci<'a> {
92    pub(crate) fn new(
93        info: PciInfo,
94        endpoint: &'a mut EndpointRc,
95        platform: PlatformDevice,
96    ) -> Self {
97        Self {
98            info,
99            endpoint,
100            platform,
101        }
102    }
103
104    pub const fn info(&self) -> PciInfo {
105        self.info
106    }
107
108    pub fn endpoint(&self) -> &Endpoint {
109        self.endpoint
110    }
111
112    pub fn endpoint_mut(&mut self) -> &mut EndpointRc {
113        self.endpoint
114    }
115
116    pub fn take_endpoint(&mut self) -> Endpoint {
117        self.endpoint.take()
118    }
119
120    pub fn into_platform_device(self) -> PlatformDevice {
121        self.platform
122    }
123
124    pub fn into_parts(self) -> (PciInfo, &'a mut EndpointRc, PlatformDevice) {
125        (self.info, self.endpoint, self.platform)
126    }
127}
128
129impl Deref for EndpointRc {
130    type Target = Endpoint;
131
132    fn deref(&self) -> &Self::Target {
133        self.0.as_ref().unwrap()
134    }
135}
136
137impl DerefMut for EndpointRc {
138    fn deref_mut(&mut self) -> &mut Self::Target {
139        self.0.as_mut().unwrap()
140    }
141}
142
143struct PcieEnumterator {
144    ctrl: Device<PcieController>,
145    probed: BTreeSet<PciAddress>,
146}
147
148impl PcieEnumterator {
149    fn probe(
150        &mut self,
151        registers: &[DriverRegister],
152        stop_if_fail: bool,
153    ) -> Result<(), ProbeError> {
154        let mut g = self.ctrl.lock().unwrap();
155
156        for ep in enumerate_by_controller_with_info(&mut g, None) {
157            debug!("PCIe endpiont: {}", ep.endpoint);
158            match self.probe_one(ep, registers, stop_if_fail) {
159                Ok(_) => {} // Successfully probed, move to the next
160                Err(e) => {
161                    if stop_if_fail {
162                        return Err(e);
163                    } else {
164                        warn!("Probe failed: {e}");
165                    }
166                }
167            }
168        }
169
170        Ok(())
171    }
172
173    fn probe_one(
174        &mut self,
175        endpoint: EnumeratedEndpoint,
176        registers: &[DriverRegister],
177        stop_if_fail: bool,
178    ) -> Result<(), ProbeError> {
179        let intx_route = endpoint.intx_route;
180        let endpoint = endpoint.endpoint;
181        let address = endpoint.address();
182        if self.probed.contains(&address) {
183            return Ok(());
184        }
185
186        let mut endpoint = EndpointRc::new(endpoint);
187
188        for register in registers {
189            let Some(pci_probe) = register.probe_kinds.iter().find_map(|probe| {
190                if let ProbeKind::Pci { on_probe } = probe {
191                    Some(on_probe)
192                } else {
193                    None
194                }
195            }) else {
196                continue;
197            };
198            let mut desc = Descriptor::new();
199            desc.name = register.name;
200            desc.irq_parent = self.ctrl.descriptor().irq_parent;
201
202            let info = PciInfo::from_endpoint(&endpoint, intx_route);
203            let plat_dev = PlatformDevice::new(desc);
204            match (pci_probe)(ProbePci::new(info, &mut endpoint, plat_dev)) {
205                Ok(_) => {
206                    self.probed.insert(address);
207                    return Ok(());
208                }
209                Err(e) => match e {
210                    OnProbeError::NotMatch => continue,
211                    e => {
212                        if stop_if_fail {
213                            return Err(ProbeError::from(e));
214                        }
215                        warn!("Probe failed: {e}");
216                    }
217                },
218            }
219        }
220
221        Ok(())
222    }
223}