diff --git a/src/hos/cpu.d b/src/hos/cpu.d index 7046603..7802f3f 100644 --- a/src/hos/cpu.d +++ b/src/hos/cpu.d @@ -24,3 +24,23 @@ ulong read_cr4() { return __asm!ulong("mov %cr4, %rax", "={rax}"); } + +ushort in16(ushort ioaddr) +{ + return __asm!ushort("inw %dx, %ax", "={ax},{dx}", ioaddr); +} + +ulong in32(ushort ioaddr) +{ + return __asm!ulong("inl %dx, %eax", "={eax},{dx}", ioaddr); +} + +void out16(ushort ioaddr, ushort v) +{ + __asm("outw %ax, %dx", "{dx},{ax}", ioaddr, v); +} + +void out32(ushort ioaddr, ulong v) +{ + __asm("outl %eax, %dx", "{dx},{eax}", ioaddr, v); +} diff --git a/src/hulk/hulk.d b/src/hulk/hulk.d index 4b10572..34283a8 100644 --- a/src/hulk/hulk.d +++ b/src/hulk/hulk.d @@ -12,6 +12,7 @@ import hulk.kfont; import hulk.klog; import hulk.hurl; import hulk.hippo; +import hulk.pci; extern extern(C) __gshared ubyte _hulk_total_size; @@ -38,6 +39,7 @@ void hulk_start() klog.writefln("Welcome to HULK, the HOS UltraLight Kernel!"); hippo.initialize(&hulk_header); + pci.initialize(); for (;;) { diff --git a/src/hulk/pci.d b/src/hulk/pci.d new file mode 100644 index 0000000..8fb8c11 --- /dev/null +++ b/src/hulk/pci.d @@ -0,0 +1,48 @@ +module hulk.pci; + +import hos.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; + + private static ulong read_config_register(ulong bus_id, ulong device_id, ulong register_id) + { + ulong addr = 0x8000_0000u | (bus_id << 16u) | (device_id << 11u) | (register_id << 2u); + out32(IO_ADDR_CONFIG_ADDRESS, addr); + return in32(IO_ADDR_CONFIG_DATA); + } + + private static void scan(ulong bus_id, ulong device_id) + { + ulong reg0 = read_config_register(bus_id, device_id, 0u); + if (reg0 != 0xFFFFFFFFu) + { + ulong reg2 = read_config_register(bus_id, device_id, 2u); + klog.writefln("Found PCI device %04x:%04x (%02x:%02x:%02x) at %02u:%02u", + (reg0 & 0xFFFFu), (reg0 >> 16u), + (reg2 >> 24u) & 0xFFu, + (reg2 >> 16u) & 0xFFu, + (reg2 >> 8u) & 0xFFu, + bus_id, device_id); + } + } + + public static void initialize() + { + klog.writefln("Scanning PCI devices..."); + for (ulong bus_id = 0u; bus_id < 256u; bus_id++) + { + for (ulong device_id = 0u; device_id < 32u; device_id++) + { + scan(bus_id, device_id); + } + } + klog.writefln("PCI scan complete."); + } +}