Files
nt-lite/code/drivers/bus/usb/usb.c
T

87 lines
3.2 KiB
C

// usb.c - USB bus driver entry point and PCI controller discovery.
#include "usb.h"
XHCI_CONTROLLER gXhci;
bool gHaveXhci = false;
const char* UsbControllerName(uint8_t progIf) {
switch (progIf) {
case 0x00: return "UHCI";
case 0x10: return "OHCI";
case 0x20: return "EHCI";
case 0x30: return "xHCI";
default: return "USB";
}
}
void UsbDiscoverControllers(const HAL_API* hal) {
uint32_t found = 0;
uint32_t xhciOk = 0;
for (uint16_t bus = 0; bus < 256; bus++) {
for (uint8_t dev = 0; dev < 32; dev++) {
for (uint8_t fn = 0; fn < 8; fn++) {
uint32_t vd = hal->Pci.Read32((uint8_t)bus, dev, fn, PCI_REG_VENDOR_DEVICE);
if ((vd & 0xFFFFu) == PCI_VENDOR_INVALID)
continue;
uint32_t classReg = hal->Pci.Read32((uint8_t)bus, dev, fn, PCI_REG_CLASS);
uint8_t classCode = (uint8_t)(classReg >> 24);
uint8_t subclass = (uint8_t)(classReg >> 16);
uint8_t progIf = (uint8_t)(classReg >> 8);
if (classCode != PCI_CLASS_SERIAL_BUS || subclass != PCI_SUBCLASS_USB)
continue;
USB_BAR bar0;
bool hasBar0 = UsbReadBar(hal, (uint8_t)bus, dev, fn, 0, &bar0);
uint32_t rawBar0 = hal->Pci.Read32((uint8_t)bus, dev, fn, PCI_REG_BAR0);
uint32_t rawBar1 = hal->Pci.Read32((uint8_t)bus, dev, fn, PCI_REG_BAR0 + 4u);
uint8_t irq = hal->Pci.GetIrqLine((uint8_t)bus, dev, fn);
DbgPrint("usb: found %s controller at %u:%u.%u vendor=%04x device=%04x irq=%u bar0raw=%08x bar1raw=%08x",
UsbControllerName(progIf),
bus, dev, fn,
vd & 0xFFFFu, vd >> 16,
irq, rawBar0, rawBar1);
if (hasBar0 && bar0.Kind == UsbBarMmio) {
DbgPrint(" mmio=0x%016llX\n", (unsigned long long)bar0.Base);
} else if (hasBar0 && bar0.Kind == UsbBarIo) {
DbgPrint(" io=0x%016llX\n", (unsigned long long)bar0.Base);
} else {
DbgPrint(" no-bar0\n");
}
if (progIf == PCI_PROGIF_XHCI) {
KSTATUS st = XhciInitialise(hal, (uint8_t)bus, dev, fn,
(uint16_t)(vd & 0xFFFFu),
(uint16_t)(vd >> 16));
if (KSUCCESS(st) || st == STATUS_ALREADY_EXISTS) xhciOk++;
else DbgPrint("usb: xHCI init failed st=0x%x\n", st);
}
found++;
}
}
}
if (!found)
DbgPrint("usb: no PCI USB controllers discovered\n");
else
DbgPrint("usb: discovery complete; controllers=%u xhci_initialised=%u\n", found, xhciOk);
}
KSTATUS DriverEntry(const HAL_API* hal) {
if (!hal) return STATUS_INVALID_PARAMETER;
DbgPrint("usb: discovery starting\n");
KSTATUS st = UsbRegisterClassMatchers();
if (!KSUCCESS(st)) {
DbgPrint("usb: class matcher registration failed st=0x%x\n", st);
return st;
}
UsbDiscoverControllers(hal);
return STATUS_SUCCESS;
}