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