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(_) => {} 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}