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:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
+33
-136
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user