ReactOS 0.4.17-dev-1281-g065abb3
intr.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS xHCI Host Controller Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Interrupt resources, event rings and event dispatch
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "xhcidrv.h"
9
10#define NDEBUG
11#include <debug.h>
12
14
16{
19
21
22/* Hard limits */
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
31
32/* Group aware processor routines are not exported by every kernel; resolved once */
37
42
43static EVT_WDF_INTERRUPT_ISR XhciEvtInterruptIsr;
44static EVT_WDF_INTERRUPT_DPC XhciEvtInterruptDpc;
45static EVT_WDF_INTERRUPT_ENABLE XhciEvtInterruptEnable;
46static EVT_WDF_INTERRUPT_DISABLE XhciEvtInterruptDisable;
47static EVT_WDF_WORKITEM XhciEvtRequeueWorkItem;
48
49/* Processor helpers **********************************************************/
50
52static
55XhciFindKernelRoutine(
57{
59
62}
63
64static
69{
72
74}
75
76static
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}
96
97#if defined(__GNUC__)
98#pragma GCC diagnostic push
99#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
100#elif defined(_MSC_VER)
101#pragma warning(push)
102#pragma warning(disable:4996)
103#endif
104
105static
106ULONG
107NTAPI
109{
112
113 /* Single group kernels: the number is the index */
115}
116
117#if defined(__GNUC__)
118#pragma GCC diagnostic pop
119#elif defined(_MSC_VER)
120#pragma warning(pop)
121#endif
122
123/* Interrupter register access ************************************************/
124
125static
126ULONG
127NTAPI
131{
132 return Entry->Controller->m_Registers.ReadRuntime32(Entry->RegisterOffset + Offset);
133}
134
135static
136VOID
137NTAPI
142{
143 Entry->Controller->m_Registers.WriteRuntime32(Entry->RegisterOffset + Offset, Value);
144}
145
146static
147VOID
148NTAPI
153{
154 Entry->Controller->m_Registers.WriteRuntime64(Entry->RegisterOffset + Offset, Value);
155}
156
158static
159VOID
160NTAPI
163 _In_ BOOLEAN ClearBusy)
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}
176
178static
179VOID
180NTAPI
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}
201
203static
204VOID
205NTAPI
208{
211 XhciWriteInterrupter64(Entry, XHCI_ERSTBA, (ULONG64)Entry->Erst->LogicalAddress.QuadPart);
212}
213
214static
215VOID
216NTAPI
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}
228
229/* Interrupt callbacks ********************************************************/
230
231static
233NTAPI
235 _In_ WDFINTERRUPT Interrupt,
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}
258
259static
261NTAPI
263 _In_ WDFINTERRUPT Interrupt,
264 _In_ WDFDEVICE AssociatedDevice)
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}
283
284static
286NTAPI
288 _In_ WDFINTERRUPT Interrupt,
289 _In_ WDFDEVICE AssociatedDevice)
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}
306
307/* Event processing ***********************************************************/
308
310static
312NTAPI
314 _Inout_ PBOOLEAN LimitsKnown,
315 _Inout_ PULONG TimeLimit,
316 _Inout_ PULONG WatchdogLimit)
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}
340
341static
343NTAPI
346{
347 return (PXHCI_TRB)Entry->Segment->VirtualAddress + Entry->DequeueIndex;
348}
349
350static
352NTAPI
355 _In_ PXHCI_TRB Trb)
356{
358
359 Control = *(volatile ULONG*)&Trb->Dword[3];
360 return (Control & XHCI_TRB_CYCLE) == Entry->CycleState;
361}
362
363static
364VOID
365NTAPI
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}
387
388static
389VOID
390NTAPI
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}
430
431static
432VOID
433NTAPI
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}
503
505static
506VOID
507NTAPI
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}
538
539static
540VOID
541NTAPI
543 _In_ WDFWORKITEM WorkItem)
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}
559
560static
561VOID
562NTAPI
564 _In_ WDFINTERRUPT Interrupt,
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}
624
625/* Resource requirements ******************************************************/
626
627static
629NTAPI
632{
634
635 return Descriptor->Type == CmResourceTypeInterrupt &&
636 (Descriptor->Flags & MessageFlags) == MessageFlags;
637}
638
639static
641NTAPI
644{
646
647 return Descriptor->Type == CmResourceTypeInterrupt &&
648 (Descriptor->Flags & MessageFlags) == MessageFlags;
649}
650
653static
655NTAPI
656XhciStripMessageRequirements(
657 _In_ WDFIORESREQLIST Requirements)
658{
659 WDFIORESLIST List;
661 IO_RESOURCE_DESCRIPTOR Preferred;
663 ULONG Index;
664 ULONG LineCount;
665 BOOLEAN AnyLine = FALSE;
666
667 ListIndex = WdfIoResourceRequirementsListGetCount(Requirements);
668 while (ListIndex > 0)
669 {
670 ListIndex -= 1;
671 List = WdfIoResourceRequirementsListGetIoResList(Requirements, ListIndex);
672 LineCount = 0;
673
674 Index = WdfIoResourceListGetCount(List);
675 while (Index > 0)
676 {
677 Index -= 1;
678 Descriptor = WdfIoResourceListGetDescriptor(List, Index);
680 continue;
681
683 {
684 WdfIoResourceListRemove(List, Index);
685 continue;
686 }
687
688 /* The line interrupt was offered as a fallback; make it the preferred choice */
689 Preferred = *Descriptor;
690 Preferred.Option = 0;
691 WdfIoResourceListUpdateDescriptor(List, &Preferred, Index);
692 LineCount++;
693 }
694
695 if (LineCount == 0)
696 {
697 DPRINT("Removing requirements list %lu, it has no line interrupt\n", ListIndex);
698 WdfIoResourceRequirementsListRemove(Requirements, ListIndex);
699 }
700 else
701 {
702 AnyLine = TRUE;
703 }
704 }
705
706 if (!AnyLine)
707 {
708 DPRINT1("Line interrupts are required but no requirements list offers one\n");
709 return STATUS_UNSUCCESSFUL;
710 }
711
712 return STATUS_SUCCESS;
713}
714
717static
719NTAPI
720XhciFindMessageList(
721 _In_ WDFIORESREQLIST Requirements,
724{
725 WDFIORESLIST List;
734
735 *ListIndex = 0;
736 *Messages = 0;
737
738 Lists = WdfIoResourceRequirementsListGetCount(Requirements);
739 for (Current = 0; Current < Lists; Current++)
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 }
770
771 return BestMsiX;
772}
773
776static
777VOID
778NTAPI
779XhciTrimMessageRequirements(
780 _In_ WDFIORESLIST List,
782{
785 ULONG Index = 0;
788
789 while (Index < WdfIoResourceListGetCount(List))
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 }
826}
827
828/* XhciInterrupters ***********************************************************/
829
833{
835
836 PAGED_CODE();
837
842 m_Count = 0;
843 m_Capacity = 0;
844 m_Table = NULL;
845 m_Lookup = NULL;
846 m_LookupSize = 0;
847
849 (PFN_XHCI_ACTIVE_COUNT)XhciFindKernelRoutine(L"KeQueryActiveProcessorCountEx");
851 (PFN_XHCI_INDEX_FROM_NUMBER)XhciFindKernelRoutine(L"KeGetProcessorIndexFromNumber");
853 (PFN_XHCI_CURRENT_NUMBER)XhciFindKernelRoutine(L"KeGetCurrentProcessorNumberEx");
855 (PFN_XHCI_DPC_WATCHDOG)XhciFindKernelRoutine(L"KeQueryDpcWatchdogInformation");
856
857 /* The primary takes the first interrupt resource KMDF finds at start */
859 if (!NT_SUCCESS(Status))
860 DPRINT1("Primary interrupt creation failed 0x%lx\n", Status);
861
862 return Status;
863}
864
869 _Out_ WDFINTERRUPT* Interrupt)
870{
874
876 Config.EvtInterruptEnable = XhciEvtInterruptEnable;
877 Config.EvtInterruptDisable = XhciEvtInterruptDisable;
878 Config.InterruptRaw = Raw;
879 Config.InterruptTranslated = Translated;
880
882
883 Status = WdfInterruptCreate(m_Controller->m_Device, &Config, &Attributes, Interrupt);
884 if (!NT_SUCCESS(Status))
885 {
886 DPRINT1("WdfInterruptCreate failed 0x%lx\n", Status);
887 *Interrupt = NULL;
888 }
889
890 return Status;
891}
892
893ULONG
895 _In_ ULONG Messages) const
896{
897 ULONG Limit;
898 ULONG Processors;
899 ULONG Count;
900
901 if (m_Controller->HasErrata(XhciErrata::IntPrimaryOnly) || Messages <= 1)
902 return 0;
903
904 /* One message always goes to the primary */
906
907 /* A single processor still gets its own secondary */
908 Processors = XhciActiveProcessors(0);
909 if (Processors <= Limit)
910 return Processors;
911
912 /* Halve until the processors split evenly over what is available */
913 Count = Processors / 2;
914 while (Count > Limit)
915 Count /= 2;
916
917 return Count;
918}
919
922 _In_ WDFIORESREQLIST Requirements)
923{
927
928 PAGED_CODE();
929
930 if (m_Controller->HasErrata(XhciErrata::IntLegacyLineOnly))
931 {
933 return XhciStripMessageRequirements(Requirements);
934 }
935
936 MsiX = XhciFindMessageList(Requirements, &ListIndex, &Messages);
938
939 DPRINT("Requirements list %lu offers %lu messages (MSI-X %u), %lu secondary interrupters\n",
941
942 if (WdfIoResourceRequirementsListGetCount(Requirements) != 0)
943 {
944 XhciTrimMessageRequirements(WdfIoResourceRequirementsListGetIoResList(Requirements, ListIndex),
945 1 + m_SecondaryCount);
946 }
947
948 return STATUS_SUCCESS;
949}
950
953 _In_ WDFIORESREQLIST Requirements)
954{
955 WDFIORESLIST List;
960 ULONG PerInterrupter;
961 ULONG NextProcessor = 0;
962 ULONG Index;
963 ULONG Step;
964 BOOLEAN Primary = TRUE;
965
966 PAGED_CODE();
967
968 if (m_SecondaryCount == 0)
969 return STATUS_SUCCESS;
970
971 if (!XhciFindMessageList(Requirements, &ListIndex, &Messages))
972 {
973 DPRINT1("Secondary interrupters planned but no MSI-X list found\n");
974 return STATUS_SUCCESS;
975 }
976
977 PerInterrupter = XhciActiveProcessors(0) / m_SecondaryCount;
978 List = WdfIoResourceRequirementsListGetIoResList(Requirements, ListIndex);
979
980 for (Index = 0; Index < WdfIoResourceListGetCount(List); Index++)
981 {
982 Descriptor = WdfIoResourceListGetDescriptor(List, Index);
984 continue;
985
986 Pinned = *Descriptor;
988 Pinned.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
989 Pinned.u.Interrupt.TargetedProcessors = 0;
990
991 /* The primary gets an empty processor set */
992 if (!Primary)
993 {
994 for (Step = 0; Step < PerInterrupter && NextProcessor < RTL_BITS_OF(KAFFINITY); Step++)
995 {
996 Pinned.u.Interrupt.TargetedProcessors |= (KAFFINITY)1 << NextProcessor;
997 NextProcessor++;
998 }
999 }
1000
1001 Primary = FALSE;
1002 WdfIoResourceListUpdateDescriptor(List, &Pinned, Index);
1003 }
1004
1005 return STATUS_SUCCESS;
1006}
1007
1011 _In_ WDFINTERRUPT Interrupt,
1013 _In_ BOOLEAN MessageSignaled)
1014{
1016 WDF_WORKITEM_CONFIG WorkConfig;
1021 ULONG Segments;
1023 ULONG Slot;
1025
1026 Entry->Controller = Controller;
1027 Entry->Interrupt = Interrupt;
1028 Entry->Index = Index;
1030 Entry->MessageSignaled = MessageSignaled;
1031 InitializeListHead(&Entry->SegmentList);
1034
1035 /* Segment count: software default capped by ERST Max, then by the errata */
1036 Segments = Controller->HasErrata(XhciErrata::EvtResetOnRingOverflow) ?
1038 Hardware = max(Controller->m_Registers.EventRingSegmentTableMax(), 1UL);
1039 Segments = min(Segments, Hardware);
1040 if (Segments > XHCI_SEGMENTS_LIMITED && Controller->HasErrata(XhciErrata::EvtTwoSegmentRingCap))
1041 Segments = XHCI_SEGMENTS_LIMITED;
1042
1043 Entry->SegmentCount = Segments;
1044 Entry->SegmentSize = PAGE_SIZE;
1045 Entry->TrbsPerSegment = PAGE_SIZE / sizeof(XHCI_TRB);
1046
1047 Entry->Erst = Controller->m_Buffers.Acquire(Segments * sizeof(XHCI_ERST_ENTRY));
1048 if (Entry->Erst == NULL)
1049 {
1050 DPRINT1("Interrupter %lu: no buffer for the segment table\n", Index);
1052 }
1053
1054 Status = Controller->m_Buffers.AcquireList(Entry->SegmentSize, Segments, &Entry->SegmentList);
1055 if (!NT_SUCCESS(Status))
1056 {
1057 DPRINT1("Interrupter %lu: no buffers for %lu event ring segments 0x%lx\n",
1058 Index, Segments, Status);
1059 goto Fail;
1060 }
1061
1063
1064 /* The table is written once here and survives power transitions */
1065 Table = (PXHCI_ERST_ENTRY)Entry->Erst->VirtualAddress;
1066 Slot = 0;
1067 for (Link = Entry->SegmentList.Flink; Link != &Entry->SegmentList; Link = Link->Flink)
1068 {
1070 Table[Slot].SegmentAddress = (ULONG64)Buffer->LogicalAddress.QuadPart;
1071 Table[Slot].SegmentSize = Entry->TrbsPerSegment;
1072 Table[Slot].Reserved = 0;
1073 Slot++;
1074 }
1075
1077 WorkConfig.AutomaticSerialization = FALSE;
1079 Attributes.ParentObject = Interrupt;
1080
1081 Status = WdfWorkItemCreate(&WorkConfig, &Attributes, &Entry->Requeue);
1082 if (!NT_SUCCESS(Status))
1083 {
1084 DPRINT1("Interrupter %lu: requeue work item creation failed 0x%lx\n", Index, Status);
1085 Entry->Requeue = NULL;
1086 goto Fail;
1087 }
1088
1089 Entry->Segment = CONTAINING_RECORD(Entry->SegmentList.Flink, XhciDmaBuffer, Link);
1090 Entry->CycleState = XHCI_TRB_CYCLE;
1091 Entry->Prepared = TRUE;
1092 XhciInterruptContext(Interrupt)->Entry = Entry;
1093 return STATUS_SUCCESS;
1094
1095Fail:
1096 if (!IsListEmpty(&Entry->SegmentList))
1097 Controller->m_Buffers.FreeList(&Entry->SegmentList);
1098 Controller->m_Buffers.Free(Entry->Erst);
1099 Entry->Erst = NULL;
1100 return Status;
1101}
1102
1105 _In_ WDFCMRESLIST Raw,
1106 _In_ WDFCMRESLIST Translated)
1107{
1109 WDFINTERRUPT Interrupt;
1110 ULONG Assigned = 0;
1111 ULONG Index;
1112 ULONG Message;
1113 ULONG Limit;
1114 BOOLEAN FirstSkipped;
1116
1117 PAGED_CODE();
1118
1120 for (Index = 0; Index < WdfCmResourceListGetCount(Raw); Index++)
1121 {
1122 Descriptor = WdfCmResourceListGetDescriptor(Raw, Index);
1124 continue;
1125
1127 {
1128 m_Mechanism = (Assigned != 0) ? Mechanism::MsiX : Mechanism::Msi;
1129 Assigned += Descriptor->u.MessageInterrupt.Raw.MessageCount;
1130 }
1131 else
1132 {
1133 Assigned++;
1134 }
1135 }
1136
1137 if (Assigned == 0)
1138 {
1139 DPRINT1("No interrupt resources were assigned\n");
1141 }
1142
1144 Assigned * sizeof(*m_Table),
1146 if (m_Table == NULL)
1147 {
1148 DPRINT1("Interrupter table allocation for %lu entries failed\n", Assigned);
1150 }
1151
1152 m_Capacity = Assigned;
1153
1155 if (!NT_SUCCESS(Status))
1156 {
1157 DPRINT1("Primary interrupter prepare failed 0x%lx\n", Status);
1158 return Status;
1159 }
1160
1161 m_Count = 1;
1162
1163 /* Register parsing may have asked for a single interrupter after filtering */
1164 if (m_Controller->HasErrata(XhciErrata::IntPrimaryOnly))
1165 m_SecondaryCount = 0;
1166
1167 /* The MSI-X table alone may allow more than MaxIntrs */
1169 if (Limit != 0 && m_SecondaryCount > Limit - 1)
1170 m_SecondaryCount = Limit - 1;
1171
1172 if (m_SecondaryCount != 0 && Assigned > 1 && m_Mechanism == Mechanism::MsiX)
1173 {
1174 FirstSkipped = FALSE;
1175 Message = 0;
1176
1177 for (Index = 0; Index < WdfCmResourceListGetCount(Translated); Index++)
1178 {
1179 Descriptor = WdfCmResourceListGetDescriptor(Translated, Index);
1180 if (Descriptor->Type != CmResourceTypeInterrupt ||
1182 {
1183 continue;
1184 }
1185
1186 /* The first message belongs to the primary */
1187 if (!FirstSkipped)
1188 {
1189 FirstSkipped = TRUE;
1190 continue;
1191 }
1192
1193 Message++;
1195 break;
1196
1197 Status = CreateInterrupt(WdfCmResourceListGetDescriptor(Raw, Index), Descriptor, &Interrupt);
1198 if (!NT_SUCCESS(Status))
1199 {
1200 DPRINT1("Secondary interrupter %lu creation failed 0x%lx\n", Message, Status);
1201 return Status;
1202 }
1203
1205 if (!NT_SUCCESS(Status))
1206 {
1207 DPRINT1("Secondary interrupter %lu prepare failed 0x%lx\n", Message, Status);
1208 return Status;
1209 }
1210
1211#if defined(NT_PROCESSOR_GROUPS)
1212 m_Table[Message].Group = Descriptor->u.MessageInterrupt.Translated.Group;
1213#endif
1214 m_Table[Message].Affinity = Descriptor->u.MessageInterrupt.Translated.Affinity;
1215
1216 /* Count only the interrupters actually set up */
1217 m_Count = Message + 1;
1218 }
1219 }
1220
1221 DPRINT("%lu interrupt messages assigned, mechanism %lu, %lu interrupters in use\n",
1222 Assigned, static_cast<ULONG>(m_Mechanism), m_Count);
1223
1224 return BuildLookup();
1225}
1226
1229{
1231 ULONG Size;
1232 ULONG Number;
1233 ULONG Target;
1234 ULONG Index;
1235
1238 max(Size, 1UL) * sizeof(*m_Lookup),
1240 if (m_Lookup == NULL)
1241 {
1242 DPRINT1("Processor lookup table allocation for %lu processors failed\n", Size);
1244 }
1245
1247
1248 /* Zero entries mean the primary; group 0 masks only */
1249 for (Target = 1; Target < m_Count; Target++)
1250 {
1251 Entry = &m_Table[Target];
1252 for (Number = 0; Number < RTL_BITS_OF(KAFFINITY); Number++)
1253 {
1254 if ((Entry->Affinity & ((KAFFINITY)1 << Number)) == 0)
1255 continue;
1256
1258 if (Index < m_LookupSize)
1260 }
1261 }
1262
1263 return STATUS_SUCCESS;
1264}
1265
1266VOID
1269{
1271
1272 if (Controller->IsAccessible())
1273 {
1277 }
1278
1279 Controller->m_Buffers.FreeList(&Entry->SegmentList);
1280 Controller->m_Buffers.Free(Entry->Erst);
1281 Entry->Erst = NULL;
1282 Entry->Segment = NULL;
1283
1284 if (Entry->Requeue != NULL)
1285 {
1286 WdfWorkItemFlush(Entry->Requeue);
1287 WdfObjectDelete(Entry->Requeue);
1288 Entry->Requeue = NULL;
1289 }
1290
1291 XhciInterruptContext(Entry->Interrupt)->Entry = NULL;
1292 Entry->Prepared = FALSE;
1293}
1294
1295VOID
1297{
1298 ULONG Index;
1299
1300 PAGED_CODE();
1301
1302 if (m_Table != NULL)
1303 {
1304 for (Index = 0; Index < m_Capacity; Index++)
1305 {
1306 if (m_Table[Index].Prepared)
1308 }
1309
1311 m_Table = NULL;
1312 }
1313
1314 if (m_Lookup != NULL)
1315 {
1317 m_Lookup = NULL;
1318 }
1319
1320 m_Count = 0;
1321 m_Capacity = 0;
1322 m_LookupSize = 0;
1323}
1324
1327 _In_ BOOLEAN StatePreserved)
1328{
1329 ULONG Index;
1330
1331 if (!m_Controller->IsAccessible())
1332 return STATUS_SUCCESS;
1333
1334 /* On a restore the ring contents and positions from before D0 exit stay valid */
1335 for (Index = 0; Index < m_Count; Index++)
1336 {
1337 if (!StatePreserved)
1339
1341 }
1342
1343 return STATUS_SUCCESS;
1344}
1345
1346VOID
1348{
1351 KIRQL OldIrql;
1352 ULONG Index;
1353
1354 PAGED_CODE();
1355
1356 for (Index = 0; Index < m_Count; Index++)
1357 {
1358 Entry = &m_Table[Index];
1359 if (Entry->Requeue == NULL)
1360 continue;
1361
1363 Entry->PendingDisable = TRUE;
1365
1366 /* Freeing state under a running work item is worse than waiting */
1368 while (KeWaitForSingleObject(&Entry->RequeueIdle,
1369 Executive,
1370 KernelMode,
1371 FALSE,
1373 {
1374 DPRINT1("Interrupter %lu requeue work item still running after 60 s\n", Index);
1375 }
1376 }
1377}
1378
1379VOID
1381{
1382 DPRINT("Interrupters stopped, %lu in use\n", m_Count);
1383}
1384
1385VOID
1387{
1388 ULONG Index;
1389
1390 if (!m_Controller->IsAccessible())
1391 return;
1392
1393 for (Index = 0; Index < m_Count; Index++)
1394 {
1397 }
1398
1399 for (Index = 0; Index < m_Count; Index++)
1400 {
1401 if (m_Table[Index].Enabled)
1403 }
1404}
1405
1406ULONG
1408{
1409 return m_Count;
1410}
1411
1412ULONG
1414{
1416}
1417
1418ULONG
1420 _In_ ULONG ProcessorIndex) const
1421{
1422 /* Processors added after start are not in the table and use the primary */
1423 if (m_Lookup == NULL || ProcessorIndex >= m_LookupSize)
1424 return 0;
1425
1426 return m_Lookup[ProcessorIndex];
1427}
#define PAGED_CODE()
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
@ Group
Definition: help.c:22
#define DPRINT1
Definition: precomp.h:8
return
Definition: dirsup.c:529
Definition: bufpool.h:45
BOOLEAN HasErrata(_In_ XhciErrata Bit) const
Definition: hc.h:58
WDFDEVICE m_Device
Definition: hc.h:85
BOOLEAN IsAccessible() const
Definition: hc.cpp:193
XhciRegisters m_Registers
Definition: hc.h:91
VOID PostReset()
Definition: intr.cpp:1386
NTSTATUS PrepareOne(_Inout_ Interrupter *Entry, _In_ WDFINTERRUPT Interrupt, _In_ ULONG Index, _In_ BOOLEAN MessageSignaled)
Definition: intr.cpp:1009
VOID D0Exit()
Definition: intr.cpp:1380
PUSHORT m_Lookup
Definition: intr.h:125
XhciController * m_Controller
Definition: intr.h:118
Interrupter * m_Table
Definition: intr.h:124
VOID ReleaseOne(_Inout_ Interrupter *Entry)
Definition: intr.cpp:1267
Mechanism m_Mechanism
Definition: intr.h:120
ULONG m_Count
Definition: intr.h:122
WDFINTERRUPT m_PrimaryInterrupt
Definition: intr.h:119
ULONG m_SecondaryCount
Definition: intr.h:121
NTSTATUS AffinitizeResourceRequirements(_In_ WDFIORESREQLIST Requirements)
Definition: intr.cpp:952
NTSTATUS Create(_In_ XhciController *Controller)
Definition: intr.cpp:831
NTSTATUS Prepare(_In_ WDFCMRESLIST Raw, _In_ WDFCMRESLIST Translated)
Definition: intr.cpp:1104
NTSTATUS FilterResourceRequirements(_In_ WDFIORESREQLIST Requirements)
Definition: intr.cpp:921
VOID D0ExitPreInterruptsDisabled()
Definition: intr.cpp:1347
ULONG m_Capacity
Definition: intr.h:123
NTSTATUS CreateInterrupt(_In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw, _In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, _Out_ WDFINTERRUPT *Interrupt)
Definition: intr.cpp:866
NTSTATUS BuildLookup()
Definition: intr.cpp:1228
ULONG Count() const
Definition: intr.cpp:1407
NTSTATUS D0Entry(_In_ BOOLEAN StatePreserved)
Definition: intr.cpp:1326
ULONG SecondaryCountFor(_In_ ULONG Messages) const
Definition: intr.cpp:894
ULONG TargetForProcessor(_In_ ULONG ProcessorIndex) const
Definition: intr.cpp:1419
ULONG m_LookupSize
Definition: intr.h:126
ULONG TargetForCurrentProcessor() const
Definition: intr.cpp:1413
VOID Release()
Definition: intr.cpp:1296
ULONG MaxInterrupters() const
Definition: mmio.cpp:549
static BOOLEAN OnUntargetedTransferEvent(_In_ XhciController *Controller, _In_ const XHCI_TRB *Event)
Definition: xferring.cpp:803
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
PUCHAR Limit
Definition: desccheck.cpp:2230
LPWSTR Name
Definition: desk.c:124
_Inout_ HubConfiguration ** Slot
Definition: devhcd.cpp:1260
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
_In_ ULONG Attributes
Definition: dispmprt.h:1077
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define NTSTATUS
Definition: precomp.h:19
ULONG_PTR KAFFINITY
Definition: compat.h:85
static const WCHAR Message[]
Definition: register.c:74
#define L(x)
Definition: resources.c:13
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
int Fail
Definition: ehthrow.cxx:24
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
Status
Definition: gdiplustypes.h:24
ASMGENDATA Table[]
Definition: genincdata.c:61
WdfWorkItemEnqueue(WorkItem)
_In_opt_ PVOID _In_ PUCXHUB_WORKITEM WorkItem
Definition: hubucx.h:227
#define XHCI_BUDGET_CHECK_EVENTS
Definition: intr.cpp:27
ULONG Lists
Definition: intr.cpp:727
static VOID NTAPI XhciDispatchEvent(_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
Definition: intr.cpp:434
static BOOLEAN NTAPI XhciIsMessageRequirement(_In_ PIO_RESOURCE_DESCRIPTOR Descriptor)
Definition: intr.cpp:630
ULONG(NTAPI * PFN_XHCI_CURRENT_NUMBER)(_Out_opt_ PPROCESSOR_NUMBER Number)
Definition: intr.cpp:35
static VOID NTAPI XhciWriteDequeue(_In_ PXHCI_INTERRUPTER Entry, _In_ BOOLEAN ClearBusy)
Definition: intr.cpp:161
static PFN_XHCI_INDEX_FROM_NUMBER XhciIndexFromNumberRoutine
Definition: intr.cpp:39
#define XHCI_SEGMENTS_DEFAULT
Definition: intr.cpp:24
ULONG Offered
Definition: intr.cpp:786
ULONG Current
Definition: intr.cpp:728
static BOOLEAN NTAPI XhciDpcBudgetSpent(_Inout_ PBOOLEAN LimitsKnown, _Inout_ PULONG TimeLimit, _Inout_ PULONG WatchdogLimit)
Definition: intr.cpp:313
BOOLEAN MsiX
Definition: intr.cpp:732
XhciInterrupters::Interrupter * PXHCI_INTERRUPTER
Definition: intr.cpp:13
static PXHCI_TRB NTAPI XhciDequeueTrb(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:344
static BOOLEAN NTAPI XhciIsMessageResource(_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor)
Definition: intr.cpp:642
IO_RESOURCE_DESCRIPTOR Trimmed
Definition: intr.cpp:784
BOOLEAN BestMsiX
Definition: intr.cpp:733
static VOID NTAPI XhciWriteInterrupter64(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG64 Value)
Definition: intr.cpp:149
#define XHCI_SEGMENTS_RING_FULL
Definition: intr.cpp:25
static VOID NTAPI XhciWriteInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG Value)
Definition: intr.cpp:138
struct _XHCI_INTERRUPT_CONTEXT XHCI_INTERRUPT_CONTEXT
#define XHCI_REASON_EVENT_RING_FULL
Definition: intr.cpp:29
static EVT_WDF_WORKITEM XhciEvtRequeueWorkItem
Definition: intr.cpp:47
static ULONG NTAPI XhciProcessorIndex(_In_ USHORT Group, _In_ ULONG Number)
Definition: intr.cpp:79
_Out_ PULONG ListIndex
Definition: intr.cpp:722
static ULONG NTAPI XhciActiveProcessors(_In_ USHORT Group)
Definition: intr.cpp:67
static PFN_XHCI_ACTIVE_COUNT XhciActiveCountRoutine
Definition: intr.cpp:38
static VOID NTAPI XhciRouteTransferEvent(_In_ PXHCI_INTERRUPTER Entry, _Inout_ PXHCI_TRB Event)
Definition: intr.cpp:391
static VOID NTAPI XhciResetEventRing(_Inout_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:181
#define XHCI_HANDBACK_EVENTS
Definition: intr.cpp:28
static VOID NTAPI XhciProgramEventRing(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:206
#define XHCI_SEGMENTS_LIMITED
Definition: intr.cpp:26
static EVT_WDF_INTERRUPT_DPC XhciEvtInterruptDpc
Definition: intr.cpp:44
XhciInterrupters::Interrupter XHCI_INTERRUPTER
Definition: intr.cpp:13
static EVT_WDF_INTERRUPT_DISABLE XhciEvtInterruptDisable
Definition: intr.cpp:46
NTSTATUS(NTAPI * PFN_XHCI_DPC_WATCHDOG)(_Out_ PKDPC_WATCHDOG_INFORMATION Information)
Definition: intr.cpp:36
static ULONG NTAPI XhciCurrentProcessorIndex(VOID)
Definition: intr.cpp:108
ULONG Index
Definition: intr.cpp:729
PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: intr.cpp:726
ULONG Claim
Definition: intr.cpp:787
struct _XHCI_INTERRUPT_CONTEXT * PXHCI_INTERRUPT_CONTEXT
static VOID NTAPI XhciAdvanceDequeue(_Inout_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:366
static ULONG NTAPI XhciReadInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset)
Definition: intr.cpp:128
_In_ ULONG Wanted
Definition: intr.cpp:782
#define XHCI_DRAIN_WAIT_MS
Definition: intr.cpp:30
ULONG(NTAPI * PFN_XHCI_INDEX_FROM_NUMBER)(_In_ PPROCESSOR_NUMBER Number)
Definition: intr.cpp:34
ULONG Descriptors
Definition: intr.cpp:731
static PFN_XHCI_DPC_WATCHDOG XhciDpcWatchdogRoutine
Definition: intr.cpp:41
static EVT_WDF_INTERRUPT_ISR XhciEvtInterruptIsr
Definition: intr.cpp:43
static VOID NTAPI XhciRequeueEvents(_Inout_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:508
static PFN_XHCI_CURRENT_NUMBER XhciCurrentNumberRoutine
Definition: intr.cpp:40
static BOOLEAN NTAPI XhciEventPending(_In_ PXHCI_INTERRUPTER Entry, _In_ PXHCI_TRB Trb)
Definition: intr.cpp:353
ULONG(NTAPI * PFN_XHCI_ACTIVE_COUNT)(_In_ USHORT GroupNumber)
Definition: intr.cpp:33
ULONG Count
Definition: intr.cpp:730
_Out_ PULONG _Out_ PULONG Messages
Definition: intr.cpp:724
#define XHCI_SECONDARY_MAX
Definition: intr.cpp:23
static VOID NTAPI XhciUnmaskInterrupter(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:217
static EVT_WDF_INTERRUPT_ENABLE XhciEvtInterruptEnable
Definition: intr.cpp:45
NTKRNLVISTAAPI ULONG NTAPI KeQueryActiveProcessorCount(OUT PKAFFINITY ActiveProcessors OPTIONAL)
Definition: ke.c:15
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define min(a, b)
Definition: monoChain.cc:55
@ Enabled
Definition: mountmgr.h:179
#define CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN
Definition: cmtypes.h:167
#define CM_RESOURCE_INTERRUPT_POLICY_INCLUDED
Definition: cmtypes.h:160
_In_ ULONG Number
Definition: haltypes.h:1940
#define KernelMode
Definition: asm.h:38
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_BITS_OF(sizeOfArg)
Definition: ntbasedef.h:680
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
* PPROCESSOR_NUMBER
Definition: ntbasedef.h:654
PROCESSOR_NUMBER
Definition: ntbasedef.h:654
#define ALL_PROCESSOR_GROUPS
Definition: ntbasedef.h:656
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ NotificationEvent
unsigned short USHORT
Definition: pedump.c:61
static ULONG Timeout
Definition: ping.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
@ Raw
Definition: sacdrv.h:279
@ IrqPolicySpecifiedProcessors
Definition: miniport.h:133
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
union _IO_RESOURCE_DESCRIPTOR::@2507 u
struct _IO_RESOURCE_DESCRIPTOR::@2507::@2510 Interrupt
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOLEAN AutomaticSerialization
Definition: wdfworkitem.h:79
Definition: xhcihw.h:165
PXHCI_INTERRUPTER Entry
Definition: intr.cpp:17
#define max(a, b)
Definition: svc.c:63
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3672
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_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
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
WdfObjectDelete(String)
for(Attempt=0;Attempt< UCX_LEGACY_NAME_ATTEMPTS;Attempt++)
Definition: userreq.cpp:715
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1707
_In_ WDFDEVICE AssociatedDevice
Definition: wdfinterrupt.h:173
_In_ WDFOBJECT AssociatedObject
Definition: wdfinterrupt.h:132
FORCEINLINE VOID WDF_INTERRUPT_CONFIG_INIT(_Out_ PWDF_INTERRUPT_CONFIG Configuration, _In_ PFN_WDF_INTERRUPT_ISR EvtInterruptIsr, _In_opt_ PFN_WDF_INTERRUPT_DPC EvtInterruptDpc)
Definition: wdfinterrupt.h:271
_In_ ULONG MessageID
Definition: wdfinterrupt.h:92
FORCEINLINE BOOLEAN WdfInterruptQueueDpcForIsr(_In_ WDFINTERRUPT Interrupt)
Definition: wdfinterrupt.h:414
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
#define WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(_contexttype, _castingfunction)
Definition: wdfobject.h:350
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IO_RESOURCE_ALTERNATIVE
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_In_ UCHAR Processor
Definition: kefuncs.h:670
@ Executive
Definition: ketypes.h:467
RtlInitUnicodeString & RoutineName
Definition: xhcientry.cpp:59
@ IsochStarveEventNoEd
@ EvtDropVendorCode199
@ EvtCheckTrbAddress
@ EvtResetOnRingOverflow
#define XHCI_ERSTSZ
Definition: xhcihw.h:155
struct _XHCI_ERST_ENTRY * PXHCI_ERST_ENTRY
#define XHCI_ERDP_BUSY
Definition: xhcihw.h:161
#define XHCI_TRB_ENDPOINT_MASK
Definition: xhcihw.h:27
#define XHCI_TRANSFER_EVENT_ED
Definition: xhcihw.h:321
#define XHCI_IMOD_INTERVAL_50US
Definition: xhcihw.h:330
#define XHCI_INTERRUPTER_STRIDE
Definition: xhcihw.h:152
#define XHCI_TRB_ENDPOINT_SHIFT
Definition: xhcihw.h:26
#define XHCI_ERSTBA
Definition: xhcihw.h:156
#define XHCI_RUNTIME_INTERRUPTER_BASE
Definition: xhcihw.h:151
#define XHCI_IMAN_PENDING
Definition: xhcihw.h:159
#define XHCI_IMOD
Definition: xhcihw.h:154
XhciTrbType
Definition: xhcihw.h:68
@ DeviceNotificationEvent
@ CommandCompletionEvent
@ PortStatusChangeEvent
@ VendorCommandCompletionEvent
#define XHCI_EVENT_DATA_TYPE_MASK
Definition: xhcihw.h:324
#define XHCI_TRB_CYCLE
Definition: xhcihw.h:22
struct _XHCI_TRB XHCI_TRB
#define XHCI_IMAN_ENABLE
Definition: xhcihw.h:160
#define XHCI_IMAN
Definition: xhcihw.h:153
#define XHCI_ERDP
Definition: xhcihw.h:157
#define XHCI_ERDP_SEGMENT_MASK
Definition: xhcihw.h:327
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
FORCEINLINE LARGE_INTEGER NTAPI XhciRelativeMs(_In_ ULONG Milliseconds)
Definition: xhciutil.h:137
#define XHCI_TAG_INTERRUPTER
Definition: xhciutil.h:15