replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.

This commit is contained in:
maksw committed 2026-10-26 10:08:03 +01:00
1 parent c0ad63c27f
commit d36f19509c
160 files changed
+6563 -7366

No files matched your search

+156 -42
View File
@@ -99,7 +99,7 @@ static KSTATUS UsbHubEnumerateRootPortWithRetries(USB_HUB_EXTENSION* hub,
DbgPrint("usb-hub: root port %u enumeration attempt %u failed st=0x%x; retrying\n",
port, attempt, last);
UsbDelayUs(xhci->Ddk, 50000);
UsbDelayUs(50000);
}
if (UsbHubRootPortConnected(xhci, port)) {
@@ -126,7 +126,7 @@ static KSTATUS UsbHubEnumerateConnectedRootPort(USB_HUB_EXTENSION* hub,
hub->RootPortSlot[port] = USB_HUB_PORT_ENUMERATING;
hub->RootPortState[port] = UsbHubPortConnectedDebounce;
UsbDelayUs(xhci->Ddk, 30000u);
UsbDelayUs(30000u);
if (!UsbHubRootPortConnected(xhci, port)) {
UsbHubClearRootPortFailure(hub, port);
hub->RootPortSlot[port] = 0;
@@ -393,13 +393,21 @@ static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uin
USB_HUB_PORT_STATUS ps;
memset(&ps, 0, sizeof(ps));
bool resetComplete = false;
for (uint32_t i = 0; i < 500u; i++) {
UsbDelayUs(((XHCI_CONTROLLER*)hub->Hcd->ControllerContext)->Ddk, 1000u);
UsbDelayUs(1000u);
st = UsbHubGetPortStatus(hub, port, &ps);
if (!KSUCCESS(st))
return st;
if (ps.Change & USB_HUB_PORT_CHANGE_RESET)
if (ps.Change & USB_HUB_PORT_CHANGE_RESET) {
resetComplete = true;
break;
}
}
if (!resetComplete) {
DbgPrint("usb-hub: slot=%u port=%u reset timed out status=%04x change=%04x\n",
hub->Device ? hub->Device->SlotId : 0, port, ps.Status, ps.Change);
return NTLSTATUS_TIMEOUT;
}
(void)UsbHubClearPortFeature(hub, port, USB_HUB_PORT_FEAT_C_RESET);
@@ -464,7 +472,7 @@ static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port)
hub->ChildSlot[port] = USB_HUB_PORT_ENUMERATING;
hub->ChildPortState[port] = UsbHubPortConnectedDebounce;
UsbDelayUs(((XHCI_CONTROLLER*)hub->Hcd->ControllerContext)->Ddk, 30000u);
UsbDelayUs(30000u);
uint8_t speed = 0;
hub->ChildPortState[port] = UsbHubPortResetting;
@@ -478,8 +486,12 @@ static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port)
}
hub->ChildPortState[port] = UsbHubPortEnumerating;
DbgPrint("usb-stage: hub-slot=%u port=%u child enumeration begin speed=%u\n",
hub->Device ? hub->Device->SlotId : 0, port, speed);
uint8_t slot = 0;
st = XhciEnumerateHubPortEx((XHCI_CONTROLLER*)hub->Hcd->ControllerContext, hub, port, speed, &slot);
DbgPrint("usb-stage: hub-slot=%u port=%u child enumeration done st=0x%x slot=%u\n",
hub->Device ? hub->Device->SlotId : 0, port, st, slot);
if (KSUCCESS(st)) {
hub->ChildSlot[port] = slot;
hub->ChildPortState[port] = UsbHubPortChildPresent;
@@ -580,6 +592,12 @@ static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) {
// Implements the hub Worker operation.
static void UsbHubWorker(void* arg) {
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)arg;
if (hub && hub->Kind == UsbHubKindRoot && hub->Hcd) {
XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)hub->Hcd->ControllerContext;
if (xhci)
DbgPrint("usb-stage: hcd=%02x:%02x.%u root worker entered ports=%u\n",
xhci->Bus, xhci->Dev, xhci->Fn, hub->PortCount);
}
while (hub && hub->WorkerRunning) {
KSTATUS st = KeWaitSemaphore(hub->WorkerSemaphore, KE_WAIT_INFINITE);
if (!KSUCCESS(st))
@@ -588,8 +606,11 @@ static void UsbHubWorker(void* arg) {
break;
if (hub->Kind == UsbHubKindRoot) {
if (UsbHubTakeInitialRootScan(hub))
(void)UsbHubDoRootPortScan(hub->Hcd);
if (UsbHubTakeInitialRootScan(hub)) {
KSTATUS scanStatus = UsbHubDoRootPortScan(hub->Hcd);
if (!KSUCCESS(scanStatus))
DbgPrint("usb-stage: root scan aborted st=0x%x\n", scanStatus);
}
uint8_t port = 0;
while (UsbHubPopPendingRootPort(hub, &port))
@@ -657,6 +678,12 @@ static KSTATUS UsbHubStartWorker(USB_HUB_EXTENSION* hub) {
UsbHubStopWorker(hub);
return status;
}
if (hub->Kind == UsbHubKindRoot && hub->Hcd) {
XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)hub->Hcd->ControllerContext;
if (xhci)
DbgPrint("usb-stage: hcd=%02x:%02x.%u root worker created\n",
xhci->Bus, xhci->Dev, xhci->Fn);
}
return NTLSTATUS_SUCCESS;
}
@@ -675,6 +702,8 @@ static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) {
if (!xhci || !xhci->Op)
return NTLSTATUS_INVALID_PARAMETER;
DbgPrint("usb-stage: hcd=%02x:%02x.%u root scan begin ports=%u\n",
xhci->Bus, xhci->Dev, xhci->Fn, hub->PortCount);
for (uint8_t port = 1; port <= hub->PortCount; port++) {
uint32_t portsc = XhciRead32(xhci->Op, XhciPortReg(port));
if (!(portsc & XHCI_PORTSC_CCS))
@@ -686,9 +715,13 @@ static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) {
continue;
}
DbgPrint("usb-stage: hcd=%02x:%02x.%u root-port=%u begin portsc=%08x\n",
xhci->Bus, xhci->Dev, xhci->Fn, port, portsc);
attempted++;
uint8_t slot = 0;
KSTATUS st = UsbHubEnumerateConnectedRootPort(hub, xhci, port, &slot);
DbgPrint("usb-stage: hcd=%02x:%02x.%u root-port=%u done st=0x%x slot=%u\n",
xhci->Bus, xhci->Dev, xhci->Fn, port, st, slot);
if (KSUCCESS(st)) {
hub->RootPortSlot[port] = slot;
hub->RootPortState[port] = UsbHubPortChildPresent;
@@ -699,27 +732,45 @@ static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) {
}
}
DbgPrint("usb-hub: root-port scan complete; attempted=%u configured=%u\n", attempted, configured);
DbgPrint("usb-hub: hcd=%02x:%02x.%u root-port scan complete; attempted=%u configured=%u\n",
xhci->Bus, xhci->Dev, xhci->Fn, attempted, configured);
uintptr_t flags = KeAcquireSpinlock(&hub->PendingLock);
hub->InitialScanComplete = true;
hub->InitialScanInProgress = false;
KeReleaseSpinlock(&hub->PendingLock, flags);
return NTLSTATUS_SUCCESS;
}
// Implements the hub Schedule Root Scan operation.
KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) {
if (!hcd || !hcd->RootHubContext)
return NTLSTATUS_INVALID_PARAMETER;
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)hcd->RootHubContext;
if (hub->Kind != UsbHubKindRoot || !hub->Started)
return NTLSTATUS_OBJECT_DEAD;
static SEMAPHORE* UsbHubQueueInitialScan(USB_HUB_EXTENSION* hub) {
if (!hub || !hub->Started || !hub->WorkerSemaphore)
return (SEMAPHORE*)0;
uintptr_t flags = KeAcquireSpinlock(&hub->PendingLock);
if (!hub->InitialScanComplete && !hub->InitialScanInProgress)
bool pending = !hub->InitialScanComplete && !hub->InitialScanInProgress;
if (pending)
hub->InitialScanPending = true;
KeReleaseSpinlock(&hub->PendingLock, flags);
if (hub->WorkerSemaphore)
KeSignalSemaphore(hub->WorkerSemaphore);
if (!pending)
return (SEMAPHORE*)0;
ObReferenceObject(&hub->WorkerSemaphore->Header);
return hub->WorkerSemaphore;
}
KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) {
if (!hcd || !hcd->RootHubPdo)
return NTLSTATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&hcd->RootHubLock);
hcd->RootScanRequested = true;
SEMAPHORE* wake = UsbHubQueueInitialScan((USB_HUB_EXTENSION*)hcd->RootHubContext);
KeReleaseSpinlock(&hcd->RootHubLock, flags);
if (wake) {
KeSignalSemaphore(wake);
ObDereferenceObject(&wake->Header);
}
return NTLSTATUS_SUCCESS;
}
@@ -800,8 +851,10 @@ static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
return;
hub->ChangeUrbPending = false;
if (!KSUCCESS(urb->Status) || hub->Removed || hub->SurpriseRemoved)
if (!KSUCCESS(urb->Status) || hub->Removed || hub->SurpriseRemoved) {
IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0);
return;
}
uint32_t actual = urb->ActualLength;
if (actual > USB_HUB_CHANGE_BITMAP_BYTES)
@@ -813,6 +866,7 @@ static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
if (byteIndex < actual && (hub->ChangeBitmap[byteIndex] & (1u << bit)))
UsbHubQueueExternalPortChange(hub, port);
}
IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0);
}
// Implements the hub Arm External Interrupt operation.
@@ -820,6 +874,10 @@ static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
if (!hub || !hub->InterruptPipe || !hub->ChangeBitmap || hub->ChangeUrbPending)
return;
KSTATUS refStatus = IoAcquireRemoveLock(&hub->RemoveLock, (IRP*)0);
if (!KSUCCESS(refStatus))
return;
hub->ChangeUrbPending = true;
memset(hub->ChangeBitmap, 0, USB_HUB_CHANGE_BITMAP_BYTES);
memset(&hub->ChangeUrb, 0, sizeof(hub->ChangeUrb));
hub->ChangeUrb.Function = UrbFunctionInterruptTransfer;
@@ -835,11 +893,12 @@ static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
hub->ChangeUrb.CompleteContext = hub;
KSTATUS st = UsbSubmitUrbAsync(hub->LowerDevice, &hub->ChangeUrb);
if (st == NTLSTATUS_PENDING) {
hub->ChangeUrbPending = true;
} else if (!KSUCCESS(st)) {
if (st != NTLSTATUS_PENDING || hub->ChangeUrb.Status != NTLSTATUS_PENDING) {
hub->ChangeUrbPending = false;
IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0);
DbgPrint("usb-hub: slot=%u interrupt arm failed st=0x%x\n",
hub->Device ? hub->Device->SlotId : 0, st);
hub->Device ? hub->Device->SlotId : 0,
st == NTLSTATUS_PENDING ? hub->ChangeUrb.Status : st);
}
}
@@ -853,12 +912,30 @@ static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* h
if (!KSUCCESS(st))
return st;
hub->Started = true;
device->PnpState = DevicePnpStarted;
if (hub->HubPdo)
hub->HubPdo->PnpState = DevicePnpStarted;
DbgPrint("usb-hub: root hub started ports=%u\n", hub->PortCount);
uintptr_t flags = KeAcquireSpinlock(&hub->Hcd->RootHubLock);
hub->Started = true;
SEMAPHORE* wake = hub->Hcd->RootScanRequested ? UsbHubQueueInitialScan(hub) : (SEMAPHORE*)0;
KeReleaseSpinlock(&hub->Hcd->RootHubLock, flags);
XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)hub->Hcd->ControllerContext;
if (xhci)
DbgPrint("usb-hub: hcd=%02x:%02x.%u root hub started ports=%u scan=%s\n",
xhci->Bus, xhci->Dev, xhci->Fn, hub->PortCount,
wake ? "queued" : "not-queued");
// Publish the startup checkpoint before waking enumeration. A bad port or
// an interrupt storm can otherwise hide which hub started the work.
if (wake) {
KeSignalSemaphore(wake);
ObDereferenceObject(&wake->Header);
if (xhci)
DbgPrint("usb-stage: hcd=%02x:%02x.%u initial scan wake returned\n",
xhci->Bus, xhci->Dev, xhci->Fn);
}
return NTLSTATUS_SUCCESS;
}
@@ -888,10 +965,24 @@ static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSIO
}
hub->PowerOnToPowerGoodMs = desc.bPwrOn2PwrGood ? (uint8_t)(desc.bPwrOn2PwrGood * 2u) : 100u;
// xHCI needs the hub's Slot Context before routing low/full-speed child
// transfers through a high-speed transaction translator.
XHCI_CONTROLLER* xhci = hub->Hcd ? (XHCI_CONTROLLER*)hub->Hcd->ControllerContext : (XHCI_CONTROLLER*)0;
XHCI_DEVICE* xdev = xhci && hub->Device->SlotId <= XHCI_MAX_TRACKED_SLOTS
? &xhci->Devices[hub->Device->SlotId] : (XHCI_DEVICE*)0;
if (!xdev || !xdev->Allocated) {
UsbHubReleaseDma(hub);
return NTLSTATUS_DEVICE_ERROR;
}
st = XhciConfigureHubContext(xhci, xdev, hub->PortCount, desc.wHubCharacteristics);
if (!KSUCCESS(st)) {
UsbHubReleaseDma(hub);
return st;
}
for (uint8_t port = 1; port <= hub->PortCount; port++)
(void)UsbHubSetPortFeature(hub, port, USB_HUB_PORT_FEAT_POWER);
UsbDelayUs(((XHCI_CONTROLLER*)hub->Hcd->ControllerContext)->Ddk,
(uint32_t)hub->PowerOnToPowerGoodMs * 1000u);
UsbDelayUs((uint32_t)hub->PowerOnToPowerGoodMs * 1000u);
st = UsbHubStartWorker(hub);
if (!KSUCCESS(st)) {
@@ -971,12 +1062,22 @@ KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
device->PnpState = DevicePnpSurpriseRemoved;
if (hub) {
hub->SurpriseRemoved = true;
if (hub->Kind == UsbHubKindRoot && hub->Hcd) {
uintptr_t flags = KeAcquireSpinlock(&hub->Hcd->RootHubLock);
if (hub->Hcd->RootHubContext == hub)
hub->Hcd->RootHubContext = (void*)0;
hub->Started = false;
KeReleaseSpinlock(&hub->Hcd->RootHubLock, flags);
}
hub->WorkerRunning = false;
if (hub->ChangeUrbPending)
(void)UsbCancelUrb(&hub->ChangeUrb);
if (hub->WorkerSemaphore)
KeSignalSemaphore(hub->WorkerSemaphore);
UsbHubStopWorker(hub);
if (hub->ChangeUrbPending) {
st = UsbCancelUrb(&hub->ChangeUrb);
if (!KSUCCESS(st)) {
IoCompleteRequest(irp, st, 0);
return NTLSTATUS_PENDING;
}
}
// Remove downstream PDOs owned by this hub FDO. The explicit
// slot arrays are still used as the hardware lookup table; the
@@ -1000,23 +1101,34 @@ KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
device->PnpState = DevicePnpDeleted;
if (hub) {
hub->Removed = true;
hub->WorkerRunning = false;
if (hub->ChangeUrbPending)
(void)UsbCancelUrb(&hub->ChangeUrb);
(void)UsbRemoveDeviceObjectChildren(device, false);
if (hub->InterruptPipe) {
hub->InterruptPipe->Open = false;
UsbDereferencePipe(hub->InterruptPipe);
hub->InterruptPipe = (USB_PIPE*)0;
if (hub->Kind == UsbHubKindRoot && hub->Hcd) {
uintptr_t flags = KeAcquireSpinlock(&hub->Hcd->RootHubLock);
if (hub->Hcd->RootHubContext == hub)
hub->Hcd->RootHubContext = (void*)0;
hub->Started = false;
KeReleaseSpinlock(&hub->Hcd->RootHubLock, flags);
}
hub->WorkerRunning = false;
UsbHubStopWorker(hub);
if (hub->Kind == UsbHubKindRoot && hub->Hcd && hub->Hcd->RootHubContext == hub)
hub->Hcd->RootHubContext = (void*)0;
if (hub->ChangeUrbPending) {
st = UsbCancelUrb(&hub->ChangeUrb);
if (!KSUCCESS(st)) {
IoCompleteRequest(irp, st, 0);
return NTLSTATUS_PENDING;
}
}
(void)UsbRemoveDeviceObjectChildren(device, false);
if (hub->InterruptPipe)
hub->InterruptPipe->Open = false;
if (hub->RemoveLockReady) {
IoReleaseRemoveLockAndWait(&hub->RemoveLock, irp);
IoDestroyRemoveLock(&hub->RemoveLock);
hub->RemoveLockReady = false;
}
if (hub->InterruptPipe) {
UsbDereferencePipe(hub->InterruptPipe);
hub->InterruptPipe = (USB_PIPE*)0;
}
UsbHubReleaseDma(hub);
}
@@ -1118,7 +1230,9 @@ KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObje
}
if (kind == UsbHubKindRoot) {
uintptr_t flags = KeAcquireSpinlock(&hub->Hcd->RootHubLock);
hub->Hcd->RootHubContext = hub;
KeReleaseSpinlock(&hub->Hcd->RootHubLock, flags);
DbgPrint("usb-hub: root hub FDO attached\n");
} else {
DbgPrint("usb-hub: external hub FDO attached slot=%u ep=%02x\n",
@@ -1135,5 +1249,5 @@ KSTATUS UsbInitializeHubDriver(void) {
gUsbHubDriver.IdTable = &gUsbHubIdTable;
gUsbHubDriver.DriverAddDevice = UsbHubAddDevice;
gUsbHubDriver.MajorFunction[IRP_MJ_PNP] = UsbHubDispatchPnp;
return IoRegisterDriverObject(&gUsbHubDriver);
return NTLSTATUS_SUCCESS;
}