Compare commits

...

3 Commits

2 changed files with 196 additions and 16 deletions

View File

@ -94,20 +94,9 @@ struct Acpi
uint[2] _reserved; uint[2] _reserved;
SGMADesc[0] sgma_descs; SGMADesc[0] sgma_descs;
void initialize() size_t n_sgma_descs()
{ {
Klog.writefln("MCFG length = %u", header.length); return (header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof;
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);
}
} }
} }
@ -158,9 +147,16 @@ struct Acpi
else if (signature == MCFG_SIGNATURE) else if (signature == MCFG_SIGNATURE)
{ {
mcfg = cast(MCFG *)address; mcfg = cast(MCFG *)address;
mcfg.initialize();
} }
} }
if (madt == null)
{
Klog.fatal_error("MADT table not found");
}
if (mcfg == null)
{
Klog.fatal_error("MCFG table not found");
}
} }
private static void map_table(ulong address, ulong length) private static void map_table(ulong address, ulong length)

View File

@ -6,6 +6,7 @@ import hulk.hurl;
import hulk.hurl.a1; import hulk.hurl.a1;
import hulk.range; import hulk.range;
import hulk.usb.xhci; import hulk.usb.xhci;
import hulk.acpi;
struct Pci struct Pci
{ {
@ -15,6 +16,10 @@ struct Pci
/* IO address for PCI configuration data. */ /* IO address for PCI configuration data. */
enum IO_ADDR_CONFIG_DATA = 0xCFCu; enum IO_ADDR_CONFIG_DATA = 0xCFCu;
enum MAX_DEVICES_PER_BUS = 32;
enum MAX_FUNCTIONS_PER_DEVICE = 8;
struct Address struct Address
{ {
/** Bus number (0-255). */ /** Bus number (0-255). */
@ -207,7 +212,7 @@ struct Pci
device.initialize(address, vendor_id, device_id); device.initialize(address, vendor_id, device_id);
if (device.multifunction) 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); scan(address);
} }
@ -215,16 +220,195 @@ struct Pci
} }
} }
static struct Configuration
{
static struct HeaderType0
{
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;
uint[6] base_addresses;
uint cardbus_cis_pointer;
ushort subsystem_vendor_id;
ushort subsystem_id;
uint expansion_rom_base_address;
ubyte capabilities_pointer;
ubyte[7] _reserved;
ubyte interrupt_line;
ubyte interrupt_pin;
ubyte min_grant;
ubyte max_latency;
}
/**
* PCI configuration format for header type 1 (PCI-to-PCI bridge).
*/
static struct HeaderType1
{
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;
uint[2] base_addresses;
ubyte primary_bus_nr;
ubyte secondary_bus_nr;
ubyte subordinate_bus_nr;
ubyte secondary_latency_timer;
ubyte io_base;
ubyte io_limit;
ushort secondary_status;
ushort memory_base;
ushort memory_limit;
ushort prefetchable_memory_base;
ushort prefetchable_memory_limit;
uint prefetchable_base_high;
uint prefetchable_limit_high;
ushort io_base_high;
ushort io_limit_high;
ubyte capability_pointer;
ubyte[3] _reserved;
uint expansion_rom_base_address;
ubyte interrupt_line;
ubyte interrupt_pin;
ushort bridge_control;
}
/**
* PCI configuration format for header type 2 (PCI-to-CardBus bridge).
*/
static struct HeaderType2
{
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;
uint cardbus_base_address;
ubyte capability_list_offset;
ubyte _reserved;
ushort secondary_status;
ubyte pci_bus_nr;
ubyte cardbus_bus_nr;
ubyte subordinate_bus_nr;
ubyte cardbus_latency_timer;
uint base_address_0;
uint memory_limit_0;
uint base_address_1;
uint memory_limit_1;
uint io_base_address_0;
uint io_limit_0;
uint io_base_address_1;
uint io_limit_1;
ubyte interrupt_line;
ubyte interrupt_pin;
ushort bridge_control;
ushort subsystem_device_id;
ushort subsystem_vendor_id;
uint legacy_base_address;
}
union
{
struct
{
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;
}
HeaderType0 header0;
HeaderType1 header1;
HeaderType2 header2;
}
}
private static void scan(ubyte bus_nr, ubyte device_nr, ubyte function_nr, ulong config_address)
{
Configuration * config = cast(Configuration *)config_address;
if (config.vendor_id != 0xFFFFu)
{
Klog.writefln("Found PCI device %04x:%04x (%02x:%02x:%02x) at %02u:%02u.%u (%p)",
config.vendor_id, config.device_id,
config.class_id, config.subclass_id, config.interface_id,
bus_nr, device_nr, function_nr, config_address);
if (function_nr == 0 && (config.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() public static void initialize()
{ {
Klog.writefln("Scanning PCI devices..."); Klog.writefln("Scanning PCI devices...");
for (uint bus_nr = 0u; bus_nr < 256u; bus_nr++) 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)); scan(Address(cast(ubyte)bus_nr, device_nr, 0u));
} }
} }
Klog.writefln("PCI scan complete."); 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.");
} }
} }