23#define XHCI_SECONDARY_MAX 16
24#define XHCI_SEGMENTS_DEFAULT 4
25#define XHCI_SEGMENTS_RING_FULL 8
26#define XHCI_SEGMENTS_LIMITED 2
27#define XHCI_BUDGET_CHECK_EVENTS 64
28#define XHCI_HANDBACK_EVENTS 128
29#define XHCI_REASON_EVENT_RING_FULL 0x1011
30#define XHCI_DRAIN_WAIT_MS 60000
98#pragma GCC diagnostic push
99#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
100#elif defined(_MSC_VER)
102#pragma warning(disable:4996)
118#pragma GCC diagnostic pop
119#elif defined(_MSC_VER)
132 return Entry->Controller->m_Registers.ReadRuntime32(
Entry->RegisterOffset +
Offset);
195 Entry->DequeueIndex = 0;
196 Entry->DequeueSegment = 0;
369 Entry->DequeueIndex++;
370 if (
Entry->DequeueIndex <
Entry->TrbsPerSegment)
373 Entry->DequeueIndex = 0;
374 Entry->DequeueSegment++;
376 if (
Entry->DequeueSegment <
Entry->SegmentCount)
383 Entry->DequeueSegment = 0;
406 Event->Dword[3] &= ~XHCI_TRANSFER_EVENT_ED;
422 DPRINT1(
"Transfer event for slot %lu endpoint %lu has no device, dropped\n",
445 DPRINT1(
"Dropping event type %lu with vendor completion code 199\n",
Type);
458 Entry->RingFullCount++;
459 DPRINT1(
"Interrupter %lu event ring full (%lu times)\n",
Entry->Index,
Entry->RingFullCount);
467 if (
Entry->Index != 0)
469 DPRINT1(
"Event type %lu on secondary interrupter %lu, dropped\n",
Type,
Entry->Index);
490 DPRINT1(
"Host controller event with completion code %lu\n",
Code);
495 DPRINT1(
"Unexpected MFINDEX wrap event\n");
514 if (
Entry->PendingDisable)
517 DPRINT(
"Interrupter %lu requeue skipped, disable pending\n",
Entry->Index);
573 ULONG WatchdogLimit = 0;
583 if (
Entry->DpcRunning)
610 if (Processed != 0 &&
636 (
Descriptor->Flags & MessageFlags) == MessageFlags;
648 (
Descriptor->Flags & MessageFlags) == MessageFlags;
656XhciStripMessageRequirements(
657 _In_ WDFIORESREQLIST Requirements)
667 ListIndex = WdfIoResourceRequirementsListGetCount(Requirements);
671 List = WdfIoResourceRequirementsListGetIoResList(Requirements,
ListIndex);
691 WdfIoResourceListUpdateDescriptor(
List, &Preferred,
Index);
697 DPRINT(
"Removing requirements list %lu, it has no line interrupt\n",
ListIndex);
698 WdfIoResourceRequirementsListRemove(Requirements,
ListIndex);
708 DPRINT1(
"Line interrupts are required but no requirements list offers one\n");
721 _In_ WDFIORESREQLIST Requirements,
738 Lists = WdfIoResourceRequirementsListGetCount(Requirements);
741 List = WdfIoResourceRequirementsListGetIoResList(Requirements,
Current);
779XhciTrimMessageRequirements(
860 DPRINT1(
"Primary interrupt creation failed 0x%lx\n",
Status);
879 Config.InterruptTranslated = Translated;
909 if (Processors <=
Limit)
913 Count = Processors / 2;
922 _In_ WDFIORESREQLIST Requirements)
933 return XhciStripMessageRequirements(Requirements);
939 DPRINT(
"Requirements list %lu offers %lu messages (MSI-X %u), %lu secondary interrupters\n",
942 if (WdfIoResourceRequirementsListGetCount(Requirements) != 0)
944 XhciTrimMessageRequirements(WdfIoResourceRequirementsListGetIoResList(Requirements,
ListIndex),
953 _In_ WDFIORESREQLIST Requirements)
960 ULONG PerInterrupter;
961 ULONG NextProcessor = 0;
973 DPRINT1(
"Secondary interrupters planned but no MSI-X list found\n");
978 List = WdfIoResourceRequirementsListGetIoResList(Requirements,
ListIndex);
1002 WdfIoResourceListUpdateDescriptor(
List, &Pinned,
Index);
1030 Entry->MessageSignaled = MessageSignaled;
1036 Segments =
Controller->HasErrata(XhciErrata::EvtResetOnRingOverflow) ?
1043 Entry->SegmentCount = Segments;
1050 DPRINT1(
"Interrupter %lu: no buffer for the segment table\n",
Index);
1057 DPRINT1(
"Interrupter %lu: no buffers for %lu event ring segments 0x%lx\n",
1084 DPRINT1(
"Interrupter %lu: requeue work item creation failed 0x%lx\n",
Index,
Status);
1106 _In_ WDFCMRESLIST Translated)
1129 Assigned +=
Descriptor->u.MessageInterrupt.Raw.MessageCount;
1139 DPRINT1(
"No interrupt resources were assigned\n");
1148 DPRINT1(
"Interrupter table allocation for %lu entries failed\n", Assigned);
1157 DPRINT1(
"Primary interrupter prepare failed 0x%lx\n",
Status);
1174 FirstSkipped =
FALSE;
1177 for (
Index = 0;
Index < WdfCmResourceListGetCount(Translated);
Index++)
1189 FirstSkipped =
TRUE;
1211#if defined(NT_PROCESSOR_GROUPS)
1221 DPRINT(
"%lu interrupt messages assigned, mechanism %lu, %lu interrupters in use\n",
1238 max(
Size, 1UL) *
sizeof(*m_Lookup),
1242 DPRINT1(
"Processor lookup table allocation for %lu processors failed\n",
Size);
1286 WdfWorkItemFlush(
Entry->Requeue);
1291 XhciInterruptContext(
Entry->Interrupt)->Entry =
NULL;
1337 if (!StatePreserved)
1374 DPRINT1(
"Interrupter %lu requeue work item still running after 60 s\n",
Index);
BOOLEAN HasErrata(_In_ XhciErrata Bit) const
BOOLEAN IsAccessible() const
XhciRegisters m_Registers
NTSTATUS PrepareOne(_Inout_ Interrupter *Entry, _In_ WDFINTERRUPT Interrupt, _In_ ULONG Index, _In_ BOOLEAN MessageSignaled)
XhciController * m_Controller
VOID ReleaseOne(_Inout_ Interrupter *Entry)
WDFINTERRUPT m_PrimaryInterrupt
NTSTATUS AffinitizeResourceRequirements(_In_ WDFIORESREQLIST Requirements)
NTSTATUS Create(_In_ XhciController *Controller)
NTSTATUS Prepare(_In_ WDFCMRESLIST Raw, _In_ WDFCMRESLIST Translated)
NTSTATUS FilterResourceRequirements(_In_ WDFIORESREQLIST Requirements)
VOID D0ExitPreInterruptsDisabled()
NTSTATUS CreateInterrupt(_In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw, _In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, _Out_ WDFINTERRUPT *Interrupt)
NTSTATUS D0Entry(_In_ BOOLEAN StatePreserved)
ULONG SecondaryCountFor(_In_ ULONG Messages) const
ULONG TargetForProcessor(_In_ ULONG ProcessorIndex) const
ULONG TargetForCurrentProcessor() const
ULONG MaxInterrupters() const
static BOOLEAN OnUntargetedTransferEvent(_In_ XhciController *Controller, _In_ const XHCI_TRB *Event)
_Inout_ HubConfiguration ** Slot
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
#define NT_SUCCESS(StatCode)
static const WCHAR Message[]
#define _IRQL_requires_(irql)
#define IsListEmpty(ListHead)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
#define KeInitializeEvent(pEvt, foo, foo2)
#define KeReleaseSpinLock(sl, irql)
#define KeSetEvent(pEvt, foo, foo2)
#define KeAcquireSpinLock(sl, irql)
#define InitializeListHead(ListHead)
#define KeInitializeSpinLock(sl)
VOID NTAPI KeClearEvent(IN PKEVENT Event)
WdfWorkItemEnqueue(WorkItem)
_In_opt_ PVOID _In_ PUCXHUB_WORKITEM WorkItem
#define XHCI_BUDGET_CHECK_EVENTS
static VOID NTAPI XhciDispatchEvent(_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
static BOOLEAN NTAPI XhciIsMessageRequirement(_In_ PIO_RESOURCE_DESCRIPTOR Descriptor)
ULONG(NTAPI * PFN_XHCI_CURRENT_NUMBER)(_Out_opt_ PPROCESSOR_NUMBER Number)
static VOID NTAPI XhciWriteDequeue(_In_ PXHCI_INTERRUPTER Entry, _In_ BOOLEAN ClearBusy)
static PFN_XHCI_INDEX_FROM_NUMBER XhciIndexFromNumberRoutine
#define XHCI_SEGMENTS_DEFAULT
static BOOLEAN NTAPI XhciDpcBudgetSpent(_Inout_ PBOOLEAN LimitsKnown, _Inout_ PULONG TimeLimit, _Inout_ PULONG WatchdogLimit)
XhciInterrupters::Interrupter * PXHCI_INTERRUPTER
static PXHCI_TRB NTAPI XhciDequeueTrb(_In_ PXHCI_INTERRUPTER Entry)
static BOOLEAN NTAPI XhciIsMessageResource(_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor)
IO_RESOURCE_DESCRIPTOR Trimmed
static VOID NTAPI XhciWriteInterrupter64(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG64 Value)
#define XHCI_SEGMENTS_RING_FULL
static VOID NTAPI XhciWriteInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG Value)
struct _XHCI_INTERRUPT_CONTEXT XHCI_INTERRUPT_CONTEXT
#define XHCI_REASON_EVENT_RING_FULL
static EVT_WDF_WORKITEM XhciEvtRequeueWorkItem
static ULONG NTAPI XhciProcessorIndex(_In_ USHORT Group, _In_ ULONG Number)
static ULONG NTAPI XhciActiveProcessors(_In_ USHORT Group)
static PFN_XHCI_ACTIVE_COUNT XhciActiveCountRoutine
static VOID NTAPI XhciRouteTransferEvent(_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
static VOID NTAPI XhciResetEventRing(_Inout_ PXHCI_INTERRUPTER Entry)
#define XHCI_HANDBACK_EVENTS
static VOID NTAPI XhciProgramEventRing(_In_ PXHCI_INTERRUPTER Entry)
#define XHCI_SEGMENTS_LIMITED
static EVT_WDF_INTERRUPT_DPC XhciEvtInterruptDpc
XhciInterrupters::Interrupter XHCI_INTERRUPTER
static EVT_WDF_INTERRUPT_DISABLE XhciEvtInterruptDisable
NTSTATUS(NTAPI * PFN_XHCI_DPC_WATCHDOG)(_Out_ PKDPC_WATCHDOG_INFORMATION Information)
static ULONG NTAPI XhciCurrentProcessorIndex(VOID)
PIO_RESOURCE_DESCRIPTOR Descriptor
struct _XHCI_INTERRUPT_CONTEXT * PXHCI_INTERRUPT_CONTEXT
static VOID NTAPI XhciAdvanceDequeue(_Inout_ PXHCI_INTERRUPTER Entry)
static ULONG NTAPI XhciReadInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset)
#define XHCI_DRAIN_WAIT_MS
ULONG(NTAPI * PFN_XHCI_INDEX_FROM_NUMBER)(_In_ PPROCESSOR_NUMBER Number)
static PFN_XHCI_DPC_WATCHDOG XhciDpcWatchdogRoutine
static EVT_WDF_INTERRUPT_ISR XhciEvtInterruptIsr
static VOID NTAPI XhciRequeueEvents(_Inout_ PXHCI_INTERRUPTER Entry)
static PFN_XHCI_CURRENT_NUMBER XhciCurrentNumberRoutine
static BOOLEAN NTAPI XhciEventPending(_In_ PXHCI_INTERRUPTER Entry, _In_ PXHCI_TRB Trb)
ULONG(NTAPI * PFN_XHCI_ACTIVE_COUNT)(_In_ USHORT GroupNumber)
_Out_ PULONG _Out_ PULONG Messages
#define XHCI_SECONDARY_MAX
static VOID NTAPI XhciUnmaskInterrupter(_In_ PXHCI_INTERRUPTER Entry)
static EVT_WDF_INTERRUPT_ENABLE XhciEvtInterruptEnable
NTKRNLVISTAAPI ULONG NTAPI KeQueryActiveProcessorCount(OUT PKAFFINITY ActiveProcessors OPTIONAL)
#define ExFreePoolWithTag(_P, _T)
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
#define CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN
#define CM_RESOURCE_INTERRUPT_POLICY_INCLUDED
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_BITS_OF(sizeOfArg)
#define UNREFERENCED_PARAMETER(P)
#define ALL_PROCESSOR_GROUPS
_In_ ULONG _In_ ULONG Offset
#define CM_RESOURCE_INTERRUPT_MESSAGE
#define CM_RESOURCE_INTERRUPT_LATCHED
#define CmResourceTypeInterrupt
@ IrqPolicySpecifiedProcessors
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
union _IO_RESOURCE_DESCRIPTOR::@2507 u
struct _IO_RESOURCE_DESCRIPTOR::@2507::@2510 Interrupt
struct _LIST_ENTRY * Flink
BOOLEAN AutomaticSerialization
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG Config
#define STATUS_UNSUCCESSFUL
#define STATUS_INSUFFICIENT_RESOURCES
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
for(Attempt=0;Attempt< UCX_LEGACY_NAME_ATTEMPTS;Attempt++)
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
_In_ WDFDEVICE AssociatedDevice
_In_ WDFOBJECT AssociatedObject
FORCEINLINE VOID WDF_INTERRUPT_CONFIG_INIT(_Out_ PWDF_INTERRUPT_CONFIG Configuration, _In_ PFN_WDF_INTERRUPT_ISR EvtInterruptIsr, _In_opt_ PFN_WDF_INTERRUPT_DPC EvtInterruptDpc)
FORCEINLINE BOOLEAN WdfInterruptQueueDpcForIsr(_In_ WDFINTERRUPT Interrupt)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
#define WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(_contexttype, _castingfunction)
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
_Must_inspect_result_ _In_ WDFCMRESLIST List
_In_ WDF_WMI_PROVIDER_CONTROL Control
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
#define IO_RESOURCE_ALTERNATIVE
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
RtlInitUnicodeString & RoutineName
struct _XHCI_ERST_ENTRY * PXHCI_ERST_ENTRY
#define XHCI_TRB_ENDPOINT_MASK
#define XHCI_TRANSFER_EVENT_ED
#define XHCI_IMOD_INTERVAL_50US
#define XHCI_INTERRUPTER_STRIDE
#define XHCI_TRB_ENDPOINT_SHIFT
#define XHCI_RUNTIME_INTERRUPTER_BASE
#define XHCI_IMAN_PENDING
@ DeviceNotificationEvent
@ VendorCommandCompletionEvent
#define XHCI_EVENT_DATA_TYPE_MASK
struct _XHCI_TRB XHCI_TRB
#define XHCI_ERDP_SEGMENT_MASK
FORCEINLINE ULONG NTAPI XhciTrbCompletionCode(_In_ const XHCI_TRB *Trb)
FORCEINLINE ULONG NTAPI XhciTrbSlotId(_In_ const XHCI_TRB *Trb)
FORCEINLINE LARGE_INTEGER NTAPI XhciRelativeMs(_In_ ULONG Milliseconds)
#define XHCI_TAG_INTERRUPTER