Files

51 lines
1.4 KiB
C

#include <zinnia/init.h>
#include <zinnia/pci.h>
#include <zinnia/spin.h>
#include <x86_64/asm.h>
constexpr uint16_t PCI_CONFIG_ADDRESS = 0xcf8;
constexpr uint16_t PCI_CONFIG_DATA = 0xcfc;
static struct spinlock port_lock = {};
static void port_select(const struct pci_address* addr, uint16_t offset) {
asm_outl(
PCI_CONFIG_ADDRESS,
1u << 31 | (uint32_t)addr->bus << 16 | (uint32_t)(addr->device & 0x1f) << 11 |
(uint32_t)(addr->function & 0x7) << 8 | (offset & 0xfc)
);
}
static uint32_t port_read32(struct pci_access*, const struct pci_address* addr, uint16_t offset) {
spin_lock(&port_lock);
port_select(addr, offset);
uint32_t value = asm_inl(PCI_CONFIG_DATA);
spin_unlock(&port_lock);
return value;
}
static void port_write32(struct pci_access*, const struct pci_address* addr, uint16_t offset, uint32_t value) {
spin_lock(&port_lock);
port_select(addr, offset);
asm_outl(PCI_CONFIG_DATA, value);
spin_unlock(&port_lock);
}
static struct pci_access port_access = {
.name = "port",
.domain = 0,
.start_bus = 0,
.end_bus = 255,
.priority = PCI_ACCESS_PRIO_LEGACY,
.read32 = port_read32,
.write32 = port_write32,
};
[[__init]]
static void pci_x86_stage_init(struct boot_info*) {
pci_access_register(&port_access);
}
INIT_TASK(pci_x86_stage, "arch.x86_64.pci", pci_x86_stage_init);
INIT_DEPENDS(pci_x86_stage, mem_stage);
INIT_ENTAILS(pci_x86_stage, pci_stage);