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}