pci_core/
chipset_device_ext.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Extension trait to simplify probing PCI [`ChipsetDevice`] devices.
5
6use crate::spec::hwid::ClassCode;
7use crate::spec::hwid::HardwareIds;
8use crate::spec::hwid::ProgrammingInterface;
9use crate::spec::hwid::Subclass;
10use chipset_device::ChipsetDevice;
11use chipset_device::pci::PciConfigSpace;
12
13/// An extension trait to simplify probing PCI [`ChipsetDevice`] devices.
14pub trait PciChipsetDeviceExt: ChipsetDevice + PciConfigSpace {
15    /// Probe the PCI device's BAR registers to retrieve the BAR masks.
16    fn probe_bar_masks(&mut self) -> [u32; 6];
17
18    /// Probe the PCI device's configuration space registers to obtain the
19    /// device's hardware ID values.
20    fn probe_hardware_ids(&mut self) -> HardwareIds;
21}
22
23impl<T: ?Sized> PciChipsetDeviceExt for T
24where
25    T: ChipsetDevice + PciConfigSpace,
26{
27    fn probe_bar_masks(&mut self) -> [u32; 6] {
28        let mut masks = [0; 6];
29        for (i, addr) in (0x10..=0x24).step_by(4).enumerate() {
30            let mut buf = 0;
31            let old = self
32                .pci_cfg_read(addr, &mut buf)
33                .now_or_never()
34                .map(|_| buf)
35                .unwrap_or(0);
36            self.pci_cfg_write(addr, !0).unwrap();
37            masks[i] = self
38                .pci_cfg_read(addr, &mut buf)
39                .now_or_never()
40                .map(|_| buf)
41                .unwrap_or(0);
42            self.pci_cfg_write(addr, old).unwrap();
43        }
44        masks
45    }
46
47    fn probe_hardware_ids(&mut self) -> HardwareIds {
48        let mut p0 = 0;
49        let mut p8 = 0;
50        let mut p2c = 0;
51        p0 = self
52            .pci_cfg_read(0, &mut p0)
53            .now_or_never()
54            .map(|_| p0)
55            .unwrap_or(0);
56        p8 = self
57            .pci_cfg_read(8, &mut p8)
58            .now_or_never()
59            .map(|_| p8)
60            .unwrap_or(0);
61        p2c = self
62            .pci_cfg_read(0x2c, &mut p2c)
63            .now_or_never()
64            .map(|_| p2c)
65            .unwrap_or(0);
66        HardwareIds {
67            vendor_id: p0 as u16,
68            device_id: (p0 >> 16) as u16,
69            revision_id: p8 as u8,
70            prog_if: ProgrammingInterface((p8 >> 8) as u8),
71            sub_class: Subclass((p8 >> 16) as u8),
72            base_class: ClassCode((p8 >> 24) as u8),
73            type0_sub_vendor_id: p2c as u16,
74            type0_sub_system_id: (p2c >> 16) as u16,
75        }
76    }
77}