87 lines
3.2 KiB
C
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;
|
|
}
|