Skip to main content

pcie/
root.rs

1use alloc::vec::Vec;
2use core::hint::spin_loop;
3
4use crate::{
5    Endpoint, PciAddress, PciConfigSpace, PciHeaderBase, PciPciBridge, chip::PcieController,
6};
7
8const MAX_DEVICE: u8 = 31;
9const MAX_FUNCTION: u8 = 7;
10
11pub fn enumerate_by_controller<'a>(
12    controller: &'a mut PcieController,
13    range: Option<core::ops::Range<usize>>,
14) -> impl Iterator<Item = Endpoint> + 'a {
15    enumerate_by_controller_with_info(controller, range).map(|item| item.endpoint)
16}
17
18pub fn enumerate_by_controller_with_info<'a>(
19    controller: &'a mut PcieController,
20    range: Option<core::ops::Range<usize>>,
21) -> impl Iterator<Item = EnumeratedEndpoint> + 'a {
22    let range = range.unwrap_or(0..0x100);
23
24    PciIterator {
25        root: controller,
26        segment: 0,
27        bus_max: (range.end - 1) as _,
28        function: 0,
29        is_mulitple_function: false,
30        is_finish: false,
31        stack: alloc::vec![Bridge::root(range.start as _)],
32    }
33}
34
35#[derive(Debug)]
36pub struct EnumeratedEndpoint {
37    pub endpoint: Endpoint,
38    pub intx_route: Option<PciIntxRoute>,
39}
40
41#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct PciIntxRoute {
43    pub root_device: u8,
44    pub root_function: u8,
45    pub root_pin: u8,
46}
47
48pub(crate) struct PciIterator<'a> {
49    root: &'a mut PcieController,
50    segment: u16,
51    stack: Vec<Bridge>,
52    bus_max: u8,
53    function: u8,
54    is_mulitple_function: bool,
55    is_finish: bool,
56}
57
58impl<'a> Iterator for PciIterator<'a> {
59    type Item = EnumeratedEndpoint;
60
61    fn next(&mut self) -> Option<Self::Item> {
62        while !self.is_finish {
63            if let Some(value) = self.get_current_valid() {
64                match value {
65                    PciConfigSpace::PciPciBridge(pci_pci_bridge) => {
66                        self.next(Some(pci_pci_bridge));
67                    }
68                    PciConfigSpace::Endpoint(ep) => {
69                        let intx_route = self.intx_route_for_endpoint(&ep);
70                        let item = EnumeratedEndpoint {
71                            endpoint: ep,
72                            intx_route,
73                        };
74                        self.next(None);
75                        return Some(item);
76                    }
77                    PciConfigSpace::CardBusBridge(_) | PciConfigSpace::Unknown(_) => {
78                        // Not handled for iteration; skip
79                        self.next(None);
80                    }
81                }
82            } else {
83                self.next(None);
84            }
85        }
86        None
87    }
88}
89
90impl<'a> PciIterator<'a> {
91    fn get_current_valid(&mut self) -> Option<PciConfigSpace> {
92        let address = self.address();
93        let header_base = PciHeaderBase::new(self.root, address)?;
94        self.is_mulitple_function = header_base.has_multiple_functions();
95
96        match header_base.header_type() {
97            pci_types::HeaderType::Endpoint => {
98                let bl = self.root.bar_allocator.as_mut();
99                let ep = Endpoint::new(header_base, bl);
100                Some(PciConfigSpace::Endpoint(ep))
101            }
102            pci_types::HeaderType::PciPciBridge => {
103                let mut bridge = PciPciBridge::new(header_base);
104                let primary_bus = address.bus();
105                let secondary_bus;
106
107                if let Some(parent) = self.stack.last_mut() {
108                    if parent.bridge.subordinate_bus_number() == self.bus_max {
109                        return None;
110                    }
111
112                    secondary_bus = parent.bridge.subordinate_bus_number() + 1;
113                } else {
114                    panic!("no parent");
115                }
116                let subordinate_bus = secondary_bus;
117                bridge.update_bus_number(|mut bus| {
118                    bus.primary = primary_bus;
119                    bus.secondary = secondary_bus;
120                    bus.subordinate = subordinate_bus;
121                    bus
122                });
123
124                Some(PciConfigSpace::PciPciBridge(bridge))
125            }
126            pci_types::HeaderType::CardBusBridge => todo!(),
127            pci_types::HeaderType::Unknown(_) => todo!(),
128            _ => unreachable!(),
129        }
130    }
131
132    fn address(&self) -> PciAddress {
133        let parent = self.stack.last().unwrap();
134        let bus = parent.bridge.secondary_bus_number();
135        let device = parent.device;
136
137        PciAddress::new(self.segment, bus, device, self.function)
138    }
139
140    fn intx_route_for_endpoint(&self, endpoint: &Endpoint) -> Option<PciIntxRoute> {
141        root_intx_route(
142            endpoint.address(),
143            endpoint.interrupt_pin(),
144            self.stack.iter().skip(1).map(|bridge| BridgeAddress {
145                device: bridge.parent_device,
146                function: bridge.parent_function,
147            }),
148        )
149    }
150
151    /// 若进位返回true
152    fn is_next_function_max(&mut self) -> bool {
153        if self.is_mulitple_function {
154            if self.function == MAX_FUNCTION {
155                self.function = 0;
156                true
157            } else {
158                self.function += 1;
159                false
160            }
161        } else {
162            self.function = 0;
163            true
164        }
165    }
166
167    /// 若进位返回true
168    fn next_device_not_ok(&mut self) -> bool {
169        if let Some(parent) = self.stack.last_mut() {
170            if parent.device == MAX_DEVICE {
171                if let Some(parent) = self.stack.pop() {
172                    self.is_finish = parent.bridge.subordinate_bus_number() == self.bus_max;
173
174                    // parent.header.sync_bus_number(&self.root);
175                    self.function = 0;
176                    return true;
177                } else {
178                    self.is_finish = true;
179                }
180            } else {
181                parent.device += 1;
182            }
183        } else {
184            self.is_finish = true;
185        }
186
187        false
188    }
189
190    fn next(&mut self, current_bridge: Option<PciPciBridge>) {
191        if let Some(bridge) = current_bridge {
192            for parent in &mut self.stack {
193                // parent.header.subordinate_bus += 1;
194
195                parent.bridge.update_bus_number(|mut bus| {
196                    bus.subordinate += 1;
197                    bus
198                });
199            }
200
201            let address = bridge.address();
202            self.stack.push(Bridge {
203                bridge,
204                device: 0,
205                parent_device: address.device(),
206                parent_function: address.function(),
207            });
208
209            self.function = 0;
210            return;
211        }
212
213        if self.is_next_function_max() {
214            while self.next_device_not_ok() {
215                spin_loop();
216            }
217        }
218    }
219}
220
221struct Bridge {
222    bridge: PciPciBridge,
223    device: u8,
224    parent_device: u8,
225    parent_function: u8,
226}
227
228impl Bridge {
229    fn root(bus_start: u8) -> Self {
230        Self {
231            bridge: PciPciBridge::root(),
232            device: bus_start,
233            parent_device: 0,
234            parent_function: 0,
235        }
236    }
237}
238
239const fn swizzle_interrupt_pin(interrupt_pin: u8, device: u8) -> Option<u8> {
240    if interrupt_pin == 0 || interrupt_pin > 4 {
241        return None;
242    }
243    Some(((interrupt_pin - 1 + (device & 0x3)) % 4) + 1)
244}
245
246#[derive(Clone, Copy)]
247struct BridgeAddress {
248    device: u8,
249    function: u8,
250}
251
252fn root_intx_route(
253    endpoint: PciAddress,
254    interrupt_pin: u8,
255    bridges_from_root: impl DoubleEndedIterator<Item = BridgeAddress>,
256) -> Option<PciIntxRoute> {
257    let mut pin = interrupt_pin;
258    if !(1..=4).contains(&pin) {
259        return None;
260    }
261
262    let mut device = endpoint.device();
263    let mut function = endpoint.function();
264    for bridge in bridges_from_root.rev() {
265        pin = swizzle_interrupt_pin(pin, device)?;
266        device = bridge.device;
267        function = bridge.function;
268    }
269
270    Some(PciIntxRoute {
271        root_device: device,
272        root_function: function,
273        root_pin: pin,
274    })
275}
276
277#[cfg(test)]
278mod tests {
279    use super::{BridgeAddress, PciIntxRoute, root_intx_route, swizzle_interrupt_pin};
280    use crate::PciAddress;
281
282    #[test]
283    fn intx_swizzle_uses_linux_slot_rotation() {
284        assert_eq!(swizzle_interrupt_pin(1, 0), Some(1));
285        assert_eq!(swizzle_interrupt_pin(1, 1), Some(2));
286        assert_eq!(swizzle_interrupt_pin(1, 2), Some(3));
287        assert_eq!(swizzle_interrupt_pin(1, 3), Some(4));
288        assert_eq!(swizzle_interrupt_pin(4, 1), Some(1));
289    }
290
291    #[test]
292    fn intx_swizzle_rejects_absent_or_invalid_pins() {
293        assert_eq!(swizzle_interrupt_pin(0, 1), None);
294        assert_eq!(swizzle_interrupt_pin(5, 1), None);
295    }
296
297    #[test]
298    fn root_endpoint_uses_its_own_device_function_and_pin() {
299        let route = root_intx_route(PciAddress::new(0, 0, 5, 2), 3, [].into_iter());
300
301        assert_eq!(
302            route,
303            Some(PciIntxRoute {
304                root_device: 5,
305                root_function: 2,
306                root_pin: 3,
307            })
308        );
309    }
310
311    #[test]
312    fn bridge_endpoint_uses_parent_bridge_slot_and_swizzled_pin() {
313        let route = root_intx_route(
314            PciAddress::new(0, 1, 3, 0),
315            1,
316            [BridgeAddress {
317                device: 2,
318                function: 0,
319            }]
320            .into_iter(),
321        );
322
323        assert_eq!(
324            route,
325            Some(PciIntxRoute {
326                root_device: 2,
327                root_function: 0,
328                root_pin: 4,
329            })
330        );
331    }
332
333    #[test]
334    fn nested_bridge_endpoint_swizzles_at_each_level() {
335        let route = root_intx_route(
336            PciAddress::new(0, 2, 1, 0),
337            2,
338            [
339                BridgeAddress {
340                    device: 4,
341                    function: 1,
342                },
343                BridgeAddress {
344                    device: 3,
345                    function: 0,
346                },
347            ]
348            .into_iter(),
349        );
350
351        assert_eq!(
352            route,
353            Some(PciIntxRoute {
354                root_device: 4,
355                root_function: 1,
356                root_pin: 2,
357            })
358        );
359    }
360}