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