hos/src/hulk/pci.d

106 lines
3.1 KiB
D

module hulk.pci;
import hulk.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;
struct SerialBusController
{
enum ID = 0x0Cu;
struct USBController
{
enum ID = 0x03u;
struct XHCIController
{
enum ID = 0x30u;
}
}
}
private static uint read_config_register(uint bus_id, uint device_idx, uint function_idx, uint register_id)
{
uint addr = 0x8000_0000u | (bus_id << 16u) | (device_idx << 11u) | (function_idx << 8u) | (register_id << 2u);
out32(IO_ADDR_CONFIG_ADDRESS, addr);
return in32(IO_ADDR_CONFIG_DATA);
}
private static void init_device(ubyte class_id, ubyte subclass_id, ubyte if_id)
{
switch (class_id)
{
case SerialBusController.ID:
switch (subclass_id)
{
case SerialBusController.USBController.ID:
switch (if_id)
{
case SerialBusController.USBController.XHCIController.ID:
/* TODO */
break;
default: break;
}
break;
default: break;
}
break;
default: break;
}
}
private static void scan(uint bus_id, uint device_idx, uint function_idx)
{
ulong reg0 = read_config_register(bus_id, device_idx, function_idx, 0u);
if (reg0 != 0xFFFFFFFFu)
{
uint reg2 = read_config_register(bus_id, device_idx, function_idx, 2u);
ushort vendor_id = reg0 & 0xFFFFu;
ushort device_id = (reg0 >> 16u) & 0xFFFFu;
ubyte class_id = (reg2 >> 24u) & 0xFFu;
ubyte subclass_id = (reg2 >> 16u) & 0xFFu;
ubyte if_id = (reg2 >> 8u) & 0xFFu;
Klog.writefln("Found PCI device %04x:%04x (%02x:%02x:%02x) at %02u:%02u.%u",
vendor_id, device_id,
class_id, subclass_id, if_id,
bus_id, device_idx, function_idx);
init_device(class_id, subclass_id, if_id);
if (function_idx == 0u)
{
uint reg3 = read_config_register(bus_id, device_idx, function_idx, 3u);
if ((reg3 & (1u << 23u)) != 0u)
{
/* Multi-function device found. */
for (function_idx = 1u; function_idx < 8u; function_idx++)
{
scan(bus_id, device_idx, function_idx);
}
}
}
}
}
public static void initialize()
{
Klog.writefln("Scanning PCI devices...");
for (uint bus_id = 0u; bus_id < 256u; bus_id++)
{
for (uint device_idx = 0u; device_idx < 32u; device_idx++)
{
scan(bus_id, device_idx, 0u);
}
}
Klog.writefln("PCI scan complete.");
}
}