The Pedigree Project 0.1
ProbeBars.h
1/* Copyright (c) 2026, Pedigree Developers. SPDX-License-Identifier: ISC */
2#ifndef PEDIGREE_PCI_PROBE_BARS_H
3#define PEDIGREE_PCI_PROBE_BARS_H
4#include <stdint.h>
5
6namespace PciBar {
7enum class ProbeResult { Success, DecodeDisableFailed, RestoreFailed };
8struct Probe {
9 ProbeResult result = ProbeResult::Success;
10 unsigned count = 0;
11 uint32_t masks[6] = {};
12};
13
14template <class Bus, class Device, class Header>
15Probe probe(Bus& pci, Device* device, const Header& header) {
16 Probe result;
17 const uint8_t headerType = header.header_type & 0x7f;
18 // Intel 324645-006, table 13-1 and section 13.1.3: QM67 LPC has no
19 // standard BARs, and its IO/MEM/BME command bits are read-only ones.
20 if (header.vendor == 0x8086 && header.device == 0x1c4f && header.class_code == 6 &&
21 header.subclass == 1 && headerType == 0)
22 return result;
23
24 result.count = headerType == 0 ? 6 : headerType == 1 ? 2 : headerType == 2 ? 1 : 0;
25 // Firmware DMA may still be active until the owning driver's handoff.
26 if (!pci.updateCommand(device, 3, 0)) {
27 result.result = ProbeResult::DecodeDisableFailed;
28 return result;
29 }
30 bool restored = true;
31 for (unsigned i = 0; i < result.count; ++i) {
32 const uint8_t offset = 4 + i;
33 pci.writeConfigSpace(device, offset, 0xffffffffU);
34 result.masks[i] = pci.readConfigSpace(device, offset);
35 pci.writeConfigSpace(device, offset, header.bar[i]);
36 if (pci.readConfigSpace(device, offset) != header.bar[i]) {
37 restored = false;
38 break;
39 }
40 }
41 if (!restored || !pci.updateCommand(device, 3, header.command & 3)) {
42 (void)pci.updateCommand(device, 7, 0);
43 result.result = ProbeResult::RestoreFailed;
44 }
45 return result;
46}
47} // namespace PciBar
48#endif
Definition Bus.h:31