Scan PCI devices via MCFG table

This commit is contained in:
Josh Holtrop 2023-09-17 14:49:02 -04:00
parent ba0befa21b
commit 673ce8f097
2 changed files with 67 additions and 16 deletions

View File

@ -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)

View File

@ -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.");
}
}