// hal_pci.c - PCI configuration space via Mechanism 1 port I/O #include #include #define PCI_CONFIG_ADDR 0xCF8 #define PCI_CONFIG_DATA 0xCFC static uint32_t MakeAddr(uint8_t bus, uint8_t dev, uint8_t fn, uint8_t reg) { return 0x80000000UL | ((uint32_t)bus << 16) | ((uint32_t)(dev & 0x1F) << 11) | ((uint32_t)(fn & 0x07) << 8) | (reg & 0xFC); } static uint32_t PciRead32(uint8_t bus, uint8_t dev, uint8_t fn, uint8_t reg) { __outdword(PCI_CONFIG_ADDR, MakeAddr(bus, dev, fn, reg)); return __indword(PCI_CONFIG_DATA); } static void PciWrite32(uint8_t bus, uint8_t dev, uint8_t fn, uint8_t reg, uint32_t val) { __outdword(PCI_CONFIG_ADDR, MakeAddr(bus, dev, fn, reg)); __outdword(PCI_CONFIG_DATA, val); } static bool PciFindDevice(uint16_t vendor, uint16_t device, uint8_t* outBus, uint8_t* outDev, uint8_t* outFn) { for (int bus = 0; bus < 256; bus++) for (int dev = 0; dev < 32; dev++) for (int fn = 0; fn < 8; fn++) { uint32_t id = PciRead32((uint8_t)bus, (uint8_t)dev, (uint8_t)fn, 0); if ((id & 0xFFFF) == vendor && (id >> 16) == device) { *outBus = (uint8_t)bus; *outDev = (uint8_t)dev; *outFn = (uint8_t)fn; return true; } } return false; } static bool PciFindClass(uint8_t classCode, uint8_t subclass, uint8_t* outBus, uint8_t* outDev, uint8_t* outFn) { for (int bus = 0; bus < 256; bus++) for (int dev = 0; dev < 32; dev++) for (int fn = 0; fn < 8; fn++) { uint32_t id = PciRead32((uint8_t)bus,(uint8_t)dev,(uint8_t)fn,0); if ((id & 0xFFFF) == 0xFFFF) continue; // no device uint32_t cc = PciRead32((uint8_t)bus,(uint8_t)dev,(uint8_t)fn,8); if (((cc >> 24) & 0xFF) == classCode && ((cc >> 16) & 0xFF) == subclass) { *outBus = (uint8_t)bus; *outDev = (uint8_t)dev; *outFn = (uint8_t)fn; return true; } } return false; } static uint8_t PciGetIrqLine(uint8_t bus, uint8_t dev, uint8_t fn) { // PCI config register 0x3C: byte 0 = IRQ line, byte 1 = IRQ pin uint32_t val = PciRead32(bus, dev, fn, 0x3C); return (uint8_t)(val & 0xFF); // 0xFF = not connected } void HalPciInitialize(HAL_PCI* out) { out->Read32 = PciRead32; out->Write32 = PciWrite32; out->FindDevice = PciFindDevice; out->FindClass = PciFindClass; out->GetIrqLine = PciGetIrqLine; }