From 673ce8f097dc8ab462a82abafb667e9811e91e40 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 17 Sep 2023 14:49:02 -0400 Subject: [PATCH] Scan PCI devices via MCFG table --- src/hulk/acpi.d | 16 ++---------- src/hulk/pci.d | 67 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/hulk/acpi.d b/src/hulk/acpi.d index 8823fa1..14f675f 100644 --- a/src/hulk/acpi.d +++ b/src/hulk/acpi.d @@ -94,20 +94,9 @@ struct Acpi uint[2] _reserved; SGMADesc[0] sgma_descs; - void initialize() + size_t n_sgma_descs() { - Klog.writefln("MCFG length = %u", header.length); - size_t n_sgma_descs = (header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof; - Klog.writefln("# SGMA descriptors = %u", (header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof); - for (size_t i = 0; i < n_sgma_descs; i++) - { - Klog.writefln("SGMA %u: SG %u; Bus %u-%u; addr %p", - i, - sgma_descs[i].pci_segment_group_number, - sgma_descs[i].start_pci_bus_number, - sgma_descs[i].end_pci_bus_number, - sgma_descs[i].base_address); - } + return (header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof; } } @@ -158,7 +147,6 @@ struct Acpi else if (signature == MCFG_SIGNATURE) { mcfg = cast(MCFG *)address; - mcfg.initialize(); } } if (madt == null) diff --git a/src/hulk/pci.d b/src/hulk/pci.d index 67224e2..aab2667 100644 --- a/src/hulk/pci.d +++ b/src/hulk/pci.d @@ -6,6 +6,7 @@ import hulk.hurl; import hulk.hurl.a1; import hulk.range; import hulk.usb.xhci; +import hulk.acpi; struct Pci { @@ -15,6 +16,10 @@ struct Pci /* IO address for PCI configuration data. */ enum IO_ADDR_CONFIG_DATA = 0xCFCu; + enum MAX_DEVICES_PER_BUS = 32; + + enum MAX_FUNCTIONS_PER_DEVICE = 8; + struct Address { /** Bus number (0-255). */ @@ -207,7 +212,7 @@ struct Pci device.initialize(address, vendor_id, device_id); if (device.multifunction) { - for (address.function_nr = 1u; address.function_nr < 8u; address.function_nr++) + for (address.function_nr = 1u; address.function_nr < MAX_FUNCTIONS_PER_DEVICE; address.function_nr++) { scan(address); } @@ -215,16 +220,74 @@ struct Pci } } + struct Header + { + ushort vendor_id; + ushort device_id; + ushort command; + ushort status; + ubyte revision_id; + ubyte interface_id; + ubyte subclass_id; + ubyte class_id; + ubyte cache_line_size; + ubyte latency_timer; + ubyte header_type; + ubyte bist; + } + + private static void scan(ubyte bus_nr, ubyte device_nr, ubyte function_nr, ulong config_address) + { + Header * header = cast(Header *)config_address; + if (header.vendor_id != 0xFFFFu) + { + Klog.writefln("Found PCI device %04x:%04x (%02x:%02x:%02x) at %02u:%02u.%u (%p)", + header.vendor_id, header.device_id, + header.class_id, header.subclass_id, header.interface_id, + bus_nr, device_nr, function_nr, config_address); + if (function_nr == 0 && (header.header_type & 0x80u) != 0u) + { + for (function_nr = 1u; function_nr < MAX_FUNCTIONS_PER_DEVICE; function_nr++) + { + config_address += PAGE_SIZE; + scan(bus_nr, device_nr, function_nr, config_address); + } + } + } + } + public static void initialize() { Klog.writefln("Scanning PCI devices..."); for (uint bus_nr = 0u; bus_nr < 256u; bus_nr++) { - for (ubyte device_nr = 0u; device_nr < 32u; device_nr++) + for (ubyte device_nr = 0u; device_nr < MAX_DEVICES_PER_BUS; device_nr++) { scan(Address(cast(ubyte)bus_nr, device_nr, 0u)); } } Klog.writefln("PCI scan complete."); + + Klog.writefln("MCFG PCI scan..."); + size_t n_sgma_descs = Acpi.mcfg.n_sgma_descs; + for (size_t i = 0u; i < n_sgma_descs; i++) + { + Acpi.MCFG.SGMADesc * sgma_desc = &Acpi.mcfg.sgma_descs[i]; + ulong base_address = sgma_desc.base_address; + uint start_pci_bus = sgma_desc.start_pci_bus_number; + uint end_pci_bus = sgma_desc.end_pci_bus_number; + ulong n_buses = (end_pci_bus - start_pci_bus) + 1u; + ulong map_length = PAGE_SIZE * MAX_FUNCTIONS_PER_DEVICE * MAX_DEVICES_PER_BUS * n_buses; + Hurl.identity_map_range(base_address, map_length, PT_DISABLE_CACHE | PT_NO_EXECUTE); + for (uint bus_nr = start_pci_bus; bus_nr <= end_pci_bus; bus_nr++) + { + for (ubyte device_nr = 0u; device_nr < MAX_DEVICES_PER_BUS; device_nr++) + { + ulong device_address = base_address + ((bus_nr - start_pci_bus) * (MAX_DEVICES_PER_BUS * MAX_FUNCTIONS_PER_DEVICE) + device_nr * MAX_FUNCTIONS_PER_DEVICE) * PAGE_SIZE; + scan(cast(ubyte)bus_nr, device_nr, 0u, device_address); + } + } + } + Klog.writefln("PCI scan 2 complete."); } }