Skip to main content

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