replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.

This commit is contained in:
maksw committed 2026-10-28 15:18:43 +01:00
1 parent d36f19509c
commit 36eef8f58d
696 files changed
+147281 -7530

No files matched your search

+1
View File
@@ -0,0 +1 @@
!include $(BASEDIR)\makefile.def
+8
View File
@@ -0,0 +1,8 @@
TARGETNAME=usb
TARGETPATH=obj
TARGETTYPE=DRIVER
FLAVOR=DRIVER
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
EXTRA_LFLAGS=/NOENTRY
SOURCES=@/code/drivers/bus/usb/usb.c @/code/drivers/bus/usb/usb_bus.c @/code/drivers/bus/usb/usb_composite.c @/code/drivers/bus/usb/usb_core.c @/code/drivers/bus/usb/usb_xhci.c @/code/drivers/bus/usb/usb_hid.c \
@/code/drivers/bus/usb/usb_storage.c @/code/drivers/bus/usb/usb_hub.c
+2 -3
View File
@@ -29,7 +29,6 @@
#if USB_DEBUG_VERBOSE
#define UsbTrace DbgPrint
#else
// Implements the trace operation.
static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; }
#endif
@@ -802,7 +801,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 +961,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);
-19
View File
@@ -11,7 +11,6 @@ DRIVER_OBJECT gUsbBusDriver;
static bool gUsbBusModelReady;
static uint8_t gUsbNextControllerIndex;
// Implements the device Destroy operation.
static void UsbDeviceDestroy(OBJECT* object) {
USB_DEVICE* dev = (USB_DEVICE*)object;
if (dev->RemoveLockReady) {
@@ -36,22 +35,18 @@ static void UsbPipeDestroy(OBJECT* object) {
}
}
// Implements the reference Device operation.
void UsbReferenceDevice(USB_DEVICE* dev) {
if (dev) ObReferenceObject(&dev->Header);
}
// Implements the dereference Device operation.
void UsbDereferenceDevice(USB_DEVICE* dev) {
if (dev) ObDereferenceObject(&dev->Header);
}
// Implements the reference Pipe operation.
void UsbReferencePipe(USB_PIPE* pipe) {
if (pipe) ObReferenceObject(&pipe->Header);
}
// Implements the dereference Pipe operation.
void UsbDereferencePipe(USB_PIPE* pipe) {
if (pipe) ObDereferenceObject(&pipe->Header);
}
@@ -111,12 +106,10 @@ KSTATUS UsbCreatePipe(USB_DEVICE* dev,
return NTLSTATUS_SUCCESS;
}
// Implements the id From Buffer operation.
static SYS_STRING_VIEW UsbIdFromBuffer(char* buf) {
return SysSvFromCstr(buf);
}
// Implements the id Put Char operation.
static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) {
if (!buf || !pos || cap == 0)
return;
@@ -129,7 +122,6 @@ static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) {
buf[cap - 1] = '\0';
}
// Implements the id Append Literal operation.
static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* text) {
if (!text)
return;
@@ -137,7 +129,6 @@ static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* t
UsbIdPutChar(buf, cap, pos, *text++);
}
// Implements the id Append Hex operation.
static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, uint8_t digits) {
static const char kHex[] = "0123456789ABCDEF";
while (digits) {
@@ -146,7 +137,6 @@ static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, u
}
}
// Implements the format Vid Pid Rev operation.
static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint16_t rev) {
size_t pos = 0;
if (cap) buf[0] = '\0';
@@ -158,7 +148,6 @@ static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid
UsbIdAppendHex(buf, cap, &pos, rev, 4);
}
// Implements the format Vid Pid operation.
static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) {
size_t pos = 0;
if (cap) buf[0] = '\0';
@@ -168,7 +157,6 @@ static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) {
UsbIdAppendHex(buf, cap, &pos, pid, 4);
}
// Implements the format Vid Pid Mi operation.
static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint8_t mi) {
size_t pos = 0;
if (cap) buf[0] = '\0';
@@ -180,7 +168,6 @@ static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid,
UsbIdAppendHex(buf, cap, &pos, mi, 2);
}
// Implements the format Class Sub Prot operation.
static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t sub, uint8_t proto) {
size_t pos = 0;
if (cap) buf[0] = '\0';
@@ -192,7 +179,6 @@ static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t su
UsbIdAppendHex(buf, cap, &pos, proto, 2);
}
// Implements the format Class operation.
static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) {
size_t pos = 0;
if (cap) buf[0] = '\0';
@@ -200,14 +186,12 @@ static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) {
UsbIdAppendHex(buf, cap, &pos, cls, 2);
}
// Implements the format Composite operation.
static void UsbFormatComposite(char* buf, size_t cap) {
size_t pos = 0;
if (cap) buf[0] = '\0';
UsbIdAppendLiteral(buf, cap, &pos, "USB\\COMPOSITE");
}
// Implements the format Root Hub operation.
static void UsbFormatRootHub(char* buf, size_t cap) {
size_t pos = 0;
if (cap) buf[0] = '\0';
@@ -452,7 +436,6 @@ KSTATUS UsbCreateInterfacePdos(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* p
return NTLSTATUS_SUCCESS;
}
// Implements the reference First Child operation.
static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) {
if (!parent) return (DEVICE_OBJECT*)0;
uintptr_t flags = KeAcquireSpinlock(&parent->Lock);
@@ -463,7 +446,6 @@ static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) {
return child;
}
// Implements the send Pnp If Alive operation.
static void UsbSendPnpIfAlive(DEVICE_OBJECT* pdo, IO_PNP_MINOR_FUNCTION minor) {
if (!pdo || pdo->DeletePending)
return;
@@ -550,7 +532,6 @@ KSTATUS UsbSubmitUrbSync(DEVICE_OBJECT* target, USB_URB* urb) {
return KSUCCESS(st) ? urb->Status : st;
}
// Implements the async Urb Irp Complete operation.
static void UsbAsyncUrbIrpComplete(IRP* irp, void* context) {
(void)context;
IoFreeIrp(irp);
-4
View File
@@ -13,7 +13,6 @@ static const IO_DRIVER_ID_TABLE gUsbCompositeIdTable = {
sizeof(gUsbCompositeIds) / sizeof(gUsbCompositeIds[0]),
};
// Implements the composite Create Interfaces operation.
static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) {
if (!ext || !ext->Device || ext->InterfacesCreated)
return NTLSTATUS_SUCCESS;
@@ -28,7 +27,6 @@ static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) {
return st;
}
// Implements the composite Forward Pnp operation.
static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS localStatus) {
if (!KSUCCESS(localStatus)) {
IoCompleteRequest(irp, localStatus, 0);
@@ -37,7 +35,6 @@ static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS l
return IoForwardIrpToLower(device, irp);
}
// Implements the composite Dispatch Pnp operation.
KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
if (!device || !irp)
return NTLSTATUS_INVALID_PARAMETER;
@@ -114,7 +111,6 @@ KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
}
}
// Implements the composite Add Device operation.
KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
return NTLSTATUS_INVALID_PARAMETER;
-4
View File
@@ -260,7 +260,6 @@ KSTATUS XhciDiscoverAndSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
return NTLSTATUS_SUCCESS;
}
// Implements the rollback Enumerated Slot operation.
static void XhciRollbackEnumeratedSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) {
if (!xhci || slotId == 0 || slotId > XHCI_MAX_TRACKED_SLOTS)
return;
@@ -399,7 +398,6 @@ static KSTATUS XhciEnumeratePathEx(XHCI_CONTROLLER* xhci,
return NTLSTATUS_SUCCESS;
}
// Implements the enumerate Port Ex operation.
KSTATUS XhciEnumeratePortEx(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSlotId) {
if (outSlotId) *outSlotId = 0;
@@ -449,12 +447,10 @@ KSTATUS XhciEnumerateHubPortEx(XHCI_CONTROLLER* xhci,
return XhciEnumeratePathEx(xhci, hubPort, speed, &path, hub->Self, outSlotId);
}
// Implements the enumerate Port operation.
KSTATUS XhciEnumeratePort(XHCI_CONTROLLER* xhci, uint8_t port) {
return XhciEnumeratePortEx(xhci, port, (uint8_t*)0);
}
// Implements the enumerate Root Ports operation.
void XhciEnumerateRootPorts(XHCI_CONTROLLER* xhci) {
uint32_t attempted = 0;
uint32_t configured = 0;
-15
View File
@@ -12,7 +12,6 @@ static void UsbHidReleaseDma(USB_HID_EXTENSION* ext) {
ext->ReportBufferDeviceAddress = 0;
}
// Implements the hid Key In Report operation.
bool XhciHidKeyInReport(const uint8_t* keys, uint8_t key) {
if (key == 0 || key == 1) return false;
for (uint8_t i = 0; i < 6; i++) {
@@ -94,7 +93,6 @@ void XhciProcessBootMouseReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_
dev->HidLastButtons = buttons;
}
// Implements the arm Hid Interrupt In operation.
KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
if (!dev->HidActive || dev->HidArmed || !dev->HidRing || !dev->HidBuffer)
return NTLSTATUS_SUCCESS;
@@ -122,7 +120,6 @@ KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
return NTLSTATUS_SUCCESS;
}
// Implements the arm All Hid operation.
void XhciArmAllHid(XHCI_CONTROLLER* xhci) {
for (uint8_t slot = 1; slot <= XHCI_MAX_TRACKED_SLOTS; slot++) {
XHCI_DEVICE* dev = &xhci->Devices[slot];
@@ -241,7 +238,6 @@ KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
return NTLSTATUS_SUCCESS;
}
// Implements the configure Hid Endpoint operation.
KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
if (!dev->HidCandidate)
return NTLSTATUS_SUCCESS;
@@ -328,7 +324,6 @@ static const IO_DRIVER_ID_TABLE gUsbHidIdTable = {
sizeof(gUsbHidIds) / sizeof(gUsbHidIds[0]),
};
// Implements the hid Is Qemu Absolute Tablet Pdo operation.
static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const USB_ENDPOINT_DESCRIPTOR* ep) {
if (!pdoExt || !pdoExt->Device || !ep)
return false;
@@ -347,7 +342,6 @@ static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const
return (ep->wMaxPacketSize & 0x07FFu) >= 6u;
}
// Implements the hid Find Interrupt In Pdo operation.
static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXTENSION* ext) {
if (!ext) return (const USB_ENDPOINT_DESCRIPTOR*)0;
@@ -361,7 +355,6 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXT
return (const USB_ENDPOINT_DESCRIPTOR*)0;
}
// Implements the hid Process Boot Keyboard Report operation.
static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
if (!ext || len < 8) return;
@@ -390,7 +383,6 @@ static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_
memcpy(ext->LastKeys, keys, sizeof(ext->LastKeys));
}
// Implements the hid Process Boot Mouse Report operation.
static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
if (!ext || len < 3) return;
@@ -411,7 +403,6 @@ static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t*
ext->LastButtons = buttons;
}
// Implements the hid Process Qemu Tablet Report operation.
static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
if (!ext || len < 5) return;
@@ -432,7 +423,6 @@ static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t*
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext);
// Implements the hid Interrupt Complete operation.
static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
USB_HID_EXTENSION* ext = (USB_HID_EXTENSION*)context;
if (!ext || urb != &ext->InterruptUrb)
@@ -470,7 +460,6 @@ static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
IoReleaseRemoveLock(&ext->RemoveLock, (IRP*)0);
}
// Implements the hid Send Boot Protocol operation.
static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) {
if (!ext || !ext->LowerDevice || !ext->Device)
return NTLSTATUS_INVALID_PARAMETER;
@@ -514,7 +503,6 @@ static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) {
return NTLSTATUS_SUCCESS;
}
// Implements the hid Arm Interrupt operation.
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) {
if (!ext || !ext->Started || ext->SurpriseRemoved || ext->Removed)
return NTLSTATUS_OBJECT_DEAD;
@@ -551,7 +539,6 @@ static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) {
return NTLSTATUS_SUCCESS;
}
// Implements the hid Start Device operation.
static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) {
if (!device || !ext || !ext->Device || !ext->InterfacePdo)
return NTLSTATUS_INVALID_PARAMETER;
@@ -660,7 +647,6 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext)
return NTLSTATUS_SUCCESS;
}
// Implements the hid Dispatch Pnp operation.
KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
if (!device || !irp)
return NTLSTATUS_INVALID_PARAMETER;
@@ -758,7 +744,6 @@ KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
}
}
// Implements the hid Add Device operation.
KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
return NTLSTATUS_INVALID_PARAMETER;
-31
View File
@@ -31,19 +31,16 @@ static const IO_DRIVER_ID_TABLE gUsbHubIdTable = {
#define USB_HUB_PORT_ENUMERATING 0xffu
#define USB_HUB_PORT_FAILED 0xfeu
// Implements the hub Slot Busy operation.
static bool UsbHubSlotBusy(uint8_t slot) {
return slot != 0 && slot != USB_HUB_PORT_ENUMERATING && slot != USB_HUB_PORT_FAILED;
}
// Implements the hub Root Port Connected operation.
static bool UsbHubRootPortConnected(XHCI_CONTROLLER* xhci, uint8_t port) {
if (!xhci || !xhci->Op || port == 0) return false;
uint32_t portsc = XhciRead32(xhci->Op, XhciPortReg(port));
return (portsc & XHCI_PORTSC_CCS) != 0;
}
// Implements the hub Clear Root Port Failure operation.
static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) {
if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return;
hub->RootPortFailCount[port] = 0;
@@ -51,7 +48,6 @@ static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) {
hub->RootPortSlot[port] = 0;
}
// Implements the hub Mark Root Port Failed operation.
static void UsbHubMarkRootPortFailed(USB_HUB_EXTENSION* hub, uint8_t port) {
if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return;
hub->RootPortSlot[port] = USB_HUB_PORT_FAILED;
@@ -146,7 +142,6 @@ static KSTATUS UsbHubEnumerateConnectedRootPort(USB_HUB_EXTENSION* hub,
return status;
}
// Implements the hub Pop Pending Root Port operation.
static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
if (!hub || !outPort) return false;
@@ -168,7 +163,6 @@ static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
return false;
}
// Implements the hub Pop Pending External Port operation.
static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
if (!hub || !outPort) return false;
@@ -193,7 +187,6 @@ static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPor
return false;
}
// Implements the hub Record Root Port Change operation.
static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
if (!hub || port == 0 || port > hub->PortCount)
return;
@@ -206,7 +199,6 @@ static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
KeSignalSemaphore(hub->WorkerSemaphore);
}
// Implements the hub Queue External Port Change operation.
void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
if (!hub || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS)
return;
@@ -217,7 +209,6 @@ void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
KeSignalSemaphore(hub->WorkerSemaphore);
}
// Implements the hub Remove Slot Child operation.
static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) {
if (!hub || !hub->Hcd || slot == 0)
return;
@@ -253,7 +244,6 @@ static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t
}
}
// Implements the hub Remove Root Child operation.
static void UsbHubRemoveRootChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) {
UsbHubRemoveSlotChild(hub, port, slot);
}
@@ -306,7 +296,6 @@ static KSTATUS UsbHubControlNoData(USB_HUB_EXTENSION* hub,
return UsbSubmitUrbSync(hub->LowerDevice, &urb);
}
// Implements the hub Read Descriptor operation.
static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* outDesc) {
if (!hub || !outDesc || !hub->ChangeBitmap || !hub->ChangeBitmapDeviceAddress)
return NTLSTATUS_INVALID_PARAMETER;
@@ -329,7 +318,6 @@ static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR*
return NTLSTATUS_SUCCESS;
}
// Implements the hub Get Port Status operation.
static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB_PORT_STATUS* outStatus) {
if (!hub || !outStatus || port == 0)
return NTLSTATUS_INVALID_PARAMETER;
@@ -350,7 +338,6 @@ static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB
return NTLSTATUS_SUCCESS;
}
// Implements the hub Set Port Feature operation.
static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) {
return UsbHubControlNoData(hub,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
@@ -359,7 +346,6 @@ static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16
port);
}
// Implements the hub Clear Port Feature operation.
static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) {
return UsbHubControlNoData(hub,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
@@ -368,7 +354,6 @@ static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint
port);
}
// Implements the hub Speed From Port Status operation.
static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) {
if (status & USB_HUB_PORT_STATUS_LOW_SPEED)
return 2u;
@@ -377,7 +362,6 @@ static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) {
return 1u;
}
// Implements the hub Reset External Port operation.
static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t* outSpeed) {
if (outSpeed) *outSpeed = 0;
if (!hub || port == 0)
@@ -426,7 +410,6 @@ static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uin
return NTLSTATUS_SUCCESS;
}
// Implements the hub Handle External Port Change operation.
static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
if (!hub || hub->Kind != UsbHubKindExternal || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS)
return;
@@ -509,7 +492,6 @@ static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port)
}
}
// Implements the hub Handle Root Port Change operation.
static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
if (!hub || !hub->Hcd || port == 0 || port > hub->PortCount || port > USB_ROOT_HUB_MAX_PORTS)
return;
@@ -575,7 +557,6 @@ static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub);
static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd);
// Implements the hub Take Initial Root Scan operation.
static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) {
if (!hub || hub->Kind != UsbHubKindRoot)
return false;
@@ -589,7 +570,6 @@ static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) {
return take;
}
// 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) {
@@ -687,7 +667,6 @@ static KSTATUS UsbHubStartWorker(USB_HUB_EXTENSION* hub) {
return NTLSTATUS_SUCCESS;
}
// Implements the hub Do Root Port Scan operation.
static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) {
if (!hcd || !hcd->RootHubContext)
return NTLSTATUS_INVALID_PARAMETER;
@@ -774,7 +753,6 @@ KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) {
return NTLSTATUS_SUCCESS;
}
// Implements the hub Queue Root Port Change operation.
void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) {
if (!hcd || !hcd->RootHubContext)
return;
@@ -782,7 +760,6 @@ void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) {
UsbHubRecordRootPortChange(hub, port);
}
// Implements the hub Scan External Ports operation.
static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) {
if (!hub || hub->Kind != UsbHubKindExternal)
return NTLSTATUS_INVALID_PARAMETER;
@@ -810,7 +787,6 @@ static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) {
return NTLSTATUS_SUCCESS;
}
// Implements the hub Find Interrupt In operation.
static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* pdoExt) {
if (!pdoExt)
return (const USB_ENDPOINT_DESCRIPTOR*)0;
@@ -844,7 +820,6 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* p
return (const USB_ENDPOINT_DESCRIPTOR*)0;
}
// Implements the hub External Change Complete operation.
static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)context;
if (!hub || urb != &hub->ChangeUrb)
@@ -869,7 +844,6 @@ static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0);
}
// Implements the hub Arm External Interrupt operation.
static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
if (!hub || !hub->InterruptPipe || !hub->ChangeBitmap || hub->ChangeUrbPending)
return;
@@ -902,7 +876,6 @@ static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
}
}
// Implements the hub Start Root Device operation.
static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
hub->PortCount = hub->Hcd ? hub->Hcd->MaxRootPorts : 0;
if (hub->PortCount > USB_ROOT_HUB_MAX_PORTS)
@@ -939,7 +912,6 @@ static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* h
return NTLSTATUS_SUCCESS;
}
// Implements the hub Start External Device operation.
static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
if (!hub || !hub->Device)
return NTLSTATUS_INVALID_PARAMETER;
@@ -1019,7 +991,6 @@ static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSIO
return NTLSTATUS_SUCCESS;
}
// Implements the hub Start Device operation.
static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
if (!device || !hub || hub->Started)
return NTLSTATUS_SUCCESS;
@@ -1029,7 +1000,6 @@ static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub)
return UsbHubStartExternalDevice(device, hub);
}
// Implements the hub Dispatch Pnp operation.
KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
if (!device || !irp)
return NTLSTATUS_INVALID_PARAMETER;
@@ -1154,7 +1124,6 @@ KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
}
}
// Implements the hub Add Device operation.
KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
return NTLSTATUS_INVALID_PARAMETER;
-17
View File
@@ -21,7 +21,6 @@ static const IO_DRIVER_ID_TABLE gUsbStorageIdTable = {
sizeof(gUsbStorageIds) / sizeof(gUsbStorageIds[0]),
};
// Implements the storage From Disk Device operation.
static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) {
if (!device || !device->DeviceExtension)
return (USB_STORAGE_EXTENSION*)0;
@@ -32,7 +31,6 @@ static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) {
return diskExt->Storage;
}
// Implements the storage From Interface Device operation.
static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* device) {
if (!device || !device->DeviceExtension)
return (USB_STORAGE_EXTENSION*)0;
@@ -43,7 +41,6 @@ static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* devic
return ext;
}
// Implements the storage Find Bulk Endpoint operation.
static const USB_ENDPOINT_DESCRIPTOR* UsbStorageFindBulkEndpoint(const USB_PDO_EXTENSION* pdoExt, bool wantIn) {
if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0;
@@ -290,7 +287,6 @@ KSTATUS UsbStorageBotCommand(USB_STORAGE_EXTENSION* storage,
(USB_STORAGE_SENSE_DATA*)0);
}
// Implements the be32 operation.
uint32_t UsbBe32(const uint8_t* p) {
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
((uint32_t)p[2] << 8) | (uint32_t)p[3];
@@ -310,7 +306,6 @@ void UsbStoreBe16(uint8_t* p, uint16_t v) {
p[1] = (uint8_t)v;
}
// Implements the storage Inquiry operation.
KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) {
if (!storage || !storage->XhciDevice)
return NTLSTATUS_INVALID_PARAMETER;
@@ -332,7 +327,6 @@ KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) {
return NTLSTATUS_SUCCESS;
}
// Implements the storage Test Unit Ready operation.
KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) {
if (!storage || !storage->XhciDevice)
return NTLSTATUS_INVALID_PARAMETER;
@@ -353,7 +347,6 @@ KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) {
return last;
}
// Implements the storage Read Capacity operation.
KSTATUS UsbStorageReadCapacity(USB_STORAGE_EXTENSION* storage) {
if (!storage || !storage->XhciDevice)
return NTLSTATUS_INVALID_PARAMETER;
@@ -463,7 +456,6 @@ static KSTATUS UsbStorageSynchronizeCache(USB_STORAGE_EXTENSION* storage) {
return NTLSTATUS_DEVICE_ERROR;
}
// Implements the storage Acquire Io operation.
void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) {
if (!storage) return;
XHCI_CONTROLLER* xhci = storage->Device ? (XHCI_CONTROLLER*)storage->Device->Hcd->ControllerContext : (XHCI_CONTROLLER*)0;
@@ -472,12 +464,10 @@ void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) {
}
}
// Implements the storage Release Io operation.
void UsbStorageReleaseIo(USB_STORAGE_EXTENSION* storage) {
if (storage) NtlAtomicExchange32(&storage->IoBusy, 0);
}
// Implements the storage Dispatch Read Write operation.
KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) {
if (!device || !irp)
return NTLSTATUS_INVALID_PARAMETER;
@@ -608,7 +598,6 @@ KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
return NTLSTATUS_SUCCESS;
}
// Implements the configure Mass Storage Endpoints operation.
KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
if (!dev->MassCandidate)
return NTLSTATUS_SUCCESS;
@@ -687,7 +676,6 @@ uint8_t UsbFindFreeDiskIndex(void) {
return 0xFFu;
}
// Implements the storage Register Disk operation.
KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) {
if (!storage || storage->BlockSize != USB_STORAGE_SECTOR_SIZE || storage->BlockCount == 0)
return NTLSTATUS_NOT_SUPPORTED;
@@ -731,7 +719,6 @@ KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) {
return NTLSTATUS_SUCCESS;
}
// Implements the storage Start Device operation.
static KSTATUS UsbStorageStartDevice(DEVICE_OBJECT* device, USB_STORAGE_EXTENSION* storage) {
if (!device || !storage || !storage->InterfacePdo || !storage->Device)
return NTLSTATUS_INVALID_PARAMETER;
@@ -849,7 +836,6 @@ fail:
return st;
}
// Implements the storage Disk Pnp operation.
static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) {
if (!device || !irp || !storage)
return NTLSTATUS_INVALID_PARAMETER;
@@ -900,7 +886,6 @@ static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EX
}
}
// Implements the storage Interface Pnp operation.
static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) {
if (!device || !irp || !storage)
return NTLSTATUS_INVALID_PARAMETER;
@@ -978,7 +963,6 @@ static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORA
}
}
// Implements the storage Dispatch Pnp operation.
KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
if (!device || !irp)
return NTLSTATUS_INVALID_PARAMETER;
@@ -998,7 +982,6 @@ KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
return NTLSTATUS_INVALID_PARAMETER;
}
// Implements the storage Add Device operation.
KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
return NTLSTATUS_INVALID_PARAMETER;
+33 -136
View File
@@ -2,52 +2,43 @@
#include "usb.h"
// Implements the align Up32 operation.
uint32_t UsbAlignUp32(uint32_t value, uint32_t align) {
return (value + align - 1u) & ~(align - 1u);
}
// Implements the barrier operation.
void XhciBarrier(void) {
_ReadWriteBarrier();
_mm_mfence();
_ReadWriteBarrier();
}
// Implements the read8 operation.
uint8_t XhciRead8(volatile uint8_t* base, uint32_t reg) {
return *(volatile uint8_t*)(base + reg);
}
// Implements the read16 operation.
uint16_t XhciRead16(volatile uint8_t* base, uint32_t reg) {
return *(volatile uint16_t*)(base + reg);
}
// Implements the read32 operation.
uint32_t XhciRead32(volatile uint8_t* base, uint32_t reg) {
return *(volatile uint32_t*)(base + reg);
}
// Implements the write32 operation.
void XhciWrite32(volatile uint8_t* base, uint32_t reg, uint32_t value) {
*(volatile uint32_t*)(base + reg) = value;
}
// Implements the read64 operation.
uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg) {
uint32_t lo = XhciRead32(base, reg);
uint32_t hi = XhciRead32(base, reg + 4u);
return ((uint64_t)hi << 32) | lo;
}
// Implements the write64 operation.
void XhciWrite64(volatile uint8_t* base, uint32_t reg, uint64_t value) {
XhciWrite32(base, reg, (uint32_t)value);
XhciWrite32(base, reg + 4u, (uint32_t)(value >> 32));
}
// Implements the delay Us operation.
void UsbDelayUs(uint32_t us) {
KeStallExecution(us);
}
@@ -169,43 +160,35 @@ static void XhciReleaseControllerDma(XHCI_CONTROLLER* xhci) {
xhci->DmaAdapter = (IO_DMA_ADAPTER*)0;
}
// Implements the scratchpad Count operation.
uint16_t XhciScratchpadCount(uint32_t hcs2) {
return (uint16_t)((((hcs2 >> 16) & 0x3E0u) | ((hcs2 >> 27) & 0x1Fu)) & 0x3FFu);
}
// Implements the trb Type operation.
uint32_t XhciTrbType(const XHCI_TRB* trb) {
return (trb->Control >> XHCI_TRB_TYPE_SHIFT) & XHCI_TRB_TYPE_MASK;
}
// Implements the completion Code operation.
uint32_t XhciCompletionCode(const XHCI_TRB* trb) {
return (trb->Status >> 24) & 0xFFu;
}
// Implements the event Slot Id operation.
uint8_t XhciEventSlotId(const XHCI_TRB* trb) {
return (uint8_t)(trb->Control >> 24);
}
// Implements the event Endpoint Id operation.
uint8_t XhciEventEndpointId(const XHCI_TRB* trb) {
return (uint8_t)((trb->Control >> 16) & 0x1Fu);
}
// Implements the transfer Residue operation.
uint32_t XhciTransferResidue(const XHCI_TRB* trb) {
return trb->Status & 0xFFFFFFu;
}
// Implements the input Control Context operation.
uint32_t* XhciInputControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
(void)xhci;
return (uint32_t*)dev->InputContext;
}
// Implements the input Slot Context operation.
uint32_t* XhciInputSlotContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
return (uint32_t*)(dev->InputContext + xhci->ContextBytes);
}
@@ -285,7 +268,6 @@ KSTATUS XhciConfigureHubContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
return NTLSTATUS_SUCCESS;
}
// Implements the ep Max Packet operation.
uint32_t XhciEpMaxPacket(uint8_t speed) {
switch (speed) {
case 2: return 8; // low-speed
@@ -297,7 +279,6 @@ uint32_t XhciEpMaxPacket(uint8_t speed) {
}
}
// Implements the setup Packet To U64 operation.
uint64_t UsbSetupPacketToU64(const USB_SETUP_PACKET* setup) {
uint64_t v = 0;
v |= (uint64_t)setup->bmRequestType;
@@ -385,7 +366,6 @@ void XhciParseSupportedProtocols(XHCI_CONTROLLER* xhci) {
(uint32_t)xhci->MaxPorts - usb2Ports - usb3Ports);
}
// Implements the port Protocol Major operation.
uint8_t XhciPortProtocolMajor(XHCI_CONTROLLER* xhci, uint8_t port, uint32_t portsc) {
if (port <= XHCI_MAX_ROOT_PORTS && xhci->PortProtocolMajor[port])
return xhci->PortProtocolMajor[port];
@@ -426,7 +406,6 @@ const char* UsbInterfaceClassName(uint8_t klass, uint8_t subclass, uint8_t proto
return "class";
}
// Implements the log Port Status operation.
void XhciLogPortStatus(XHCI_CONTROLLER* xhci) {
for (uint8_t port = 1; port <= xhci->MaxPorts; port++) {
uint32_t off = XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE;
@@ -448,7 +427,6 @@ void XhciLogPortStatus(XHCI_CONTROLLER* xhci) {
}
}
// Implements the power Root Ports operation.
void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) {
if (!xhci || !xhci->Op)
return;
@@ -474,7 +452,6 @@ void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) {
}
}
// Implements the ack Interrupter0 operation.
void XhciAckInterrupter0(XHCI_CONTROLLER* xhci) {
if (!xhci->Runtime) return;
volatile uint8_t* ir0 = xhci->Runtime + 0x20u;
@@ -680,7 +657,6 @@ void XhciRegisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) {
KeReleaseSpinlock(&xhci->WaitLock, flags);
}
// Implements the unregister Wait Target operation.
void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) {
if (!xhci || !target || !target->Registered)
return;
@@ -761,58 +737,18 @@ 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)
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;
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;
}
xhci->InterruptCount++;
XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK);
XhciAckInterrupter0(xhci);
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
}
// 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);
}
}
// Implements the bios Handoff operation.
KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) {
uint32_t xecp = (xhci->Hcc1 >> 16) & 0xFFFFu;
if (!xecp) return NTLSTATUS_SUCCESS;
@@ -856,7 +792,6 @@ KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) {
return NTLSTATUS_SUCCESS;
}
// Implements the stop And Reset operation.
KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci) {
uint32_t cmd = XhciRead32(xhci->Op, XHCI_OP_USBCMD);
if (cmd & XHCI_USBCMD_RS) {
@@ -991,7 +926,6 @@ KSTATUS XhciAllocateRuntimeMemory(XHCI_CONTROLLER* xhci) {
return NTLSTATUS_SUCCESS;
}
// Implements the program Runtime operation.
KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci) {
uint8_t slots = xhci->MaxSlots;
if (slots == 0) return NTLSTATUS_DEVICE_ERROR;
@@ -1159,7 +1093,6 @@ KSTATUS XhciDisableSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) {
return NTLSTATUS_SUCCESS;
}
// Implements the address Device operation.
KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
XHCI_COMMAND_RESULT result;
memset(&result, 0, sizeof(result));
@@ -1206,7 +1139,6 @@ void XhciEnableInterrupts(XHCI_CONTROLLER* xhci) {
XhciWrite32(xhci->Op, XHCI_OP_USBCMD, cmd | XHCI_USBCMD_INTE | XHCI_USBCMD_HSEE);
}
// Implements the port Reg operation.
uint32_t XhciPortReg(uint8_t port) {
return XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE;
}
@@ -1227,7 +1159,6 @@ void XhciClearPortChanges(XHCI_CONTROLLER* xhci, uint8_t port) {
}
}
// Implements the reset Port operation.
KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) {
uint32_t off = XhciPortReg(port);
uint32_t portsc = XhciRead32(xhci->Op, off);
@@ -1647,14 +1578,12 @@ KSTATUS XhciGetConfigurationDescriptor(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
return NTLSTATUS_SUCCESS;
}
// Implements the endpoint Id From Address operation.
uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress) {
uint8_t number = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
if (number == 0) return 1;
return (uint8_t)(number * 2u + ((endpointAddress & USB_ENDPOINT_DIR_IN) ? 1u : 0u));
}
// Implements the interrupt Interval operation.
uint8_t XhciInterruptInterval(uint8_t speed, uint8_t usbInterval) {
if (usbInterval == 0) usbInterval = 1;
@@ -1781,7 +1710,6 @@ KSTATUS XhciBulkTransfer(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
return NTLSTATUS_SUCCESS;
}
// Implements the configure Pipe Endpoint operation.
KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_PIPE* pipe) {
if (!xhci || !dev || !pipe || !pipe->Open)
return NTLSTATUS_INVALID_PARAMETER;
@@ -1868,7 +1796,6 @@ KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_P
return NTLSTATUS_SUCCESS;
}
// Implements the hcd Submit Interrupt Urb operation.
static KSTATUS XhciHcdSubmitInterruptUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) {
if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0)
return NTLSTATUS_INVALID_PARAMETER;
@@ -1966,7 +1893,6 @@ static bool XhciClaimAsyncCompletion(XHCI_CONTROLLER* xhci, uint64_t trbDeviceAd
return true;
}
// Implements the hcd Submit Bulk Urb operation.
static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) {
if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0)
return NTLSTATUS_INVALID_PARAMETER;
@@ -2006,7 +1932,6 @@ static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB
return st;
}
// Implements the hcd Submit Urb operation.
static KSTATUS XhciHcdSubmitUrb(USB_HCD* hcd, USB_URB* urb) {
if (!hcd || !urb || !urb->Device)
return NTLSTATUS_INVALID_PARAMETER;
@@ -2105,7 +2030,6 @@ static KSTATUS XhciHcdCancelUrb(USB_HCD* hcd, USB_URB* urb) {
return NTLSTATUS_SUCCESS;
}
// Implements the hcd Allocate Dma operation.
static void* XhciHcdAllocateDma(USB_HCD* hcd,
size_t pages,
uint64_t* outDeviceAddress,
@@ -2130,13 +2054,11 @@ static void XhciHcdDestroyPipe(USB_HCD* hcd, USB_PIPE* pipe) {
MmFreePool(ctx);
}
// Implements the hcd Reset Root Port operation.
static KSTATUS XhciHcdResetRootPort(USB_HCD* hcd, uint8_t port, uint8_t* outSpeed) {
if (!hcd) return NTLSTATUS_INVALID_PARAMETER;
return XhciResetPort((XHCI_CONTROLLER*)hcd->ControllerContext, port, outSpeed);
}
// Implements the hcd Clear Root Port Changes operation.
static KSTATUS XhciHcdClearRootPortChanges(USB_HCD* hcd, uint8_t port) {
if (!hcd) return NTLSTATUS_INVALID_PARAMETER;
XhciClearPortChanges((XHCI_CONTROLLER*)hcd->ControllerContext, port);
@@ -2181,35 +2103,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,12 +2166,11 @@ 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",
UsbTrace("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",
UsbTrace("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,
xhci->ScratchpadCount, xhci->Hcs2, xhci->Hcc1, xhci->DbOff,
xhci->RtsOff, XhciRead32(xhci->Op, XHCI_OP_PAGESIZE));
@@ -2331,22 +2230,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;
@@ -2354,15 +2249,16 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
if (!KSUCCESS(st))
DbgPrint("usb: root hub async scan scheduling failed st=0x%x\n", st);
else
DbgPrint("usb: root hub initial scan requested\n");
UsbTrace("usb: root hub scan scheduled\n");
DbgPrint("usb: xHCI host controller initialised; HID boot input active=%u mass-storage will arrive through hotplug\n",
xhci->HidDeviceCount);
DbgPrint("usb: xHCI ready pci=%02x:%02x.%u ports=%u\n",
xhci->Bus, xhci->Dev, xhci->Fn, xhci->MaxPorts);
return NTLSTATUS_SUCCESS;
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 +2296,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 +2305,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);
@@ -2422,7 +2321,6 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
}
}
// Implements the add Device operation.
KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
return NTLSTATUS_INVALID_PARAMETER;
@@ -2439,7 +2337,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);