From 7eb66b5729d22ad12ac9610592053a5daa5cf7c8 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Tue, 10 Feb 2026 02:37:31 -0300 Subject: [PATCH] refactor: move x86 PCI driver from src/drivers/pci.c to src/hal/x86/pci.c PCI config space access via I/O ports 0xCF8/0xCFC is x86-specific. The full PCI enumeration implementation now lives in src/hal/x86/pci.c (no #if guards). src/drivers/pci.c contains only weak stubs that are overridden by the arch-specific version at link time. Passes: make, cppcheck, QEMU smoke test. --- src/drivers/pci.c | 164 ++++------------------------------------------ src/hal/x86/pci.c | 146 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 151 deletions(-) create mode 100644 src/hal/x86/pci.c diff --git a/src/drivers/pci.c b/src/drivers/pci.c index 657bc48..41ad556 100644 --- a/src/drivers/pci.c +++ b/src/drivers/pci.c @@ -1,168 +1,30 @@ #include "pci.h" #include "uart_console.h" -#include "utils.h" - -#if defined(__i386__) || defined(__x86_64__) - -#include "io.h" - -#define PCI_CONFIG_ADDR 0xCF8 -#define PCI_CONFIG_DATA 0xCFC - -static struct pci_device pci_devices[PCI_MAX_DEVICES]; -static int pci_device_count = 0; - -uint32_t pci_config_read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { - uint32_t address = (1U << 31) - | ((uint32_t)bus << 16) - | ((uint32_t)(slot & 0x1F) << 11) - | ((uint32_t)(func & 0x07) << 8) - | ((uint32_t)offset & 0xFC); - outl(PCI_CONFIG_ADDR, address); - return inl(PCI_CONFIG_DATA); -} - -void pci_config_write(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t value) { - uint32_t address = (1U << 31) - | ((uint32_t)bus << 16) - | ((uint32_t)(slot & 0x1F) << 11) - | ((uint32_t)(func & 0x07) << 8) - | ((uint32_t)offset & 0xFC); - outl(PCI_CONFIG_ADDR, address); - outl(PCI_CONFIG_DATA, value); -} - -static void pci_scan_func(uint8_t bus, uint8_t slot, uint8_t func) { - uint32_t reg0 = pci_config_read(bus, slot, func, 0x00); - uint16_t vendor = (uint16_t)(reg0 & 0xFFFF); - uint16_t device = (uint16_t)(reg0 >> 16); - - if (vendor == 0xFFFF) return; - if (pci_device_count >= PCI_MAX_DEVICES) return; - - struct pci_device* d = &pci_devices[pci_device_count]; - d->bus = bus; - d->slot = slot; - d->func = func; - d->vendor_id = vendor; - d->device_id = device; - - uint32_t reg2 = pci_config_read(bus, slot, func, 0x08); - d->class_code = (uint8_t)(reg2 >> 24); - d->subclass = (uint8_t)(reg2 >> 16); - d->prog_if = (uint8_t)(reg2 >> 8); - - uint32_t reg3 = pci_config_read(bus, slot, func, 0x0C); - d->header_type = (uint8_t)(reg3 >> 16); - - for (int i = 0; i < 6; i++) { - d->bar[i] = pci_config_read(bus, slot, func, (uint8_t)(0x10 + i * 4)); - } - - uint32_t reg_irq = pci_config_read(bus, slot, func, 0x3C); - d->irq_line = (uint8_t)(reg_irq & 0xFF); - - pci_device_count++; -} - -static void pci_scan_slot(uint8_t bus, uint8_t slot) { - uint32_t reg0 = pci_config_read(bus, slot, 0, 0x00); - if ((reg0 & 0xFFFF) == 0xFFFF) return; - - pci_scan_func(bus, slot, 0); - - uint32_t reg3 = pci_config_read(bus, slot, 0, 0x0C); - uint8_t header_type = (uint8_t)(reg3 >> 16); - if (header_type & 0x80) { - for (uint8_t func = 1; func < 8; func++) { - pci_scan_func(bus, slot, func); - } - } -} - -static void pci_scan_bus(uint8_t bus) { - for (uint8_t slot = 0; slot < 32; slot++) { - pci_scan_slot(bus, slot); - } -} - -void pci_init(void) { - pci_device_count = 0; - - uint32_t reg3 = pci_config_read(0, 0, 0, 0x0C); - uint8_t header_type = (uint8_t)(reg3 >> 16); - - if (header_type & 0x80) { - for (uint8_t func = 0; func < 8; func++) { - uint32_t r = pci_config_read(0, 0, func, 0x00); - if ((r & 0xFFFF) == 0xFFFF) continue; - pci_scan_bus(func); - } - } else { - pci_scan_bus(0); - } - - uart_print("[PCI] Enumerated "); - char buf[8]; - itoa(pci_device_count, buf, 10); - uart_print(buf); - uart_print(" device(s)\n"); - - for (int i = 0; i < pci_device_count; i++) { - struct pci_device* d = &pci_devices[i]; - uart_print(" "); - char hex[12]; - itoa_hex(d->vendor_id, hex); uart_print(hex); - uart_print(":"); - itoa_hex(d->device_id, hex); uart_print(hex); - uart_print(" class="); - itoa_hex(d->class_code, hex); uart_print(hex); - uart_print(":"); - itoa_hex(d->subclass, hex); uart_print(hex); - uart_print("\n"); - } -} - -int pci_get_device_count(void) { - return pci_device_count; -} - -const struct pci_device* pci_get_device(int index) { - if (index < 0 || index >= pci_device_count) return 0; - return &pci_devices[index]; -} - -const struct pci_device* pci_find_device(uint16_t vendor, uint16_t device) { - for (int i = 0; i < pci_device_count; i++) { - if (pci_devices[i].vendor_id == vendor && pci_devices[i].device_id == device) - return &pci_devices[i]; - } - return 0; -} - -const struct pci_device* pci_find_class(uint8_t class_code, uint8_t subclass) { - for (int i = 0; i < pci_device_count; i++) { - if (pci_devices[i].class_code == class_code && pci_devices[i].subclass == subclass) - return &pci_devices[i]; - } - return 0; -} - -#else /* non-x86 stubs */ +__attribute__((weak)) uint32_t pci_config_read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { (void)bus; (void)slot; (void)func; (void)offset; return 0xFFFFFFFFU; } + +__attribute__((weak)) void pci_config_write(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t value) { (void)bus; (void)slot; (void)func; (void)offset; (void)value; } + +__attribute__((weak)) void pci_init(void) { uart_print("[PCI] Not supported on this architecture.\n"); } + +__attribute__((weak)) int pci_get_device_count(void) { return 0; } + +__attribute__((weak)) const struct pci_device* pci_get_device(int index) { (void)index; return 0; } + +__attribute__((weak)) const struct pci_device* pci_find_device(uint16_t vendor, uint16_t device) { (void)vendor; (void)device; return 0; } -const struct pci_device* pci_find_class(uint8_t class_code, uint8_t subclass) { (void)class_code; (void)subclass; return 0; } -#endif +__attribute__((weak)) +const struct pci_device* pci_find_class(uint8_t class_code, uint8_t subclass) { (void)class_code; (void)subclass; return 0; } diff --git a/src/hal/x86/pci.c b/src/hal/x86/pci.c new file mode 100644 index 0000000..face81a --- /dev/null +++ b/src/hal/x86/pci.c @@ -0,0 +1,146 @@ +#include "pci.h" +#include "uart_console.h" +#include "utils.h" +#include "io.h" + +#define PCI_CONFIG_ADDR 0xCF8 +#define PCI_CONFIG_DATA 0xCFC + +static struct pci_device pci_devices[PCI_MAX_DEVICES]; +static int pci_device_count = 0; + +uint32_t pci_config_read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + uint32_t address = (1U << 31) + | ((uint32_t)bus << 16) + | ((uint32_t)(slot & 0x1F) << 11) + | ((uint32_t)(func & 0x07) << 8) + | ((uint32_t)offset & 0xFC); + outl(PCI_CONFIG_ADDR, address); + return inl(PCI_CONFIG_DATA); +} + +void pci_config_write(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t value) { + uint32_t address = (1U << 31) + | ((uint32_t)bus << 16) + | ((uint32_t)(slot & 0x1F) << 11) + | ((uint32_t)(func & 0x07) << 8) + | ((uint32_t)offset & 0xFC); + outl(PCI_CONFIG_ADDR, address); + outl(PCI_CONFIG_DATA, value); +} + +static void pci_scan_func(uint8_t bus, uint8_t slot, uint8_t func) { + uint32_t reg0 = pci_config_read(bus, slot, func, 0x00); + uint16_t vendor = (uint16_t)(reg0 & 0xFFFF); + uint16_t device = (uint16_t)(reg0 >> 16); + + if (vendor == 0xFFFF) return; + if (pci_device_count >= PCI_MAX_DEVICES) return; + + struct pci_device* d = &pci_devices[pci_device_count]; + d->bus = bus; + d->slot = slot; + d->func = func; + d->vendor_id = vendor; + d->device_id = device; + + uint32_t reg2 = pci_config_read(bus, slot, func, 0x08); + d->class_code = (uint8_t)(reg2 >> 24); + d->subclass = (uint8_t)(reg2 >> 16); + d->prog_if = (uint8_t)(reg2 >> 8); + + uint32_t reg3 = pci_config_read(bus, slot, func, 0x0C); + d->header_type = (uint8_t)(reg3 >> 16); + + for (int i = 0; i < 6; i++) { + d->bar[i] = pci_config_read(bus, slot, func, (uint8_t)(0x10 + i * 4)); + } + + uint32_t reg_irq = pci_config_read(bus, slot, func, 0x3C); + d->irq_line = (uint8_t)(reg_irq & 0xFF); + + pci_device_count++; +} + +static void pci_scan_slot(uint8_t bus, uint8_t slot) { + uint32_t reg0 = pci_config_read(bus, slot, 0, 0x00); + if ((reg0 & 0xFFFF) == 0xFFFF) return; + + pci_scan_func(bus, slot, 0); + + uint32_t reg3 = pci_config_read(bus, slot, 0, 0x0C); + uint8_t header_type = (uint8_t)(reg3 >> 16); + if (header_type & 0x80) { + for (uint8_t func = 1; func < 8; func++) { + pci_scan_func(bus, slot, func); + } + } +} + +static void pci_scan_bus(uint8_t bus) { + for (uint8_t slot = 0; slot < 32; slot++) { + pci_scan_slot(bus, slot); + } +} + +void pci_init(void) { + pci_device_count = 0; + + uint32_t reg3 = pci_config_read(0, 0, 0, 0x0C); + uint8_t header_type = (uint8_t)(reg3 >> 16); + + if (header_type & 0x80) { + for (uint8_t func = 0; func < 8; func++) { + uint32_t r = pci_config_read(0, 0, func, 0x00); + if ((r & 0xFFFF) == 0xFFFF) continue; + pci_scan_bus(func); + } + } else { + pci_scan_bus(0); + } + + uart_print("[PCI] Enumerated "); + char buf[8]; + itoa(pci_device_count, buf, 10); + uart_print(buf); + uart_print(" device(s)\n"); + + for (int i = 0; i < pci_device_count; i++) { + struct pci_device* d = &pci_devices[i]; + uart_print(" "); + char hex[12]; + itoa_hex(d->vendor_id, hex); uart_print(hex); + uart_print(":"); + itoa_hex(d->device_id, hex); uart_print(hex); + uart_print(" class="); + itoa_hex(d->class_code, hex); uart_print(hex); + uart_print(":"); + itoa_hex(d->subclass, hex); uart_print(hex); + uart_print("\n"); + } +} + +int pci_get_device_count(void) { + return pci_device_count; +} + +const struct pci_device* pci_get_device(int index) { + if (index < 0 || index >= pci_device_count) return 0; + return &pci_devices[index]; +} + +const struct pci_device* pci_find_device(uint16_t vendor, uint16_t device) { + for (int i = 0; i < pci_device_count; i++) { + if (pci_devices[i].vendor_id == vendor && pci_devices[i].device_id == device) + return &pci_devices[i]; + } + return 0; +} + +const struct pci_device* pci_find_class(uint8_t class_code, uint8_t subclass) { + for (int i = 0; i < pci_device_count; i++) { + if (pci_devices[i].class_code == class_code && pci_devices[i].subclass == subclass) + return &pci_devices[i]; + } + return 0; +} -- 2.43.0