pci_x86/iter.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2025.
4
5use crate::bdf::Bdf;
6use crate::device::Device;
7
8/// Iterator which enumerates all valid BDF combinations and yields those
9/// for which a device is present.
10struct Iter {
11 bus: u8,
12 dev: u8,
13 func: u8,
14}
15
16impl Iter {
17 /// Creates a new iterator starting from bus 0, device 0, function 0.
18 fn new() -> Self {
19 Self {
20 bus: 0,
21 dev: 0,
22 func: 0,
23 }
24 }
25}
26
27impl Iterator for Iter {
28 type Item = Device;
29
30 fn next(&mut self) -> Option<Self::Item> {
31 // Loop over all valid bus indices 0..=255
32 loop {
33 // Loop over all valid device indices 0..=31
34 while self.dev <= 31 {
35 // Loop over all valid function indices 0..=7
36 while self.func <= 7 {
37 let bdf = Bdf::new(self.bus, self.dev, self.func);
38
39 // Increment function index before potentially returning
40 // a device, so that the next call starts with the next
41 // function.
42 self.func += 1;
43
44 // Query vendor ID and check if it is valid before yielding
45 // this device instance
46 let device = Device::new(bdf);
47 if device.vendor_id() != 0xFFFF {
48 return Some(device);
49 }
50 }
51
52 // Reset function index and increment device index
53 self.func = 0;
54 self.dev += 1;
55 }
56
57 // Break early before incrementing bus index if we have reached the
58 // end (else we would overflow u8 and enumerate everything again).
59 if self.bus == 255 {
60 break;
61 }
62
63 // Reset device index and increment bus index
64 self.dev = 0;
65 self.bus += 1;
66 }
67
68 None
69 }
70}
71
72/// Returns an iterator over all present PCI devices.
73///
74/// A PCI device is considered "present" if the vendor ID read from its
75/// configuration space is not 0xFFFF.
76pub fn iter() -> impl Iterator<Item = Device> {
77 Iter::new()
78}