ReactOS 0.4.17-dev-1281-g065abb3
intr.cpp File Reference
#include "xhcidrv.h"
#include <debug.h>
Include dependency graph for intr.cpp:

Go to the source code of this file.

Classes

struct  _XHCI_INTERRUPT_CONTEXT
 

Macros

#define NDEBUG
 
#define XHCI_SECONDARY_MAX   16
 
#define XHCI_SEGMENTS_DEFAULT   4
 
#define XHCI_SEGMENTS_RING_FULL   8
 
#define XHCI_SEGMENTS_LIMITED   2
 
#define XHCI_BUDGET_CHECK_EVENTS   64
 
#define XHCI_HANDBACK_EVENTS   128
 
#define XHCI_REASON_EVENT_RING_FULL   0x1011
 
#define XHCI_DRAIN_WAIT_MS   60000
 

Typedefs

typedef XhciInterrupters::Interrupter XHCI_INTERRUPTER
 
typedef XhciInterrupters::Interrupter * PXHCI_INTERRUPTER
 
typedef struct _XHCI_INTERRUPT_CONTEXT XHCI_INTERRUPT_CONTEXT
 
typedef struct _XHCI_INTERRUPT_CONTEXT * PXHCI_INTERRUPT_CONTEXT
 
typedef ULONG(NTAPI * PFN_XHCI_ACTIVE_COUNT) (_In_ USHORT GroupNumber)
 
typedef ULONG(NTAPI * PFN_XHCI_INDEX_FROM_NUMBER) (_In_ PPROCESSOR_NUMBER Number)
 
typedef ULONG(NTAPI * PFN_XHCI_CURRENT_NUMBER) (_Out_opt_ PPROCESSOR_NUMBER Number)
 
typedef NTSTATUS(NTAPI * PFN_XHCI_DPC_WATCHDOG) (_Out_ PKDPC_WATCHDOG_INFORMATION Information)
 

Functions

 _IRQL_requires_ (PASSIVE_LEVEL) static PVOID NTAPI XhciFindKernelRoutine(_In_ PCWSTR Name)
 Sends a synchronous IOCTL to the specified device object.
 
static ULONG NTAPI XhciActiveProcessors (_In_ USHORT Group)
 
static ULONG NTAPI XhciProcessorIndex (_In_ USHORT Group, _In_ ULONG Number)
 
static ULONG NTAPI XhciCurrentProcessorIndex (VOID)
 
static ULONG NTAPI XhciReadInterrupter (_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset)
 
static VOID NTAPI XhciWriteInterrupter (_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG Value)
 
static VOID NTAPI XhciWriteInterrupter64 (_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG64 Value)
 
static VOID NTAPI XhciWriteDequeue (_In_ PXHCI_INTERRUPTER Entry, _In_ BOOLEAN ClearBusy)
 
static VOID NTAPI XhciResetEventRing (_Inout_ PXHCI_INTERRUPTER Entry)
 
static VOID NTAPI XhciProgramEventRing (_In_ PXHCI_INTERRUPTER Entry)
 
static VOID NTAPI XhciUnmaskInterrupter (_In_ PXHCI_INTERRUPTER Entry)
 
static BOOLEAN NTAPI XhciEvtInterruptIsr (_In_ WDFINTERRUPT Interrupt, _In_ ULONG MessageID)
 
static NTSTATUS NTAPI XhciEvtInterruptEnable (_In_ WDFINTERRUPT Interrupt, _In_ WDFDEVICE AssociatedDevice)
 
static NTSTATUS NTAPI XhciEvtInterruptDisable (_In_ WDFINTERRUPT Interrupt, _In_ WDFDEVICE AssociatedDevice)
 
static BOOLEAN NTAPI XhciDpcBudgetSpent (_Inout_ PBOOLEAN LimitsKnown, _Inout_ PULONG TimeLimit, _Inout_ PULONG WatchdogLimit)
 
static PXHCI_TRB NTAPI XhciDequeueTrb (_In_ PXHCI_INTERRUPTER Entry)
 
static BOOLEAN NTAPI XhciEventPending (_In_ PXHCI_INTERRUPTER Entry, _In_ PXHCI_TRB Trb)
 
static VOID NTAPI XhciAdvanceDequeue (_Inout_ PXHCI_INTERRUPTER Entry)
 
