20#include "pedigree/kernel/LockGuard.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/Spinlock.h"
23#include "pedigree/kernel/machine/Device.h"
24#include "pedigree/kernel/machine/Machine.h"
25#include "pedigree/kernel/machine/Pci.h"
26#include "pedigree/kernel/machine/PciConfigAccess.h"
27#include "pedigree/kernel/processor/IoPort.h"
32IoPort configSpace(
"PCI config space");
34bool configAvailable =
false;
37struct FunctionConfig {
39 bool read8(uint16_t offset, uint8_t& value) {
40 return PciBus::instance().readConfig8(device, offset, value);
42 bool read16(uint16_t offset, uint16_t& value) {
43 return PciBus::instance().readConfig16(device, offset, value);
45 bool read32(uint16_t offset, uint32_t& value) {
46 return PciBus::instance().readConfig32(device, offset, value);
48 bool write16(uint16_t offset, uint16_t value) {
49 return PciBus::instance().writeConfig16(device, offset, value);
53bool readFunction(
Device* device, uint16_t offset, uint8_t width, uint32_t& value) {
54 return configAvailable && device &&
55 config.read(device->getPciBusPosition(), device->getPciDevicePosition(),
56 device->getPciFunctionNumber(), offset, width, value);
58bool writeFunction(
Device* device, uint16_t offset, uint8_t width, uint32_t value) {
59 return configAvailable && device &&
60 config.write(device->getPciBusPosition(), device->getPciDevicePosition(),
61 device->getPciFunctionNumber(), offset, width, value);
70 if (!configSpace.allocate(0xCF8, 8)) {
71 ERROR(
"PCI: Config space - unable to allocate IO port!");
76 configSpace.write32(0x80000000, 0);
77 configAvailable = configSpace.read32(0) == 0x80000000;
80 ERROR(
"PCI: Controller not detected.");
84 uint32_t value = 0xffffffffU;
85 readConfig32(device, uint16_t{offset} * 4, value);
89 uint32_t value = 0xffffffffU;
91 config.read(bus, device, function, uint16_t{offset} * 4, 4, value);
95 writeConfig32(device, uint16_t{offset} * 4, value);
100 config.write(bus, device, function, uint16_t{offset} * 4, 4, value);
102bool PciBus::readConfig8(
Device* device, uint16_t offset, uint8_t& value) {
104 if (!readFunction(device, offset, 1, data))
109bool PciBus::readConfig16(
Device* device, uint16_t offset, uint16_t& value) {
111 if (!readFunction(device, offset, 2, data))
116bool PciBus::readConfig32(
Device* device, uint16_t offset, uint32_t& value) {
117 return readFunction(device, offset, 4, value);
119bool PciBus::writeConfig8(
Device* device, uint16_t offset, uint8_t value) {
120 return writeFunction(device, offset, 1, value);
122bool PciBus::writeConfig16(
Device* device, uint16_t offset, uint16_t value) {
123 return writeFunction(device, offset, 2, value);
125bool PciBus::writeConfig32(
Device* device, uint16_t offset, uint32_t value) {
126 return writeFunction(device, offset, 4, value);
128bool PciBus::updateCommand(
Device* device, uint16_t clearBits, uint16_t setBits) {
129 return configAvailable && device &&
130 config.updateCommand(device->getPciBusPosition(), device->getPciDevicePosition(),
131 device->getPciFunctionNumber(), clearBits, setBits);
134 FunctionConfig function{device};
135 return PciFunctionState::inspect(function, state) &&
136 state.interruptLine == device->getInterruptNumber();
139 FunctionConfig function{device};
140 return PciFunctionState::disableMessageInterrupts(function, state);
143 FunctionConfig function{device};
144 return PciFunctionState::resourcesUnchanged(function, state);
148 cpuPhysical = pciAddress;
158uint32_t PciBus::interruptRoute(uint8_t, uint8_t, uint8_t, uint8_t) {
166bool PciBus::reserveLegacyInterrupt(uint8_t irq) {
167 return Machine::instance().getIrqManager() == &
Pic::instance() &&
uint32_t readConfigSpace(Device *pDev, uint8_t offset)
bool translateAddress(uint64_t pciAddress, uint64_t bytes, bool io, uint64_t &cpuPhysical)
bool busRange(uint8_t &first, uint8_t &last)
void writeConfigSpace(Device *pDev, uint8_t offset, uint32_t data)
bool assignBar(Device *device, uint8_t index, uint32_t low, uint32_t high, uint32_t maskLow, uint32_t maskHigh)
bool reservePciRoute(uint8_t irq)