ReactOS 0.4.17-dev-1281-g065abb3
rootports.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: Root hub ports and the UCX root hub callbacks
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "xhcidrv.h"
10
11#define NDEBUG
12#include <debug.h>
13
14/* Hub class requests (USB 2.0 11.24.2, USB 3.x 10.16.2) */
15static const UCHAR HubRequestToHub = 0x20;
16static const UCHAR HubRequestFromHub = 0xA0;
17static const UCHAR HubRequestToPort = 0x23;
18static const UCHAR HubRequestFromPort = 0xA3;
19
21{
44};
45
46/* Default TDRSMDN; USB 2.0 7.1.7.7 asks for at least 20 ms */
47static const ULONG XhciResumeSignalMs = 50;
48
49/* Busy wait budgets in 10 us steps */
50static const ULONG XhciU3WaitSteps = 2400;
51static const ULONG XhciU0WaitSteps = 1200;
52static const ULONG XhciResumeWaitSteps = 1200;
53
54static const ULONG XhciPortGone = 0xFFFFFFFF;
55
57{
60
62
67 _In_ ULONG PortSc)
68{
70}
71
76 _In_ ULONG PortSc)
77{
79}
80
87{
89}
90
96 _In_ ULONG PortSc)
97{
99
100 if ((PortSc & Needed) != Needed || (PortSc & XHCI_PORTSC_CSC))
101 return FALSE;
102
103 return XhciLinkState(PortSc) != PORT_LINK_STATE_DISABLED;
104}
105
106static
107PVOID
108NTAPI
110 _In_ WDFREQUEST Request)
111{
113
115 WdfRequestGetParameters(Request, &Parameters);
116 return Parameters.Parameters.Others.Arg1;
117}
118
121NTAPI
123 _In_ PURB Urb)
124{
125 /* Same offset in the plain and the _EX control transfer URBs */
126 return (PUSB_DEFAULT_PIPE_SETUP_PACKET)Urb->UrbControlTransfer.SetupPacket;
127}
128
130static
131PVOID
132NTAPI
137 _In_ ULONG Needed)
138{
139 if (Length < Needed)
140 return NULL;
141
142 if (Buffer == NULL && Mdl != NULL)
144
145 return Buffer;
146}
147
148static
149PVOID
150NTAPI
152 _In_ PURB Urb,
153 _In_ ULONG Needed)
154{
155 struct _URB_CONTROL_TRANSFER* Transfer = &Urb->UrbControlTransfer;
156
157 return XhciTransferBuffer(Transfer->TransferBuffer,
158 Transfer->TransferBufferMDL,
159 Transfer->TransferBufferLength,
160 Needed);
161}
162
163static
164VOID
165NTAPI
168 _In_ PURB Urb)
169{
171
172 DPRINT1("Root hub %s: rejecting setup %02x %02x %04x %04x %04x\n",
173 Callback, Setup->bmRequestType.B, Setup->bRequest, Setup->wValue.W, Setup->wIndex.W, Setup->wLength);
174}
175
176/* Lifetime *******************************************************************/
177
180 _In_ UCXROOTHUB UcxRootHub)
181{
182 return XhciGetRootHubContext(UcxRootHub)->RootHub;
183}
184
188{
191 UCXROOTHUB Handle;
193
195 m_Ucx = NULL;
196 m_Ports = NULL;
197 m_PortCount = 0;
202
215
216 /* UCX gives this context to every request it sends down for the root hub and its devices */
218
220
221 Status = UcxRootHubCreate(Controller->m_Ucx, &Config, &Attributes, &Handle);
222 if (!NT_SUCCESS(Status))
223 {
224 DPRINT1("UcxRootHubCreate failed 0x%lx\n", Status);
225 return Status;
226 }
227
228 XhciGetRootHubContext(Handle)->RootHub = this;
229 m_Ucx = Handle;
230 return STATUS_SUCCESS;
231}
232
236 _In_ ULONG Capability,
238{
241 ULONG Name;
242 ULONG Ports;
243 ULONG First;
244 ULONG Count;
246 UCHAR Major;
247
248 *Usable = FALSE;
249
250 Revision = Registers->ReadExtended32(Capability + XHCI_PROTOCOL_REVISION);
251 Name = Registers->ReadExtended32(Capability + XHCI_PROTOCOL_NAME);
252 Ports = Registers->ReadExtended32(Capability + XHCI_PROTOCOL_PORTS);
253
255 {
256 DPRINT1("Protocol capability at 0x%lx has name 0x%08lx, skipped\n", Capability, Name);
257 return STATUS_SUCCESS;
258 }
259
261 if (Major != 2 && Major != 3)
262 {
263 DPRINT1("USB protocol capability at 0x%lx with major revision %u, skipped\n", Capability, Major);
264 return STATUS_SUCCESS;
265 }
266
269 if (First == 0 || Count == 0 || First + Count - 1 > m_PortCount)
270 {
271 DPRINT1("USB %u protocol covers ports %lu+%lu, controller has %lu\n", Major, First, Count, m_PortCount);
273 }
274
275 *Usable = TRUE;
276
277 if (Major == 3)
279
280 for (Number = First; Number < First + Count; Number++)
281 {
282 Port* P = &m_Ports[Number - 1];
283
284 if (P->Major != 0)
285 {
286 DPRINT1("Port %lu claimed by USB %u and USB %u protocol capabilities\n", Number, P->Major, Major);
288 }
289
290 if (Major == 2)
292 else
294
295 P->Major = Major;
297 P->HighSpeedOnly = (Ports & XHCI_PROTOCOL_HSO) != 0;
298 P->IntegratedHub = (Ports & XHCI_PROTOCOL_IHI) != 0;
299 P->LpmCapabilities = 0;
301 P->LpmCapabilities |= 0x01;
303 P->LpmCapabilities |= 0x02;
305 P->SpeedCount = (UCHAR)(Ports >> XHCI_PROTOCOL_PSIC_SHIFT);
306 P->SpeedTable = Capability + XHCI_PROTOCOL_PSI;
307 P->Removable = (Registers->ReadPort32(Number, XHCI_PORT_SC) & XHCI_PORTSC_DR) == 0;
308 }
309
310 return STATUS_SUCCESS;
311}
312
315{
317 BOOLEAN AnyUsable = FALSE;
320 ULONG Capability;
323
324 m_PortCount = Registers->MaxPorts();
327
328 Params = Registers->Hcsparams3();
331
332 Capability = Registers->FindExtendedCapability(XHCI_EXTCAP_DEBUG, 0);
333 if (Capability != 0)
334 m_DebugCapability = Capability;
335
336 Capability = Registers->FindExtendedCapability(XHCI_EXTCAP_USB4_TUNNELING, 0);
337 m_PortScTunnelValid = Capability != 0 &&
338 (Registers->ReadExtended32(Capability) & XHCI_USB4_CAP_PORTSC_TUNNEL_VALID) != 0;
340
341 if (m_PortCount == 0)
342 {
343 DPRINT1("Controller reports no root hub ports\n");
345 }
346
348 if (m_Ports == NULL)
349 {
350 DPRINT1("No memory for %lu root hub ports\n", m_PortCount);
351 m_PortCount = 0;
353 }
354
355 for (Capability = Registers->FindExtendedCapability(XHCI_EXTCAP_SUPPORTED_PROTOCOL, 0);
356 Capability != 0;
357 Capability = Registers->FindExtendedCapability(XHCI_EXTCAP_SUPPORTED_PROTOCOL, Capability))
358 {
359 Status = ParseProtocol(Capability, &Usable);
360 if (!NT_SUCCESS(Status))
361 break;
362
363 AnyUsable |= Usable;
364 }
365
366 if (NT_SUCCESS(Status) && !AnyUsable)
367 {
368 DPRINT1("No USB 2.x or 3.x protocol capability found\n");
370 }
371
372 if (!NT_SUCCESS(Status))
373 {
374 DPRINT1("Root hub prepare failed 0x%lx\n", Status);
376 m_Ports = NULL;
377 m_PortCount = 0;
380 return Status;
381 }
382
383 for (Number = 1; Number <= m_PortCount; Number++)
384 {
385 Port* P = &m_Ports[Number - 1];
386
387 KeInitializeSpinLock(&P->Lock);
388 P->Hub = this;
389 P->Number = Number;
390
391 if (P->Major == 2)
392 {
393 KeInitializeTimer(&P->ResumeTimer);
394 KeInitializeDpc(&P->ResumeDpc, ResumeTimerDpc, P);
395 P->TimerReady = TRUE;
396 }
397 }
398
399 DPRINT("Root hub: %lu ports, %u USB 2.x, %u USB 3.x\n", m_PortCount, m_Usb20PortCount, m_Usb30PortCount);
400 return STATUS_SUCCESS;
401}
402
403VOID
405{
406 ULONG Index;
407
408 if (m_Ports == NULL)
409 return;
410
411 for (Index = 0; Index < m_PortCount; Index++)
412 {
413 if (m_Ports[Index].TimerReady)
415 }
416
417 /* Wait for a running resume timer callback before freeing the ports */
418 KeFlushQueuedDpcs();
419
421 m_Ports = NULL;
422 m_PortCount = 0;
425}
426
427/* Port register helpers ******************************************************/
428
431 _In_ ULONG PortNumber) const
432{
433 if (m_Ports == NULL || PortNumber == 0 || PortNumber > m_PortCount)
434 return NULL;
435
436 return &m_Ports[PortNumber - 1];
437}
438
439ULONG
441 _In_ const Port* P) const
442{
444}
445
447ULONG
449 _In_ Port* P,
450 _In_ ULONG Keep,
451 _In_ ULONG Set)
452{
453 ULONG PortSc = ReadPortSc(P);
454
455 m_Controller->m_Registers.WritePort32(P->Number, XHCI_PORT_SC, (PortSc & Keep) | Set);
456 return PortSc;
457}
458
459ULONG
461 _In_ Port* P,
462 _In_ ULONG Keep,
463 _In_ ULONG Set)
464{
465 XhciSpinLockGuard Guard(&P->Lock);
466
467 return UpdatePortScLocked(P, Keep, Set);
468}
469
471VOID
473 _In_ Port* P,
476 _In_ ULONG Set)
477{
479 ULONG Value;
480
481 Value = Registers->ReadPort32(P->Number, Offset);
482 Registers->WritePort32(P->Number, Offset, (Value & ~Clear) | Set);
483}
484
485VOID
487 _In_ Port* P)
488{
493 0);
497 0);
498 P->LpmDirty = FALSE;
499}
500
504 _In_ const Port* P) const
505{
507
508 if (P->Major != 3 || !KD_DEBUGGER_ENABLED || m_DebugCapability == 0)
509 return FALSE;
510
511 if (!m_Controller->HasErrata(XhciErrata::PortMaskDebugPortNoise))
512 return FALSE;
513
515 return (Status >> XHCI_DBC_DCST_PORT_SHIFT) == P->Number;
516}
517
520 _In_ const Port* P) const
521{
522 ULONG PortSc = ReadPortSc(P);
523 ULONG Link = XhciLinkState(PortSc);
524
525 if (!(PortSc & XHCI_PORTSC_PP) || !(PortSc & XHCI_PORTSC_CCS))
526 return FALSE;
527
528 return Link != PORT_LINK_STATE_DISABLED &&
531}
532
533/* Resume handling ************************************************************/
534
535VOID
537 _In_ Port* P)
538{
539 ULONG Milliseconds = XhciResumeSignalMs;
540
541 if (P->ResumeOverrideCount > 0)
542 Milliseconds = P->ResumeOverrideMs;
543
544 KeSetTimer(&P->ResumeTimer, XhciRelativeMs(Milliseconds), &P->ResumeDpc);
545}
546
548VOID
549NTAPI
551 _In_ PKDPC Dpc,
555{
556 Port* P = (Port*)Context;
557 XhciRootHub* Hub = P->Hub;
558
562
563 if (!Hub->m_Controller->IsAccessible())
564 return;
565
566 /* U0 ends resume signaling and the PLC write acknowledges the start of resume */
568
569 if (Hub->m_Controller->HasErrata(XhciErrata::PortHighSpeedLpmOffForSuspend) && P->LpmEnabled)
570 {
571 XhciSpinLockGuard Guard(&P->Lock);
572
573 Hub->UpdatePortReg(P, XHCI_PORT_PMSC, 0, XHCI_PORTPMSC_HLE);
574 }
575}
576
583 _In_ Port* P,
585{
587 ULONG PortSc;
588
589 if (P->Major == 0)
590 return FALSE;
591
592 KeAcquireSpinLock(&P->Lock, &OldIrql);
593
594 PortSc = ReadPortSc(P);
595 if (PortSc == XhciPortGone)
596 {
597 KeReleaseSpinLock(&P->Lock, OldIrql);
598 return FALSE;
599 }
600
601 if (P->Major == 3 &&
602 (PortSc & XHCI_PORTSC_PLC) &&
604 m_Controller->HasErrata(XhciErrata::PortWakeToU0BeforeSuspend))
605 {
606 /* Put back the U1/U2 timeouts WaitU0 zeroed */
610 P->U1Timeout | ((ULONG)P->U2Timeout << XHCI_PORTPMSC_U2_TIMEOUT_SHIFT));
611 }
612
613 if (XhciLinkState(PortSc) != XHCI_PLS_RESUME ||
614 (!PowerUp && !(PortSc & XHCI_PORTSC_PLC)))
615 {
616 KeReleaseSpinLock(&P->Lock, OldIrql);
617 return FALSE;
618 }
619
620 if (P->ResumeHandled)
621 {
622 KeReleaseSpinLock(&P->Lock, OldIrql);
623 return TRUE;
624 }
625
626 P->ResumeHandled = TRUE;
627
628 if (P->Major == 2)
629 {
630 KeReleaseSpinLock(&P->Lock, OldIrql);
631 DPRINT1("Port %lu: USB 2.x device initiated resume\n", P->Number);
632
633 /* PLC stays set until the timer, so a power down in between still wakes */
635 return TRUE;
636 }
637
638 /* PLC rides along so it is cleared only if it was set */
640 KeReleaseSpinLock(&P->Lock, OldIrql);
641
642 DPRINT1("Port %lu: USB 3.x device initiated resume\n", P->Number);
643 return TRUE;
644}
645
646/* Link state helpers *********************************************************/
647
651 _In_ Port* P,
652 _In_ BOOLEAN RepeatRequest)
653{
654 ULONG LastSeen = XhciPortGone;
655 ULONG Step;
656
657 for (Step = 0; Step < XhciU3WaitSteps; Step++)
658 {
659 ULONG PortSc;
660 ULONG Link;
661
662 /* Some controllers drop the first U3 request; ask again every 30 us */
663 if (RepeatRequest && Step != 0 && (Step % 3) == 0)
665
666 PortSc = ReadPortSc(P);
667 if (PortSc != LastSeen)
668 {
669 LastSeen = PortSc;
670
671 if (P->Major == 0)
672 {
673 DPRINT1("Port %lu: U3 wait on a port with no protocol\n", P->Number);
674 return STATUS_SUCCESS;
675 }
676
677 Link = XhciLinkState(PortSc);
678 if (Link == PORT_LINK_STATE_U3 ||
679 !XhciPortActive(PortSc) ||
685 (PortSc & XHCI_PORTSC_PR) ||
686 P->ResumeHandled)
687 {
688 return STATUS_SUCCESS;
689 }
690 }
691
693 }
694
695 DPRINT1("Port %lu: U3 transition still pending after 24 ms, PORTSC 0x%08lx\n", P->Number, LastSeen);
696 return STATUS_UNSUCCESSFUL;
697}
698
702 _In_ Port* P)
703{
704 ULONG Remaining = XhciU0WaitSteps;
705
706 if (P->Major == 2)
707 {
708 if (!P->LpmEnabled)
709 return STATUS_SUCCESS;
710
711 XhciSpinLockGuard Guard(&P->Lock);
712
714 }
715 else if (P->Major == 3)
716 {
717 XhciSpinLockGuard Guard(&P->Lock);
718
721 }
722 else
723 {
724 return STATUS_SUCCESS;
725 }
726
727 for (;;)
728 {
729 ULONG PortSc = ReadPortSc(P);
730 ULONG Link = XhciLinkState(PortSc);
731
732 if (PortSc == XhciPortGone)
733 break;
735 return STATUS_SUCCESS;
739 !XhciPortActive(PortSc))
740 {
741 break;
742 }
744 {
745 DPRINT1("Port %lu: link state %lu while forcing U0\n", P->Number, Link);
746 break;
747 }
748 if ((PortSc & XHCI_PORTSC_PR) || Remaining == 0)
749 break;
750
751 Remaining--;
753 }
754
755 return STATUS_UNSUCCESSFUL;
756}
757
759VOID
761 _In_ Port* P)
762{
763 XhciSpinLockGuard Guard(&P->Lock);
764 ULONG PortSc;
765
766 P->ResumeHandled = FALSE;
767
769 if (!(PortSc & XHCI_PORTSC_PED) || XhciLinkState(PortSc) >= PORT_LINK_STATE_U3)
770 DPRINT1("Port %lu: suspend requested with PORTSC 0x%08lx\n", P->Number, PortSc);
771}
772
774VOID
776{
778
779 for (Number = 1; Number <= m_PortCount; Number++)
780 {
781 Port* P = &m_Ports[Number - 1];
782 ULONG Remaining = XhciResumeWaitSteps;
783 ULONG PortSc;
784 ULONG Link;
785
786 if (P->Major == 2 && KeCancelTimer(&P->ResumeTimer))
787 {
788 /* Left in Resume with PLC set, which wakes the controller once it is down */
789 P->ResumeHandled = FALSE;
790 continue;
791 }
792
793 if (P->Major == 0)
794 continue;
795
796 for (;;)
797 {
798 PortSc = ReadPortSc(P);
799 Link = XhciLinkState(PortSc);
800
801 if (PortSc == XhciPortGone ||
802 !P->ResumeHandled ||
803 !XhciPortActive(PortSc) ||
805 {
806 break;
807 }
808
809 if (Remaining == 0)
810 {
811 DPRINT1("Port %lu: acknowledged resume not done after 12 ms\n", Number);
812 break;
813 }
814
815 Remaining--;
817 }
818
819 if (PortSc == XhciPortGone || !XhciPortActive(PortSc))
820 continue;
821
822 if (Link != PORT_LINK_STATE_U0 &&
826 {
827 continue;
828 }
829
830 if ((P->Major == 2 && m_Controller->HasErrata(XhciErrata::PortHighSpeedLpmOffForSuspend)) ||
831 (P->Major == 3 && m_Controller->HasErrata(XhciErrata::PortWakeToU0BeforeSuspend)))
832 {
833 if (!NT_SUCCESS(WaitU0(P)))
834 continue;
835 }
836
837 SuspendPort(P);
838 }
839}
840
841/* Power **********************************************************************/
842
843VOID
845{
847
849
850 for (Number = 1; Number <= m_PortCount; Number++)
851 {
852 Port* P = &m_Ports[Number - 1];
853
854 if (P->Major == 0)
855 {
856 DPRINT1("Port %lu has no USB protocol, skipped at D0 entry\n", Number);
857 continue;
858 }
859
860 /* Some controllers miss connect and disconnect in D0 without the wake enables */
861 if (m_Controller->HasErrata(XhciErrata::PortHoldWakeMaskAwake))
863 }
864}
865
866VOID
868{
870
871 /* A port already in Resume at power up may never raise an event of its own */
872 for (Number = 1; Number <= m_PortCount; Number++)
874}
875
876VOID
878{
881 BOOLEAN SystemPoweringDown = (Action >= XhciController::SystemAction::Sleep &&
884 BOOLEAN AnyConnected = FALSE;
886
888
889 for (Number = 1; Number <= m_PortCount; Number++)
890 {
891 Port* P = &m_Ports[Number - 1];
892
893 if (!FinalPowerOff)
894 {
895 /* Let the hub recover the port instead of leaving a dead device behind */
896 if (!NT_SUCCESS(WaitForU3(P, FALSE)) && S0Idle)
897 UcxRootHubPortChanged(m_Ucx);
898
899 if (IsPortConnected(P))
900 AnyConnected = TRUE;
901 }
902
903 if (m_Controller->HasErrata(XhciErrata::PortAckCscOnPowerDown))
905
906 if (SystemPoweringDown && m_Controller->HasErrata(XhciErrata::PortHoldWakeMaskAwake))
908 }
909
910 m_Controller->NotifyPortConnectState(AnyConnected);
911}
912
913VOID
915{
916 /* Resume, LPM and U1/U2 bookkeeping deliberately survive the reset */
917 D0Entry();
918}
919
920VOID
922{
923 ULONG Index;
924
925 if (m_Ports == NULL)
926 return;
927
928 for (Index = 0; Index < m_PortCount; Index++)
929 {
930 if (m_Ports[Index].TimerReady)
932 }
933}
934
935VOID
937 _In_ BOOLEAN Arm)
938{
940
941 if (!Arm && m_Controller->HasErrata(XhciErrata::PortHoldWakeMaskAwake))
942 return;
943
944 for (Number = 1; Number <= m_PortCount; Number++)
945 {
946 Port* P = &m_Ports[Number - 1];
947
948 if (Arm)
950 else
952 }
953}
954
955VOID
957{
958 if (m_Ucx != NULL)
959 UcxRootHubPortChanged(m_Ucx);
960}
961
962/* Queries ********************************************************************/
963
964ULONG
966{
967 return m_PortCount;
968}
969
971USHORT
973{
974 UCHAR Major = 0;
975 UCHAR Minor = 0;
976 ULONG Index;
977
978 for (Index = 0; Index < m_PortCount; Index++)
979 {
980 const Port* P = &m_Ports[Index];
981
982 /* A later port with the same major and a higher minor does not count */
983 if (P->Major > Major)
984 {
985 Major = P->Major;
986 if (P->Minor > Minor)
987 Minor = P->Minor;
988 }
989 }
990
991 return (USHORT)((Major << 8) | Minor);
992}
993
996 _In_ ULONG PortNumber) const
997{
998 const Port* P = PortAt(PortNumber);
999
1000 return P != NULL && P->Major == 2;
1001}
1002
1003/* QUIRK: no accessibility check, so a removed controller reads as tunneled */
1004UCHAR
1006 _In_ ULONG PortNumber) const
1007{
1008 const XhciRegisters* Registers = &m_Controller->m_Registers;
1009 const Port* P = PortAt(PortNumber);
1010 ULONG Value;
1011 ULONG Mask;
1012
1013 if (P == NULL || P->Major != 3)
1015
1016 if (m_Controller->HasErrata(XhciErrata::Usb4TunnelFromVendorPortReg))
1017 {
1021 }
1022 else if (m_Controller->HasErrata(XhciErrata::Usb4TunnelFromVendorStatusReg))
1023 {
1026 }
1027 else if (m_PortScTunnelValid)
1028 {
1029 Value = ReadPortSc(P);
1031 }
1032 else
1033 {
1035 }
1036
1037 DPRINT("Root port %lu tunnel register 0x%08lx\n", PortNumber, Value);
1039}
1040
1041/* Port change events *********************************************************/
1042
1043VOID
1045 _In_ const XHCI_TRB* Event)
1046{
1048 Port* P = PortAt(PortNumber);
1049
1050 /* PortAt rejects a Port ID outside the port array */
1051 if (P == NULL)
1052 {
1053 DPRINT1("Port status change event for port %lu, controller has %lu\n", PortNumber, m_PortCount);
1054 return;
1055 }
1056
1057 if (IsHiddenDebugPort(P))
1058 {
1063 return;
1064 }
1065
1067 return;
1068
1069 UcxRootHubPortChanged(m_Ucx);
1070}
1071
1072/* Services for usbdevice *****************************************************/
1073
1074VOID
1077 _In_ ULONG SlotId,
1079{
1080 Port* P = PortAt(PortNumber);
1081 ULONG Value;
1082
1083 if (P == NULL)
1084 {
1085 DPRINT1("LPM update for bad root port %lu\n", PortNumber);
1086 return;
1087 }
1088
1089 NT_ASSERT(P->Major == 2);
1090
1091 XhciSpinLockGuard Guard(&P->Lock);
1092
1093 /* Parameters before the enable bit (xHCI 4.23.5.1.1.1) */
1094 Value = Parameters->HostInitiatedResumeDurationMode |
1096 (Parameters->BestEffortServiceLatencyDeep << XHCI_PORTHLPMC_BESLD_SHIFT);
1100 Value);
1101
1102 Value = (Parameters->BestEffortServiceLatency << XHCI_PORTPMSC_BESL_SHIFT) |
1104 if (Parameters->RemoteWakeEnable)
1106 if (Parameters->HardwareLpmEnable)
1111 Value);
1112
1113 P->LpmEnabled = Parameters->HardwareLpmEnable != 0;
1114 P->LpmDirty = TRUE;
1115}
1116
1117VOID
1120 _In_ ULONG SlotId)
1121{
1122 Port* P = PortAt(PortNumber);
1123 ULONG Owner;
1124
1125 if (P == NULL)
1126 return;
1127
1128 XhciSpinLockGuard Guard(&P->Lock);
1129
1130 if (!P->LpmDirty)
1131 return;
1132
1133 /* The port may already belong to a newer device */
1137}
1138
1139VOID
1142 _In_ ULONG Milliseconds)
1143{
1144 Port* P = PortAt(PortNumber);
1145
1146 if (P == NULL)
1147 return;
1148
1149 XhciSpinLockGuard Guard(&P->Lock);
1150
1151 P->ResumeOverrideMs = Milliseconds;
1152 P->ResumeOverrideCount++;
1153}
1154
1155VOID
1158{
1159 Port* P = PortAt(PortNumber);
1160
1161 if (P == NULL)
1162 return;
1163
1164 XhciSpinLockGuard Guard(&P->Lock);
1165
1166 P->ResumeOverrideCount--;
1167}
1168
1169/* Hub class requests *********************************************************/
1170
1171VOID
1173 _In_ WDFREQUEST Request,
1174 _In_ PURB Urb,
1176{
1179
1180 switch (Result)
1181 {
1182 case Outcome::Ok:
1185 break;
1186
1190 break;
1191
1192 case Outcome::Gone:
1195 break;
1196
1197 case Outcome::Halted:
1200 break;
1201
1202 case Outcome::Stall:
1203 default:
1206 break;
1207 }
1208
1209 Urb->UrbHeader.Status = UsbdStatus;
1210 WdfRequestComplete(Request, Status);
1211}
1212
1216{
1218
1219 if (Status == XhciPortGone)
1220 {
1221 DPRINT1("Root hub port feature: USBSTS reads all ones, controller gone\n");
1223 return Outcome::Gone;
1224 }
1225
1226 if (Status & XHCI_USBSTS_HCH)
1227 {
1228 DPRINT1("Root hub port feature: controller halted, USBSTS 0x%08lx\n", Status);
1229 return Outcome::Halted;
1230 }
1231
1232 return Outcome::Ok;
1233}
1234
1237 _In_ PURB Urb)
1238{
1240
1241 if (Setup->bmRequestType.B == HubRequestToHub &&
1242 Setup->bRequest == USB_REQUEST_CLEAR_FEATURE &&
1243 Setup->wIndex.W == 0 &&
1244 Setup->wLength == 0 &&
1246 {
1247 return Outcome::Ok;
1248 }
1249
1250 XhciTraceBadRequest("ClearHubFeature", Urb);
1251 return Outcome::Stall;
1252}
1253
1256 _In_ PURB Urb)
1257{
1259 PULONG Buffer;
1260
1261 if (Setup->bmRequestType.B != HubRequestFromHub ||
1262 Setup->bRequest != USB_REQUEST_GET_STATUS ||
1263 Setup->wValue.W != 0 ||
1264 Setup->wIndex.W != 0 ||
1265 Setup->wLength != sizeof(*Buffer))
1266 {
1267 XhciTraceBadRequest("GetHubStatus", Urb);
1268 return Outcome::Stall;
1269 }
1270
1272 if (Buffer == NULL)
1273 {
1274 XhciTraceBadRequest("GetHubStatus buffer", Urb);
1275 return Outcome::Stall;
1276 }
1277
1278 /* No local power or over current status, no changes */
1279 *Buffer = 0;
1280 return Outcome::Ok;
1281}
1282
1285 _In_ PURB Urb)
1286{
1289 BOOLEAN Extended;
1290 ULONG Length;
1291 ULONG PortSc;
1292 ULONG Link;
1293 Port* P;
1294
1295 if (!m_Controller->IsAccessible())
1296 {
1297 DPRINT1("GetPortStatus: controller not accessible\n");
1298 return Outcome::Gone;
1299 }
1300
1301 Extended = (Setup->wValue.W == USB_STATUS_EXT_PORT_STATUS);
1302 Length = Extended ? sizeof(Out->AsUlong64) : sizeof(Out->PortStatusChange);
1303 P = PortAt(Setup->wIndex.W);
1304
1305 if (Setup->bmRequestType.B != HubRequestFromPort ||
1306 Setup->bRequest != USB_REQUEST_GET_STATUS ||
1307 (Setup->wValue.W != USB_STATUS_PORT_STATUS && !Extended) ||
1308 P == NULL ||
1309 Setup->wLength != Length ||
1310 !((P->Major == 2 && !Extended) || P->Major == 3))
1311 {
1312 XhciTraceBadRequest("GetPortStatus", Urb);
1313 return Outcome::Stall;
1314 }
1315
1317 if (Out == NULL)
1318 {
1319 XhciTraceBadRequest("GetPortStatus buffer", Urb);
1320 return Outcome::Stall;
1321 }
1322
1323 PortSc = ReadPortSc(P);
1324 if (PortSc == XhciPortGone)
1325 {
1326 DPRINT1("GetPortStatus: port %lu PORTSC reads all ones\n", P->Number);
1328 return Outcome::Gone;
1329 }
1330
1331 Out->PortStatusChange.AsUlong32 = 0;
1332 Link = XhciLinkState(PortSc);
1333
1334 if (P->Major == 2)
1335 {
1336 PUSB_20_PORT_STATUS Status = &Out->PortStatusChange.PortStatus.Usb20PortStatus;
1337 PUSB_20_PORT_CHANGE Change = &Out->PortStatusChange.PortChange.Usb20PortChange;
1338 ULONG Speed = XhciPortSpeed(PortSc);
1339
1340 Status->CurrentConnectStatus = (PortSc & XHCI_PORTSC_CCS) != 0;
1341 Status->PortEnabledDisabled = (PortSc & XHCI_PORTSC_PED) != 0;
1342 Status->Suspend = (Link == PORT_LINK_STATE_U3 || Link == XHCI_PLS_RESUME);
1343 Status->OverCurrent = (PortSc & XHCI_PORTSC_OCA) != 0;
1344 Status->Reset = (PortSc & XHCI_PORTSC_PR) != 0;
1345 Status->L1 = (Link == PORT_LINK_STATE_U2);
1346 Status->PortPower = (PortSc & XHCI_PORTSC_PP) != 0;
1347 Status->LowSpeedDeviceAttached = (Speed == XHCI_SPEED_LOW);
1348 Status->HighSpeedDeviceAttached = (Speed == XHCI_SPEED_HIGH);
1349 Status->PortIndicatorControl = (PortSc & XHCI_PORTSC_PIC_MASK) != 0;
1351 {
1352 DPRINT1("GetPortStatus: port %lu is in test mode\n", P->Number);
1353 Status->PortTestMode = 1;
1354 }
1355
1356 Change->ConnectStatusChange = (PortSc & XHCI_PORTSC_CSC) != 0;
1357 Change->PortEnableDisableChange = (PortSc & XHCI_PORTSC_PEC) != 0;
1358 Change->OverCurrentIndicatorChange = (PortSc & XHCI_PORTSC_OCC) != 0;
1359 Change->ResetChange = (PortSc & XHCI_PORTSC_PRC) != 0;
1360
1361 /* A resume this driver is still timing shows as suspended with no change yet */
1362 if (Link == XHCI_PLS_RESUME)
1364
1365 Change->SuspendChange = (PortSc & XHCI_PORTSC_PLC) != 0;
1366 return Outcome::Ok;
1367 }
1368
1369 PUSB_30_PORT_STATUS Status = &Out->PortStatusChange.PortStatus.Usb30PortStatus;
1370 PUSB_30_PORT_CHANGE Change = &Out->PortStatusChange.PortChange.Usb30PortChange;
1371
1372 if (IsHiddenDebugPort(P))
1373 {
1374 /* An empty powered port; the extended dword is left as the caller had it */
1375 Status->PortPower = 1;
1376 Status->PortLinkState = PORT_LINK_STATE_RX_DETECT;
1377 return Outcome::Ok;
1378 }
1379
1380 /* Resume is no hub link state; CAS means the device likely sits in Compliance */
1381 if (Link == XHCI_PLS_RESUME)
1383 if (PortSc & XHCI_PORTSC_CAS)
1385
1386 Status->CurrentConnectStatus = (PortSc & XHCI_PORTSC_CCS) != 0;
1387 Status->PortEnabledDisabled = (PortSc & XHCI_PORTSC_PED) != 0;
1388 Status->OverCurrent = (PortSc & XHCI_PORTSC_OCA) != 0;
1389 Status->Reset = (PortSc & XHCI_PORTSC_PR) != 0;
1390 Status->PortLinkState = Link;
1391 Status->PortPower = (PortSc & XHCI_PORTSC_PP) != 0;
1392
1393 Change->ConnectStatusChange = (PortSc & XHCI_PORTSC_CSC) != 0;
1394 Change->OverCurrentIndicatorChange = (PortSc & XHCI_PORTSC_OCC) != 0;
1395 Change->ResetChange = (PortSc & XHCI_PORTSC_PRC) != 0;
1396 Change->BHResetChange = (PortSc & XHCI_PORTSC_WRC) != 0;
1397 Change->PortLinkStateChange = (PortSc & XHCI_PORTSC_PLC) != 0;
1398 Change->PortConfigErrorChange = (PortSc & XHCI_PORTSC_CEC) != 0;
1399
1400 if (Extended)
1401 {
1402 PUSB_PORT_EXT_STATUS ExtStatus = &Out->PortExtStatus;
1403 ULONG LinkInfo = m_Controller->m_Registers.ReadPort32(P->Number, XHCI_PORT_LI);
1404 ULONG Speed = XhciPortSpeed(PortSc);
1405
1406 /* Without a PSI table, speed 1 on a 3.x port means the controller did not report it */
1407 if (P->SpeedCount == 0 && Speed == XHCI_SPEED_FULL)
1408 Speed = XHCI_SPEED_SUPER;
1409
1410 ExtStatus->AsUlong32 = 0;
1411 ExtStatus->RxSublinkSpeedID = Speed;
1412 ExtStatus->TxSublinkSpeedID = Speed;
1415 }
1416
1417 return Outcome::Ok;
1418}
1419
1422 _In_ PURB Urb)
1423{
1426 Port* P;
1427
1428 if (!m_Controller->IsAccessible())
1429 {
1430 DPRINT1("ClearPortFeature: controller not accessible\n");
1431 return Outcome::Gone;
1432 }
1433
1434 Result = CheckRunning();
1435 if (Result != Outcome::Ok)
1436 return Result;
1437
1438 P = PortAt(Setup->wIndex.LowByte);
1439 if (Setup->bmRequestType.B != HubRequestToPort ||
1440 Setup->bRequest != USB_REQUEST_CLEAR_FEATURE ||
1441 P == NULL ||
1442 Setup->wLength != 0)
1443 {
1444 XhciTraceBadRequest("ClearPortFeature", Urb);
1445 return Outcome::Stall;
1446 }
1447
1448 if (P->Major == 2)
1449 Result = ClearUsb20PortFeature(P, Setup->wValue.W, Setup->wIndex.HiByte);
1450 else if (P->Major == 3)
1451 Result = ClearUsb30PortFeature(P, Setup->wValue.W, Setup->wIndex.HiByte);
1452 else
1454
1455 if (Result == Outcome::Stall)
1456 XhciTraceBadRequest("ClearPortFeature", Urb);
1457
1458 return Result;
1459}
1460
1463 _In_ Port* P,
1466{
1467 ULONG PortSc;
1468
1469 if (Value != 0 && Feature != FeaturePortIndicator)
1470 return Outcome::Stall;
1471
1472 switch (Feature)
1473 {
1474 case FeaturePortEnable:
1475 if (m_Controller->HasErrata(XhciErrata::PortHighSpeedDisableSuspends))
1476 {
1477 XhciSpinLockGuard Guard(&P->Lock);
1478
1480 if (!(PortSc & XHCI_PORTSC_PED) || XhciLinkState(PortSc) >= PORT_LINK_STATE_U3)
1481 DPRINT1("Port %lu: disable mapped to suspend with PORTSC 0x%08lx\n", P->Number, PortSc);
1482 }
1483 else
1484 {
1486 }
1487 return Outcome::Ok;
1488
1489 case FeaturePortSuspend:
1490 {
1491 /* Host initiated resume (xHCI 4.15.2.2) */
1492 if (!NT_SUCCESS(WaitForU3(P, FALSE)))
1493 return Outcome::Stall;
1494
1495 {
1496 XhciSpinLockGuard Guard(&P->Lock);
1497 ULONG Link;
1498
1500 Link = XhciLinkState(PortSc);
1501 if (!(PortSc & XHCI_PORTSC_PED) || (Link != PORT_LINK_STATE_U3 && Link != XHCI_PLS_RESUME))
1502 DPRINT1("Port %lu: resume requested with PORTSC 0x%08lx\n", P->Number, PortSc);
1503 }
1504
1506 return Outcome::Ok;
1507 }
1508
1509 case FeaturePortPower:
1511 return Outcome::Ok;
1512
1514 if (Value > 3)
1515 return Outcome::Stall;
1516
1518 return Outcome::Ok;
1519
1522 return Outcome::Ok;
1523
1526 return Outcome::Ok;
1527
1530 return Outcome::Ok;
1531
1534 return Outcome::Ok;
1535
1536 case FeatureResetChange:
1538 return Outcome::Ok;
1539
1540 default:
1541 return Outcome::Stall;
1542 }
1543}
1544
1547 _In_ Port* P,
1550{
1551 ULONG ChangeBit;
1552
1553 if (Value != 0)
1554 return Outcome::Stall;
1555
1556 switch (Feature)
1557 {
1558 case FeaturePortPower:
1560 return Outcome::Ok;
1561
1563 {
1564 XhciSpinLockGuard Guard(&P->Lock);
1565
1567 return Outcome::Ok;
1568 }
1569
1571 ChangeBit = XHCI_PORTSC_CSC;
1572 break;
1573
1575 ChangeBit = XHCI_PORTSC_OCC;
1576 break;
1577
1578 case FeatureResetChange:
1579 ChangeBit = XHCI_PORTSC_PRC;
1580 break;
1581
1583 ChangeBit = XHCI_PORTSC_PLC;
1584 break;
1585
1587 ChangeBit = XHCI_PORTSC_CEC;
1588 break;
1589
1591 ChangeBit = XHCI_PORTSC_WRC;
1592 break;
1593
1594 default:
1595 return Outcome::Stall;
1596 }
1597
1598 UpdatePortSc(P, XHCI_PORTSC_PRESERVE, ChangeBit);
1599 return Outcome::Ok;
1600}
1601
1604 _In_ PURB Urb)
1605{
1608 Port* P;
1609
1610 if (!m_Controller->IsAccessible())
1611 {
1612 DPRINT1("SetPortFeature: controller not accessible\n");
1613 return Outcome::Gone;
1614 }
1615
1616 Result = CheckRunning();
1617 if (Result != Outcome::Ok)
1618 return Result;
1619
1620 P = PortAt(Setup->wIndex.LowByte);
1621 if (Setup->bmRequestType.B != HubRequestToPort ||
1622 Setup->bRequest != USB_REQUEST_SET_FEATURE ||
1623 P == NULL ||
1624 Setup->wLength != 0)
1625 {
1626 XhciTraceBadRequest("SetPortFeature", Urb);
1627 return Outcome::Stall;
1628 }
1629
1630 if (P->Major == 2)
1631 Result = SetUsb20PortFeature(P, Setup->wValue.W, Setup->wIndex.HiByte);
1632 else if (P->Major == 3)
1633 Result = SetUsb30PortFeature(P, Setup->wValue.W, Setup->wIndex.HiByte);
1634 else
1636
1637 if (Result == Outcome::Stall)
1638 XhciTraceBadRequest("SetPortFeature", Urb);
1639
1640 return Result;
1641}
1642
1645 _In_ Port* P,
1648{
1650 return Outcome::Stall;
1651
1652 switch (Feature)
1653 {
1654 case FeaturePortReset:
1655 {
1656 XhciSpinLockGuard Guard(&P->Lock);
1657
1658 /* LpmEnabled is kept on purpose, the resume timer may turn HLE back on */
1659 if (P->LpmDirty)
1661
1663 return Outcome::Ok;
1664 }
1665
1666 case FeaturePortSuspend:
1667 /* xHCI 4.15.1; some controllers only enter U3 from L0 */
1668 if (m_Controller->HasErrata(XhciErrata::PortHighSpeedLpmOffForSuspend) &&
1669 !NT_SUCCESS(WaitU0(P)))
1670 {
1671 return Outcome::Stall;
1672 }
1673
1674 SuspendPort(P);
1675 return Outcome::Ok;
1676
1677 case FeaturePortPower:
1679 return Outcome::Ok;
1680
1681 case FeaturePortTest:
1682 {
1683 if (Value > 5)
1684 return Outcome::Stall;
1685
1686 XhciSpinLockGuard Guard(&P->Lock);
1687
1688 /* No xHCI 4.19.6 preconditions are enforced */
1690 return Outcome::Ok;
1691 }
1692
1694 if (Value > 3)
1695 return Outcome::Stall;
1696
1697 /* Hub "off" (3) and "automatic" (0) both become xHCI off */
1698 if (Value == 3)
1699 Value = 0;
1700
1702 return Outcome::Ok;
1703
1704 default:
1705 return Outcome::Stall;
1706 }
1707}
1708
1711 _In_ Port* P,
1714{
1715 if (Value != 0 &&
1720 {
1721 return Outcome::Stall;
1722 }
1723
1724 switch (Feature)
1725 {
1726 case FeaturePortReset:
1728 return Outcome::Ok;
1729
1730 case FeatureWarmReset:
1732 return Outcome::Ok;
1733
1734 case FeaturePortPower:
1736 return Outcome::Ok;
1737
1738 case FeatureU1Timeout:
1739 {
1740 XhciSpinLockGuard Guard(&P->Lock);
1741
1743 P->U1Timeout = Value;
1744 return Outcome::Ok;
1745 }
1746
1747 case FeatureU2Timeout:
1748 {
1749 XhciSpinLockGuard Guard(&P->Lock);
1750
1755 P->U2Timeout = Value;
1756 return Outcome::Ok;
1757 }
1758
1760 return SetUsb30LinkState(P, Value);
1761
1763 if (Value & ~0x07)
1764 return Outcome::Stall;
1765
1767 return Outcome::Ok;
1768
1770 {
1771 XhciSpinLockGuard Guard(&P->Lock);
1772
1774 return Outcome::Ok;
1775 }
1776
1777 default:
1778 return Outcome::Stall;
1779 }
1780}
1781
1784 _In_ Port* P,
1785 _In_ UCHAR LinkState)
1786{
1787 if (LinkState > PORT_LINK_STATE_RX_DETECT)
1788 return Outcome::Stall;
1789
1790 /* Applies to every non U0 target, not only U3 */
1791 if (LinkState != PORT_LINK_STATE_U0 &&
1792 m_Controller->HasErrata(XhciErrata::PortWakeToU0BeforeSuspend) &&
1793 !NT_SUCCESS(WaitU0(P)))
1794 {
1795 return Outcome::Stall;
1796 }
1797
1798 /* A U3 request completes before the link gets there */
1799 if (LinkState == PORT_LINK_STATE_U0 && !NT_SUCCESS(WaitForU3(P, FALSE)))
1800 return Outcome::Stall;
1801
1802 {
1803 XhciSpinLockGuard Guard(&P->Lock);
1804
1805 if (LinkState == PORT_LINK_STATE_U3)
1806 P->ResumeHandled = FALSE;
1807
1808 /* SS.Disabled is entered through PED (xHCI 4.19.1.2) */
1809 if (LinkState == PORT_LINK_STATE_DISABLED)
1811 else
1813 }
1814
1815 if (LinkState == PORT_LINK_STATE_U3 &&
1816 m_Controller->HasErrata(XhciErrata::PortRetrySuspendEntry) &&
1818 {
1819 return Outcome::Stall;
1820 }
1821
1822 return Outcome::Ok;
1823}
1824
1827 _In_ PURB Urb)
1828{
1831 ULONG Errors;
1832 Port* P;
1833
1834 if (!m_Controller->IsAccessible())
1835 {
1836 DPRINT("GetPortErrorCount: controller not accessible\n");
1837 return Outcome::Gone;
1838 }
1839
1840 /* UCX only routes 0x80 here, so this check fails every request it sends */
1841 P = PortAt(Setup->wIndex.W);
1842 if (Setup->bmRequestType.B != HubRequestFromPort ||
1844 Setup->wValue.W != 0 ||
1845 P == NULL ||
1846 Setup->wLength != sizeof(*Buffer) ||
1847 P->Major != 3)
1848 {
1849 XhciTraceBadRequest("GetPortErrorCount", Urb);
1850 return Outcome::Stall;
1851 }
1852
1854 if (Buffer == NULL)
1855 {
1856 XhciTraceBadRequest("GetPortErrorCount buffer", Urb);
1857 return Outcome::Stall;
1858 }
1859
1861 if (Errors > 10)
1862 DPRINT1("Port %lu: %lu link errors\n", P->Number, Errors);
1863
1864 *Buffer = (USHORT)Errors;
1865 return Outcome::Ok;
1866}
1867
1871 _In_ PURB Urb)
1872{
1873 struct _URB_BULK_OR_INTERRUPT_TRANSFER* Transfer = &Urb->UrbBulkOrInterruptTransfer;
1874 ULONG Length = Transfer->TransferBufferLength;
1875 PUCHAR Bitmap;
1876 ULONG Last;
1877 ULONG Number;
1878
1879 if (!m_Controller->IsAccessible())
1880 {
1881 DPRINT1("Status change transfer: controller not accessible\n");
1882 return Outcome::Gone;
1883 }
1884
1885 /* UCX has no callback for the root hub PDO reaching D0; this is the first sign of it */
1887 {
1888 m_Controller->OnRootHubD0Entry();
1890 }
1891
1892 if (Length == 0)
1893 return Outcome::Ok;
1894
1896 if (Bitmap == NULL)
1897 {
1898 DPRINT1("Status change transfer without a buffer\n");
1899 return Outcome::Stall;
1900 }
1901
1903
1904 Last = (Length > 32) ? 255 : (Length * 8 - 1);
1905 if (Last > m_PortCount)
1906 Last = m_PortCount;
1907
1908 for (Number = 1; Number <= Last; Number++)
1909 {
1910 Port* P = &m_Ports[Number - 1];
1911 ULONG Changes;
1912 ULONG PortSc;
1913
1914 if (P->Major == 0)
1915 continue;
1916
1917 PortSc = ReadPortSc(P);
1918 if (PortSc == XhciPortGone)
1919 {
1920 DPRINT1("Status change transfer: port %lu PORTSC reads all ones\n", Number);
1922 return Outcome::Gone;
1923 }
1924
1925 if (P->Major == 2)
1926 {
1927 Changes = PortSc & (XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_PLC |
1929
1930 /* This driver finishes a resume itself; its PLC is not for the hub */
1931 if (XhciLinkState(PortSc) == XHCI_PLS_RESUME)
1932 Changes &= ~XHCI_PORTSC_PLC;
1933 }
1934 else
1935 {
1936 Changes = PortSc & (XHCI_PORTSC_CSC | XHCI_PORTSC_OCC | XHCI_PORTSC_PRC |
1938
1939 if (Changes != 0 && IsHiddenDebugPort(P))
1940 Changes = 0;
1941 }
1942
1943 if (Changes != 0)
1944 Bitmap[Number / 8] |= (UCHAR)(1 << (Number % 8));
1945 }
1946
1947 return Outcome::Ok;
1948}
1949
1950typedef struct _XHCI_SPEED_LIST
1951{
1957
1959static
1960VOID
1961NTAPI
1964 _In_ ULONG Id,
1965 _In_ ULONG Exponent,
1966 _In_ ULONG Mantissa,
1967 _In_ ULONG Mode,
1969{
1970 if (List->Count < List->Capacity)
1971 {
1972 PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED Speed = &List->Speeds[List->Count];
1973
1974 Speed->AsUlong32 = 0;
1975 Speed->SublinkSpeedAttrID = Id;
1976 Speed->LaneSpeedExponent = Exponent;
1977 Speed->SublinkTypeMode = Mode;
1978 Speed->SublinkTypeDir = Direction;
1979 Speed->LinkProtocol = (List->Minor != 0 && Id > 4) ? 1 : 0;
1980 Speed->LaneSpeedMantissa = Mantissa;
1981 }
1982
1983 List->Count++;
1984}
1985
1992 _In_ const Port* P,
1994{
1995 XhciRegisters* Registers = &m_Controller->m_Registers;
1997 ULONG SeenIds = 0;
1998 ULONG Index;
1999
2000 List.Speeds = Entry->Speeds;
2001 List.Capacity = (Entry->Speeds != NULL) ? Entry->MaxSpeedsCount : 0;
2002 List.Count = 0;
2003 List.Minor = P->Minor;
2004
2005 for (Index = 0; Index < P->SpeedCount; Index++)
2006 {
2007 ULONG Psi = Registers->ReadExtended32(P->SpeedTable + Index * sizeof(ULONG));
2008 ULONG Id = Psi & XHCI_PSI_ID_MASK;
2010 ULONG Mantissa = Psi >> XHCI_PSI_MANTISSA_SHIFT;
2011 ULONG Next;
2012
2013 if (SeenIds & (1UL << Id))
2014 {
2015 DPRINT1("Port %lu: speed ID %lu listed twice\n", P->Number, Id);
2017 }
2018 SeenIds |= 1UL << Id;
2019
2020 switch ((Psi & XHCI_PSI_TYPE_MASK) >> XHCI_PSI_TYPE_SHIFT)
2021 {
2023 XhciAddSpeed(&List, Id, Exponent, Mantissa, 0, 0);
2024 XhciAddSpeed(&List, Id, Exponent, Mantissa, 0, 1);
2025 break;
2026
2028 XhciAddSpeed(&List, Id, Exponent, Mantissa, 1, 0);
2029
2030 if (++Index >= P->SpeedCount)
2031 {
2032 DPRINT1("Port %lu: speed ID %lu has RX but no TX entry\n", P->Number, Id);
2034 }
2035
2036 Next = Registers->ReadExtended32(P->SpeedTable + Index * sizeof(ULONG));
2037 if ((Next & XHCI_PSI_ID_MASK) != Id ||
2039 {
2040 DPRINT1("Port %lu: speed ID %lu RX entry followed by 0x%08lx\n", P->Number, Id, Next);
2042 }
2043
2047 1,
2048 1);
2049 break;
2050
2052 DPRINT1("Port %lu: speed ID %lu TX entry without RX\n", P->Number, Id);
2054
2055 default:
2056 /* Reserved type, nothing reported */
2057 break;
2058 }
2059 }
2060
2061 /*
2062 * Default 5 Gb/s and 10 Gb/s pairs. The gates test the ID bitmask against
2063 * the raw IDs instead of their bits, so both pairs are nearly always added.
2064 */
2065 if ((SeenIds & 4) == 0)
2066 {
2067 XhciAddSpeed(&List, 4, 3, 5, 0, 0);
2068 XhciAddSpeed(&List, 4, 3, 5, 0, 1);
2069 }
2070 if ((SeenIds & 5) == 0)
2071 {
2072 XhciAddSpeed(&List, 5, 3, 10, 0, 0);
2073 XhciAddSpeed(&List, 5, 3, 10, 0, 1);
2074 }
2075
2076 Entry->SpeedsCount = List.Count;
2077 return STATUS_SUCCESS;
2078}
2079
2080/* UCX callbacks **************************************************************/
2081
2082VOID
2083NTAPI
2085 _In_ UCXROOTHUB UcxRootHub,
2086 _In_ WDFREQUEST Request)
2087{
2089
2091}
2092
2093VOID
2094NTAPI
2096 _In_ UCXROOTHUB UcxRootHub,
2097 _In_ WDFREQUEST Request)
2098{
2100
2102}
2103
2104VOID
2105NTAPI
2107 _In_ UCXROOTHUB UcxRootHub,
2108 _In_ WDFREQUEST Request)
2109{
2111
2113}
2114
2115VOID
2116NTAPI
2118 _In_ UCXROOTHUB UcxRootHub,
2119 _In_ WDFREQUEST Request)
2120{
2122
2124}
2125
2126VOID
2127NTAPI
2129 _In_ UCXROOTHUB UcxRootHub,
2130 _In_ WDFREQUEST Request)
2131{
2133
2135
2136 /* The root hub has no settable hub feature; no validation either */
2137 DPRINT("SetHubFeature stalled\n");
2139}
2140
2141VOID
2142NTAPI
2144 _In_ UCXROOTHUB UcxRootHub,
2145 _In_ WDFREQUEST Request)
2146{
2148
2150}
2151
2152VOID
2153NTAPI
2155 _In_ UCXROOTHUB UcxRootHub,
2156 _In_ WDFREQUEST Request)
2157{
2159
2161}
2162
2163VOID
2164NTAPI
2166 _In_ UCXROOTHUB UcxRootHub,
2167 _In_ WDFREQUEST Request)
2168{
2170
2172}
2173
2174VOID
2175NTAPI
2177 _In_ UCXROOTHUB UcxRootHub,
2178 _In_ WDFREQUEST Request)
2179{
2182
2183 if (Info == NULL || Info->Size < sizeof(*Info))
2184 {
2185 DPRINT1("GetInfo: buffer too small\n");
2186 WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
2187 return;
2188 }
2189
2190 Info->ControllerType = ControllerTypeXhci;
2191 Info->NumberOf20Ports = Hub->m_Usb20PortCount;
2192 Info->NumberOf30Ports = Hub->m_Usb30PortCount;
2193 Info->MaxU1ExitLatency = Hub->m_U1ExitLatency;
2194 Info->MaxU2ExitLatency = Hub->m_U2ExitLatency;
2195
2196 WdfRequestComplete(Request, STATUS_SUCCESS);
2197}
2198
2199VOID
2200NTAPI
2202 _In_ UCXROOTHUB UcxRootHub,
2203 _In_ WDFREQUEST Request)
2204{
2207 BOOLEAN NoLpm;
2208 ULONG Next = 0;
2209 ULONG Index;
2210
2211 if (Info == NULL ||
2212 Info->Size < sizeof(*Info) ||
2213 Info->NumberOfPorts != Hub->m_Usb20PortCount ||
2214 Info->PortInfoSize < sizeof(ROOTHUB_20PORT_INFO))
2215 {
2216 DPRINT1("Get20PortInfo: bad request, %u ports of %u bytes\n",
2217 Info ? Info->NumberOfPorts : 0, Info ? Info->PortInfoSize : 0);
2218 WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
2219 return;
2220 }
2221
2222 NoLpm = Hub->m_Controller->HasErrata(XhciErrata::PortHighSpeedLpmOff);
2223
2224 for (Index = 0; Index < Hub->m_PortCount; Index++)
2225 {
2226 const Port* P = &Hub->m_Ports[Index];
2228
2229 if (P->Major != 2)
2230 continue;
2231
2232 Entry = Info->PortInfoArray[Next++];
2233 Entry->PortNumber = (USHORT)P->Number;
2234 Entry->MinorRevision = P->Minor;
2235 Entry->HubDepth = P->HubDepth;
2236 Entry->Removable = P->Removable ? TriStateTrue : TriStateFalse;
2237 Entry->IntegratedHubImplemented = P->IntegratedHub ? TriStateTrue : TriStateFalse;
2238
2239 /* Report no LPM flags when 2.0 LPM is disabled */
2240 Entry->ControllerUsb20HardwareLpmFlags.AsUchar = NoLpm ? 0 : P->LpmCapabilities;
2241 }
2242
2243 WdfRequestComplete(Request, STATUS_SUCCESS);
2244}
2245
2246VOID
2247NTAPI
2249 _In_ UCXROOTHUB UcxRootHub,
2250 _In_ WDFREQUEST Request)
2251{
2255 ULONG Next = 0;
2256 ULONG Index;
2257
2258 if (Info == NULL ||
2259 Info->Size < sizeof(*Info) ||
2260 Info->NumberOfPorts != Hub->m_Usb30PortCount ||
2261 Info->PortInfoSize < sizeof(ROOTHUB_30PORT_INFO))
2262 {
2263 DPRINT1("Get30PortInfo: bad request, %u ports of %u bytes\n",
2264 Info ? Info->NumberOfPorts : 0, Info ? Info->PortInfoSize : 0);
2265 WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
2266 return;
2267 }
2268
2269 for (Index = 0; Index < Hub->m_PortCount; Index++)
2270 {
2271 const Port* P = &Hub->m_Ports[Index];
2273
2274 if (P->Major != 3)
2275 continue;
2276
2277 Entry = Info->PortInfoArray[Next++];
2278 Entry->PortNumber = (USHORT)P->Number;
2279 Entry->MinorRevision = P->Minor;
2280 Entry->HubDepth = P->HubDepth;
2281 Entry->Removable = P->Removable ? TriStateTrue : TriStateFalse;
2282 Entry->DebugCapable = (Hub->m_DebugCapability != 0) ? TriStateTrue : TriStateFalse;
2283
2284 if (Info->PortInfoSize >= sizeof(ROOTHUB_30PORT_INFO_EX))
2285 {
2286 /* One bad speed table fails the whole request */
2287 Status = Hub->FillSpeeds(P, (PROOTHUB_30PORT_INFO_EX)Entry);
2288 if (!NT_SUCCESS(Status))
2289 {
2290 DPRINT1("Get30PortInfo: port %lu speed list failed 0x%lx\n", P->Number, Status);
2291 WdfRequestComplete(Request, Status);
2292 return;
2293 }
2294 }
2295 }
2296
2297 WdfRequestComplete(Request, STATUS_SUCCESS);
2298}
DWORD Id
WCHAR First[]
Definition: FormatMessage.c:11
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
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
HubFdo * Hub
Definition: bootdev.cpp:261
USHORT Change
Definition: bootdev.cpp:133
_In_ ULONG const Usable
Definition: cdrom.h:1084
_In_ ULONG const _In_ FEATURE_NUMBER const Feature
Definition: cdrom.h:1077
Definition: bufpool.h:45
ULONG m_PortCount
Definition: fdo.h:379
WDF_POWER_DEVICE_STATE m_PowerState
Definition: hc.h:117
BOOLEAN HasErrata(_In_ XhciErrata Bit) const
Definition: hc.h:58
BOOLEAN IsAccessible() const
Definition: hc.cpp:193
SystemAction
Definition: hc.h:121
XhciRegisters m_Registers
Definition: hc.h:91
SystemAction m_SystemAction
Definition: hc.h:131
VOID MarkGone()
Definition: hc.cpp:1924
ULONG ReadOperational32(_In_ ULONG Offset) const
Definition: mmio.cpp:431
ULONG MaxPorts() const
Definition: mmio.cpp:555
ULONG ReadPort32(_In_ ULONG Port, _In_ ULONG Offset) const
Definition: mmio.cpp:516
ULONG FindExtendedCapability(_In_ ULONG Id, _In_ ULONG Start) const
Definition: mmio.cpp:284
ULONG Hcsparams3() const
Definition: mmio.cpp:591
ULONG ReadExtended32(_In_ ULONG Offset) const
Definition: mmio.cpp:319
VOID WritePort32(_In_ ULONG Port, _In_ ULONG Offset, _In_ ULONG Value)
Definition: mmio.cpp:528
NTSTATUS Prepare()
Definition: rootports.cpp:314
VOID Release()
Definition: rootports.cpp:404
static XhciRootHub * FromUcx(_In_ UCXROOTHUB UcxRootHub)
Definition: rootports.cpp:179
VOID ResuspendResumedPorts()
Definition: rootports.cpp:775
Outcome GetPortStatus(_In_ PURB Urb)
Definition: rootports.cpp:1284
BOOLEAN AcknowledgeResume(_In_ Port *P, _In_ BOOLEAN PowerUp)
Definition: rootports.cpp:582
NTSTATUS WaitForU3(_In_ Port *P, _In_ BOOLEAN RepeatRequest)
Definition: rootports.cpp:650
Outcome GetHubStatus(_In_ PURB Urb)
Definition: rootports.cpp:1255
Outcome SetUsb30LinkState(_In_ Port *P, _In_ UCHAR LinkState)
Definition: rootports.cpp:1783
BOOLEAN IsPortConnected(_In_ const Port *P) const
Definition: rootports.cpp:519
static EVT_UCX_ROOTHUB_INTERRUPT_TX EvtInterruptTransfer
Definition: rootports.h:120
USHORT m_Usb30PortCount
Definition: rootports.h:249
VOID SignalPortChange()
Definition: rootports.cpp:956
USHORT m_U1ExitLatency
Definition: rootports.h:250
USHORT HighestUsbVersion() const
Definition: rootports.cpp:972
VOID Update20HardwareLpm(_In_ ULONG PortNumber, _In_ ULONG SlotId, _In_ const USBDEVICE_UPDATE_20_HARDWARE_LPM_PARAMETERS *Parameters)
Definition: rootports.cpp:1075
Outcome ClearUsb20PortFeature(_In_ Port *P, _In_ USHORT Feature, _In_ UCHAR Value)
Definition: rootports.cpp:1462
VOID ClearUsb20LpmLocked(_In_ Port *P)
Definition: rootports.cpp:486
static KDEFERRED_ROUTINE ResumeTimerDpc
Definition: rootports.h:124
static VOID CompleteHubRequest(_In_ WDFREQUEST Request, _In_ PURB Urb, _In_ Outcome Result)
Definition: rootports.cpp:1172
VOID OnPortStatusChangeEvent(_In_ const XHCI_TRB *Event)
Definition: rootports.cpp:1044
Outcome InterruptTransfer(_In_ PURB Urb)
Definition: rootports.cpp:1870
ULONG m_DebugCapability
Definition: rootports.h:247
ULONG ReadPortSc(_In_ const Port *P) const
Definition: rootports.cpp:440
ULONG PortCount() const
Definition: rootports.cpp:965
VOID SetWakeEnables(_In_ BOOLEAN Arm)
Definition: rootports.cpp:936
Outcome ClearUsb30PortFeature(_In_ Port *P, _In_ USHORT Feature, _In_ UCHAR Value)
Definition: rootports.cpp:1546
ULONG UpdatePortSc(_In_ Port *P, _In_ ULONG Keep, _In_ ULONG Set)
Definition: rootports.cpp:460
ULONG m_PortCount
Definition: rootports.h:246
BOOLEAN m_PortScTunnelValid
Definition: rootports.h:253
USHORT m_Usb20PortCount
Definition: rootports.h:248
BOOLEAN m_AwaitingStatusRead
Definition: rootports.h:252
NTSTATUS ParseProtocol(_In_ ULONG Capability, _Out_ PBOOLEAN Usable)
Definition: rootports.cpp:235
VOID DisableLpmForSlot(_In_ ULONG PortNumber, _In_ ULONG SlotId)
Definition: rootports.cpp:1118
BOOLEAN IsUsb20Port(_In_ ULONG PortNumber) const
Definition: rootports.cpp:995
UCXROOTHUB m_Ucx
Definition: rootports.h:244
VOID StartResumeTimer(_In_ Port *P)
Definition: rootports.cpp:536
Port * m_Ports
Definition: rootports.h:245
Outcome SetUsb20PortFeature(_In_ Port *P, _In_ USHORT Feature, _In_ UCHAR Value)
Definition: rootports.cpp:1644
BOOLEAN IsHiddenDebugPort(_In_ const Port *P) const
Definition: rootports.cpp:503
static EVT_UCX_ROOTHUB_CONTROL_URB EvtClearPortFeature
Definition: rootports.h:114
Port * PortAt(_In_ ULONG PortNumber) const
Definition: rootports.cpp:430
VOID D0Entry()
Definition: rootports.cpp:844
static EVT_UCX_ROOTHUB_CONTROL_URB EvtGetPortErrorCount
Definition: rootports.h:119
static EVT_UCX_ROOTHUB_GET_20PORT_INFO EvtGet20PortInfo
Definition: rootports.h:122
static EVT_UCX_ROOTHUB_CONTROL_URB EvtSetHubFeature
Definition: rootports.h:117
Outcome SetUsb30PortFeature(_In_ Port *P, _In_ USHORT Feature, _In_ UCHAR Value)
Definition: rootports.cpp:1710
VOID PostReset()
Definition: rootports.cpp:914
Outcome CheckRunning()
Definition: rootports.cpp:1215
Outcome ClearPortFeature(_In_ PURB Urb)
Definition: rootports.cpp:1421
NTSTATUS WaitU0(_In_ Port *P)
Definition: rootports.cpp:701
ULONG m_FirstUsb30Port
Definition: rootports.h:254
VOID D0Exit()
Definition: rootports.cpp:877
static EVT_UCX_ROOTHUB_GET_30PORT_INFO EvtGet30PortInfo
Definition: rootports.h:123
VOID ArmPortResumeTimer(_In_ ULONG PortNumber, _In_ ULONG Milliseconds)
Definition: rootports.cpp:1140
Outcome ClearHubFeature(_In_ PURB Urb)
Definition: rootports.cpp:1236
static EVT_UCX_ROOTHUB_CONTROL_URB EvtGetHubStatus
Definition: rootports.h:115
UCHAR QueryTunnelState(_In_ ULONG PortNumber) const
Definition: rootports.cpp:1005
static EVT_UCX_ROOTHUB_CONTROL_URB EvtSetPortFeature
Definition: rootports.h:118
VOID SuspendPort(_In_ Port *P)
Definition: rootports.cpp:760
VOID DisarmPortResumeTimer(_In_ ULONG PortNumber)
Definition: rootports.cpp:1156
static EVT_UCX_ROOTHUB_CONTROL_URB EvtClearHubFeature
Definition: rootports.h:113
XhciController * m_Controller
Definition: rootports.h:243
USHORT m_U2ExitLatency
Definition: rootports.h:251
static EVT_UCX_ROOTHUB_CONTROL_URB EvtGetPortStatus
Definition: rootports.h:116
static EVT_UCX_ROOTHUB_GET_INFO EvtGetInfo
Definition: rootports.h:121
Outcome GetPortErrorCount(_In_ PURB Urb)
Definition: rootports.cpp:1826
VOID OnHostLost()
Definition: rootports.cpp:921
VOID PostInterruptsEntry()
Definition: rootports.cpp:867
Outcome SetPortFeature(_In_ PURB Urb)
Definition: rootports.cpp:1603
VOID UpdatePortReg(_In_ Port *P, _In_ ULONG Offset, _In_ ULONG Clear, _In_ ULONG Set)
Definition: rootports.cpp:472
NTSTATUS FillSpeeds(_In_ const Port *P, _Inout_ PROOTHUB_30PORT_INFO_EX Entry) const
Definition: rootports.cpp:1991
ULONG UpdatePortScLocked(_In_ Port *P, _In_ ULONG Keep, _In_ ULONG Set)
Definition: rootports.cpp:448
NTSTATUS Create(_In_ XhciController *Controller)
Definition: rootports.cpp:186
ULONG Minor
Definition: classlib.cpp:73
_In_ PVOID Argument2
Definition: classpnp.h:721
LPWSTR Name
Definition: desk.c:124
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
@ Out
_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
_In_ ULONG _In_ ULONG _In_opt_ DXGKCB_MIRACAST_SEND_MESSAGE_CALLBACK Callback
Definition: dispmprt.h:620
#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
static const struct token_string Errors[]
Definition: error.c:43
#define P(row, col)
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
unsigned int Mask
Definition: fpcontrol.c:82
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:24
CPPORT Port[4]
Definition: headless.c:38
_In_ ULONG Mode
Definition: hubbusif.h:303
#define UCXHUB_TUNNEL_STATE_TUNNELED
Definition: hubucx.h:539
#define UCXHUB_TUNNEL_STATE_UNKNOWN
Definition: hubucx.h:541
_In_ ULONG PortNumber
Definition: hubucx.h:272
#define UCXHUB_TUNNEL_STATE_NATIVE
Definition: hubucx.h:540
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
@ NormalPagePriority
Definition: imports.h:54
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
static void Clear(void)
Definition: treeview.c:388
_In_ ULONG Number
Definition: haltypes.h:1940
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1629
#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
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_ADAPTER_HARDWARE_ERROR
Definition: ntstatus.h:524
static BOOL Set
Definition: pageheap.c:10
unsigned short USHORT
Definition: pedump.c:61
static PS2_PORT Ports[PS2_PORTS]
Definition: ps2.c:52
FORCEINLINE PUSB_DEFAULT_PIPE_SETUP_PACKET NTAPI XhciSetupOf(_In_ PURB Urb)
Definition: rootports.cpp:122
struct _XHCI_SPEED_LIST XHCI_SPEED_LIST
static PVOID NTAPI XhciTransferBuffer(_In_opt_ PVOID Buffer, _In_opt_ PMDL Mdl, _In_ ULONG Length, _In_ ULONG Needed)
Definition: rootports.cpp:133
static const UCHAR HubRequestFromPort
Definition: rootports.cpp:18
struct _XHCI_ROOTHUB_CONTEXT XHCI_ROOTHUB_CONTEXT
static const ULONG XhciU0WaitSteps
Definition: rootports.cpp:51
static VOID NTAPI XhciAddSpeed(_Inout_ PXHCI_SPEED_LIST List, _In_ ULONG Id, _In_ ULONG Exponent, _In_ ULONG Mantissa, _In_ ULONG Mode, _In_ ULONG Direction)
Definition: rootports.cpp:1962
static PVOID NTAPI XhciRequestArgument(_In_ WDFREQUEST Request)
Definition: rootports.cpp:109
static VOID NTAPI XhciTraceBadRequest(_In_ PCSTR Callback, _In_ PURB Urb)
Definition: rootports.cpp:166
static const UCHAR HubRequestFromHub
Definition: rootports.cpp:16
@ FeatureRemoteWakeMask
Definition: rootports.cpp:40
@ FeaturePortReset
Definition: rootports.cpp:26
@ FeatureWarmResetChange
Definition: rootports.cpp:42
@ FeaturePortTest
Definition: rootports.cpp:34
@ FeatureEnableChange
Definition: rootports.cpp:30
@ FeatureHubOverCurrentChange
Definition: rootports.cpp:23
@ FeatureOverCurrentChange
Definition: rootports.cpp:32
@ FeatureU2Timeout
Definition: rootports.cpp:37
@ FeaturePortEnable
Definition: rootports.cpp:24
@ FeaturePortPower
Definition: rootports.cpp:28
@ FeaturePortIndicator
Definition: rootports.cpp:35
@ FeatureU1Timeout
Definition: rootports.cpp:36
@ FeatureHubLocalPowerChange
Definition: rootports.cpp:22
@ FeatureConnectChange
Definition: rootports.cpp:29
@ FeatureWarmReset
Definition: rootports.cpp:41
@ FeatureConfigErrorChange
Definition: rootports.cpp:39
@ FeaturePortLinkState
Definition: rootports.cpp:27
@ FeaturePortSuspend
Definition: rootports.cpp:25
@ FeatureResetChange
Definition: rootports.cpp:33
@ FeatureForceLinkPmAccept
Definition: rootports.cpp:43
@ FeatureLinkStateChange
Definition: rootports.cpp:38
@ FeatureSuspendChange
Definition: rootports.cpp:31
static const UCHAR HubRequestToHub
Definition: rootports.cpp:15
FORCEINLINE ULONG NTAPI XhciPortSpeed(_In_ ULONG PortSc)
Definition: rootports.cpp:75
struct _XHCI_ROOTHUB_CONTEXT * PXHCI_ROOTHUB_CONTEXT
struct _XHCI_SPEED_LIST * PXHCI_SPEED_LIST
static PVOID NTAPI XhciHubRequestBuffer(_In_ PURB Urb, _In_ ULONG Needed)
Definition: rootports.cpp:151
static const ULONG XhciPortGone
Definition: rootports.cpp:54
static const ULONG XhciResumeWaitSteps
Definition: rootports.cpp:52
static const UCHAR HubRequestToPort
Definition: rootports.cpp:17
FORCEINLINE BOOLEAN NTAPI XhciPortActive(_In_ ULONG PortSc)
Definition: rootports.cpp:95
static const ULONG XhciResumeSignalMs
Definition: rootports.cpp:47
static const ULONG XhciU3WaitSteps
Definition: rootports.cpp:50
FORCEINLINE ULONG NTAPI XhciLinkState(_In_ ULONG PortSc)
Definition: rootports.cpp:66
FORCEINLINE ULONG NTAPI XhciLinkWrite(_In_ ULONG State)
Definition: rootports.cpp:85
#define STATUS_SUCCESS
Definition: shellext.h:65
PACPI_METHOD_ARGUMENT Next
Definition: slotdev.cpp:96
_In_ const GUID _In_ ULONG Revision
Definition: slotdev.cpp:85
#define DPRINT
Definition: sndvol32.h:73
Definition: ketypes.h:767
PMDL TransferBufferMDL
Definition: usb.h:484
ULONG TransferBufferLength
Definition: usb.h:482
PVOID TransferBuffer
Definition: usb.h:483
Definition: usb.h:565
XhciRootHub * RootHub
Definition: rootports.cpp:58
PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED Speeds
Definition: rootports.cpp:1952
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:282
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
uint32_t * PULONG
Definition: typedefs.h:59
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
const char * PCSTR
Definition: typedefs.h:52
#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_ PUCX_CONTROLLER_CONFIG Config
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
@ TriStateFalse
Definition: ucxroothub.h:23
@ TriStateTrue
Definition: ucxroothub.h:24
struct _ROOTHUB_INFO * PROOTHUB_INFO
FORCEINLINE VOID NTAPI UCX_ROOTHUB_CONFIG_INIT(_Out_ PUCX_ROOTHUB_CONFIG Config, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubClearHubFeature, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubClearPortFeature, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubGetHubStatus, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubGetPortStatus, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubSetHubFeature, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubSetPortFeature, _In_ PFN_UCX_ROOTHUB_CONTROL_URB EvtRootHubGetPortErrorCount, _In_ PFN_UCX_ROOTHUB_INTERRUPT_TX EvtRootHubInterruptTx, _In_ PFN_UCX_ROOTHUB_GET_INFO EvtRootHubGetInfo, _In_ PFN_UCX_ROOTHUB_GET_20PORT_INFO EvtRootHubGet20PortInfo, _In_ PFN_UCX_ROOTHUB_GET_30PORT_INFO EvtRootHubGet30PortInfo)
Definition: ucxroothub.h:252
struct _ROOTHUB_20PORTS_INFO * PROOTHUB_20PORTS_INFO
struct _ROOTHUB_30PORT_INFO ROOTHUB_30PORT_INFO
struct _ROOTHUB_30PORTS_INFO * PROOTHUB_30PORTS_INFO
struct _ROOTHUB_20PORT_INFO ROOTHUB_20PORT_INFO
@ ControllerTypeXhci
Definition: ucxroothub.h:16
#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
ULONG TxSublinkSpeedID
Definition: usb300.h:300
ULONG RxSublinkSpeedID
Definition: usb300.h:299
#define USB_REQUEST_GET_STATUS
Definition: usb100.h:78
#define USB_REQUEST_SET_FEATURE
Definition: usb100.h:80
#define USB_REQUEST_CLEAR_FEATURE
Definition: usb100.h:79
#define PORT_LINK_STATE_DISABLED
Definition: usb200.h:196
#define PORT_LINK_STATE_U3
Definition: usb200.h:195
#define PORT_LINK_STATE_U1
Definition: usb200.h:193
#define PORT_LINK_STATE_COMPLIANCE_MODE
Definition: usb200.h:202
#define PORT_LINK_STATE_HOT_RESET
Definition: usb200.h:201
#define PORT_LINK_STATE_RECOVERY
Definition: usb200.h:200
#define PORT_LINK_STATE_TEST_MODE
Definition: usb200.h:204
#define USB_REQUEST_GET_PORT_ERR_COUNT
Definition: usb200.h:289
#define PORT_LINK_STATE_INACTIVE
Definition: usb200.h:198
#define PORT_LINK_STATE_U2
Definition: usb200.h:194
#define PORT_LINK_STATE_RX_DETECT
Definition: usb200.h:197
#define PORT_LINK_STATE_U0
Definition: usb200.h:192
#define USB_STATUS_EXT_PORT_STATUS
Definition: usb300.h:351
#define USB_STATUS_PORT_STATUS
Definition: usb300.h:349
union _USB_PORT_EXT_STATUS_AND_CHANGE * PUSB_PORT_EXT_STATUS_AND_CHANGE
#define USBD_STATUS_DEVICE_GONE
Definition: usb.h:222
struct _URB * PURB
#define USBD_STATUS_STALL_PID
Definition: usb.h:183
#define USBD_STATUS_SUCCESS
Definition: usb.h:177
#define USBD_STATUS_PORT_OPERATION_PENDING
Definition: usb.h:178
#define USBD_STATUS_XACT_ERROR
Definition: usb.h:195
LONG USBD_STATUS
Definition: usb.h:172
_In_opt_ PUSB_CONFIGURATION_DESCRIPTOR _Inout_ PUSBD_INTERFACE_LIST_ENTRY _Outptr_ PURB * Urb
Definition: usbdlib.h:333
USHORT Count
Definition: userreq.cpp:200
for(Attempt=0;Attempt< UCX_LEGACY_NAME_ATTEMPTS;Attempt++)
Definition: userreq.cpp:715
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ WDFCOLLECTION _In_ ULONG Index
@ WdfPowerDeviceD3Final
Definition: wdfdevice.h:427
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION Direction
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
#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 _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define FORCEINLINE
Definition: wdftypes.h:67
_In_ NTSTATUS _In_ USBD_STATUS UsbdStatus
Definition: wdfusb.h:403
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_IRQL_requires_same_ _In_opt_ PVOID Argument1
Definition: cmtypes.h:697
#define KD_DEBUGGER_ENABLED
Definition: kdfuncs.h:130
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define NT_ASSERT
Definition: rtlfuncs.h:3334
#define XHCI_PORTSC_WRC
Definition: xhcihw.h:223
#define XHCI_SPEED_LOW
Definition: xhcihw.h:242
#define XHCI_PORTSC_PP
Definition: xhcihw.h:215
#define XHCI_PORTPMSC_HLE
Definition: xhcihw.h:258
#define XHCI_PSI_TYPE_MASK
Definition: xhcihw.h:303
#define XHCI_PSI_TYPE_ASYMMETRIC_RX
Definition: xhcihw.h:307
#define XHCI_EXTCAP_DEBUG
Definition: xhcihw.h:311
#define XHCI_PORTSC_PLC
Definition: xhcihw.h:226
#define XHCI_PORTHLPMC_L1_TIMEOUT_SHIFT
Definition: xhcihw.h:271
#define XHCI_PROTOCOL_NAME_USB
Definition: xhcihw.h:285
#define XHCI_PORTHLPMC_L1_TIMEOUT_MASK
Definition: xhcihw.h:272
#define XHCI_PORTPMSC_L1_SLOT_MASK
Definition: xhcihw.h:257
#define XHCI_PORTPMSC_BESL_SHIFT
Definition: xhcihw.h:254
#define XHCI_PSI_TYPE_ASYMMETRIC_TX
Definition: xhcihw.h:308
#define XHCI_PORTSC_CSC
Definition: xhcihw.h:221
#define XHCI_PORTPMSC_U2_TIMEOUT_MASK
Definition: xhcihw.h:249
#define XHCI_VENDOR_PORT_TUNNEL_STRIDE
Definition: xhcihw.h:651
#define XHCI_PORTSC_WAKE_MASK
Definition: xhcihw.h:230
#define XHCI_EXTCAP_USB4_TUNNELING
Definition: xhcihw.h:645
#define XHCI_PROTOCOL_HSO
Definition: xhcihw.h:290
#define XHCI_PORTPMSC_FLA
Definition: xhcihw.h:250
#define XHCI_PORTSC_OCC
Definition: xhcihw.h:224
#define XHCI_HCS3_U2_LATENCY_SHIFT
Definition: xhcihw.h:365
#define XHCI_PORTSC_PIC_SHIFT
Definition: xhcihw.h:218
#define XHCI_PORTSC_LWS
Definition: xhcihw.h:220
#define XHCI_PORTPMSC_BESL_MASK
Definition: xhcihw.h:255
#define XHCI_PORTPMSC_TEST_SHIFT
Definition: xhcihw.h:259
#define XHCI_PROTOCOL_COUNT_MASK
Definition: xhcihw.h:289
#define XHCI_PORTPMSC_TEST_MASK
Definition: xhcihw.h:260
#define XHCI_PROTOCOL_PORTS
Definition: xhcihw.h:280
#define XHCI_PORTLI_TX_LANES_SHIFT
Definition: xhcihw.h:266
#define XHCI_DBC_DCST_PORT_SHIFT
Definition: xhcihw.h:313
#define XHCI_PROTOCOL_OFFSET_MASK
Definition: xhcihw.h:287
#define XHCI_PORTSC_CCS
Definition: xhcihw.h:209
#define XHCI_EXTCAP_SUPPORTED_PROTOCOL
Definition: xhcihw.h:277
#define XHCI_PORTLI_RX_LANES_SHIFT
Definition: xhcihw.h:264
#define XHCI_PORTSC_PED
Definition: xhcihw.h:210
#define XHCI_PORTSC_PR
Definition: xhcihw.h:212
#define XHCI_PSI_MANTISSA_SHIFT
Definition: xhcihw.h:304
#define XHCI_PORTSC_PLS_SHIFT
Definition: xhcihw.h:213
#define XHCI_PROTOCOL_PSIC_SHIFT
Definition: xhcihw.h:296
#define XHCI_PROTOCOL_NAME
Definition: xhcihw.h:279
#define XHCI_PORTSC_DR
Definition: xhcihw.h:231
#define XHCI_PORTSC_WAKE_SHIFT
Definition: xhcihw.h:229
#define XHCI_PSI_TYPE_SYMMETRIC
Definition: xhcihw.h:306
#define XHCI_SPEED_SUPER
Definition: xhcihw.h:244
#define XHCI_PORTHLPMC_BESLD_MASK
Definition: xhcihw.h:274
#define XHCI_PORTSC_SPEED_MASK
Definition: xhcihw.h:217
#define XHCI_PROTOCOL_MHD_SHIFT
Definition: xhcihw.h:294
#define XHCI_VENDOR_PORT_TUNNEL_BASE
Definition: xhcihw.h:650
#define XHCI_PSI_ID_MASK
Definition: xhcihw.h:299
#define XHCI_PROTOCOL_BLC
Definition: xhcihw.h:293
#define XHCI_VENDOR_PORT_TUNNEL_ACTIVE
Definition: xhcihw.h:652
#define XHCI_PROTOCOL_REVISION
Definition: xhcihw.h:278
#define XHCI_PORTHLPMC_HIRDM_MASK
Definition: xhcihw.h:270
#define XHCI_PROTOCOL_MHD_MASK
Definition: xhcihw.h:295
#define XHCI_DBC_DCST
Definition: xhcihw.h:312
#define XHCI_SPEED_HIGH
Definition: xhcihw.h:243
#define XHCI_PORTSC_CAS
Definition: xhcihw.h:228
#define XHCI_PORTPMSC_U2_TIMEOUT_SHIFT
Definition: xhcihw.h:248
#define XHCI_PROTOCOL_PSI
Definition: xhcihw.h:281
#define XHCI_PORTPMSC_U1_TIMEOUT_MASK
Definition: xhcihw.h:247
#define XHCI_PORTPMSC_RWE
Definition: xhcihw.h:253
#define XHCI_PROTOCOL_COUNT_SHIFT
Definition: xhcihw.h:288
#define XHCI_PORTSC_PRC
Definition: xhcihw.h:225
#define XHCI_SPEED_FULL
Definition: xhcihw.h:241
#define XHCI_PROTOCOL_HLC
Definition: xhcihw.h:292
#define XHCI_PORTSC_PRESERVE
Definition: xhcihw.h:235
#define XHCI_PORTLI_ERROR_COUNT_MASK
Definition: xhcihw.h:263
#define XHCI_PROTOCOL_IHI
Definition: xhcihw.h:291
#define XHCI_PSI_TYPE_SHIFT
Definition: xhcihw.h:302
#define XHCI_PORTPMSC_L1_SLOT_SHIFT
Definition: xhcihw.h:256
#define XHCI_PSI_EXPONENT_MASK
Definition: xhcihw.h:301
#define XHCI_OP_USBSTS
Definition: xhcihw.h:382
#define XHCI_PORTHLPMC_BESLD_SHIFT
Definition: xhcihw.h:273
#define XHCI_EVENT_PORT_ID_SHIFT
Definition: xhcihw.h:316
#define XHCI_PORTSC_PIC_MASK
Definition: xhcihw.h:219
#define XHCI_PORTSC_OCA
Definition: xhcihw.h:211
#define XHCI_PORTSC_SPEED_SHIFT
Definition: xhcihw.h:216
#define XHCI_PORTSC_TUNNELED
Definition: xhcihw.h:647
#define XHCI_PORTLI_TX_LANES_MASK
Definition: xhcihw.h:267
#define XHCI_USB4_CAP_PORTSC_TUNNEL_VALID
Definition: xhcihw.h:646
#define XHCI_USBSTS_HCH
Definition: xhcihw.h:401
#define XHCI_PORT_HLPMC
Definition: xhcihw.h:206
#define XHCI_PROTOCOL_MAJOR_SHIFT
Definition: xhcihw.h:284
#define XHCI_PORT_LI
Definition: xhcihw.h:205
#define XHCI_PLS_RESUME
Definition: xhcihw.h:238
#define XHCI_PORTSC_PLS_MASK
Definition: xhcihw.h:214
#define XHCI_PORT_PMSC
Definition: xhcihw.h:204
#define XHCI_PORTSC_PEC
Definition: xhcihw.h:222
#define XHCI_HCS3_U1_LATENCY_MASK
Definition: xhcihw.h:364
#define XHCI_PORT_SC
Definition: xhcihw.h:203
#define XHCI_PSI_EXPONENT_SHIFT
Definition: xhcihw.h:300
#define XHCI_VENDOR_TUNNEL_STATUS
Definition: xhcihw.h:653
#define XHCI_VENDOR_TUNNEL_STATUS_ACTIVE
Definition: xhcihw.h:654
#define XHCI_PROTOCOL_MINOR_SHIFT
Definition: xhcihw.h:283
#define XHCI_PORTLI_RX_LANES_MASK
Definition: xhcihw.h:265
#define XHCI_PORTSC_CEC
Definition: xhcihw.h:227
#define XHCI_PORTSC_WPR
Definition: xhcihw.h:232
FORCEINLINE LARGE_INTEGER NTAPI XhciRelativeMs(_In_ ULONG Milliseconds)
Definition: xhciutil.h:137
#define XHCI_TAG_ROOTHUB
Definition: xhciutil.h:16
_In_ PLARGE_INTEGER _In_opt_ PTIMER_APC_ROUTINE _In_opt_ PVOID _In_ BOOLEAN ResumeTimer
Definition: zwfuncs.h:431