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