The Pedigree Project 0.1
PciMessageBar.h
1/* Copyright (c) 2026, Pedigree Developers. SPDX-License-Identifier: ISC */
2#ifndef PEDIGREE_PCI_MESSAGE_BAR_H
3#define PEDIGREE_PCI_MESSAGE_BAR_H
4
5#include "pedigree/kernel/machine/Device.h"
6#include "pedigree/kernel/machine/PciFunctionState.h"
7#include "pedigree/kernel/processor/IoBase.h"
8
9namespace PciFunctionState {
10inline IoBase* msixTableIo(Device* device, const State& state, const MsixTable& table, bool map) {
11 if (!device || (state.barCount != 2 && state.barCount != 6)) {
12 return nullptr;
13 }
14 const PciBus::ConfigSpace original = device->getPciConfigHeader();
15 const auto findBar = [&](uint8_t index, uint64_t end) -> Device::Address* {
16 if (index >= state.barCount || state.bars[index] != original.bar[index] ||
17 (state.bars[index] & 1U) ||
18 ((state.bars[index] & 6U) != 0 && (state.bars[index] & 6U) != 4)) {
19 return nullptr;
20 }
21 for (uint8_t i = 0; i < index;) {
22 i += !(state.bars[i] & 1U) && (state.bars[i] & 6U) == 4 ? 2 : 1;
23 if (i > index)
24 return nullptr;
25 }
26 if ((state.bars[index] & 6U) == 4 &&
27 (index + 1 >= state.barCount || state.bars[index + 1] != original.bar[index + 1])) {
28 return nullptr;
29 }
30 char name[] = "bar0";
31 name[3] = '0' + index;
32 for (auto* address : device->addresses()) {
33 if (address->m_Name == name && !address->m_IsIoSpace && end <= address->m_Size)
34 return address;
35 }
36 return nullptr;
37 };
38 const uint64_t tableEnd = uint64_t(table.offset) + uint64_t(table.vectors) * 16;
39 const uint64_t pbaEnd = uint64_t(table.pbaOffset) + uint64_t((table.vectors + 63) / 64) * 8;
40 Device::Address* address = findBar(table.bar, tableEnd);
41 if (!address || !findBar(table.pbaBar, pbaEnd))
42 return nullptr;
43 if (map)
44 address->map();
45 return address->m_Io && address->m_Io->size() >= tableEnd ? address->m_Io : nullptr;
46}
47} // namespace PciFunctionState
48
49#endif
Abstrace base class for hardware I/O capabilities.
Definition IoBase.h:32