]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
refactor: move x86 PCI driver from src/drivers/pci.c to src/hal/x86/pci.c
authorTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 05:37:31 +0000 (02:37 -0300)
committerTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 05:37:31 +0000 (02:37 -0300)
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
src/hal/x86/pci.c [new file with mode: 0644]

index 657bc481ca5ee9c0f2a3e17597f933ea87fc3274..41ad5568531958d5b2d5598c3390065b4606541a 100644 (file)
 #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 (file)
index 0000000..face81a
--- /dev/null
@@ -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;
+}