This commit is contained in:
maksw committed 2026-10-27 09:28:31 +01:00
1 parent d36f19509c
commit 30d20457f0
309 files changed
+121746 -1963

No files matched your search

+2 -2
View File
@@ -802,7 +802,7 @@ typedef struct XHCI_CONTROLLER {
uint8_t Bus;
uint8_t Dev;
uint8_t Fn;
uint8_t Irq;
PCI_INTERRUPT_REQUEST InterruptRequest;
bool UsingMsi;
uint64_t MmioPhys;
@@ -962,7 +962,7 @@ void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target);
KSTATUS XhciWaitForArmedTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs);
KSTATUS XhciWaitForTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs);
void XhciEventDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2);
void XhciIsr(void);
void XhciIsr(void* context);
KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci);
KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci);
KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci);
+30 -92
View File
@@ -761,55 +761,17 @@ void XhciEventDpcRoutine(KDPC* dpc, void* context,
}
#define XHCI_CONTROLLER_MAGIC 0x58484349u // XHCI
#define XHCI_MAX_CONTROLLERS 8u
static XHCI_CONTROLLER* gXhciControllers[XHCI_MAX_CONTROLLERS];
static uint32_t gXhciControllerCount;
// Registers controller.
static KSTATUS XhciRegisterController(XHCI_CONTROLLER* xhci) {
if (!xhci) return NTLSTATUS_INVALID_PARAMETER;
for (uint32_t i = 0; i < gXhciControllerCount; i++) {
if (gXhciControllers[i] == xhci)
return NTLSTATUS_SUCCESS;
}
if (gXhciControllerCount >= XHCI_MAX_CONTROLLERS)
return NTLSTATUS_NO_MEMORY;
gXhciControllers[gXhciControllerCount++] = xhci;
return NTLSTATUS_SUCCESS;
}
// Removes a controller from the interrupt-dispatch registry.
static void XhciUnregisterController(XHCI_CONTROLLER* xhci) {
if (!xhci)
return;
for (uint32_t i = 0; i < gXhciControllerCount; i++) {
if (gXhciControllers[i] != xhci)
continue;
for (uint32_t next = i + 1; next < gXhciControllerCount; next++)
gXhciControllers[next - 1] = gXhciControllers[next];
gXhciControllerCount--;
gXhciControllers[gXhciControllerCount] = (XHCI_CONTROLLER*)0;
return;
}
}
// Implements the isr operation.
void XhciIsr(void) {
for (uint32_t i = 0; i < gXhciControllerCount; i++) {
XHCI_CONTROLLER* xhci = gXhciControllers[i];
if (!xhci || !xhci->Running || !xhci->Op || !xhci->Runtime)
continue;
uint32_t status = XhciRead32(xhci->Op, XHCI_OP_USBSTS);
if (!(status & (XHCI_USBSTS_EINT | XHCI_USBSTS_PCD | XHCI_USBSTS_HSE | XHCI_USBSTS_HCE)))
continue;
xhci->InterruptCount++;
XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK);
XhciAckInterrupter0(xhci);
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
}
void XhciIsr(void* context) {
XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)context;
if (!xhci || !xhci->Running || !xhci->Op || !xhci->Runtime) return;
uint32_t status = XhciRead32(xhci->Op, XHCI_OP_USBSTS);
if (!(status & (XHCI_USBSTS_EINT | XHCI_USBSTS_PCD | XHCI_USBSTS_HSE | XHCI_USBSTS_HCE)))
return;
xhci->InterruptCount++;
XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK);
XhciAckInterrupter0(xhci);
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
}
// Implements the bios Handoff operation.
@@ -2181,35 +2143,13 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
return NTLSTATUS_DEVICE_ERROR;
}
xhci->Irq = 0xFFu;
xhci->InterruptRequest.Routine = XhciIsr;
xhci->InterruptRequest.Context = xhci;
xhci->InterruptRequest.Affinity = 0;
xhci->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
xhci->UsingMsi = false;
st = PciEnableMsiAuto(xhci->Pdo, &xhci->Irq);
if (KSUCCESS(st)) {
xhci->UsingMsi = true;
DbgPrint("usb: xHCI using MSI IRQ slot %u\n", xhci->Irq);
} else {
KSTATUS intxStatus = PciGetInterrupt(xhci->Pdo, &xhci->Irq);
if (KSUCCESS(intxStatus) && xhci->Irq != 0xFFu) {
DbgPrint("usb: xHCI using legacy INTx IRQ %u\n", xhci->Irq);
} else {
xhci->Irq = 0xFFu;
DbgPrint("usb: xHCI no MSI/INTx interrupt available; using polled event-ring mode (msi=0x%x intx=0x%x)\n",
st, intxStatus);
}
}
uint32_t enableFlags = PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER;
if (xhci->UsingMsi || xhci->Irq == 0xFFu)
enableFlags |= PCI_DISABLE_INTX;
else
enableFlags |= PCI_ENABLE_INTX;
st = PciEnableDevice(xhci->Pdo, enableFlags);
if (!KSUCCESS(st)) {
DbgPrint("usb: xHCI PciEnableDevice failed st=0x%x\n", st);
return st;
}
st = PciEnableDevice(xhci->Pdo, PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER | PCI_DISABLE_INTX);
if (!KSUCCESS(st)) return st;
xhci->MmioPhys = xhci->MmioBar.Base;
@@ -2266,10 +2206,9 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
UsbInitializeHcd(&xhci->Hcd, &gXhciHcdOperations, xhci, 0, xhci->MaxPorts);
xhci->Hcd.ControllerDevice = xhci->Fdo;
DbgPrint("usb: xHCI init %02x:%02x.%x vendor=%04x device=%04x irq=%u mmio=0x%016llX caplen=%u version=%04x\n",
DbgPrint("usb: xHCI init %02x:%02x.%x vendor=%04x device=%04x mmio=0x%016llX caplen=%u version=%04x\n",
xhci->Bus, xhci->Dev, xhci->Fn,
xhci->PciInfo.VendorId, xhci->PciInfo.DeviceId,
xhci->Irq,
(unsigned long long)xhci->MmioPhys, xhci->CapLength, xhci->Version);
DbgPrint("usb: xHCI caps slots=%u intrs=%u ports=%u ctx=%u scratchpads=%u hcs2=%08x hcc1=%08x dboff=0x%x rtsoff=0x%x pagesize=%08x\n",
xhci->MaxSlots, xhci->MaxIntrs, xhci->MaxPorts, xhci->ContextBytes,
@@ -2331,22 +2270,18 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
goto failDma;
}
st = XhciRegisterController(xhci);
if (!KSUCCESS(st)) {
DbgPrint("usb: xHCI controller registry full st=0x%x\n", st);
goto failDma;
}
if (xhci->Irq != 0xFFu) {
KeIrqRegister(xhci->Irq, XhciIsr);
st = PciConnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u, &xhci->UsingMsi);
if (KSUCCESS(st)) {
XhciEnableInterrupts(xhci);
xhci->InterruptsEnabled = true;
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
DbgPrint("usb: xHCI ISR registered on IRQ %u (%s); event ring handled by DPC\n",
xhci->Irq, xhci->UsingMsi ? "MSI" : "INTx");
KE_INTERRUPT_INFO info;
if (KSUCCESS(KeInterruptQuery(xhci->InterruptRequest.Interrupt, &info)))
DbgPrint("usb: xHCI interrupt cpu=%u vector=0x%02x mode=%s\n",
info.CpuIndex, info.Vector, xhci->UsingMsi ? "MSI/MSI-X" : "INTx");
} else {
xhci->InterruptsEnabled = false;
DbgPrint("usb: xHCI started in polling mode; synchronous waits drain event ring\n");
DbgPrint("usb: xHCI polling fallback status=0x%x\n", st);
}
xhci->Fdo->PnpState = DevicePnpStarted;
@@ -2362,7 +2297,8 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
failDma:
XhciHaltForDmaRelease(xhci);
XhciUnregisterController(xhci);
if (xhci->InterruptRequest.Interrupt)
PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u);
if (xhci->Hcd.RootHubPdo) {
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0;
@@ -2400,6 +2336,8 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
xhci->SurpriseRemoved = true;
xhci->Running = false;
xhci->InterruptsEnabled = false;
if (xhci->InterruptRequest.Interrupt)
PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u);
if (xhci->Hcd.RootHubPdo)
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
return NTLSTATUS_SUCCESS;
@@ -2407,11 +2345,12 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
case IRP_MN_REMOVE_DEVICE:
device->PnpState = DevicePnpDeleted;
XhciHaltForDmaRelease(xhci);
if (xhci->InterruptRequest.Interrupt)
PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u);
if (xhci->Hcd.RootHubPdo) {
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0;
}
XhciUnregisterController(xhci);
XhciReleaseControllerDma(xhci);
IoDetachDevice(device);
IoDeleteDevice(device);
@@ -2439,7 +2378,6 @@ KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject
xhci->Fdo = fdo;
xhci->Pdo = physicalDeviceObject;
xhci->Irq = 0xFFu;
KeInitializeDpc(&xhci->EventDpc, XhciEventDpcRoutine, xhci);
xhci->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);