Compare commits
3 Commits
fa4de31aa4
...
cfd42550fc
Author | SHA1 | Date | |
---|---|---|---|
cfd42550fc | |||
673ce8f097 | |||
ba0befa21b |
@ -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)
|
||||||
|
188
src/hulk/pci.d
188
src/hulk/pci.d
@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user