module hulk.pci; import hulk.cpu; import hulk.klog; struct Pci { /* IO address for PCI configuration address. */ enum IO_ADDR_CONFIG_ADDRESS = 0xCF8u; /* IO address for PCI configuration data. */ enum IO_ADDR_CONFIG_DATA = 0xCFCu; struct SerialBusController { enum ID = 0x0Cu; struct USBController { enum ID = 0x03u; struct XHCIController { enum ID = 0x30u; } } } private static uint read_config_register(uint bus_id, uint device_idx, uint function_idx, uint register_id) { uint addr = 0x8000_0000u | (bus_id << 16u) | (device_idx << 11u) | (function_idx << 8u) | (register_id << 2u); out32(IO_ADDR_CONFIG_ADDRESS, addr); return in32(IO_ADDR_CONFIG_DATA); } private static void init_device(ubyte class_id, ubyte subclass_id, ubyte if_id) { switch (class_id) { case SerialBusController.ID: switch (subclass_id) { case SerialBusController.USBController.ID: switch (if_id) { case SerialBusController.USBController.XHCIController.ID: /* TODO */ break; default: break; } break; default: break; } break; default: break; } } private static void scan(uint bus_id, uint device_idx, uint function_idx) { ulong reg0 = read_config_register(bus_id, device_idx, function_idx, 0u); if (reg0 != 0xFFFFFFFFu) { uint reg2 = read_config_register(bus_id, device_idx, function_idx, 2u); ushort vendor_id = reg0 & 0xFFFFu; ushort device_id = (reg0 >> 16u) & 0xFFFFu; ubyte class_id = (reg2 >> 24u) & 0xFFu; ubyte subclass_id = (reg2 >> 16u) & 0xFFu; ubyte if_id = (reg2 >> 8u) & 0xFFu; Klog.writefln("Found PCI device %04x:%04x (%02x:%02x:%02x) at %02u:%02u.%u", vendor_id, device_id, class_id, subclass_id, if_id, bus_id, device_idx, function_idx); init_device(class_id, subclass_id, if_id); if (function_idx == 0u) { uint reg3 = read_config_register(bus_id, device_idx, function_idx, 3u); if ((reg3 & (1u << 23u)) != 0u) { /* Multi-function device found. */ for (function_idx = 1u; function_idx < 8u; function_idx++) { scan(bus_id, device_idx, function_idx); } } } } } public static void initialize() { Klog.writefln("Scanning PCI devices..."); for (uint bus_id = 0u; bus_id < 256u; bus_id++) { for (uint device_idx = 0u; device_idx < 32u; device_idx++) { scan(bus_id, device_idx, 0u); } } Klog.writefln("PCI scan complete."); } }