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