ReactOS 0.4.17-dev-1281-g065abb3
epctx.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: Endpoints, static streams and the endpoint machine actions
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "xhcidrv.h"
11
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS ********************************************************************/
16
17#define XHCI_TAG_ENDPOINT 'eHCX'
18
19/* Facts kept in XhciEndpoint::m_Flags until the next mapping start */
20#define XHCI_EP_CANCEL_REPORTED 0x00000001
21#define XHCI_EP_FAILURE_REPORTED 0x00000002
22#define XHCI_EP_STREAM_HALT_PENDING 0x00000004
23#define XHCI_EP_STOPPED_HANDSHAKE 0x00000008
24#define XHCI_EP_STOPPED_RECEIVED 0x00000010
25#define XHCI_EP_HALT_RECEIVED 0x00000020
26#define XHCI_EP_IGNORE_STOPPED 0x00000040
27#define XHCI_EP_RESET_ACK_HANDSHAKE 0x00000080
28#define XHCI_EP_CLIENT_RESET_HANDSHAKE 0x00000100
29
30/* Hardware verifier conditions raised here */
31#define XHCI_VERIFY_CONTROL_DEQUEUE 0x00000080
32#define XHCI_VERIFY_RESET_ENDPOINT 0x00000100
33#define XHCI_VERIFY_CANCEL_DEQUEUE 0x00000200
34#define XHCI_VERIFY_STOP_EXHAUSTED 0x00000400
35#define XHCI_VERIFY_EVENT_CODE 0x00000800
36#define XHCI_VERIFY_STOP_ENDPOINT 0x00800000
37#define XHCI_VERIFY_DUPLICATE_EVENT 0x02000000
38
39/* Recovery reasons reported with a controller reset */
40#define XHCI_REASON_NO_LIVE_DUMP 0x0000
41#define XHCI_REASON_STOP_ERROR 0x1003
42#define XHCI_REASON_STOP_CONTEXT 0x1004
43#define XHCI_REASON_CONTROL_DEQUEUE 0x1005
44#define XHCI_REASON_CONTROL_RESET 0x1006
45#define XHCI_REASON_CANCEL_DEQUEUE 0x100A
46#define XHCI_REASON_EVENT_CODE 0x1010
47#define XHCI_REASON_DROP_FAILED 0x1017
48#define XHCI_REASON_CLIENT_DEQUEUE 0x101A
49#define XHCI_REASON_CLIENT_RESET 0x101B
50#define XHCI_REASON_STOP_ADD_FAILED 0x101D
51#define XHCI_REASON_EVENT_DATA_POINTER 0x101E
52#define XHCI_REASON_EVENT_POINTER 0x101F
53#define XHCI_REASON_DUPLICATE_POINTER 0x1020
54#define XHCI_REASON_STREAM_RECONFIGURE 0x1021
55#define XHCI_REASON_RECONFIGURE 0x1022
56#define XHCI_REASON_NOT_STOPPED 0x1023
57
58#define XHCI_RECLAIM_TAG reinterpret_cast<PVOID>(static_cast<ULONG_PTR>('lcRX'))
59#define XHCI_STOP_ATTEMPTS_MAX 20
60#define XHCI_CLEAR_STALL_TIMEOUT_MS 5000
61#define XHCI_CLEAR_STALL_STACK_SIZE 4
62
63/* Reuse flag our 1.17 headers lack; the framework accepts it */
64#define XHCI_REQUEST_REUSE_MUST_COMPLETE 0x00000002
65
68{
71};
72
78{
83 volatile LONG UpdateCount;
87};
88
91{
93 WDFREQUEST Request;
94 struct _URB_CONTROL_TRANSFER_EX Urb;
95};
96
99
100/* FUNCTIONS ******************************************************************/
101
102static
103ULONG
104NTAPI
107{
109}
110
112static
113ULONG
114NTAPI
117{
118 ULONG Value = 1;
119
120 while ((Count >> (Value + 1)) != 0)
121 Value++;
122
123 return Value;
124}
125
126static
127ULONG
128NTAPI
130 _In_ ULONG MaxPrimary)
131{
132 return sizeof(XHCI_STREAM_CONTEXT) << (MaxPrimary + 1);
133}
134
135static
137NTAPI
140{
141 switch (static_cast<XhciCompletionCode>(Code))
142 {
151 return TRUE;
152
153 default:
154 return FALSE;
155 }
156}
157
158static
160NTAPI
163{
164 return (Code == static_cast<ULONG>(XhciCompletionCode::Stopped)) ||
167}
168
170static
171ULONG
172NTAPI
174 _In_ enum XhciTrbType Type,
175 _In_ ULONG Dci,
176 _In_ ULONG SlotId)
177{
178 return (static_cast<ULONG>(Type) << XHCI_TRB_TYPE_SHIFT) |
179 (Dci << XHCI_TRB_ENDPOINT_SHIFT) |
180 (SlotId << XHCI_TRB_SLOT_SHIFT);
181}
182
183static
184PURB
185NTAPI
187 _In_ WDFREQUEST Request)
188{
190
192 WdfRequestGetParameters(Request, &Parameters);
193 return static_cast<PURB>(Parameters.Parameters.Others.Arg1);
194}
195
197static
199NTAPI
202 _In_ XhciTransferRing* MainRing,
203 _In_ ULONG ArrayMaxPrimary)
204{
205 XhciStreams* Streams;
206
207 Streams = static_cast<XhciStreams*>(ExAllocatePoolZero(NonPagedPool,
210 if (Streams == NULL)
211 return NULL;
212
213 Streams->Endpoint = Endpoint;
214 Streams->Count = 1;
215 Streams->MaxPrimary = 1;
216 Streams->Entry[0].Ring = MainRing;
217
218 Streams->ContextArray =
219 Endpoint->Controller()->m_Buffers.Acquire(XhciStreamArrayBytes(ArrayMaxPrimary));
220 if (Streams->ContextArray == NULL)
221 {
223 return NULL;
224 }
225
226 return Streams;
227}
228
229/* Accessors ******************************************************************/
230
233 _In_ UCXENDPOINT Endpoint)
234{
235 return XhciGetEndpoint(Endpoint);
236}
237
240{
241 return m_Controller;
242}
243
246{
247 return m_Device;
248}
249
250UCXENDPOINT
252{
253 return m_Ucx;
254}
255
256ULONG
258{
259 return m_Dci;
260}
261
262ULONG
264{
266}
267
270{
271 return &m_Descriptor;
272}
273
274USHORT
276{
277 return m_Descriptor.wMaxPacketSize & 0x7FF;
278}
279
280ULONG
282{
283 /* The bulk ring asks at enable, before the first context was built */
284 if (m_Device->Speed() >= UsbSuperSpeed)
285 return m_Companion.bMaxBurst;
286
287 return m_MaxBurst;
288}
289
290ULONG
292{
293 return m_MaxPayload;
294}
295
298{
299 return m_StreamsCapable;
300}
301
302/* Creation and cleanup *******************************************************/
303
306 _In_ UCXCONTROLLER UcxController,
307 _In_ UCXUSBDEVICE UcxUsbDevice,
312{
314 UCXENDPOINT Endpoint;
315 XhciEndpoint* Self;
317
319 Attributes.EvtCleanupCallback = EvtCleanup;
320
321 Status = UcxEndpointCreate(UcxUsbDevice, &EndpointInit, &Attributes, &Endpoint);
322 if (!NT_SUCCESS(Status))
323 {
324 DPRINT1("UcxEndpointCreate for endpoint 0x%02x failed 0x%lx\n",
325 Descriptor->bEndpointAddress, Status);
326 return Status;
327 }
328
329 Self = new (XhciGetEndpoint(Endpoint)) XhciEndpoint;
330 Self->m_Machine.Initialize(Self);
331
332 /* UCX deletes the endpoint on failure; the cleanup callback frees what was made */
335 Endpoint,
337 Companion,
338 IsochCompanion);
339}
340
344 _In_ UCXUSBDEVICE UcxUsbDevice,
345 _In_ UCXENDPOINT Endpoint,
349{
351 WDF_TIMER_CONFIG TimerConfig;
352 ULONG Type;
355
359 m_Ucx = Endpoint;
362
363 WDF_TIMER_CONFIG_INIT(&TimerConfig, EvtTimer);
364 TimerConfig.AutomaticSerialization = FALSE;
366 Attributes.ParentObject = Endpoint;
367
368 Status = WdfTimerCreate(&TimerConfig, &Attributes, &m_Timer);
369 if (!NT_SUCCESS(Status))
370 {
371 DPRINT1("Endpoint %p state timer creation failed 0x%lx\n", this, Status);
372 return Status;
373 }
374
376 if (Companion != NULL)
378 if (IsochCompanion != NULL)
379 RtlCopyMemory(&m_IsochCompanion, IsochCompanion, sizeof(m_IsochCompanion));
380
381 /* EP Type (xHCI 6.2.3): OUT types are 1..3, IN adds 4, control is 4 either way */
382 Type = TransferType();
385 m_XhciType += 4;
386
387 /* DCI (xHCI 4.5.1): control and IN endpoints are odd */
389 m_Dci = Number * 2;
391 m_Dci++;
392
393 /* Streams also need controller support */
396 (m_Companion.bmAttributes.Bulk.MaxStreams != 0) &&
398
399 if (m_StreamsCapable && m_Controller->HasErrata(XhciErrata::StrmReconfigOnStop))
400 {
402 if (!NT_SUCCESS(Status))
403 {
404 DPRINT1("Endpoint %p clear stall context creation failed 0x%lx\n", this, Status);
405 return Status;
406 }
407 }
408
409 /* The main ring of a streams capable endpoint is stream 1 of the default record */
411 if (!NT_SUCCESS(Status))
412 {
413 DPRINT1("Endpoint %p DCI %lu main ring creation failed 0x%lx\n", this, m_Dci, Status);
414 return Status;
415 }
416
418
419 m_Device->AddEndpoint(this);
420 m_Listed = TRUE;
421
422 DPRINT("Endpoint %p created, address 0x%02x DCI %lu type %lu\n",
424 return STATUS_SUCCESS;
425}
426
429{
432
434 sizeof(*m_ClearStall),
436 if (m_ClearStall == NULL)
438
440 if (m_ClearStall->Irp == NULL)
442
444 Status = WdfRequestCreate(&Attributes, NULL, &m_ClearStall->Request);
445 if (!NT_SUCCESS(Status))
447
448 return Status;
449}
450
451VOID
452NTAPI
455{
456 XhciEndpoint* Self = XhciGetEndpoint(Object);
457
458 if (Self->m_Ucx != Object)
459 return;
460
461 Self->Cleanup();
462}
463
464/* Also frees what a failed create left behind */
465VOID
467{
468 if (m_ClearStall != NULL)
469 {
470 if (m_ClearStall->Request != NULL)
472 if (m_ClearStall->Irp != NULL)
474
477 }
478
483
484 if (m_StopInput != NULL)
485 {
488 }
489
490 /* Last: dropping the list reference may free this object */
491 if (m_Listed)
492 {
493 m_Listed = FALSE;
494 m_Device->RemoveEndpoint(this);
495 }
496}
497
498VOID
500 _In_opt_ XhciStreams* Streams)
501{
502 if (Streams == NULL)
503 return;
504
505 if (Streams->ContextArray != NULL)
506 m_Controller->m_Buffers.Free(Streams->ContextArray);
507
509}
510
511VOID
512NTAPI
514 _In_ WDFTIMER Timer)
515{
516 XhciEndpoint* Self = XhciGetEndpoint(WdfTimerGetParentObject(Timer));
517
518 Self->PostEvent(XepEvent::TimerFired);
519}
520
521/* UCX endpoint add callbacks *************************************************/
522
524NTAPI
526 _In_ UCXCONTROLLER UcxController,
527 _In_ UCXUSBDEVICE UcxUsbDevice,
530{
534
536 Descriptor.bLength = sizeof(Descriptor);
538 Descriptor.wMaxPacketSize = static_cast<USHORT>(MaxPacketSize);
539
546
547 /* The forward progress hook travels in the reserved slot */
548 Callbacks.Reserved1 = reinterpret_cast<HANDLE>(XhciEndpoint::EvtEnableForwardProgress);
550
552 if (!NT_SUCCESS(Status))
553 DPRINT1("Default endpoint creation failed 0x%lx\n", Status);
554
555 return Status;
556}
557
559NTAPI
561 _In_ UCXCONTROLLER UcxController,
562 _In_ UCXUSBDEVICE UcxUsbDevice,
567{
571
573
583 Callbacks.Reserved1 = reinterpret_cast<HANDLE>(XhciEndpoint::EvtEnableForwardProgress);
585
586 /* QUIRK: the SSP isoch companion is assumed to follow the companion, unchecked against the length */
588 ((UsbEndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS) &&
589 SuperSpeedEndpointCompanionDescriptor->bmAttributes.Isochronous.SspCompanion)
590 {
591 IsochCompanion = reinterpret_cast<PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR>(
594 }
595
599 UsbEndpointDescriptor,
601 IsochCompanion);
602 if (!NT_SUCCESS(Status))
603 {
604 DPRINT1("Endpoint 0x%02x creation failed 0x%lx\n",
605 UsbEndpointDescriptor->bEndpointAddress, Status);
606 }
607
608 return Status;
609}
610
611/* Enable, disable and context construction ***********************************/
612
614XhciEndpoint::Enable()
615{
616 XhciTransferRing* Ring;
617 XhciStreams* Streams;
618 UCXSSTREAMS UcxStreams;
620 ULONG Index;
621
622 /* UCX decides whether client streams are open; they may close while we are disabled */
623 UcxStreams = UcxEndpointGetStaticStreamsReferenced(m_Ucx, this);
624
625 if (!m_StreamsCapable)
626 {
627 Status = m_MainRing->Enable();
628 }
629 else if (UcxStreams == NULL)
630 {
631 /* A default record kept across a disable for forward progress is reused as is */
632 if (m_DefaultStreams == NULL)
633 {
636 if (m_DefaultStreams == NULL)
638 }
639 else if (m_CurrentStreams == NULL)
640 {
642 }
643
644 if (NT_SUCCESS(Status))
645 Status = m_MainRing->Enable();
646
647 if (NT_SUCCESS(Status))
649 }
650 else
651 {
652 Streams = XhciGetStreams(UcxStreams);
654 m_CurrentStreams = Streams;
655
656 if (Streams->ContextArray == NULL)
657 {
658 Streams->ContextArray =
660 if (Streams->ContextArray == NULL)
662 }
663
664 for (Index = 0; NT_SUCCESS(Status) && (Index < Streams->Count); Index++)
665 {
666 Ring = Streams->Entry[Index].Ring;
667 Status = Ring->Enable();
668 if (NT_SUCCESS(Status))
670 }
671 }
672
673 if (NT_SUCCESS(Status))
674 {
675 PostEvent(XepEvent::Enable);
676 }
677 else
678 {
679 DPRINT1("Endpoint %p DCI %lu enable failed 0x%lx\n", this, m_Dci, Status);
681 }
682
683 if (UcxStreams != NULL)
684 WdfObjectDereferenceWithTag(UcxStreams, this);
685
686 return Status;
687}
688
689VOID
690XhciEndpoint::Disable()
691{
692 Disable(FALSE);
693}
694
695VOID
696XhciEndpoint::Disable(
697 _In_ BOOLEAN SlotDisabling)
698{
699 WDFREQUEST Pending;
700
701 /* Complete a client reset that raced a controller reset so it does not stay pending */
702 Pending = static_cast<WDFREQUEST>(
704 if (Pending != NULL)
705 {
706 DPRINT1("Endpoint %p DCI %lu disabled with a client reset pending; completing it\n", this, m_Dci);
707 WdfRequestComplete(Pending, STATUS_SUCCESS);
708 }
709
710 DisableRings(SlotDisabling);
711 PostEvent(XepEvent::Disable);
712}
713
714VOID
716 _In_ BOOLEAN SlotDisabling)
717{
719 ULONG Index;
720
721 /* Forward progress keeps the ring resources unless the whole device goes away */
722 FreeResources = !m_ForwardProgress || SlotDisabling;
723
724 if (!m_StreamsCapable)
725 {
726 m_MainRing->Disable(FreeResources);
727 return;
728 }
729
730 if (m_CurrentStreams == NULL)
731 return;
732
733 for (Index = 0; Index < m_CurrentStreams->Count; Index++)
735
736 if (!FreeResources)
737 return;
738
740 {
743 }
745 {
748 }
749
751}
752
753VOID
755 _Out_writes_bytes_(ContextSize) PVOID EndpointContext,
756 _In_ ULONG ContextSize) const
757{
758 PXHCI_ENDPOINT_CONTEXT Context = static_cast<PXHCI_ENDPOINT_CONTEXT>(EndpointContext);
763 BOOLEAN Periodic;
764 ULONG Interval = 0;
765 ULONG Burst = 0;
766 ULONG Mult = 0;
767 ULONG Esit = 0;
768
769 NT_ASSERT(ContextSize >= sizeof(*Context));
771
773
774 Context->EndpointType = m_XhciType;
775 Context->MaxPacketSize = Packet;
776
777 /*
778 * Isochronous endpoints never retry. The interrupt IN of one scanner behind an external
779 * hub also gets unlimited retries on flagged controllers.
780 */
782 {
783 Context->ErrorCount = 0;
784 }
785 else if (Type == USB_ENDPOINT_TYPE_INTERRUPT &&
787 m_Controller->HasErrata(XhciErrata::EpInfiniteCerr) &&
788 m_Device->DeviceDescriptor()->idVendor == 0x05F9 &&
789 m_Device->DeviceDescriptor()->idProduct == 0x1101 &&
791 {
792 Context->ErrorCount = 0;
793 }
794 else
795 {
796 Context->ErrorCount = 3;
797 }
798
799 if (Speed == UsbLowSpeed)
800 {
802 {
803 Interval = (Period < 16) ? 6 : ((Period < 32) ? 7 : 8);
804 Esit = Packet;
805 }
806
808 }
809 else if (Speed == UsbFullSpeed)
810 {
812 {
813 /* Frames to 125 us units as a power of two, 1 ms (3) at the least */
814 Interval = 3;
815 while ((Interval < 8) && (Period >= (2U << (Interval - 3))))
816 Interval++;
817 Esit = Packet;
818 }
820 {
821 /* QUIRK: full speed isoch is always serviced every frame */
822 Interval = 3;
823 Esit = Packet;
824 }
825
827 }
828 else if (Speed == UsbHighSpeed)
829 {
830 if (Periodic)
831 {
832 /* QUIRK: bInterval 6 and up is clamped to 32 microframes */
833 Interval = min(max(Period, 1), 6) - 1;
834 Burst = (m_Descriptor.wMaxPacketSize >> 11) & 3;
835 Esit = Packet * (Burst + 1);
836 }
837
838 m_MaxPayload = Packet * (Burst + 1);
839 }
840 else
841 {
842 Burst = m_Companion.bMaxBurst;
843
844 if (Periodic)
845 {
846 Interval = min(max(Period, 1), 6) - 1;
847
848 if (m_Companion.bmAttributes.Isochronous.SspCompanion)
849 {
851 }
852 else
853 {
856 }
857 }
858
859 /* QUIRK: everything but isoch ignores the burst here */
861 }
862
863 if (m_Controller->HasErrata(XhciErrata::EpClampIntervalTo7) && (Interval > 7))
864 Interval = 7;
865
866 m_MaxBurst = Burst;
867
868 Context->Interval = Interval;
869 Context->MaxBurstSize = Burst;
870 Context->Mult = Mult;
871 Context->MaxEsitPayloadLo = Esit & 0xFFFF;
872 Context->MaxEsitPayloadHi = (Esit >> 16) & 0xFF;
873
874 /* QUIRK: control and bulk get an Average TRB Length of 0 */
875 Context->AverageTrbLength = Esit / 2;
876
878 Context->MaxPStreams = m_CurrentStreams->MaxPrimary;
879
880 Context->TRDequeuePointer = EndpointDequeuePointer();
881 Context->LinearStreamArray = (Context->MaxPStreams != 0) ? 1 : 0;
882}
883
886{
887 if (!m_StreamsCapable)
889
891 return 0;
892
894}
895
896/* Rings and stream contexts **************************************************/
897
900{
902}
903
904ULONG
906{
907 return UsesStreams() ? m_CurrentStreams->Count : 1;
908}
909
912 _In_ ULONG Index) const
913{
915}
916
917VOID
920{
922 ULONG Index;
923
924 if (UsesStreams())
926
927 for (Index = 0; Index < Count; Index++)
928 (RingAt(Index)->*Action)();
929}
930
935{
936 if (UsesStreams() &&
938 {
939 return FALSE;
940 }
941
943 return TRUE;
944}
945
948{
950 ULONG Index;
951
952 for (Index = 0; Index < Count; Index++)
953 {
954 if (RingAt(Index)->HasQueuedWork())
955 return TRUE;
956 }
957
958 return FALSE;
959}
960
963{
964 return static_cast<ULONG>(InterlockedIncrement(&m_CurrentStreams->UpdateCount)) ==
966}
967
970 _In_ ULONG StreamId) const
971{
972 return static_cast<PXHCI_STREAM_CONTEXT>(m_CurrentStreams->ContextArray->VirtualAddress) + StreamId;
973}
974
977 _In_ ULONG StreamId) const
978{
980 return 0;
981
982 return StreamContext(StreamId)->DequeuePointer;
983}
984
986ULONG
988 _In_ ULONG StreamId) const
989{
993 ULONG Length = 0;
994
996 return 0;
997
998 Context = StreamContext(StreamId);
999 First = m_Controller->HasErrata(XhciErrata::StrmByteCountLayoutA);
1000 Second = m_Controller->HasErrata(XhciErrata::StrmByteCountLayoutB);
1001
1002 if (!First && !Second)
1003 {
1005 }
1006 else if (First && !Second)
1007 {
1008 Length = Context->Dword2 >> 8;
1009 if (m_Controller->HasErrata(XhciErrata::StrmByteCountHasValidFlag) && !(Context->Dword2 & 0x80))
1010 Length = 0;
1011 }
1012 else if (!First && Second)
1013 {
1015 }
1016
1017 if (m_Controller->HasErrata(XhciErrata::StrmByteCountTruncated))
1018 {
1019 NT_ASSERT(!Second);
1020 Length += Context->Dword3 & 0x1FFFF;
1021 }
1022
1023 return Length;
1024}
1025
1026VOID
1028 _In_ ULONG StreamId)
1029{
1031 BOOLEAN First;
1033
1034 if (!m_Controller->HasErrata(XhciErrata::StrmByteCountRearm))
1035 return;
1036
1037 Context = StreamContext(StreamId);
1038 First = m_Controller->HasErrata(XhciErrata::StrmByteCountLayoutA);
1039 Second = m_Controller->HasErrata(XhciErrata::StrmByteCountLayoutB);
1040
1041 if (!First && !Second)
1042 Context->Dword2 &= ~XHCI_STREAM_EDTLA_MASK;
1043 else if (First && !Second)
1044 Context->Dword2 &= 0xFF;
1045 else if (!First && Second)
1046 Context->Dword3 &= ~XHCI_STREAM_EDTLA_MASK;
1047}
1048
1050BOOLEAN
1052 _In_ ULONG StreamId) const
1053{
1054 XhciTransferRing* Ring = m_CurrentStreams->Entry[StreamId - 1].Ring;
1055 ULONG64 Pointer = StreamContext(StreamId)->DequeuePointer & ~XHCI_DEQUEUE_FLAGS_MASK;
1056
1057 return (Pointer == Ring->SegmentBase()) && (Pointer == Ring->EnqueuePointer());
1058}
1059
1060ULONG
1062{
1063 return UsesStreams() ? m_CurrentStreams->HaltedCode : 0;
1064}
1065
1066/* Events and hooks ***********************************************************/
1067
1068VOID
1071{
1073}
1074
1075VOID
1077{
1079 PostEvent(XepEvent::CommandFailed);
1080}
1081
1082VOID
1085{
1086 m_Controller->RaiseControllerFault(XhciRecovery::ResetHost, Reason);
1087}
1088
1089ULONG
1091{
1092 return static_cast<PXHCI_ENDPOINT_CONTEXT>(m_Device->OutputContext(m_Dci))->EndpointState;
1093}
1094
1097{
1098 return reinterpret_cast<PENDPOINT_RESET>(XhciRequestUrb(m_ResetRequest));
1099}
1100
1101VOID
1103 _In_ const XHCI_TRB* Event)
1104{
1106 ULONG64 Pointer;
1107 ULONG64 ArrayStart;
1108 ULONG Index;
1109
1110 if ((Code == static_cast<ULONG>(XhciCompletionCode::TrbError)) ||
1111 (Code == static_cast<ULONG>(XhciCompletionCode::UndefinedError)) ||
1112 ((Code >= 192) && (Code <= 223)))
1113 {
1114 DPRINT1("Endpoint %p DCI %lu transfer event with completion code %lu\n", this, m_Dci, Code);
1115 m_Controller->VerifierCheck(XHCI_VERIFY_EVENT_CODE);
1117 return;
1118 }
1119
1120 if (!UsesStreams())
1121 {
1123 return;
1124 }
1125
1126 Pointer = XhciTrbPointer(Event);
1128
1129 if ((Pointer != 0) &&
1130 ((Pointer < ArrayStart) || (Pointer >= ArrayStart + m_CurrentStreams->ContextArray->Size)))
1131 {
1132 for (Index = 0; Index < m_CurrentStreams->Count; Index++)
1133 {
1135 return;
1136 }
1137
1138 if (Event->Dword[3] & XHCI_TRANSFER_EVENT_ED)
1139 {
1140 DPRINT1("Endpoint %p DCI %lu event data 0x%I64x matched no stream\n", this, m_Dci, Pointer);
1142 return;
1143 }
1144
1145 if (!XhciIsStoppedCode(Code))
1146 {
1147 for (Index = 0; Index < m_CurrentStreams->Count; Index++)
1148 {
1150 continue;
1151
1152 if (m_Controller->HasErrata(XhciErrata::EvtDiscardRepeatedEd0))
1153 {
1154 DPRINT1("Endpoint %p DCI %lu dropping a likely duplicate event at 0x%I64x\n",
1155 this, m_Dci, Pointer);
1156 return;
1157 }
1158
1159 DPRINT1("Endpoint %p DCI %lu likely duplicate event at 0x%I64x\n", this, m_Dci, Pointer);
1161 return;
1162 }
1163
1164 DPRINT1("Endpoint %p DCI %lu event at 0x%I64x matched no stream\n", this, m_Dci, Pointer);
1166 return;
1167 }
1168
1169 /* Hardware compliance: a stopped event should point into some stream ring */
1170 DPRINT1("Endpoint %p DCI %lu stopped event at 0x%I64x matched no stream\n", this, m_Dci, Pointer);
1171 }
1172
1173 /* An event for the endpoint as a whole */
1176 else if (XhciIsStoppedCode(Code))
1178 else
1179 DPRINT1("Endpoint %p DCI %lu ignoring endpoint event code %lu\n", this, m_Dci, Code);
1180}
1181
1182VOID
1184{
1186 PostEvent(XepEvent::TransferAborted);
1187}
1188
1189VOID
1191 _In_ ULONG CompletionCode,
1192 _In_ BOOLEAN TransferFound)
1193{
1195 {
1197 return;
1198 }
1199
1200 if (!TransferFound)
1201 {
1202 if (UsesStreams())
1203 m_CurrentStreams->HaltedCode = CompletionCode;
1205 }
1206
1207 PostEvent(XepEvent::HaltReported);
1208}
1209
1210BOOLEAN
1212{
1213 return (m_Flags & XHCI_EP_IGNORE_STOPPED) != 0;
1214}
1215
1216VOID
1218{
1219 /* QUIRK: a second stopped event reports the duplicate halt verifier condition */
1221 {
1223 return;
1224 }
1225
1227 PostEvent(XepEvent::StoppedEventSeen);
1228}
1229
1230VOID
1232{
1233 PostWhenAllRings(XepEvent::ExpectedEventsDone);
1234}
1235
1236VOID
1238{
1239 PostWhenAllRings(XepEvent::StreamMapStopped);
1240}
1241
1242VOID
1244{
1245 /* Drops the reference NotifyRingsReclaim took, once the machine has the event */
1246 if (PostWhenAllRings(XepEvent::TransfersRecovered))
1248}
1249
1250/* Controller reset and removal ***********************************************/
1251
1252VOID
1254{
1255 PostEvent(XepEvent::ControllerResetStarting);
1256}
1257
1258VOID
1259XhciEndpoint::ControllerResetDone()
1260{
1262 PostEvent(XepEvent::ControllerResetDone);
1263
1264 /* Whoever toggles second finishes the handshake; wait only if the machine has not acknowledged */
1267}
1268
1269VOID
1271{
1272 PostEvent(XepEvent::ControllerRemoved);
1273}
1274
1275/* UCX endpoint callbacks *****************************************************/
1276
1277VOID
1278NTAPI
1280 _In_ UCXCONTROLLER UcxController,
1281 _In_ UCXENDPOINT UcxEndpoint)
1282{
1284 ULONG Index;
1285
1287
1288 if (!Self->UsesStreams())
1289 {
1290 WdfIoQueuePurge(Self->m_MainRing->Queue(), EvtPurgeDone, UcxEndpoint);
1291 return;
1292 }
1293
1294 /* QUIRK: purge and abort share this counter */
1296 for (Index = 0; Index < Self->m_CurrentStreams->Count; Index++)
1297 WdfIoQueuePurge(Self->m_CurrentStreams->Entry[Index].Ring->Queue(), EvtPurgeDone, UcxEndpoint);
1298}
1299
1300VOID
1301NTAPI
1303 _In_ WDFQUEUE Queue,
1305{
1306 UCXENDPOINT UcxEndpoint = static_cast<UCXENDPOINT>(Context);
1308
1310
1312 return;
1313
1314 UcxEndpointPurgeComplete(UcxEndpoint);
1315}
1316
1317/* Start and abort use the stream rings only while a streams record is current */
1318VOID
1319NTAPI
1321 _In_ UCXCONTROLLER UcxController,
1322 _In_ UCXENDPOINT UcxEndpoint)
1323{
1325 ULONG Index;
1326
1328
1329 if (!Self->UsesStreams())
1330 {
1331 WdfIoQueueStart(Self->m_MainRing->Queue());
1332 return;
1333 }
1334
1335 for (Index = 0; Index < Self->m_CurrentStreams->Count; Index++)
1336 WdfIoQueueStart(Self->m_CurrentStreams->Entry[Index].Ring->Queue());
1337}
1338
1339VOID
1340NTAPI
1342 _In_ UCXCONTROLLER UcxController,
1343 _In_ UCXENDPOINT UcxEndpoint)
1344{
1346 ULONG Index;
1347
1349
1350 if (!Self->UsesStreams())
1351 {
1352 WdfIoQueueStopAndPurge(Self->m_MainRing->Queue(), EvtAbortDone, UcxEndpoint);
1353 return;
1354 }
1355
1357 for (Index = 0; Index < Self->m_CurrentStreams->Count; Index++)
1358 WdfIoQueueStopAndPurge(Self->m_CurrentStreams->Entry[Index].Ring->Queue(), EvtAbortDone, UcxEndpoint);
1359}
1360
1361VOID
1362NTAPI
1364 _In_ WDFQUEUE Queue,
1366{
1367 UCXENDPOINT UcxEndpoint = static_cast<UCXENDPOINT>(Context);
1369
1371
1373 return;
1374
1375 UcxEndpointAbortComplete(UcxEndpoint);
1376}
1377
1378VOID
1379NTAPI
1381 _In_ UCXCONTROLLER UcxController,
1382 _In_ UCXENDPOINT UcxEndpoint,
1383 _In_ WDFREQUEST Request)
1384{
1386 XhciEndpointReset* Data = &XhciGetRequestData(Request)->EndpointReset;
1387 WDFREQUEST Taken;
1388
1390
1391 RtlZeroMemory(Data, sizeof(*Data));
1392 Data->Endpoint = Self;
1393
1394 /* Publish the request before the handshake so the machine can always find it */
1396 InterlockedExchangePointer(reinterpret_cast<PVOID volatile*>(&Self->m_ResetRequest), Request);
1397
1399 {
1400 Self->PostEvent(XepEvent::ClientReset);
1401 return;
1402 }
1403
1404 /* The machine already allowed completion: the endpoint is fenced or removed */
1405 Taken = static_cast<WDFREQUEST>(
1406 InterlockedExchangePointer(reinterpret_cast<PVOID volatile*>(&Self->m_ResetRequest), NULL));
1407 if (Taken != NULL)
1408 {
1410 WdfRequestComplete(Taken, STATUS_SUCCESS);
1411 }
1412}
1413
1414VOID
1415NTAPI
1417 _In_ UCXENDPOINT UcxEndpoint)
1418{
1419 FromUcx(UcxEndpoint)->PostEvent(XepEvent::CancelAllowed);
1420}
1421
1423NTAPI
1425 _In_ UCXENDPOINT Endpoint,
1427{
1428 XhciEndpoint* Self = FromUcx(Endpoint);
1429 XhciTransferRing* Ring;
1431
1432 /* QUIRK: UCX may ask again with a larger size; that is not supported */
1434
1435 /* The main ring serves until a streams record is current */
1436 Ring = Self->UsesStreams() ? Self->m_CurrentStreams->Entry[0].Ring : Self->m_MainRing;
1437
1438 Status = Ring->EnableForwardProgress(MaxTransferSize);
1439 if (NT_SUCCESS(Status))
1440 Self->m_ForwardProgress = TRUE;
1441 else
1442 DPRINT1("Endpoint %p forward progress enable failed 0x%lx\n", Self, Status);
1443
1444 return Status;
1445}
1446
1447/* Default endpoint update ****************************************************/
1448
1449VOID
1450NTAPI
1452 _In_ UCXCONTROLLER UcxController,
1453 _In_ WDFREQUEST Request)
1454{
1455 XhciDefaultEndpointUpdate* Data = &XhciGetRequestData(Request)->DefaultEndpointUpdate;
1460 XhciEndpoint* Self;
1461 ULONG64 InputAddress;
1462 ULONG Size;
1463 PUCHAR Base;
1464
1466
1467 /* QUIRK: the endpoint comes from the payload, not from the device UCX dispatched on */
1468 Payload = reinterpret_cast<PDEFAULT_ENDPOINT_UPDATE>(XhciRequestUrb(Request));
1469 Self = FromUcx(Payload->DefaultEndpoint);
1470 Controller = Self->m_Controller;
1471
1472 RtlZeroMemory(Data, sizeof(*Data));
1473 Data->Endpoint = Self;
1474 Data->MaxPacketSize = Payload->MaxPacketSize;
1475
1476 Size = Controller->m_Registers.ContextSize();
1477 Data->InputContext = Controller->m_Buffers.Acquire(Size * XHCI_INPUT_CONTEXT_COUNT);
1478 if (Data->InputContext == NULL)
1479 {
1480 DPRINT1("Endpoint %p no input context for the max packet size update\n", Self);
1481 WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
1482 return;
1483 }
1484
1485 Base = static_cast<PUCHAR>(Data->InputContext->VirtualAddress);
1486 InputAddress = Data->InputContext->LogicalAddress.QuadPart;
1487
1488 /* Evaluate Context looks only at the EP0 Max Packet Size (xHCI 4.6.7) */
1489 Control = reinterpret_cast<PXHCI_INPUT_CONTROL_CONTEXT>(Base);
1490 Control->AddFlags = 1 << 1;
1491
1492 Context = reinterpret_cast<PXHCI_ENDPOINT_CONTEXT>(Base + 2 * Size);
1494 Context->MaxPacketSize = Data->MaxPacketSize;
1495 Context->ErrorCount = 3;
1496 Context->TRDequeuePointer = Self->m_MainRing->DequeuePointerValue();
1497
1498 Self->m_MaxPayload = Data->MaxPacketSize;
1499
1500 /* QUIRK: the controller keeps the old dequeue pointer until the next Address Device */
1501 Self->m_MainRing->InitializeRing();
1502
1503 Data->Command.Trb.Dword[0] = static_cast<ULONG>(InputAddress);
1504 Data->Command.Trb.Dword[1] = static_cast<ULONG>(InputAddress >> 32);
1505 Data->Command.Trb.Dword[3] = XhciEndpointCommandControl(XhciTrbType::EvaluateContext,
1506 0, Self->m_Device->SlotId());
1507 Data->Command.Done = DefaultUpdateDone;
1508 Data->Command.Context = Request;
1509
1510 Controller->m_Commands.Submit(&Data->Command);
1511}
1512
1513VOID
1514NTAPI
1517{
1518 WDFREQUEST Request = static_cast<WDFREQUEST>(Command->Context);
1519 XhciDefaultEndpointUpdate* Data = &XhciGetRequestData(Request)->DefaultEndpointUpdate;
1520 XhciEndpoint* Self = Data->Endpoint;
1522
1523 Self->m_Controller->m_Buffers.Free(Data->InputContext);
1524 Data->InputContext = NULL;
1525
1526 if (Command->Status == STATUS_NO_SUCH_DEVICE)
1527 {
1528 DPRINT1("Endpoint %p max packet size update lost with the controller\n", Self);
1529 }
1530 else if (Command->Code != XhciCompletionCode::Success)
1531 {
1532 DPRINT1("Endpoint %p Evaluate Context failed with code %lu\n",
1533 Self, static_cast<ULONG>(Command->Code));
1534 }
1535 else
1536 {
1537 Self->m_Descriptor.wMaxPacketSize = static_cast<USHORT>(Data->MaxPacketSize);
1539 }
1540
1541 WdfRequestComplete(Request, Status);
1542}
1543
1544/* Static streams *************************************************************/
1545
1547NTAPI
1549 _In_ UCXENDPOINT UcxEndpoint,
1552{
1556 XhciStreams* Streams;
1557 UCXSSTREAMS UcxStreams;
1558 XhciTransferRing* Ring;
1560 ULONG StreamId;
1561
1562 if (!Self->m_StreamsCapable)
1563 {
1564 DPRINT1("Endpoint %p is not streams capable\n", Self);
1566 }
1567
1569 {
1570 DPRINT1("Endpoint %p bad stream count %lu\n", Self, NumberOfStreams);
1572 }
1573
1575 Attributes.ContextSizeOverride = XhciStreamsSize(NumberOfStreams);
1576 Attributes.EvtCleanupCallback = EvtStreamsCleanup;
1577
1578 Status = UcxStaticStreamsCreate(UcxEndpoint, &UcxStaticStreamsInit, &Attributes, &UcxStreams);
1579 if (!NT_SUCCESS(Status))
1580 {
1581 DPRINT1("Endpoint %p UcxStaticStreamsCreate failed 0x%lx\n", Self, Status);
1582 return Status;
1583 }
1584
1585 Streams = XhciGetStreams(UcxStreams);
1586 Streams->Endpoint = Self;
1587 Streams->Count = NumberOfStreams;
1589
1590 for (StreamId = 1; StreamId <= NumberOfStreams; StreamId++)
1591 {
1592 Status = XhciTransferRing::Create(Self, UcxStreams, StreamId, &Ring);
1593 if (!NT_SUCCESS(Status))
1594 {
1595 DPRINT1("Endpoint %p stream %lu ring creation failed 0x%lx\n", Self, StreamId, Status);
1596 return Status;
1597 }
1598
1599 Streams->Entry[StreamId - 1].Ring = Ring;
1600
1601 STREAM_INFO_INIT(&Info, Ring->Queue(), StreamId);
1602 UcxStaticStreamsSetStreamInfo(UcxStreams, &Info);
1603 }
1604
1605 return STATUS_SUCCESS;
1606}
1607
1608VOID
1609NTAPI
1612{
1613 XhciStreams* Streams = XhciGetStreams(Object);
1614
1615 if ((Streams->ContextArray != NULL) && (Streams->Endpoint != NULL))
1616 {
1617 Streams->Endpoint->m_Controller->m_Buffers.Free(Streams->ContextArray);
1618 Streams->ContextArray = NULL;
1619 }
1620}
1621
1622VOID
1624 _In_ XhciStreams* Streams)
1625{
1626 ULONG Index;
1627
1628 for (Index = 0; Index < Streams->Count; Index++)
1629 Streams->Entry[Index].Ring->Disable(TRUE);
1630}
1631
1632VOID
1633NTAPI
1635 _In_ UCXENDPOINT UcxEndpoint,
1636 _In_ UCXSSTREAMS UcxStaticStreams,
1637 _In_ WDFREQUEST Request)
1638{
1640
1642 if (Status != STATUS_PENDING)
1643 WdfRequestComplete(Request, Status);
1644}
1645
1649 _In_ XhciStreams* Streams,
1650 _In_ WDFREQUEST Request)
1651{
1653 WDFQUEUE MainQueue = m_MainRing->Queue();
1654 XhciTransferRing* Ring;
1655 ULONG Queued;
1656 ULONG Owned;
1658 ULONG Index;
1659
1660 /* The main queue stays drained for as long as client streams are open */
1661 WdfIoQueueDrain(MainQueue, NULL, NULL);
1662 WdfIoQueueGetState(MainQueue, &Queued, &Owned);
1663 if ((Queued != 0) || (Owned != 0))
1664 {
1665 DPRINT1("Endpoint %p streams open with requests still on the main queue\n", this);
1666 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
1668 goto Failure;
1669 }
1670
1671 if ((Streams->Count == 0) || (Streams->Count > m_Controller->m_Registers.SupportedStreams()))
1672 {
1673 DPRINT1("Endpoint %p streams open with bad stream count %lu\n", this, Streams->Count);
1674 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
1676 goto Failure;
1677 }
1678
1679 XhciGetRequestData(Request)->StreamsConfigure.Streams = Streams;
1680
1681 Streams->ContextArray = m_Controller->m_Buffers.Acquire(XhciStreamArrayBytes(Streams->MaxPrimary));
1682 if (Streams->ContextArray == NULL)
1683 {
1684 DPRINT1("Endpoint %p no stream context array for %lu streams\n", this, Streams->Count);
1685 Urb->UrbHeader.Status = USBD_STATUS_INSUFFICIENT_RESOURCES;
1687 goto Failure;
1688 }
1689
1690 m_CurrentStreams = Streams;
1691
1692 for (Index = 0; Index < Streams->Count; Index++)
1693 {
1694 Ring = Streams->Entry[Index].Ring;
1695 Status = Ring->Enable();
1696 if (!NT_SUCCESS(Status))
1697 {
1698 DPRINT1("Endpoint %p stream %lu ring enable failed 0x%lx\n", this, Index + 1, Status);
1699 Urb->UrbHeader.Status = USBD_STATUS_INSUFFICIENT_RESOURCES;
1700 goto Failure;
1701 }
1702
1704 }
1705
1706 m_Device->ReconfigureEndpoint(this, StreamsEnableDone, Request);
1707 return STATUS_PENDING;
1708
1709Failure:
1710 DisableStreamRings(Streams);
1712 if (Streams->ContextArray != NULL)
1713 {
1714 m_Controller->m_Buffers.Free(Streams->ContextArray);
1715 Streams->ContextArray = NULL;
1716 }
1717
1718 WdfIoQueueStart(MainQueue);
1719 return Status;
1720}
1721
1722VOID
1723NTAPI
1727{
1728 WDFREQUEST Request = static_cast<WDFREQUEST>(Context);
1729 XhciStreams* Streams = XhciGetRequestData(Request)->StreamsConfigure.Streams;
1730 XhciEndpoint* Self = Streams->Endpoint;
1732
1733 if (NT_SUCCESS(Status))
1734 {
1735 Self->m_MainRing->Disable(TRUE);
1737 Self->m_DefaultStreams = NULL;
1738 Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
1739 }
1740 else
1741 {
1742 DPRINT1("Endpoint %p streams open reconfigure failed 0x%lx\n", Self, Status);
1743 Self->DisableStreamRings(Streams);
1744 if (Streams->ContextArray != NULL)
1745 {
1746 Self->m_Controller->m_Buffers.Free(Streams->ContextArray);
1747 Streams->ContextArray = NULL;
1748 }
1749
1750 Self->m_CurrentStreams = Self->m_DefaultStreams;
1751 Urb->UrbHeader.Status = USBD_STATUS_INTERNAL_HC_ERROR;
1752 WdfIoQueueStart(Self->m_MainRing->Queue());
1753 }
1754
1755 if (NT_SUCCESS(Status))
1756 Self->PostEvent(XepEvent::StreamsOn);
1757
1758 WdfRequestComplete(Request, Status);
1759}
1760
1761VOID
1762NTAPI
1764 _In_ UCXENDPOINT UcxEndpoint,
1765 _In_ UCXSSTREAMS UcxStaticStreams,
1766 _In_ WDFREQUEST Request)
1767{
1769
1771 if (Status != STATUS_PENDING)
1772 WdfRequestComplete(Request, Status);
1773}
1774
1778 _In_ XhciStreams* Streams,
1779 _In_ WDFREQUEST Request)
1780{
1784
1785 XhciGetRequestData(Request)->StreamsConfigure.Streams = Streams;
1786
1787 /* QUIRK: the array is sized for the client stream count, larger than one stream needs */
1788 Default = XhciNewDefaultStreams(this, m_MainRing, Streams->MaxPrimary);
1789 if (Default == NULL)
1790 {
1791 DPRINT1("Endpoint %p no default stream record for the streams close\n", this);
1792 Urb->UrbHeader.Status = USBD_STATUS_INSUFFICIENT_RESOURCES;
1794 }
1795
1798
1799 Status = m_MainRing->Enable();
1800 if (!NT_SUCCESS(Status))
1801 {
1802 DPRINT1("Endpoint %p main ring enable for the streams close failed 0x%lx\n", this, Status);
1803 Urb->UrbHeader.Status = USBD_STATUS_INSUFFICIENT_RESOURCES;
1804
1805 /* Restore the client record so the freed default record is not left current */
1806 m_CurrentStreams = Streams;
1809 return Status;
1810 }
1811
1813
1814 m_Device->ReconfigureEndpoint(this, StreamsDisableDone, Request);
1815 return STATUS_PENDING;
1816}
1817
1818VOID
1819NTAPI
1823{
1824 WDFREQUEST Request = static_cast<WDFREQUEST>(Context);
1825 XhciStreams* Streams = XhciGetRequestData(Request)->StreamsConfigure.Streams;
1826 XhciEndpoint* Self = Streams->Endpoint;
1828
1829 if (NT_SUCCESS(Status))
1830 {
1831 Self->DisableStreamRings(Streams);
1832 if (Streams->ContextArray != NULL)
1833 {
1834 Self->m_Controller->m_Buffers.Free(Streams->ContextArray);
1835 Streams->ContextArray = NULL;
1836 }
1837
1838 WdfIoQueueStart(Self->m_MainRing->Queue());
1839 Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
1840 }
1841 else
1842 {
1843 /* QUIRK: the main ring enabled for the close stays enabled */
1844 DPRINT1("Endpoint %p streams close reconfigure failed 0x%lx\n", Self, Status);
1845 Self->m_CurrentStreams = Streams;
1847 Self->m_DefaultStreams = NULL;
1848 Urb->UrbHeader.Status = USBD_STATUS_INTERNAL_HC_ERROR;
1849 }
1850
1851 if (NT_SUCCESS(Status))
1852 Self->PostEvent(XepEvent::StreamsOff);
1853
1854 WdfRequestComplete(Request, Status);
1855}
1856
1857/* Endpoint commands **********************************************************/
1858
1859VOID
1862 _In_ ULONG64 DequeuePointer,
1863 _In_ ULONG StreamId,
1865{
1866 RtlZeroMemory(Command, sizeof(*Command));
1867 Command->Trb.Dword[0] = static_cast<ULONG>(DequeuePointer);
1868 Command->Trb.Dword[1] = static_cast<ULONG>(DequeuePointer >> 32);
1869 Command->Trb.Dword[2] = StreamId << XHCI_CMD_STREAM_ID_SHIFT;
1870 Command->Trb.Dword[3] = XhciEndpointCommandControl(XhciTrbType::SetTrDequeuePointer,
1871 m_Dci, m_Device->SlotId());
1872 Command->Done = Done;
1873 Command->Context = this;
1874}
1875
1878 _In_ XhciDmaBuffer* Input) const
1879{
1881
1882 return reinterpret_cast<PXHCI_ENDPOINT_CONTEXT>(static_cast<PUCHAR>(Input->VirtualAddress) +
1883 (m_Dci + 1) * Size);
1884}
1885
1887VOID
1890 _In_opt_ const VOID* EndpointContext,
1891 _In_ BOOLEAN Drop,
1892 _In_ BOOLEAN Add,
1895{
1897 PUCHAR Base = static_cast<PUCHAR>(Input->VirtualAddress);
1899 PXHCI_SLOT_CONTEXT Slot = reinterpret_cast<PXHCI_SLOT_CONTEXT>(Base + Size);
1900 ULONG64 InputAddress = Input->LogicalAddress.QuadPart;
1901
1903
1904 /* QUIRK: controller owned fields of the output contexts travel along; the xHC ignores them */
1906 if (EndpointContext != NULL)
1907 RtlCopyMemory(InputEndpointContext(Input), EndpointContext, Size);
1908
1909 /* The cached count, since a temporary drop lowers the controller's own value */
1910 Slot->ContextEntries = m_Device->ContextEntries();
1911
1912 Control->AddFlags = 1;
1913 if (Add)
1914 Control->AddFlags |= 1 << m_Dci;
1915 if (Drop)
1916 Control->DropFlags = 1 << m_Dci;
1917
1918 RtlZeroMemory(Command, sizeof(*Command));
1919 Command->Trb.Dword[0] = static_cast<ULONG>(InputAddress);
1920 Command->Trb.Dword[1] = static_cast<ULONG>(InputAddress >> 32);
1921 Command->Trb.Dword[3] = XhciEndpointCommandControl(XhciTrbType::ConfigureEndpoint,
1922 0, m_Device->SlotId());
1923 Command->Done = Done;
1924 Command->Context = this;
1925}
1926
1927VOID
1928NTAPI
1931{
1932 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
1934
1935 if (Command->Status == STATUS_NO_SUCH_DEVICE)
1936 {
1937 Self->PostCommandFailure();
1938 return;
1939 }
1940
1941 if (Command->Code == XhciCompletionCode::Success)
1942 {
1944 {
1945 Self->PostEvent(XepEvent::CommandSucceeded);
1946 return;
1947 }
1948
1949 DPRINT1("Endpoint %p DCI %lu in state %lu after a successful stop\n", Self, Self->m_Dci, State);
1951 Self->PostCommandFailure();
1952 return;
1953 }
1954
1955 if (Command->Code == XhciCompletionCode::ContextStateError)
1956 {
1957 switch (State)
1958 {
1960 /* A doorbell raced the stop */
1961 Self->PostEvent(XepEvent::StopFailedRunning);
1962 return;
1963
1965 Self->PostEvent(XepEvent::StopFailedStopped);
1966 return;
1967
1970 {
1971 Self->PostEvent(XepEvent::StopFailedHalted);
1972 return;
1973 }
1974
1975 DPRINT1("Endpoint %p DCI %lu isoch endpoint halted on stop\n", Self, Self->m_Dci);
1977 Self->PostCommandFailure();
1978 return;
1979
1980 default:
1981 DPRINT1("Endpoint %p DCI %lu stop context error in state %lu\n", Self, Self->m_Dci, State);
1983 Self->PostCommandFailure();
1984 return;
1985 }
1986 }
1987
1988 DPRINT1("Endpoint %p DCI %lu Stop Endpoint failed with code %lu\n",
1989 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
1990 Self->m_Controller->VerifierCheck(XHCI_VERIFY_STOP_ENDPOINT);
1992 Self->PostCommandFailure();
1993}
1994
1996VOID
1998 _In_ ULONG StreamId)
1999{
2002
2003 if (StreamId != 0)
2004 {
2005 Ring = m_CurrentStreams->Entry[StreamId - 1].Ring;
2006 Command = &m_CurrentStreams->Entry[StreamId - 1].Command;
2007
2008 if (StreamRingEmpty(StreamId) &&
2009 !m_Controller->HasErrata(XhciErrata::StrmReconfigOnStop))
2010 {
2011 if (StreamCommandDone())
2012 PostEvent(XepEvent::CommandSucceeded);
2013 return;
2014 }
2015
2016 ResetStreamTransferLength(StreamId);
2017 }
2018
2019 Ring->InitializeRing();
2022}
2023
2024VOID
2025NTAPI
2028{
2029 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2030
2031 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2032 {
2033 Self->PostCommandFailure();
2034 return;
2035 }
2036
2037 if (Command->Code != XhciCompletionCode::Success)
2038 {
2039 DPRINT1("Endpoint %p DCI %lu Set TR Dequeue Pointer after stop failed with code %lu\n",
2040 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2041 Self->m_Controller->VerifierCheck(XHCI_VERIFY_CANCEL_DEQUEUE);
2043 Self->PostCommandFailure();
2044 return;
2045 }
2046
2047 if ((Command != &Self->m_Command) && !Self->StreamCommandDone())
2048 return;
2049
2050 Self->PostEvent(XepEvent::CommandSucceeded);
2051}
2052
2053VOID
2054NTAPI
2057{
2058 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2059
2060 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2061 {
2062 Self->PostCommandFailure();
2063 return;
2064 }
2065
2066 /* QUIRK: a Context State error is fatal too, although it could go on to the dequeue update */
2067 if (Command->Code != XhciCompletionCode::Success)
2068 {
2069 DPRINT1("Endpoint %p DCI %lu Reset Endpoint failed with code %lu\n",
2070 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2071 Self->m_Controller->VerifierCheck(XHCI_VERIFY_RESET_ENDPOINT);
2073 Self->PostCommandFailure();
2074 return;
2075 }
2076
2077 Self->m_MainRing->InitializeRing();
2079 Self->m_Controller->m_Commands.Submit(&Self->m_Command);
2080}
2081
2082VOID
2083NTAPI
2086{
2087 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2088
2089 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2090 {
2091 Self->PostCommandFailure();
2092 return;
2093 }
2094
2095 if (Command->Code != XhciCompletionCode::Success)
2096 {
2097 DPRINT1("Endpoint %p DCI %lu Set TR Dequeue Pointer after reset failed with code %lu\n",
2098 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2099 Self->m_Controller->VerifierCheck(XHCI_VERIFY_CONTROL_DEQUEUE);
2101 Self->PostCommandFailure();
2102 return;
2103 }
2104
2106 Self->PostEvent(XepEvent::CommandSucceeded);
2107}
2108
2109VOID
2110NTAPI
2113{
2114 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2115 ULONG StreamId;
2116
2117 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2118 {
2120 Self->PostCommandFailure();
2121 return;
2122 }
2123
2124 if (Command->Code != XhciCompletionCode::Success)
2125 {
2126 DPRINT1("Endpoint %p DCI %lu client Reset Endpoint failed with code %lu\n",
2127 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2128 Self->m_Controller->VerifierCheck(XHCI_VERIFY_RESET_ENDPOINT);
2131 Self->PostCommandFailure();
2132 return;
2133 }
2134
2136
2137 if (!Self->UsesStreams())
2138 {
2139 Self->DequeueAfterReset(0);
2140 return;
2141 }
2142
2144 for (StreamId = 1; StreamId <= Self->m_CurrentStreams->Count; StreamId++)
2145 Self->DequeueAfterReset(StreamId);
2146}
2147
2149VOID
2151 _In_ ULONG StreamId)
2152{
2155
2156 if (StreamId != 0)
2157 {
2158 Ring = m_CurrentStreams->Entry[StreamId - 1].Ring;
2159 Command = &m_CurrentStreams->Entry[StreamId - 1].Command;
2160
2161 if (StreamRingEmpty(StreamId))
2162 {
2163 if (StreamCommandDone())
2164 {
2166 PostEvent(XepEvent::CommandSucceeded);
2167 }
2168 return;
2169 }
2170 }
2171
2174}
2175
2176VOID
2177NTAPI
2180{
2181 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2182
2183 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2184 {
2186 Self->PostCommandFailure();
2187 return;
2188 }
2189
2190 if (Command->Code != XhciCompletionCode::Success)
2191 {
2192 DPRINT1("Endpoint %p DCI %lu Set TR Dequeue Pointer for the client reset failed with code %lu\n",
2193 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2194 Self->m_Controller->VerifierCheck(XHCI_VERIFY_CONTROL_DEQUEUE);
2197 Self->PostCommandFailure();
2198 return;
2199 }
2200
2201 if ((Command != &Self->m_Command) && !Self->StreamCommandDone())
2202 return;
2203
2205 Self->PostEvent(XepEvent::CommandSucceeded);
2206}
2207
2208VOID
2209NTAPI
2212{
2213 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2214 XhciEndpointReset* Data = &XhciGetRequestData(Self->m_ResetRequest)->EndpointReset;
2215 XhciTransferRing* Ring;
2216 ULONG StreamId;
2217
2218 if ((Command->Status == STATUS_NO_SUCH_DEVICE) || (Command->Code != XhciCompletionCode::Success))
2219 {
2220 if (Command->Status != STATUS_NO_SUCH_DEVICE)
2221 {
2222 DPRINT1("Endpoint %p DCI %lu drop for the client reset failed with code %lu\n",
2223 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2225 }
2226
2227 Self->m_Controller->m_Buffers.Free(Data->InputContext);
2228 Data->InputContext = NULL;
2230 Self->PostCommandFailure();
2231 return;
2232 }
2233
2234 for (StreamId = 1; StreamId <= Self->m_CurrentStreams->Count; StreamId++)
2235 {
2236 Ring = Self->m_CurrentStreams->Entry[StreamId - 1].Ring;
2237 Self->ResetStreamTransferLength(StreamId);
2238 Ring->InitializeRing();
2239 Self->StreamContext(StreamId)->DequeuePointer = Ring->DequeuePointerValue();
2240 }
2241
2242 /* Add it back with the endpoint context stashed by the drop */
2243 Self->BuildEndpointConfigure(Data->InputContext, NULL, FALSE, TRUE, &Data->Command, ResetConfigureDone);
2244 Self->InputEndpointContext(Data->InputContext)->TRDequeuePointer = Self->EndpointDequeuePointer();
2245 Self->m_Controller->m_Commands.Submit(&Data->Command);
2246}
2247
2248VOID
2249NTAPI
2252{
2253 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2254 XhciEndpointReset* Data = &XhciGetRequestData(Self->m_ResetRequest)->EndpointReset;
2255
2256 Self->m_Controller->m_Buffers.Free(Data->InputContext);
2257 Data->InputContext = NULL;
2258
2259 /* QUIRK: the client reset succeeds even when the configure fails */
2261
2262 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2263 {
2264 Self->PostCommandFailure();
2265 return;
2266 }
2267
2268 if (Command->Code != XhciCompletionCode::Success)
2269 {
2270 DPRINT1("Endpoint %p DCI %lu add for the client reset failed with code %lu\n",
2271 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2273 Self->PostCommandFailure();
2274 return;
2275 }
2276
2277 Self->PostEvent(XepEvent::CommandSucceeded);
2278}
2279
2280VOID
2281NTAPI
2284{
2285 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2286
2287 if ((Command->Status == STATUS_NO_SUCH_DEVICE) || (Command->Code != XhciCompletionCode::Success))
2288 {
2289 if (Command->Status != STATUS_NO_SUCH_DEVICE)
2290 {
2291 DPRINT1("Endpoint %p DCI %lu drop after stop failed with code %lu\n",
2292 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2294 }
2295
2296 Self->m_Controller->m_Buffers.Free(Self->m_StopInput);
2297 Self->m_StopInput = NULL;
2298 Self->PostCommandFailure();
2299 return;
2300 }
2301
2302 /* Leave the stream context array alone; pending events are matched against the old ring contents */
2305 Self->m_Controller->m_Commands.Submit(&Self->m_Command);
2306}
2307
2308VOID
2309NTAPI
2312{
2313 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Command->Context);
2314
2315 Self->m_Controller->m_Buffers.Free(Self->m_StopInput);
2316 Self->m_StopInput = NULL;
2317
2318 if (Command->Status == STATUS_NO_SUCH_DEVICE)
2319 {
2320 Self->PostCommandFailure();
2321 return;
2322 }
2323
2324 if (Command->Code != XhciCompletionCode::Success)
2325 {
2326 DPRINT1("Endpoint %p DCI %lu add after stop failed with code %lu\n",
2327 Self, Self->m_Dci, static_cast<ULONG>(Command->Code));
2329 Self->PostCommandFailure();
2330 return;
2331 }
2332
2333 Self->SendClearStall();
2334}
2335
2337VOID
2339{
2342 struct _URB_CONTROL_TRANSFER_EX* Urb;
2346 PIRP Irp;
2347
2348 if (m_ClearStall == NULL)
2349 {
2350 PostEvent(XepEvent::CommandSucceeded);
2351 return;
2352 }
2353
2354 Control = m_Device->EndpointAt(1);
2355 if (Control == NULL)
2356 {
2357 /* Post anyway so the endpoint machine does not wait forever */
2358 DPRINT1("Endpoint %p DCI %lu has no default endpoint for the clear stall\n", this, m_Dci);
2359 PostEvent(XepEvent::CommandSucceeded);
2360 return;
2361 }
2362
2363 Irp = m_ClearStall->Irp;
2365
2366 Urb = &m_ClearStall->Urb;
2367 RtlZeroMemory(Urb, sizeof(*Urb));
2368 Urb->Hdr.Length = sizeof(*Urb);
2369 Urb->Hdr.Function = URB_FUNCTION_CONTROL_TRANSFER_EX;
2372
2373 /* UCX never sees this URB, so the control ring picks the current processor's interrupter */
2375
2376 Setup = reinterpret_cast<PUSB_DEFAULT_PIPE_SETUP_PACKET>(Urb->SetupPacket);
2378 Setup->bRequest = USB_REQUEST_CLEAR_FEATURE;
2381 Setup->wLength = 0;
2382
2383 /* Make the top location look like a dispatched internal IOCTL with our routine attached */
2385 RtlZeroMemory(Stack, sizeof(*Stack));
2386 Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
2387 Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
2388 Stack->Parameters.Others.Argument1 = Urb;
2389
2391 if (!NT_SUCCESS(Status))
2393
2395
2399 Reuse.NewIrp = Irp;
2400 WdfRequestReuse(m_ClearStall->Request, &Reuse);
2401
2402 Status = WdfRequestForwardToIoQueue(m_ClearStall->Request, Control->m_MainRing->Queue());
2403 if (!NT_SUCCESS(Status))
2404 {
2405 DPRINT1("Endpoint %p clear stall forward failed 0x%lx\n", this, Status);
2406 WdfRequestComplete(m_ClearStall->Request, Status);
2407 }
2408}
2409
2410/* A failed clear feature only leaves the device sequence number behind, the client recovers */
2412NTAPI
2415 _In_ PIRP Irp,
2416 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
2417{
2418 XhciEndpoint* Self = static_cast<XhciEndpoint*>(Context);
2419
2421
2422 if (!NT_SUCCESS(Irp->IoStatus.Status))
2423 DPRINT1("Endpoint %p clear stall finished with 0x%lx\n", Self, Irp->IoStatus.Status);
2424
2425 Self->PostEvent(XepEvent::CommandSucceeded);
2427}
2428
2429/* Endpoint machine actions ***************************************************/
2430
2431VOID
2433{
2435}
2436
2437VOID
2439{
2441}
2442
2443BOOLEAN
2445{
2446 return WdfTimerStop(m_Endpoint->m_Timer, FALSE);
2447}
2448
2449VOID
2451 _In_ ULONG Milliseconds)
2452{
2453 WdfTimerStart(m_Endpoint->m_Timer, WDF_REL_TIMEOUT_IN_MS(Milliseconds));
2454}
2455
2456/* FIXME: these are ETW events; without ETW support they only go to the debug log */
2457VOID
2460{
2462
2463 switch (Timeout)
2464 {
2465 case XepTimeoutHalt:
2466 DPRINT1("Endpoint %p DCI %lu stop failed as halted but no halt event came\n", Ep, Ep->m_Dci);
2467 break;
2468
2470 DPRINT1("Endpoint %p DCI %lu got no stopped event after the stop\n", Ep, Ep->m_Dci);
2471 break;
2472
2474 DPRINT1("Endpoint %p DCI %lu expected events still missing after the stop\n", Ep, Ep->m_Dci);
2475 break;
2476
2477 default:
2478 DPRINT1("Endpoint %p DCI %lu expected events still missing after the halt\n", Ep, Ep->m_Dci);
2479 break;
2480 }
2481}
2482
2483VOID
2485{
2487
2489 if (Ep->UsesStreams())
2491
2493}
2494
2495VOID
2497{
2499}
2500
2501VOID
2503{
2505
2508}
2509
2510VOID
2512{
2514 WDFREQUEST Request;
2516
2518
2519 Status = Ep->m_ResetStatus;
2521 Request = static_cast<WDFREQUEST>(
2522 InterlockedExchangePointer(reinterpret_cast<PVOID volatile*>(&Ep->m_ResetRequest), NULL));
2523
2524 if (Request == NULL)
2525 return;
2526
2527 /* A controller reset or removal got here first; complete with success, not STATUS_PENDING */
2528 if (Status == STATUS_PENDING)
2530
2531 DPRINT("Endpoint %p client reset completed with 0x%lx\n", Ep, Status);
2532 WdfRequestComplete(Request, Status);
2533}
2534
2535VOID
2537{
2539
2542}
2543
2544VOID
2546{
2548
2550 Ep->PostEvent(XepEvent::StoppedEventSeen);
2551}
2552
2553VOID
2555{
2557}
2558
2559VOID
2561{
2563}
2564
2565VOID
2567{
2569}
2570
2571VOID
2573{
2576
2577 RtlZeroMemory(Command, sizeof(*Command));
2578 Command->Trb.Dword[3] = XhciEndpointCommandControl(XhciTrbType::StopEndpoint,
2579 Ep->m_Dci, Ep->m_Device->SlotId());
2581 Command->Context = Ep;
2582
2583 Ep->m_Controller->m_Commands.Submit(Command);
2584}
2585
2586VOID
2588{
2590}
2591
2592VOID
2594{
2596}
2597
2598VOID
2600{
2602}
2603
2604VOID
2606{
2608}
2609
2610VOID
2612{
2614}
2615
2616/* The endpoint stays referenced until every ring reported its transfers reclaimed */
2617VOID
2619{
2622}
2623
2624VOID
2626{
2627 UcxEndpointNeedToCancelTransfers(m_Endpoint->m_Ucx);
2628}
2629
2630/* Stream queues are purged only when a halt matched no stream transfer */
2631VOID
2633{
2635 ULONG Index;
2636
2637 if (!(Ep->m_Flags & XHCI_EP_STREAM_HALT_PENDING) || !Ep->UsesStreams())
2638 return;
2639
2640 for (Index = 0; Index < Ep->m_CurrentStreams->Count; Index++)
2641 WdfIoQueuePurge(Ep->m_CurrentStreams->Entry[Index].Ring->Queue(), NULL, NULL);
2642}
2643
2644VOID
2646{
2648 ULONG Index;
2649
2650 if (!(Ep->m_Flags & XHCI_EP_STREAM_HALT_PENDING) || !Ep->UsesStreams())
2651 return;
2652
2653 for (Index = 0; Index < Ep->m_CurrentStreams->Count; Index++)
2654 WdfIoQueueStart(Ep->m_CurrentStreams->Entry[Index].Ring->Queue());
2655}
2656
2657/* Resets the data toggle or sequence number of an endpoint that is not halted */
2658VOID
2660{
2662 XhciEndpointReset* Data = &XhciGetRequestData(Ep->m_ResetRequest)->EndpointReset;
2665
2666 Data->InputContext = Ep->m_Controller->m_Buffers.Acquire(Size * XHCI_INPUT_CONTEXT_COUNT);
2667 if (Data->InputContext == NULL)
2668 {
2669 DPRINT1("Endpoint %p DCI %lu no input context for the client reset\n", Ep, Ep->m_Dci);
2671 Ep->PostEvent(XepEvent::BufferAllocFailed);
2672 return;
2673 }
2674
2675 if (Ep->UsesStreams())
2676 {
2677 /* Drop first; the copied endpoint context waits in the buffer for the add */
2678 Ep->BuildEndpointConfigure(Data->InputContext, Original, TRUE, FALSE,
2680 }
2681 else
2682 {
2683 Ep->BuildEndpointConfigure(Data->InputContext, Original, TRUE, TRUE,
2687 }
2688
2689 Ep->m_Controller->m_Commands.Submit(&Data->Command);
2690}
2691
2692/* Some controllers need a stream endpoint configured again after a stop */
2693VOID
2695{
2699
2701 if (Ep->m_StopInput == NULL)
2702 {
2703 DPRINT1("Endpoint %p DCI %lu no input context for the reconfigure after stop\n", Ep, Ep->m_Dci);
2704 Ep->m_Controller->RaiseControllerFault(XhciRecovery::ResetHost, XHCI_REASON_NO_LIVE_DUMP);
2705 Ep->PostCommandFailure();
2706 return;
2707 }
2708
2711 Ep->m_Controller->m_Commands.Submit(&Ep->m_Command);
2712}
2713
2714/* Moves every ring past the canceled transfers */
2715VOID
2717{
2719 ULONG StreamId;
2720
2721 if (!Ep->UsesStreams())
2722 {
2723 Ep->DequeueAfterStop(0);
2724 return;
2725 }
2726
2728 for (StreamId = 1; StreamId <= Ep->m_CurrentStreams->Count; StreamId++)
2729 Ep->DequeueAfterStop(StreamId);
2730}
2731
2732VOID
2734{
2737
2738 RtlZeroMemory(Command, sizeof(*Command));
2739 Command->Trb.Dword[3] = XhciEndpointCommandControl(XhciTrbType::ResetEndpoint,
2740 Ep->m_Dci, Ep->m_Device->SlotId());
2742 Command->Context = Ep;
2743
2744 Ep->m_Controller->m_Commands.Submit(Command);
2745}
2746
2747VOID
2749{
2751 XhciCommand* Command = &XhciGetRequestData(Ep->m_ResetRequest)->EndpointReset.Command;
2752
2753 RtlZeroMemory(Command, sizeof(*Command));
2754 Command->Trb.Dword[3] = XhciEndpointCommandControl(XhciTrbType::ResetEndpoint,
2755 Ep->m_Dci, Ep->m_Device->SlotId());
2758
2760 Command->Context = Ep;
2761
2762 Ep->m_Controller->m_Commands.Submit(Command);
2763}
2764
2765VOID
2767{
2769
2770 DPRINT1("Endpoint %p DCI %lu would not stop after %lu attempts\n", Ep, Ep->m_Dci, Ep->m_StopAttempts);
2771 Ep->m_Controller->VerifierCheck(XHCI_VERIFY_STOP_EXHAUSTED);
2773}
2774
2775/* Endpoint machine queries ***************************************************/
2776
2777BOOLEAN
2779{
2781}
2782
2783BOOLEAN
2785{
2786 return m_Endpoint->m_Controller->HasErrata(XhciErrata::IntPrimaryOnly);
2787}
2788
2789BOOLEAN
2791{
2792 return m_Endpoint->m_Controller->HasErrata(XhciErrata::EpDeferFirstStop);
2793}
2794
2795BOOLEAN
2797{
2799
2800 if (!Controller->HasErrata(XhciErrata::EpStopContextErrorIsStopped))
2801 return FALSE;
2802
2803 NT_ASSERT(Controller->HasErrata(XhciErrata::IntPrimaryOnly));
2804 return TRUE;
2805}
2806
2807BOOLEAN
2809{
2811}
2812
2813BOOLEAN
2815{
2817 ULONG Index;
2818
2819 if (!Ep->UsesStreams())
2820 return Ep->m_MainRing->DoorbellRungSinceFill();
2821
2822 /* QUIRK: asking also resets the shared stream counter */
2824 for (Index = 0; Index < Ep->m_CurrentStreams->Count; Index++)
2825 {
2827 return TRUE;
2828 }
2829
2830 return FALSE;
2831}
2832
2833BOOLEAN
2835{
2836 return m_Endpoint->m_StreamsCapable &&
2837 m_Endpoint->m_Controller->HasErrata(XhciErrata::StrmReconfigOnStop);
2838}
2839
2840BOOLEAN
2842{
2844 ULONG Type = Ep->TransferType();
2845
2846 /* Like the USB 2.0 stack: nothing to do for a preserved state, control or isoch */
2850 {
2852 return FALSE;
2853 }
2854
2855 if (!Ep->AnyTransfersPending())
2856 return TRUE;
2857
2858 /* QUIRK: with transfers pending a bulk or interrupt reset succeeds without a toggle reset */
2860 return FALSE;
2861}
2862
2863BOOLEAN
2865{
2867
2868 if (Ep->m_StreamsCapable && Ep->AnyTransfersPending())
2869 {
2871 return FALSE;
2872 }
2873
2874 return TRUE;
2875}
WCHAR Second[]
Definition: FormatMessage.c:12
WCHAR First[]
Definition: FormatMessage.c:11
Type
Definition: Type.h:7
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 ACPI_NOTIFY_HANDLER void *Context ACPI_ADR_SPACE_TYPE ACPI_ADR_SPACE_HANDLER ACPI_ADR_SPACE_SETUP Setup
Definition: acpixf.h:834
unsigned char BOOLEAN
Definition: actypes.h:127
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
const struct winhelp_callbacks Callbacks
Definition: callback.c:161
BOOLEAN SmPost(_In_ Event Ev)
Definition: smengine.h:370
XhciCommonBuffer m_Buffers
Definition: hc.h:92
BOOLEAN HasErrata(_In_ XhciErrata Bit) const
Definition: hc.h:58
PDEVICE_OBJECT m_WdmDevice
Definition: hc.h:86
XhciCommandRing m_Commands
Definition: hc.h:95
XhciRegisters m_Registers
Definition: hc.h:91
static XhciController * FromUcx(_In_ UCXCONTROLLER UcxController)
Definition: hc.cpp:176
VOID ReportStoppedEvent()
Definition: epctx.cpp:2545
VOID DropStoppedEvent()
Definition: epctx.cpp:2554
VOID ResetStopAttempts()
Definition: epctx.cpp:2560
VOID NotifyRingsClientReset()
Definition: epctx.cpp:2593
VOID UpdateDequeuePointers()
Definition: epctx.cpp:2716
VOID AskUcxToCancel()
Definition: epctx.cpp:2625
BOOLEAN StopAttemptsExhausted()
Definition: epctx.cpp:2808
VOID StartTimer(_In_ ULONG Milliseconds)
Definition: epctx.cpp:2450
VOID ReportTimeout(_In_ XEP_TIMEOUT Timeout)
Definition: epctx.cpp:2458
VOID NotifyRingsReclaim()
Definition: epctx.cpp:2618
VOID ResumeRingFill()
Definition: epctx.cpp:2484
VOID ReconfigureForReset()
Definition: epctx.cpp:2659
VOID AckControllerReset()
Definition: epctx.cpp:2502
VOID ResetEndpoint()
Definition: epctx.cpp:2748
VOID NotifyRingsReclaimOnCancel()
Definition: epctx.cpp:2605
VOID Initialize(_In_ XhciEndpoint *Endpoint)
Definition: epstate.cpp:181
VOID CompleteResetRequestIfAllowed()
Definition: epctx.cpp:2536
VOID SuspendRingFill()
Definition: epctx.cpp:2496
VOID CompleteResetRequest()
Definition: epctx.cpp:2511
BOOLEAN OnPrimaryInterrupterOnly()
Definition: epctx.cpp:2784
VOID SendStopCommand()
Definition: epctx.cpp:2572
VOID PurgeStreamQueues()
Definition: epctx.cpp:2632
BOOLEAN CanResetAfterHalt()
Definition: epctx.cpp:2864
VOID RequestControllerReset()
Definition: epctx.cpp:2766
VOID NotifyRingsHalted()
Definition: epctx.cpp:2587
BOOLEAN IgnoresStopContextError()
Definition: epctx.cpp:2796
VOID CountStopAttempt()
Definition: epctx.cpp:2566
VOID NotifyRingsStoppedEvent()
Definition: epctx.cpp:2599
VOID ResetDefaultPipe()
Definition: epctx.cpp:2733
BOOLEAN StopTimer()
Definition: epctx.cpp:2444
XhciEndpoint * m_Endpoint
Definition: epstate.h:318
BOOLEAN ShouldReconfigureForReset()
Definition: epctx.cpp:2841
BOOLEAN DelaysFirstStop()
Definition: epctx.cpp:2790
VOID DereferenceEndpoint()
Definition: epctx.cpp:2438
BOOLEAN DoorbellRungSinceFill()
Definition: epctx.cpp:2814
VOID ReconfigureAfterStop()
Definition: epctx.cpp:2694
VOID RestartStreamQueues()
Definition: epctx.cpp:2645
BOOLEAN IsControlEndpoint()
Definition: epctx.cpp:2778
BOOLEAN NeedsContextRebuildAfterStop()
Definition: epctx.cpp:2834
VOID ReferenceEndpoint()
Definition: epctx.cpp:2432
VOID NotifyRingsDrainEvents()
Definition: epctx.cpp:2611
ULONG Dci() const
Definition: epctx.cpp:257
static VOID NTAPI ControlDequeueDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2084
static EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtStreamsCleanup
Definition: epctx.h:121
BOOLEAN m_ForwardProgress
Definition: epctx.h:283
PXHCI_ENDPOINT_CONTEXT InputEndpointContext(_In_ XhciDmaBuffer *Input) const
Definition: epctx.cpp:1877
BOOLEAN UsesStreams() const
Definition: epctx.cpp:899
BOOLEAN m_StreamsCapable
Definition: epctx.h:284
BOOLEAN IsStreamsCapable() const
Definition: epctx.cpp:297
ULONG MaxBurst() const
Definition: epctx.cpp:281
static EVT_WDF_IO_QUEUE_STATE EvtPurgeDone
Definition: epctx.h:123
volatile LONG m_Flags
Definition: epctx.h:285
VOID OnStoppedEvent()
Definition: epctx.cpp:1217
ULONG StreamTransferLength(_In_ ULONG StreamId) const
Definition: epctx.cpp:987
static EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanup
Definition: epctx.h:120
static EVT_WDF_IO_QUEUE_STATE EvtAbortDone
Definition: epctx.h:124
NTSTATUS CloseStreams(_In_ XhciStreams *Streams, _In_ WDFREQUEST Request)
Definition: epctx.cpp:1777
XhciController * m_Controller
Definition: epctx.h:278
static XhciEndpoint * FromUcx(_In_ UCXENDPOINT Endpoint)
Definition: epctx.cpp:232
VOID FatalError(_In_ ULONG Reason)
Definition: epctx.cpp:1083
VOID SendClearStall()
Definition: epctx.cpp:2338
BOOLEAN m_Listed
Definition: epctx.h:282
static VOID NTAPI ClientDequeueDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2178
BOOLEAN PostWhenAllRings(_In_ XepEvent Event)
Definition: epctx.cpp:933
VOID BuildEndpointConfigure(_In_ XhciDmaBuffer *Input, _In_opt_ const VOID *EndpointContext, _In_ BOOLEAN Drop, _In_ BOOLEAN Add, _Out_ XhciCommand *Command, _In_ PFN_XHCI_COMMAND_DONE Done)
Definition: epctx.cpp:1888
ULONG TransferType() const
Definition: epctx.cpp:263
UCXENDPOINT Handle() const
Definition: epctx.cpp:251
ULONG StreamHaltedCode() const
Definition: epctx.cpp:1061
static EVT_UCX_ENDPOINT_OK_TO_CANCEL_TRANSFERS EvtOkToCancel
Definition: epctx.h:103
VOID OnTransferCanceled()
Definition: epctx.cpp:1183
ULONG m_StopAttempts
Definition: epctx.h:303
XhciCommand m_Command
Definition: epctx.h:304
static VOID NTAPI StopDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:1929
XhciDmaBuffer * m_StopInput
Definition: epctx.h:305
static EVT_UCX_ENDPOINT_STATIC_STREAMS_DISABLE EvtStreamsDisable
Definition: epctx.h:107
ULONG m_MaxBurst
Definition: epctx.h:297
NTSTATUS m_ResetStatus
Definition: epctx.h:309
static EVT_WDF_TIMER EvtTimer
Definition: epctx.h:122
VOID Cleanup()
Definition: epctx.cpp:466
VOID OnMappingStopped()
Definition: epctx.cpp:1237
static VOID NTAPI StopAddDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2310
BOOLEAN StreamCommandDone()
Definition: epctx.cpp:962
VOID OnTransferEvent(_In_ const XHCI_TRB *Event)
Definition: epctx.cpp:1102
static VOID NTAPI DefaultUpdateDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:1515
static VOID NTAPI ResetConfigureDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2250
const USB_ENDPOINT_DESCRIPTOR * Descriptor() const
Definition: epctx.cpp:269
static VOID NTAPI ResetDropDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2210
PXHCI_STREAM_CONTEXT StreamContext(_In_ ULONG StreamId) const
Definition: epctx.cpp:969
static EVT_UCX_ENDPOINT_ABORT EvtAbort
Definition: epctx.h:101
static VOID NTAPI StreamsEnableDone(_In_ PVOID Context, _In_ NTSTATUS Status)
Definition: epctx.cpp:1724
VOID OnHaltedCompletionCode(_In_ ULONG CompletionCode, _In_ BOOLEAN TransferFound)
Definition: epctx.cpp:1190
VOID BuildContext(_Out_writes_bytes_(ContextSize) PVOID EndpointContext, _In_ ULONG ContextSize) const
Definition: epctx.cpp:754
XhciUsbDevice * Device() const
Definition: epctx.cpp:245
PENDPOINT_RESET ResetPayload() const
Definition: epctx.cpp:1096
static VOID NTAPI CancelDequeueDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2026
VOID OnExpectedEventsProcessed()
Definition: epctx.cpp:1231
VOID PostCommandFailure()
Definition: epctx.cpp:1076
static IO_COMPLETION_ROUTINE ClearStallDone
Definition: epctx.h:125
USHORT MaxPacketSize() const
Definition: epctx.cpp:275
USB_ENDPOINT_DESCRIPTOR m_Descriptor
Definition: epctx.h:290
BOOLEAN StreamRingEmpty(_In_ ULONG StreamId) const
Definition: epctx.cpp:1051
static VOID NTAPI ClientResetDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2111
static VOID NTAPI ControlResetDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2055
USB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR m_IsochCompanion
Definition: epctx.h:292
NTSTATUS Initialize(_In_ XhciController *Controller, _In_ UCXUSBDEVICE UcxUsbDevice, _In_ UCXENDPOINT Endpoint, _In_ const USB_ENDPOINT_DESCRIPTOR *Descriptor, _In_opt_ const USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR *Companion, _In_opt_ const USB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR *IsochCompanion)
Definition: epctx.cpp:342
VOID ForEachRing(_In_ VOID(XhciTransferRing::*Action)())
Definition: epctx.cpp:918
ULONG OutputEndpointState() const
Definition: epctx.cpp:1090
NTSTATUS CreateClearStall()
Definition: epctx.cpp:428
VOID ControllerRemoved()
Definition: epctx.cpp:1270
HaltClearBlock * m_ClearStall
Definition: epctx.h:306
BOOLEAN ShouldDropStoppedEvent() const
Definition: epctx.cpp:1211
UCXUSBDEVICE m_UcxDevice
Definition: epctx.h:280
ULONG64 EndpointDequeuePointer() const
Definition: epctx.cpp:885
VOID BuildSetDequeue(_Out_ XhciCommand *Command, _In_ ULONG64 DequeuePointer, _In_ ULONG StreamId, _In_ PFN_XHCI_COMMAND_DONE Done)
Definition: epctx.cpp:1860
static EVT_UCX_ENDPOINT_PURGE EvtPurge
Definition: epctx.h:99
WDFREQUEST volatile m_ResetRequest
Definition: epctx.h:308
static NTSTATUS NTAPI EvtEnableForwardProgress(_In_ UCXENDPOINT Endpoint, _In_ ULONG MaxTransferSize)
Definition: epctx.cpp:1424
XhciController * Controller() const
Definition: epctx.cpp:239
VOID DequeueAfterStop(_In_ ULONG StreamId)
Definition: epctx.cpp:1997
XhciTransferRing * m_MainRing
Definition: epctx.h:288
static EVT_UCX_DEFAULT_ENDPOINT_UPDATE EvtDefaultUpdate
Definition: epctx.h:104
static EVT_UCX_ENDPOINT_STATIC_STREAMS_ADD EvtStreamsAdd
Definition: epctx.h:105
KEVENT m_ResetAck
Definition: epctx.h:286
ULONG RingCount() const
Definition: epctx.cpp:905
static NTSTATUS Create(_In_ UCXCONTROLLER UcxController, _In_ UCXUSBDEVICE UcxUsbDevice, _In_ PUCXENDPOINT_INIT EndpointInit, _In_ const USB_ENDPOINT_DESCRIPTOR *Descriptor, _In_opt_ const USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR *Companion, _In_opt_ const USB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR *IsochCompanion)
Definition: epctx.cpp:305
XhciEndpointMachine m_Machine
Definition: epctx.h:69
XhciStreams * m_DefaultStreams
Definition: epctx.h:300
ULONG m_MaxPayload
Definition: epctx.h:298
VOID OnTransfersReclaimed()
Definition: epctx.cpp:1243
BOOLEAN AnyTransfersPending() const
Definition: epctx.cpp:947
XhciTransferRing * RingAt(_In_ ULONG Index) const
Definition: epctx.cpp:911
VOID DisableRings(_In_ BOOLEAN SlotDisabling)
Definition: epctx.cpp:715
XhciStreams * m_CurrentStreams
Definition: epctx.h:301
USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR m_Companion
Definition: epctx.h:291
ULONG MaxEsitPayload() const
Definition: epctx.cpp:291
VOID ResetStreamTransferLength(_In_ ULONG StreamId)
Definition: epctx.cpp:1027
static EVT_UCX_ENDPOINT_START EvtStart
Definition: epctx.h:100
ULONG m_Dci
Definition: epctx.h:294
static VOID NTAPI StreamsDisableDone(_In_ PVOID Context, _In_ NTSTATUS Status)
Definition: epctx.cpp:1820
VOID PostEvent(_In_ XepEvent Event)
Definition: epctx.cpp:1069
ULONG m_XhciType
Definition: epctx.h:293
ULONG64 StreamDequeuePointer(_In_ ULONG StreamId) const
Definition: epctx.cpp:976
VOID DequeueAfterReset(_In_ ULONG StreamId)
Definition: epctx.cpp:2150
VOID DisableStreamRings(_In_ XhciStreams *Streams)
Definition: epctx.cpp:1623
UCXENDPOINT m_Ucx
Definition: epctx.h:281
XhciUsbDevice * m_Device
Definition: epctx.h:279
VOID FreeDefaultStreams(_In_opt_ XhciStreams *Streams)
Definition: epctx.cpp:499
static EVT_UCX_ENDPOINT_STATIC_STREAMS_ENABLE EvtStreamsEnable
Definition: epctx.h:106
VOID ControllerResetStarting()
Definition: epctx.cpp:1253
WDFTIMER m_Timer
Definition: epctx.h:287
static EVT_UCX_ENDPOINT_RESET EvtReset
Definition: epctx.h:102
static VOID NTAPI StopDropDone(_In_ XhciCommand *Command)
Definition: epctx.cpp:2282
NTSTATUS OpenStreams(_In_ XhciStreams *Streams, _In_ WDFREQUEST Request)
Definition: epctx.cpp:1648
ULONG SupportedStreams() const
Definition: mmio.cpp:585
ULONG ContextSize() const
Definition: mmio.cpp:651
VOID AllowReclaimOnCancel()
Definition: xferring.cpp:730
ULONG64 DequeuePointerValue() const
Definition: xferring.cpp:670
BOOLEAN OnTransferEvent(_In_ const XHCI_TRB *Event)
Definition: xferring.cpp:787
ULONG64 EnqueuePointer() const
Definition: xferring.cpp:664
static NTSTATUS Create(_In_ XhciEndpoint *Endpoint, _In_ WDFOBJECT Parent, _In_ ULONG StreamId, _Out_ XhciTransferRing **Ring)
VOID ConsumePendingEvents()
Definition: xferring.cpp:741
VOID OnClientPipeReset()
Definition: xferring.cpp:714
ULONG64 SegmentBase() const
Definition: xferring.cpp:658
VOID SuspendRingFill()
Definition: xferring.cpp:695
BOOLEAN IsLikelyDuplicate(_In_ const XHCI_TRB *Event) const
Definition: xferring.cpp:843
BOOLEAN DoorbellRungSinceFill() const
Definition: xferring.cpp:763
VOID InitializeRing()
Definition: xferring.cpp:648
VOID OnPipeHalted()
Definition: xferring.cpp:706
WDFQUEUE Queue() const
Definition: xferring.cpp:315
VOID ResumeRingFill()
Definition: xferring.cpp:684
VOID StoppedEventReceived()
Definition: xferring.cpp:722
VOID RecoverTransfers()
Definition: xferring.cpp:752
ULONG SlotId() const
Definition: slotdev.cpp:335
const USB_DEVICE_DESCRIPTOR * DeviceDescriptor() const
Definition: slotdev.cpp:365
static XhciUsbDevice * FromUcx(_In_ UCXUSBDEVICE UsbDevice)
Definition: slotdev.cpp:178
PVOID OutputContext(_In_ ULONG Dci) const
Definition: slotdev.cpp:269
USB_DEVICE_SPEED Speed() const
Definition: slotdev.cpp:341
const USB_DEVICE_PORT_PATH * PortPath() const
Definition: slotdev.cpp:371
ULONG ContextEntries() const
Definition: slotdev.cpp:321
VOID(NTAPI * PFN_XHCI_COMMAND_DONE)(_In_ XhciCommand *Command)
Definition: cmdring.h:13
Walk Base
Definition: desccheck.cpp:2270
_Inout_ HubConfiguration ** Slot
Definition: devhcd.cpp:1260
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
KEVENT Done
Definition: devreq.cpp:1162
_In_ ULONG Attributes
Definition: dispmprt.h:1077
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
Definition: dispmprt.h:321
_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 InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#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 KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define NonPagedPool
Definition: env_spec_w32.h:307
#define XHCI_VERIFY_CANCEL_DEQUEUE
Definition: epctx.cpp:33
#define XHCI_REASON_CONTROL_RESET
Definition: epctx.cpp:44
#define XHCI_VERIFY_RESET_ENDPOINT
Definition: epctx.cpp:32
#define XHCI_REASON_RECONFIGURE
Definition: epctx.cpp:55
#define XHCI_REASON_STOP_ERROR
Definition: epctx.cpp:41
#define XHCI_REASON_CANCEL_DEQUEUE
Definition: epctx.cpp:45
#define XHCI_REASON_EVENT_DATA_POINTER
Definition: epctx.cpp:51
#define XHCI_EP_FAILURE_REPORTED
Definition: epctx.cpp:21
#define XHCI_REASON_STREAM_RECONFIGURE
Definition: epctx.cpp:54
#define XHCI_CLEAR_STALL_TIMEOUT_MS
Definition: epctx.cpp:60
#define XHCI_EP_STREAM_HALT_PENDING
Definition: epctx.cpp:22
#define XHCI_TAG_ENDPOINT
Definition: epctx.cpp:17
#define XHCI_EP_STOPPED_HANDSHAKE
Definition: epctx.cpp:23
#define XHCI_REASON_STOP_ADD_FAILED
Definition: epctx.cpp:50
#define XHCI_STOP_ATTEMPTS_MAX
Definition: epctx.cpp:59
#define XHCI_EP_CANCEL_REPORTED
Definition: epctx.cpp:20
#define XHCI_REASON_EVENT_CODE
Definition: epctx.cpp:46
#define XHCI_RECLAIM_TAG
Definition: epctx.cpp:58
#define XHCI_VERIFY_STOP_ENDPOINT
Definition: epctx.cpp:36
#define XHCI_EP_IGNORE_STOPPED
Definition: epctx.cpp:26
#define XHCI_REASON_NO_LIVE_DUMP
Definition: epctx.cpp:40
#define XHCI_EP_STOPPED_RECEIVED
Definition: epctx.cpp:24
static BOOLEAN NTAPI XhciIsHaltedCode(_In_ ULONG Code)
Definition: epctx.cpp:138
static ULONG NTAPI XhciMaxPrimaryStreams(_In_ ULONG Count)
Definition: epctx.cpp:115
#define XHCI_CLEAR_STALL_STACK_SIZE
Definition: epctx.cpp:61
#define XHCI_VERIFY_CONTROL_DEQUEUE
Definition: epctx.cpp:31
#define XHCI_REASON_CONTROL_DEQUEUE
Definition: epctx.cpp:43
static ULONG NTAPI XhciStreamsSize(_In_ ULONG Count)
Definition: epctx.cpp:105
static BOOLEAN NTAPI XhciIsStoppedCode(_In_ ULONG Code)
Definition: epctx.cpp:161
static ULONG NTAPI XhciStreamArrayBytes(_In_ ULONG MaxPrimary)
Definition: epctx.cpp:129
static XhciStreams *NTAPI XhciNewDefaultStreams(_In_ XhciEndpoint *Endpoint, _In_ XhciTransferRing *MainRing, _In_ ULONG ArrayMaxPrimary)
Definition: epctx.cpp:200
#define XHCI_REASON_CLIENT_DEQUEUE
Definition: epctx.cpp:48
#define XHCI_EP_HALT_RECEIVED
Definition: epctx.cpp:25
static PURB NTAPI XhciRequestUrb(_In_ WDFREQUEST Request)
Definition: epctx.cpp:186
#define XHCI_REASON_CLIENT_RESET
Definition: epctx.cpp:49
#define XHCI_REASON_DUPLICATE_POINTER
Definition: epctx.cpp:53
#define XHCI_VERIFY_STOP_EXHAUSTED
Definition: epctx.cpp:34
#define XHCI_EP_RESET_ACK_HANDSHAKE
Definition: epctx.cpp:27
#define XHCI_REASON_DROP_FAILED
Definition: epctx.cpp:47
#define XHCI_REASON_NOT_STOPPED
Definition: epctx.cpp:56
#define XHCI_VERIFY_DUPLICATE_EVENT
Definition: epctx.cpp:37
static ULONG NTAPI XhciEndpointCommandControl(_In_ enum XhciTrbType Type, _In_ ULONG Dci, _In_ ULONG SlotId)
Definition: epctx.cpp:173
#define XHCI_REASON_EVENT_POINTER
Definition: epctx.cpp:52
#define XHCI_REQUEST_REUSE_MUST_COMPLETE
Definition: epctx.cpp:64
#define XHCI_EP_CLIENT_RESET_HANDSHAKE
Definition: epctx.cpp:28
#define XHCI_VERIFY_EVENT_CODE
Definition: epctx.cpp:35
#define XHCI_REASON_STOP_CONTEXT
Definition: epctx.cpp:42
XepEvent
Definition: epstate.h:15
@ XepTimeoutStoppedEvent
Definition: epstate.h:51
@ XepTimeoutDrainAfterStop
Definition: epstate.h:52
@ XepTimeoutHalt
Definition: epstate.h:50
enum _XEP_TIMEOUT XEP_TIMEOUT
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T ContextSize
Definition: fltkernel.h:1444
@ Pending
Definition: fs_rec.h:186
return pRequest Reuse(ReuseParams)
Status
Definition: gdiplustypes.h:24
#define USB3_URB_RESERVED_RESOURCES
Definition: hubreq.cpp:15
_Must_inspect_result_ _In_ UCXUSBDEVICE _In_ ULONG MaxPacketSize
Definition: hubucx.h:289
_Must_inspect_result_ _In_ UCXUSBDEVICE _In_ ULONG _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR Companion
Definition: hubucx.h:308
_In_ UCXHUB_DEVICE_CONTEXT _In_ UCXENDPOINT Endpoint
Definition: hubucx.h:238
#define InterlockedOr
Definition: interlocked.h:239
#define InterlockedXor
Definition: interlocked.h:281
#define InterlockedAnd
Definition: interlocked.h:77
NTSTATUS NTAPI IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PIO_COMPLETION_ROUTINE CompletionRoutine, IN PVOID Context, IN BOOLEAN InvokeOnSuccess, IN BOOLEAN InvokeOnError, IN BOOLEAN InvokeOnCancel)
Definition: iocomp.c:220
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
_In_ PIRP Irp
Definition: kse.h:79
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned __int64 ULONG64
Definition: imports.h:198
PVOID PVOID PWCHAR PVOID USHORT PULONG Reason
Definition: env.c:47
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define min(a, b)
Definition: monoChain.cc:55
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
_In_ ULONG Number
Definition: haltypes.h:1940
#define KernelMode
Definition: asm.h:38
DWORD Interval
Definition: netstat.c:28
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_
Definition: no_sal2.h:160
#define _In_reads_opt_(s)
Definition: no_sal2.h:222
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:647
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:2003
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1698
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static ULONG Timeout
Definition: ping.c:61
_In_ ULONG MaxTransferSize
Definition: pipe.h:72
_In_ ULONG _In_ WDFMEMORY Input
Definition: portacpi.cpp:109
#define volatile
Definition: prototyp.h:117
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
Definition: shell.h:41
ULONG Size
Definition: dmapool.h:18
PHYSICAL_ADDRESS LogicalAddress
Definition: dmapool.h:17
PVOID VirtualAddress
Definition: dmapool.h:16
struct _URB_CONTROL_TRANSFER_EX Urb
Definition: epctx.cpp:94
XhciTransferRing * Ring
Definition: epctx.cpp:69
XhciCommand Command
Definition: epctx.cpp:70
volatile LONG UpdateCount
Definition: epctx.cpp:83
volatile LONG StreamsLeftToFlush
Definition: epctx.cpp:82
XhciEndpoint * Endpoint
Definition: epctx.cpp:79
ULONG Count
Definition: epctx.cpp:80
ULONG MaxPrimary
Definition: epctx.cpp:81
ULONG HaltedCode
Definition: epctx.cpp:84
XhciDmaBuffer * ContextArray
Definition: epctx.cpp:85
XhciStreamEntry Entry[1]
Definition: epctx.cpp:86
UCXENDPOINT DefaultEndpoint
Definition: ucxendpoint.h:55
ENDPOINT_RESET_FLAGS Flags
Definition: ucxendpoint.h:49
Definition: usb.h:565
struct _USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR::@4130::@4132 Isochronous
union _USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR::@4130 bmAttributes
struct _USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR::@4130::@4131 Bulk
BOOLEAN AutomaticSerialization
Definition: wdftimer.h:90
ULONG64 TRDequeuePointer
Definition: xhcihw.h:514
ULONG64 DequeuePointer
Definition: xhcihw.h:599
#define max(a, b)
Definition: svc.c:63
#define STATUS_PENDING
Definition: telnetd.h:14
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned char * PUCHAR
Definition: typedefs.h:53
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_ WDFREQUEST Request
FORCEINLINE VOID NTAPI UCX_ENDPOINT_EVENT_CALLBACKS_INIT(_Out_ PUCX_ENDPOINT_EVENT_CALLBACKS Callbacks, _In_ PFN_UCX_ENDPOINT_PURGE EvtEndpointPurge, _In_ PFN_UCX_ENDPOINT_START EvtEndpointStart, _In_ PFN_UCX_ENDPOINT_ABORT EvtEndpointAbort, _In_ PFN_UCX_ENDPOINT_RESET EvtEndpointReset, _In_ PFN_UCX_ENDPOINT_OK_TO_CANCEL_TRANSFERS EvtEndpointOkToCancelTransfers, _In_ PFN_UCX_ENDPOINT_STATIC_STREAMS_ADD EvtEndpointStaticStreamsAdd, _In_ PFN_UCX_ENDPOINT_STATIC_STREAMS_ENABLE EvtEndpointStaticStreamsEnable, _In_ PFN_UCX_ENDPOINT_STATIC_STREAMS_DISABLE EvtEndpointStaticStreamsDisable)
Definition: ucxendpoint.h:237
@ FlagEndpointResetPreserveTransferState
Definition: ucxendpoint.h:16
FORCEINLINE VOID NTAPI UcxDefaultEndpointInitSetEventCallbacks(_Inout_ PUCXENDPOINT_INIT EndpointInit, _In_ PUCX_DEFAULT_ENDPOINT_EVENT_CALLBACKS EventCallbacks)
Definition: ucxendpoint.h:441
FORCEINLINE VOID NTAPI UcxEndpointInitSetEventCallbacks(_Inout_ PUCXENDPOINT_INIT EndpointInit, _In_ PUCX_ENDPOINT_EVENT_CALLBACKS EventCallbacks)
Definition: ucxendpoint.h:427
FORCEINLINE VOID NTAPI UCX_DEFAULT_ENDPOINT_EVENT_CALLBACKS_INIT(_Out_ PUCX_DEFAULT_ENDPOINT_EVENT_CALLBACKS Callbacks, _In_ PFN_UCX_ENDPOINT_PURGE EvtEndpointPurge, _In_ PFN_UCX_ENDPOINT_START EvtEndpointStart, _In_ PFN_UCX_ENDPOINT_ABORT EvtEndpointAbort, _In_ PFN_UCX_ENDPOINT_OK_TO_CANCEL_TRANSFERS EvtEndpointOkToCancelTransfers, _In_ PFN_UCX_DEFAULT_ENDPOINT_UPDATE EvtDefaultEndpointUpdate)
Definition: ucxendpoint.h:276
FORCEINLINE VOID NTAPI UcxEndpointSetWdfIoQueue(_In_ UCXENDPOINT Endpoint, _In_ WDFQUEUE WdfQueue)
Definition: ucxendpoint.h:455
_Must_inspect_result_ _In_ UCXUSBDEVICE _Inout_ PUCXENDPOINT_INIT * EndpointInit
Definition: ucxendpoint.h:314
_In_ ULONG NumberOfStreams
Definition: ucxendpoint.h:165
FORCEINLINE VOID NTAPI UcxStaticStreamsSetStreamInfo(_In_ UCXSSTREAMS StaticStreams, _In_ PSTREAM_INFO StreamInfo)
Definition: ucxsstreams.h:60
WDF_EXTERN_C_START struct _STREAM_INFO STREAM_INFO
FORCEINLINE VOID NTAPI STREAM_INFO_INIT(_Out_ PSTREAM_INFO StreamInfo, _In_ WDFQUEUE WdfQueue, _In_ ULONG StreamId)
Definition: ucxsstreams.h:26
_In_ UCXUSBDEVICE _In_ ULONG _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR SuperSpeedEndpointCompanionDescriptor
Definition: ucxusbdevice.h:303
_In_ UCXUSBDEVICE _In_ ULONG UsbEndpointDescriptorBufferLength
Definition: ucxusbdevice.h:302
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: usb100.h:65
#define USB_FEATURE_ENDPOINT_STALL
Definition: usb100.h:102
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usb100.h:53
#define USB_ENDPOINT_TYPE_CONTROL
Definition: usb100.h:62
#define BMREQUEST_HOST_TO_DEVICE
Definition: usb100.h:31
#define BMREQUEST_TO_ENDPOINT
Definition: usb100.h:40
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
#define BMREQUEST_STANDARD
Definition: usb100.h:34
#define USB_REQUEST_CLEAR_FEATURE
Definition: usb100.h:79
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
#define USB_ENDPOINT_TYPE_BULK
Definition: usb100.h:64
#define USB_ENDPOINT_DIRECTION_IN(x)
Definition: usb100.h:76
@ UsbSuperSpeed
Definition: usb200.h:45
@ UsbHighSpeed
Definition: usb200.h:44
@ UsbLowSpeed
Definition: usb200.h:42
@ UsbFullSpeed
Definition: usb200.h:43
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
#define USB_ENDPOINT_ADDRESS_MASK
Definition: usb300.h:64
#define USBD_STATUS_INTERNAL_HC_ERROR
Definition: usb.h:207
#define USBD_STATUS_SUCCESS
Definition: usb.h:177
#define USBD_STATUS_INSUFFICIENT_RESOURCES
Definition: usb.h:215
#define USBD_STATUS_INVALID_PARAMETER
Definition: usb.h:203
#define USBD_DEFAULT_PIPE_TRANSFER
Definition: usb.h:163
_In_opt_ PUSB_CONFIGURATION_DESCRIPTOR _Inout_ PUSBD_INTERFACE_LIST_ENTRY _Outptr_ PURB * Urb
Definition: usbdlib.h:333
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:32
USHORT Count
Definition: userreq.cpp:200
WdfObjectDelete(String)
WDFSTRING Original
Definition: userreq.cpp:198
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFCOLLECTION _In_ ULONG Index
FORCEINLINE LONGLONG WDF_REL_TIMEOUT_IN_MS(_In_ ULONGLONG Time)
Definition: wdfcore.h:80
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2231
_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_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
#define WdfObjectDereferenceWithTag(Handle, Tag)
Definition: wdfobject.h:829
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 WdfObjectReference(Handle)
Definition: wdfobject.h:803
#define WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(_contexttype, _castingfunction)
Definition: wdfobject.h:350
#define WdfObjectReferenceWithTag(Handle, Tag)
Definition: wdfobject.h:806
#define WdfObjectDereference(Handle)
Definition: wdfobject.h:826
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
@ WDF_REQUEST_REUSE_SET_NEW_IRP
Definition: wdfrequest.h:93
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
FORCEINLINE VOID WDF_REQUEST_REUSE_PARAMS_INIT(_Out_ PWDF_REQUEST_REUSE_PARAMS Params, _In_ ULONG Flags, _In_ NTSTATUS Status)
Definition: wdfrequest.h:364
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
FORCEINLINE VOID WDF_TIMER_CONFIG_INIT(_Out_ PWDF_TIMER_CONFIG Config, _In_ PFN_WDF_TIMER EvtTimerFunc)
Definition: wdftimer.h:111
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
static VOID FreeResources(VOID)
Definition: welcome.c:710
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2721
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2706
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1304
@ Executive
Definition: ketypes.h:467
#define NT_ASSERT
Definition: rtlfuncs.h:3334
#define XHCI_URB_NO_PROCESSOR
Definition: xferring.h:15
EVT_UCX_USBDEVICE_DEFAULT_ENDPOINT_ADD XhciEvtUsbDeviceDefaultEndpointAdd
Definition: xhcidrv.h:52
EVT_UCX_USBDEVICE_ENDPOINT_ADD XhciEvtUsbDeviceEndpointAdd
Definition: xhcidrv.h:53
#define XHCI_ENDPOINT_TYPE_CONTROL
Definition: xhcihw.h:543
#define XHCI_TRB_TYPE_SHIFT
Definition: xhcihw.h:23
FORCEINLINE ULONG64 NTAPI XhciTrbPointer(_In_ const XHCI_TRB *Trb)
Definition: xhcihw.h:60
#define XHCI_TRANSFER_EVENT_ED
Definition: xhcihw.h:321
#define XHCI_CMD_STREAM_ID_SHIFT
Definition: xhcihw.h:590
#define XHCI_TRB_ENDPOINT_SHIFT
Definition: xhcihw.h:26
#define XHCI_CMD_TRANSFER_STATE_PRESERVE
Definition: xhcihw.h:586
struct _XHCI_STREAM_CONTEXT XHCI_STREAM_CONTEXT
#define XHCI_TRB_SLOT_SHIFT
Definition: xhcihw.h:25
#define XHCI_ENDPOINT_STATE_STOPPED
Definition: xhcihw.h:536
#define XHCI_INPUT_CONTEXT_COUNT
Definition: xhcihw.h:450
XhciTrbType
Definition: xhcihw.h:68
XhciCompletionCode
Definition: xhcihw.h:110
#define XHCI_STREAM_EDTLA_MASK
Definition: xhcihw.h:606
#define XHCI_ENDPOINT_STATE_RUNNING
Definition: xhcihw.h:534
#define XHCI_ENDPOINT_STATE_HALTED
Definition: xhcihw.h:535
FORCEINLINE ULONG NTAPI XhciTrbCompletionCode(_In_ const XHCI_TRB *Trb)
Definition: xhcihw.h:42