static VOID NTAPI XhciRouteTransferEvent (_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
 
static VOID NTAPI XhciDispatchEvent (_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
 
static VOID NTAPI XhciRequeueEvents (_Inout_ PXHCI_INTERRUPTER Entry)
 
static VOID NTAPI XhciEvtRequeueWorkItem (_In_ WDFWORKITEM WorkItem)
 
static VOID NTAPI XhciEvtInterruptDpc (_In_ WDFINTERRUPT Interrupt, _In_ WDFOBJECT AssociatedObject)
 
static BOOLEAN NTAPI XhciIsMessageRequirement (_In_ PIO_RESOURCE_DESCRIPTOR Descriptor)
 
static BOOLEAN NTAPI XhciIsMessageResource (_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor)
 
 for (Current=0;Current< Lists;Current++)
 
 while (Index< WdfIoResourceListGetCount(List))
 

Variables

static PFN_XHCI_ACTIVE_COUNT XhciActiveCountRoutine
 
static PFN_XHCI_INDEX_FROM_NUMBER XhciIndexFromNumberRoutine
 
static PFN_XHCI_CURRENT_NUMBER XhciCurrentNumberRoutine
 
static PFN_XHCI_DPC_WATCHDOG XhciDpcWatchdogRoutine
 
static EVT_WDF_INTERRUPT_ISR XhciEvtInterruptIsr
 
static EVT_WDF_INTERRUPT_DPC XhciEvtInterruptDpc
 
static EVT_WDF_INTERRUPT_ENABLE XhciEvtInterruptEnable
 
static EVT_WDF_INTERRUPT_DISABLE XhciEvtInterruptDisable
 
static EVT_WDF_WORKITEM XhciEvtRequeueWorkItem
 
_Out_ PULONG ListIndex = 0
 
_Out_ PULONG _Out_ PULONG Messages
 
PIO_RESOURCE_DESCRIPTOR Descriptor
 
ULONG Lists = WdfIoResourceRequirementsListGetCount(Requirements)
 
ULONG Current
 
ULONG Index = 0
 
ULONG Count
 
ULONG Descriptors
 
BOOLEAN MsiX
 
BOOLEAN BestMsiX = FALSE
 
_In_ ULONG Wanted
 
IO_RESOURCE_DESCRIPTOR Trimmed
 
ULONG Offered
 
ULONG Claim
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 10 of file intr.cpp.

◆ XHCI_BUDGET_CHECK_EVENTS

#define XHCI_BUDGET_CHECK_EVENTS   64

Definition at line 27 of file intr.cpp.

◆ XHCI_DRAIN_WAIT_MS

#define XHCI_DRAIN_WAIT_MS   60000

Definition at line 30 of file intr.cpp.

◆ XHCI_HANDBACK_EVENTS

#define XHCI_HANDBACK_EVENTS   128

Definition at line 28 of file intr.cpp.

◆ XHCI_REASON_EVENT_RING_FULL

#define XHCI_REASON_EVENT_RING_FULL   0x1011

Definition at line 29 of file intr.cpp.

◆ XHCI_SECONDARY_MAX

#define XHCI_SECONDARY_MAX   16

Definition at line 23 of file intr.cpp.

◆ XHCI_SEGMENTS_DEFAULT

#define XHCI_SEGMENTS_DEFAULT   4

Definition at line 24 of file intr.cpp.

◆ XHCI_SEGMENTS_LIMITED

#define XHCI_SEGMENTS_LIMITED   2

Definition at line 26 of file intr.cpp.

◆ XHCI_SEGMENTS_RING_FULL

#define XHCI_SEGMENTS_RING_FULL   8

Definition at line 25 of file intr.cpp.

Typedef Documentation

◆ PFN_XHCI_ACTIVE_COUNT

typedef ULONG(NTAPI * PFN_XHCI_ACTIVE_COUNT) (_In_ USHORT GroupNumber)

Definition at line 33 of file intr.cpp.

◆ PFN_XHCI_CURRENT_NUMBER

typedef ULONG(NTAPI * PFN_XHCI_CURRENT_NUMBER) (_Out_opt_ PPROCESSOR_NUMBER Number)

Definition at line 35 of file intr.cpp.

◆ PFN_XHCI_DPC_WATCHDOG

typedef NTSTATUS(NTAPI * PFN_XHCI_DPC_WATCHDOG) (_Out_ PKDPC_WATCHDOG_INFORMATION Information)

Definition at line 36 of file intr.cpp.

◆ PFN_XHCI_INDEX_FROM_NUMBER

typedef ULONG(NTAPI * PFN_XHCI_INDEX_FROM_NUMBER) (_In_ PPROCESSOR_NUMBER Number)

Definition at line 34 of file intr.cpp.

◆ PXHCI_INTERRUPT_CONTEXT

◆ PXHCI_INTERRUPTER

Definition at line 13 of file intr.cpp.

◆ XHCI_INTERRUPT_CONTEXT

◆ XHCI_INTERRUPTER

Definition at line 13 of file intr.cpp.

Function Documentation

◆ _IRQL_requires_()

_IRQL_requires_ ( PASSIVE_LEVEL  )

Sends a synchronous IOCTL to the specified device object.

Drops every MSI descriptor and keeps only lists that still offer a line interrupt.

Picks the list with the best MSI offer: MSI-X first, then the most messages.

Keeps message descriptors covering Wanted messages and removes the others.

Definition at line 51 of file intr.cpp.

57{
59
62}
LPWSTR Name
Definition: desk.c:124
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3672
RtlInitUnicodeString & RoutineName
Definition: xhcientry.cpp:59

◆ for()

for ( )

Definition at line 739 of file intr.cpp.

740 {
741 List = WdfIoResourceRequirementsListGetIoResList(Requirements, Current);
742 Count = 0;
743 Descriptors = 0;
744
745 for (Index = 0; Index < WdfIoResourceListGetCount(List); Index++)
746 {
747 Descriptor = WdfIoResourceListGetDescriptor(List, Index);
749 continue;
750
751 Descriptors++;
752 Count += Descriptor->u.Interrupt.MaximumVector - Descriptor->u.Interrupt.MinimumVector + 1;
753 }
754
755 /* MSI-X lists carry one descriptor per message, MSI a single ranged one */
756 MsiX = (Descriptors > 1);
757
758 if (MsiX && (!BestMsiX || Count > *Messages))
759 {
760 BestMsiX = TRUE;
762 *Messages = Count;
763 }
764 else if (!MsiX && !BestMsiX && Count > *Messages)
765 {
767 *Messages = Count;
768 }
769 }
#define TRUE
Definition: types.h:120
static BOOLEAN NTAPI XhciIsMessageRequirement(_In_ PIO_RESOURCE_DESCRIPTOR Descriptor)
Definition: intr.cpp:630
ULONG Current
Definition: intr.cpp:728
BOOLEAN MsiX
Definition: intr.cpp:732
BOOLEAN BestMsiX
Definition: intr.cpp:733
_Out_ PULONG ListIndex
Definition: intr.cpp:722
ULONG Descriptors
Definition: intr.cpp:731
ULONG Count
Definition: intr.cpp:730
_Out_ PULONG _Out_ PULONG Messages
Definition: intr.cpp:724
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define IO_RESOURCE_ALTERNATIVE

◆ while()

while ( )

Definition at line 789 of file intr.cpp.

790 {
791 Descriptor = WdfIoResourceListGetDescriptor(List, Index);
793 {
794 Index++;
795 continue;
796 }
797
798 if (Wanted == 0)
799 {
800 WdfIoResourceListRemove(List, Index);
801 continue;
802 }
803
804 Offered = Descriptor->u.Interrupt.MaximumVector - Descriptor->u.Interrupt.MinimumVector + 1;
805 if (Offered <= Wanted)
806 {
807 Wanted -= Offered;
808 Index++;
809 continue;
810 }
811
812 /* Multi message MSI grants powers of two only */
813 Claim = 1;
814 while (Claim < Wanted)
815 Claim <<= 1;
816
820 WdfIoResourceListUpdateDescriptor(List, &Trimmed, Index);
821
822 DPRINT("Message descriptor %lu trimmed to %lu messages\n", Index, Claim);
823 Wanted = 0;
824 Index++;
825 }
ULONG Offered
Definition: intr.cpp:786
IO_RESOURCE_DESCRIPTOR Trimmed
Definition: intr.cpp:784
PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: intr.cpp:726
ULONG Claim
Definition: intr.cpp:787
_In_ ULONG Wanted
Definition: intr.cpp:782
#define CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN
Definition: cmtypes.h:167
#define DPRINT
Definition: sndvol32.h:73
union _IO_RESOURCE_DESCRIPTOR::@2507 u
struct _IO_RESOURCE_DESCRIPTOR::@2507::@2510 Interrupt

◆ XhciActiveProcessors()

static ULONG NTAPI XhciActiveProcessors ( _In_ USHORT  Group)
static

Definition at line 67 of file intr.cpp.

69{
72
74}
@ Group
Definition: help.c:22
#define NULL
Definition: types.h:112
static PFN_XHCI_ACTIVE_COUNT XhciActiveCountRoutine
Definition: intr.cpp:38
NTKRNLVISTAAPI ULONG NTAPI KeQueryActiveProcessorCount(OUT PKAFFINITY ActiveProcessors OPTIONAL)
Definition: ke.c:15

Referenced by XhciInterrupters::AffinitizeResourceRequirements(), XhciInterrupters::BuildLookup(), and XhciInterrupters::SecondaryCountFor().

◆ XhciAdvanceDequeue()

static VOID NTAPI XhciAdvanceDequeue ( _Inout_ PXHCI_INTERRUPTER  Entry)
static

Definition at line 366 of file intr.cpp.

368{
369 Entry->DequeueIndex++;
370 if (Entry->DequeueIndex < Entry->TrbsPerSegment)
371 return;
372
373 Entry->DequeueIndex = 0;
374 Entry->DequeueSegment++;
375
376 if (Entry->DequeueSegment < Entry->SegmentCount)
377 {
378 Entry->Segment = CONTAINING_RECORD(Entry->Segment->Link.Flink, XhciDmaBuffer, Link);
379 return;
380 }
381
382 /* Wrapped past the last ERST entry: the producer toggled its cycle state too */
383 Entry->DequeueSegment = 0;
384 Entry->CycleState ^= XHCI_TRB_CYCLE;
385 Entry->Segment = CONTAINING_RECORD(Entry->SegmentList.Flink, XhciDmaBuffer, Link);
386}
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define XHCI_TRB_CYCLE
Definition: xhcihw.h:22

Referenced by XhciEvtInterruptDpc().

◆ XhciCurrentProcessorIndex()

static ULONG NTAPI XhciCurrentProcessorIndex ( VOID  )
static

Definition at line 108 of file intr.cpp.

109{
112
113 /* Single group kernels: the number is the index */
115}
static PFN_XHCI_CURRENT_NUMBER XhciCurrentNumberRoutine
Definition: intr.cpp:40
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341

Referenced by XhciInterrupters::TargetForCurrentProcessor().

◆ XhciDequeueTrb()

static PXHCI_TRB NTAPI XhciDequeueTrb ( _In_ PXHCI_INTERRUPTER  Entry)
static

Definition at line 344 of file intr.cpp.

346{
347 return (PXHCI_TRB)Entry->Segment->VirtualAddress + Entry->DequeueIndex;
348}

Referenced by XhciEvtInterruptDpc().

◆ XhciDispatchEvent()

static VOID NTAPI XhciDispatchEvent ( _In_ PXHCI_INTERRUPTER  Entry,
_Inout_ PXHCI_TRB  Event 
)
static

Definition at line 434 of file intr.cpp.

437{
438 XhciController* Controller = Entry->Controller;
441
442 if (Code == static_cast<ULONG>(XhciCompletionCode::VendorQuirk199) &&
444 {
445 DPRINT1("Dropping event type %lu with vendor completion code 199\n", Type);
446 return;
447 }
448
449 if (Type == static_cast<ULONG>(XhciTrbType::TransferEvent))
450 {
452 return;
453 }
454
455 if (Type == static_cast<ULONG>(XhciTrbType::HostControllerEvent) &&
457 {
458 Entry->RingFullCount++;
459 DPRINT1("Interrupter %lu event ring full (%lu times)\n", Entry->Index, Entry->RingFullCount);
460
463 return;
464 }
465
466 /* Only transfer events are targeted at secondary interrupters */
467 if (Entry->Index != 0)
468 {
469 DPRINT1("Event type %lu on secondary interrupter %lu, dropped\n", Type, Entry->Index);
470 return;
471 }
472
473 switch (Type)
474 {
477 Controller->m_Commands.OnCompletionEvent(Event);
478 break;
479
480 case static_cast<ULONG>(XhciTrbType::PortStatusChangeEvent):
481 Controller->m_RootHub.OnPortStatusChangeEvent(Event);
482 break;
483
485 if (Controller->m_Slots.LookupSlot(XhciTrbSlotId(Event)) != NULL)
486 Controller->m_Slots.OnDeviceNotificationEvent(Event);
487 break;
488
489 case static_cast<ULONG>(XhciTrbType::HostControllerEvent):
490 DPRINT1("Host controller event with completion code %lu\n", Code);
491 break;
492
493 case static_cast<ULONG>(XhciTrbType::MfindexWrapEvent):
494 /* USBCMD.EWE is never set, so the controller should not send these */
495 DPRINT1("Unexpected MFINDEX wrap event\n");
496 break;
497
498 default:
499 DPRINT1("Unknown event type %lu (code %lu), dropped\n", Type, Code);
500 break;
501 }
502}
Type
Definition: Type.h:7
#define DPRINT1
Definition: precomp.h:8
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define XHCI_REASON_EVENT_RING_FULL
Definition: intr.cpp:29
static VOID NTAPI XhciRouteTransferEvent(_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
Definition: intr.cpp:391
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1707
@ EvtDropVendorCode199
@ EvtResetOnRingOverflow
XhciTrbType
Definition: xhcihw.h:68
@ DeviceNotificationEvent
@ CommandCompletionEvent
@ PortStatusChangeEvent
@ VendorCommandCompletionEvent
FORCEINLINE ULONG NTAPI XhciTrbCompletionCode(_In_ const XHCI_TRB *Trb)
Definition: xhcihw.h:42
FORCEINLINE ULONG NTAPI XhciTrbSlotId(_In_ const XHCI_TRB *Trb)
Definition: xhcihw.h:51

Referenced by XhciEvtInterruptDpc().

◆ XhciDpcBudgetSpent()

static BOOLEAN NTAPI XhciDpcBudgetSpent ( _Inout_ PBOOLEAN  LimitsKnown,
_Inout_ PULONG  TimeLimit,
_Inout_ PULONG  WatchdogLimit 
)
static

Remaining DPC budget check. Limits are computed on the first successful query.

Definition at line 313 of file intr.cpp.

317{
319
320 /* ReactOS may not export it; the DPC then never yields */
322 return FALSE;
323
324 if (!NT_SUCCESS(XhciDpcWatchdogRoutine(&Watchdog)))
325 return FALSE;
326
327 if (!*LimitsKnown)
328 {
329 *TimeLimit = (Watchdog.DpcTimeLimit * 95) / 100;
330 *WatchdogLimit = (Watchdog.DpcWatchdogLimit * 25) / 100;
331 *LimitsKnown = TRUE;
332 }
333
334 /* The counts are ticks left, so this yields early on purpose */
335 if (Watchdog.DpcTimeCount < *TimeLimit)
336 return TRUE;
337
338 return (Watchdog.DpcWatchdogCount < *WatchdogLimit);
339}
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static PFN_XHCI_DPC_WATCHDOG XhciDpcWatchdogRoutine
Definition: intr.cpp:41

Referenced by XhciEvtInterruptDpc().

◆ XhciEventPending()

static BOOLEAN NTAPI XhciEventPending ( _In_ PXHCI_INTERRUPTER  Entry,
_In_ PXHCI_TRB  Trb 
)
static

Definition at line 353 of file intr.cpp.

356{
358
359 Control = *(volatile ULONG*)&Trb->Dword[3];
360 return (Control & XHCI_TRB_CYCLE) == Entry->CycleState;
361}
return
Definition: dirsup.c:529
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166

Referenced by XhciEvtInterruptDpc().

◆ XhciEvtInterruptDisable()

static NTSTATUS NTAPI XhciEvtInterruptDisable ( _In_ WDFINTERRUPT  Interrupt,
_In_ WDFDEVICE  AssociatedDevice 
)
static

Definition at line 287 of file intr.cpp.

290{
292 ULONG Iman;
293
295
296 Entry = XhciInterruptContext(Interrupt)->Entry;
297 if (Entry == NULL)
298 return STATUS_SUCCESS;
299
300 Entry->Enabled = FALSE;
301
304 return STATUS_SUCCESS;
305}
static VOID NTAPI XhciWriteInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG Value)
Definition: intr.cpp:138
static ULONG NTAPI XhciReadInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset)
Definition: intr.cpp:128
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define STATUS_SUCCESS
Definition: shellext.h:65
_In_ WDFDEVICE AssociatedDevice
Definition: wdfinterrupt.h:173
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
#define XHCI_IMAN_ENABLE
Definition: xhcihw.h:160
#define XHCI_IMAN
Definition: xhcihw.h:153

◆ XhciEvtInterruptDpc()

static VOID NTAPI XhciEvtInterruptDpc ( _In_ WDFINTERRUPT  Interrupt,
_In_ WDFOBJECT  AssociatedObject 
)
static

Definition at line 563 of file intr.cpp.

566{
568 PXHCI_TRB Trb;
570 ULONG Processed;
571 BOOLEAN LimitsKnown = FALSE;
572 ULONG TimeLimit = 0;
573 ULONG WatchdogLimit = 0;
574
576
577 Entry = XhciInterruptContext(Interrupt)->Entry;
578 if (Entry == NULL)
579 return;
580
581 /* A second DPC or a pending requeue already owns the ring */
583 if (Entry->DpcRunning)
584 {
586 return;
587 }
588 Entry->DpcRunning = TRUE;
590
591 Trb = XhciDequeueTrb(Entry);
592 for (Processed = 0; XhciEventPending(Entry, Trb); Processed++)
593 {
594 if ((Processed % XHCI_BUDGET_CHECK_EVENTS) == 0 &&
595 XhciDpcBudgetSpent(&LimitsKnown, &TimeLimit, &WatchdogLimit))
596 {
599 return;
600 }
601
602 /* Copy only after the cycle bit said the TRB is complete */
603 RtlCopyMemory(&Event, Trb, sizeof(Event));
606
607 Trb = XhciDequeueTrb(Entry);
608
609 /* Give consumed TRBs back early on long bursts; EHB stays set */
610 if (Processed != 0 &&
611 (Processed % XHCI_HANDBACK_EVENTS) == 0 &&
613 {
615 }
616 }
617
618 /* Written even when nothing was consumed, so a spurious interrupt still clears EHB */
620 Entry->DpcRunning = FALSE;
623}
unsigned char BOOLEAN
Definition: actypes.h:127
#define XHCI_BUDGET_CHECK_EVENTS
Definition: intr.cpp:27
static VOID NTAPI XhciDispatchEvent(_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
Definition: intr.cpp:434
static VOID NTAPI XhciWriteDequeue(_In_ PXHCI_INTERRUPTER Entry, _In_ BOOLEAN ClearBusy)
Definition: intr.cpp:161
static BOOLEAN NTAPI XhciDpcBudgetSpent(_Inout_ PBOOLEAN LimitsKnown, _Inout_ PULONG TimeLimit, _Inout_ PULONG WatchdogLimit)
Definition: intr.cpp:313
static PXHCI_TRB NTAPI XhciDequeueTrb(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:344
#define XHCI_HANDBACK_EVENTS
Definition: intr.cpp:28
static VOID NTAPI XhciAdvanceDequeue(_Inout_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:366
static VOID NTAPI XhciRequeueEvents(_Inout_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:508
static BOOLEAN NTAPI XhciEventPending(_In_ PXHCI_INTERRUPTER Entry, _In_ PXHCI_TRB Trb)
Definition: intr.cpp:353
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_In_ WDFOBJECT AssociatedObject
Definition: wdfinterrupt.h:132

◆ XhciEvtInterruptEnable()

static NTSTATUS NTAPI XhciEvtInterruptEnable ( _In_ WDFINTERRUPT  Interrupt,
_In_ WDFDEVICE  AssociatedDevice 
)
static

Definition at line 262 of file intr.cpp.

265{
267
269
270 Entry = XhciInterruptContext(Interrupt)->Entry;
271 if (Entry == NULL)
272 return STATUS_SUCCESS;
273
274 Entry->Enabled = TRUE;
275 Entry->PendingDisable = FALSE;
276
277 /* Drop a stale DpcRunning left by a requeue skipped at D0 exit */
278 Entry->DpcRunning = FALSE;
279
281 return STATUS_SUCCESS;
282}
static VOID NTAPI XhciUnmaskInterrupter(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:217

◆ XhciEvtInterruptIsr()

static BOOLEAN NTAPI XhciEvtInterruptIsr ( _In_ WDFINTERRUPT  Interrupt,
_In_ ULONG  MessageID 
)
static

Definition at line 234 of file intr.cpp.

237{
239 ULONG Iman;
240
241 Entry = XhciInterruptContext(Interrupt)->Entry;
242 if (Entry == NULL)
243 return FALSE;
244
245 /* A shared line needs IMAN to tell whether this controller raised it */
246 if (MessageID == 0 && !Entry->MessageSignaled)
247 {
249 if ((Iman & XHCI_IMAN_PENDING) == 0)
250 return FALSE;
251
253 }
254
256 return TRUE;
257}
_In_ ULONG MessageID
Definition: wdfinterrupt.h:92
FORCEINLINE BOOLEAN WdfInterruptQueueDpcForIsr(_In_ WDFINTERRUPT Interrupt)
Definition: wdfinterrupt.h:414
#define XHCI_IMAN_PENDING
Definition: xhcihw.h:159

◆ XhciEvtRequeueWorkItem()

static VOID NTAPI XhciEvtRequeueWorkItem ( _In_ WDFWORKITEM  WorkItem)
static

Definition at line 542 of file intr.cpp.

544{
545 WDFINTERRUPT Interrupt;
548
549 Interrupt = (WDFINTERRUPT)WdfWorkItemGetParentObject(WorkItem);
550 Entry = XhciInterruptContext(Interrupt)->Entry;
551
553 Entry->DpcRunning = FALSE;
554 KeSetEvent(&Entry->RequeueIdle, IO_NO_INCREMENT, FALSE);
556
558}
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
_In_opt_ PVOID _In_ PUCXHUB_WORKITEM WorkItem
Definition: hubucx.h:227
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

◆ XhciIsMessageRequirement()

static BOOLEAN NTAPI XhciIsMessageRequirement ( _In_ PIO_RESOURCE_DESCRIPTOR  Descriptor)
static

Definition at line 630 of file intr.cpp.

632{
634
635 return Descriptor->Type == CmResourceTypeInterrupt &&
636 (Descriptor->Flags & MessageFlags) == MessageFlags;
637}
unsigned short USHORT
Definition: pedump.c:61
#define CM_RESOURCE_INTERRUPT_MESSAGE
Definition: restypes.h:118
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: restypes.h:117
#define CmResourceTypeInterrupt
Definition: restypes.h:105

Referenced by XhciInterrupters::AffinitizeResourceRequirements(), for(), and while().

◆ XhciIsMessageResource()

static BOOLEAN NTAPI XhciIsMessageResource ( _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  Descriptor)
static

Definition at line 642 of file intr.cpp.

644{
646
647 return Descriptor->Type == CmResourceTypeInterrupt &&
648 (Descriptor->Flags & MessageFlags) == MessageFlags;
649}

Referenced by XhciInterrupters::Prepare().

◆ XhciProcessorIndex()

static ULONG NTAPI XhciProcessorIndex ( _In_ USHORT  Group,
_In_ ULONG  Number 
)
static

Definition at line 79 of file intr.cpp.

82{
84
86 {
88 Processor.Group = Group;
89 Processor.Number = (UCHAR)Number;
91 }
92
93 /* Without group support only group 0 exists and the index is the number */
94 return (Group == 0) ? Number : MAXULONG;
95}
static PFN_XHCI_INDEX_FROM_NUMBER XhciIndexFromNumberRoutine
Definition: intr.cpp:39
_In_ ULONG Number
Definition: haltypes.h:1940
PROCESSOR_NUMBER
Definition: ntbasedef.h:654
#define MAXULONG
Definition: typedefs.h:251
unsigned char UCHAR
Definition: typedefs.h:53
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_In_ UCHAR Processor
Definition: kefuncs.h:670

Referenced by XhciInterrupters::BuildLookup().

◆ XhciProgramEventRing()

static VOID NTAPI XhciProgramEventRing ( _In_ PXHCI_INTERRUPTER  Entry)
static

ERSTSZ, ERDP, then ERSTBA, which arms the event ring (xHCI 4.9.4).

Definition at line 206 of file intr.cpp.

208{
211 XhciWriteInterrupter64(Entry, XHCI_ERSTBA, (ULONG64)Entry->Erst->LogicalAddress.QuadPart);
212}
static VOID NTAPI XhciWriteInterrupter64(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG64 Value)
Definition: intr.cpp:149
unsigned __int64 ULONG64
Definition: imports.h:198
#define XHCI_ERSTSZ
Definition: xhcihw.h:155
#define XHCI_ERSTBA
Definition: xhcihw.h:156

Referenced by XhciInterrupters::D0Entry(), and XhciInterrupters::PostReset().

◆ XhciReadInterrupter()

static ULONG NTAPI XhciReadInterrupter ( _In_ PXHCI_INTERRUPTER  Entry,
_In_ ULONG  Offset 
)
static

Definition at line 128 of file intr.cpp.

131{
132 return Entry->Controller->m_Registers.ReadRuntime32(Entry->RegisterOffset + Offset);
133}
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101

Referenced by XhciEvtInterruptDisable(), XhciEvtInterruptIsr(), and XhciUnmaskInterrupter().

◆ XhciRequeueEvents()

static VOID NTAPI XhciRequeueEvents ( _Inout_ PXHCI_INTERRUPTER  Entry)
static

Hands the rest of the ring to a later DPC. EHB stays set, so no interrupt arrives meanwhile.

Definition at line 508 of file intr.cpp.

510{
512
513 /* D0 exit is draining: leave the rest for the next D0 entry */
514 if (Entry->PendingDisable)
515 {
517 DPRINT("Interrupter %lu requeue skipped, disable pending\n", Entry->Index);
518 return;
519 }
520
521 KeClearEvent(&Entry->RequeueIdle);
523
524 /* Requeue is NULL if creation failed or it was already torn down */
525 if (Entry->Requeue != NULL)
526 {
527 WdfWorkItemEnqueue(Entry->Requeue);
528 return;
529 }
530
532 Entry->DpcRunning = FALSE;
533 KeSetEvent(&Entry->RequeueIdle, IO_NO_INCREMENT, FALSE);
535
537}
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
WdfWorkItemEnqueue(WorkItem)

Referenced by XhciEvtInterruptDpc().

◆ XhciResetEventRing()

static VOID NTAPI XhciResetEventRing ( _Inout_ PXHCI_INTERRUPTER  Entry)
static

Zeroes the event ring and puts the consumer back at the start (xHC halted).

Definition at line 181 of file intr.cpp.

183{
186
187 for (Link = Entry->SegmentList.Flink; Link != &Entry->SegmentList; Link = Link->Flink)
188 {
190 RtlZeroMemory(Buffer->VirtualAddress, Entry->SegmentSize);
191 }
192
193 Entry->Segment = CONTAINING_RECORD(Entry->SegmentList.Flink, XhciDmaBuffer, Link);
194 Entry->CycleState = XHCI_TRB_CYCLE;
195 Entry->DequeueIndex = 0;
196 Entry->DequeueSegment = 0;
197
198 /* A requeue skipped at D0 exit can leave this set */
199 Entry->DpcRunning = FALSE;
200}
Definition: bufpool.h:45
Definition: typedefs.h:120

Referenced by XhciInterrupters::D0Entry(), and XhciInterrupters::PostReset().

◆ XhciRouteTransferEvent()

static VOID NTAPI XhciRouteTransferEvent ( _In_ PXHCI_INTERRUPTER  Entry,
_Inout_ PXHCI_TRB  Event 
)
static

Definition at line 391 of file intr.cpp.

394{
395 XhciController* Controller = Entry->Controller;
398 BOOLEAN Direct;
399
400 if ((Event->Dword[3] & XHCI_TRANSFER_EVENT_ED) &&
402 (Code == static_cast<ULONG>(XhciCompletionCode::RingUnderrun) ||
404 {
405 /* These parts report ring empty with ED set and a zero pointer */
406 Event->Dword[3] &= ~XHCI_TRANSFER_EVENT_ED;
407 }
408
410 Direct = (Event->Dword[3] & XHCI_TRANSFER_EVENT_ED) &&
411 !Isoch &&
413
414 /* The transfer ring takes it straight away unless it has to go through the endpoint */
416 return;
417
418 if (Controller->m_Slots.LookupSlot(XhciTrbSlotId(Event)) == NULL)
419 {
420 if (!Isoch)
421 {
422 DPRINT1("Transfer event for slot %lu endpoint %lu has no device, dropped\n",
424 }
425 return;
426 }
427
428 Controller->m_Slots.OnTransferEvent(Event);
429}
static BOOLEAN OnUntargetedTransferEvent(_In_ XhciController *Controller, _In_ const XHCI_TRB *Event)
Definition: xferring.cpp:803
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
@ IsochStarveEventNoEd
@ EvtCheckTrbAddress
#define XHCI_TRB_ENDPOINT_MASK
Definition: xhcihw.h:27
#define XHCI_TRANSFER_EVENT_ED
Definition: xhcihw.h:321
#define XHCI_TRB_ENDPOINT_SHIFT
Definition: xhcihw.h:26
#define XHCI_EVENT_DATA_TYPE_MASK
Definition: xhcihw.h:324

Referenced by XhciDispatchEvent().

◆ XhciUnmaskInterrupter()

static VOID NTAPI XhciUnmaskInterrupter ( _In_ PXHCI_INTERRUPTER  Entry)
static

Definition at line 217 of file intr.cpp.

219{
220 ULONG Iman;
221
223
224 /* IP is write one to clear, so writing back what was read also drops a stale IP */
227}
#define XHCI_IMOD_INTERVAL_50US
Definition: xhcihw.h:330
#define XHCI_IMOD
Definition: xhcihw.h:154

Referenced by XhciInterrupters::PostReset(), and XhciEvtInterruptEnable().

◆ XhciWriteDequeue()

static VOID NTAPI XhciWriteDequeue ( _In_ PXHCI_INTERRUPTER  Entry,
_In_ BOOLEAN  ClearBusy 
)
static

Writes ERDP from the software dequeue position; ClearBusy also writes EHB to clear it.

Definition at line 161 of file intr.cpp.

164{
166
167 Value = (ULONG64)Entry->Segment->LogicalAddress.QuadPart +
168 (ULONG64)Entry->DequeueIndex * sizeof(XHCI_TRB);
169 Value |= Entry->DequeueSegment & XHCI_ERDP_SEGMENT_MASK;
170
171 if (ClearBusy)
173
175}
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define XHCI_ERDP_BUSY
Definition: xhcihw.h:161
struct _XHCI_TRB XHCI_TRB
#define XHCI_ERDP
Definition: xhcihw.h:157
#define XHCI_ERDP_SEGMENT_MASK
Definition: xhcihw.h:327

Referenced by XhciEvtInterruptDpc(), and XhciProgramEventRing().

◆ XhciWriteInterrupter()

static VOID NTAPI XhciWriteInterrupter ( _In_ PXHCI_INTERRUPTER  Entry,
_In_ ULONG  Offset,
_In_ ULONG  Value 
)
static

Definition at line 138 of file intr.cpp.

142{
143 Entry->Controller->m_Registers.WriteRuntime32(Entry->RegisterOffset + Offset, Value);
144}

Referenced by XhciInterrupters::PrepareOne(), XhciInterrupters::ReleaseOne(), XhciEvtInterruptDisable(), XhciEvtInterruptIsr(), XhciProgramEventRing(), and XhciUnmaskInterrupter().

◆ XhciWriteInterrupter64()

static VOID NTAPI XhciWriteInterrupter64 ( _In_ PXHCI_INTERRUPTER  Entry,
_In_ ULONG  Offset,
_In_ ULONG64  Value 
)
static

Definition at line 149 of file intr.cpp.

153{
154 Entry->Controller->m_Registers.WriteRuntime64(Entry->RegisterOffset + Offset, Value);
155}

Referenced by XhciInterrupters::ReleaseOne(), XhciProgramEventRing(), and XhciWriteDequeue().

Variable Documentation

◆ BestMsiX

return BestMsiX = FALSE

Definition at line 733 of file intr.cpp.

Referenced by for().

◆ Claim

ULONG Claim

Definition at line 787 of file intr.cpp.

Referenced by while().

◆ Count

ULONG Count

Definition at line 730 of file intr.cpp.

Referenced by for().

◆ Current

ULONG Current

Definition at line 728 of file intr.cpp.

Referenced by for().

◆ Descriptor

Definition at line 726 of file intr.cpp.

Referenced by while().

◆ Descriptors

◆ Index

ULONG Index = 0

Definition at line 729 of file intr.cpp.

◆ ListIndex

◆ Lists

Lists = WdfIoResourceRequirementsListGetCount(Requirements)

Definition at line 727 of file intr.cpp.

◆ Messages

◆ MsiX

BOOLEAN MsiX

Definition at line 732 of file intr.cpp.

Referenced by for().

◆ Offered

ULONG Offered

Definition at line 786 of file intr.cpp.

Referenced by while().

◆ Trimmed

Definition at line 784 of file intr.cpp.

Referenced by MmWorkingSetManager(), and while().

◆ Wanted

◆ XhciActiveCountRoutine

PFN_XHCI_ACTIVE_COUNT XhciActiveCountRoutine
static

Definition at line 38 of file intr.cpp.

Referenced by XhciInterrupters::Create(), and XhciActiveProcessors().

◆ XhciCurrentNumberRoutine

PFN_XHCI_CURRENT_NUMBER XhciCurrentNumberRoutine
static

Definition at line 40 of file intr.cpp.

Referenced by XhciInterrupters::Create(), and XhciCurrentProcessorIndex().

◆ XhciDpcWatchdogRoutine

PFN_XHCI_DPC_WATCHDOG XhciDpcWatchdogRoutine
static

Definition at line 41 of file intr.cpp.

Referenced by XhciInterrupters::Create(), and XhciDpcBudgetSpent().

◆ XhciEvtInterruptDisable

EVT_WDF_INTERRUPT_DISABLE XhciEvtInterruptDisable
static

Definition at line 46 of file intr.cpp.

Referenced by XhciInterrupters::CreateInterrupt().

◆ XhciEvtInterruptDpc

EVT_WDF_INTERRUPT_DPC XhciEvtInterruptDpc
static

Definition at line 44 of file intr.cpp.

Referenced by XhciInterrupters::CreateInterrupt().

◆ XhciEvtInterruptEnable

EVT_WDF_INTERRUPT_ENABLE XhciEvtInterruptEnable
static

Definition at line 45 of file intr.cpp.

Referenced by XhciInterrupters::CreateInterrupt().

◆ XhciEvtInterruptIsr

EVT_WDF_INTERRUPT_ISR XhciEvtInterruptIsr
static

Definition at line 43 of file intr.cpp.

Referenced by XhciInterrupters::CreateInterrupt().

◆ XhciEvtRequeueWorkItem

EVT_WDF_WORKITEM XhciEvtRequeueWorkItem
static

Definition at line 47 of file intr.cpp.

Referenced by XhciInterrupters::PrepareOne().

◆ XhciIndexFromNumberRoutine

PFN_XHCI_INDEX_FROM_NUMBER XhciIndexFromNumberRoutine
static

Definition at line 39 of file intr.cpp.

Referenced by XhciInterrupters::Create(), and XhciProcessorIndex().