TianoCore EDK2 master
Loading...
Searching...
No Matches
XhcPeim.c
Go to the documentation of this file.
1
11#include "XhcPeim.h"
12
13//
14// Two arrays used to translate the XHCI port state (change)
15// to the UEFI protocol's port state (change).
16//
17USB_PORT_STATE_MAP mUsbPortStateMap[] = {
18 { XHC_PORTSC_CCS, USB_PORT_STAT_CONNECTION },
19 { XHC_PORTSC_PED, USB_PORT_STAT_ENABLE },
20 { XHC_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT },
21 { XHC_PORTSC_PP, USB_PORT_STAT_POWER },
22 { XHC_PORTSC_RESET, USB_PORT_STAT_RESET }
23};
24
25USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
26 { XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION },
27 { XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE },
28 { XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT },
29 { XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET }
30};
31
32USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {
33 { XHC_PORTSC_CSC, EfiUsbPortConnectChange },
34 { XHC_PORTSC_PEC, EfiUsbPortEnableChange },
35 { XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange },
36 { XHC_PORTSC_PRC, EfiUsbPortResetChange }
37};
38
39USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {
40 { XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION },
41 { XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE },
42 { XHC_HUB_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT },
43 { XHC_HUB_PORTSC_PP, USB_PORT_STAT_POWER },
44 { XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET }
45};
46
47USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {
48 { XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION },
49 { XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE },
50 { XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT },
51 { XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET }
52};
53
54USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {
55 { XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange },
56 { XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange },
57 { XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange },
58 { XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange },
59 { XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange }
60};
61
71UINT32
73 IN PEI_XHC_DEV *Xhc,
74 IN UINT32 Offset
75 )
76{
77 UINT32 Data;
78
79 ASSERT (Xhc->CapLength != 0);
80
81 Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Xhc->CapLength + Offset);
82 return Data;
83}
84
93VOID
95 IN PEI_XHC_DEV *Xhc,
96 IN UINT32 Offset,
97 IN UINT32 Data
98 )
99{
100 ASSERT (Xhc->CapLength != 0);
101
102 MmioWrite32 (Xhc->UsbHostControllerBaseAddress + Xhc->CapLength + Offset, Data);
103}
104
113VOID
115 IN PEI_XHC_DEV *Xhc,
116 IN UINT32 Offset,
117 IN UINT32 Bit
118 )
119{
120 UINT32 Data;
121
122 Data = XhcPeiReadOpReg (Xhc, Offset);
123 Data |= Bit;
124 XhcPeiWriteOpReg (Xhc, Offset, Data);
125}
126
135VOID
137 IN PEI_XHC_DEV *Xhc,
138 IN UINT32 Offset,
139 IN UINT32 Bit
140 )
141{
142 UINT32 Data;
143
144 Data = XhcPeiReadOpReg (Xhc, Offset);
145 Data &= ~Bit;
146 XhcPeiWriteOpReg (Xhc, Offset, Data);
147}
148
165 IN PEI_XHC_DEV *Xhc,
166 IN UINT32 Offset,
167 IN UINT32 Bit,
168 IN BOOLEAN WaitToSet,
169 IN UINT32 Timeout
170 )
171{
172 UINT64 Index;
173
174 for (Index = 0; Index < Timeout * XHC_1_MILLISECOND; Index++) {
175 if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
176 return EFI_SUCCESS;
177 }
178
179 MicroSecondDelay (XHC_1_MICROSECOND);
180 }
181
182 return EFI_TIMEOUT;
183}
184
194UINT32
196 IN PEI_XHC_DEV *Xhc,
197 IN UINT32 Offset
198 )
199{
200 UINT32 Data;
201
202 Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Offset);
203
204 return Data;
205}
206
215VOID
217 IN PEI_XHC_DEV *Xhc,
218 IN UINT32 Offset,
219 IN UINT32 Data
220 )
221{
222 ASSERT (Xhc->DBOff != 0);
223
224 MmioWrite32 (Xhc->UsbHostControllerBaseAddress + Xhc->DBOff + Offset, Data);
225}
226
236UINT32
238 IN PEI_XHC_DEV *Xhc,
239 IN UINT32 Offset
240 )
241{
242 UINT32 Data;
243
244 ASSERT (Xhc->RTSOff != 0);
245
246 Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Xhc->RTSOff + Offset);
247
248 return Data;
249}
250
259VOID
261 IN PEI_XHC_DEV *Xhc,
262 IN UINT32 Offset,
263 IN UINT32 Data
264 )
265{
266 ASSERT (Xhc->RTSOff != 0);
267
268 MmioWrite32 (Xhc->UsbHostControllerBaseAddress + Xhc->RTSOff + Offset, Data);
269}
270
279VOID
281 IN PEI_XHC_DEV *Xhc,
282 IN UINT32 Offset,
283 IN UINT32 Bit
284 )
285{
286 UINT32 Data;
287
288 Data = XhcPeiReadRuntimeReg (Xhc, Offset);
289 Data |= Bit;
290 XhcPeiWriteRuntimeReg (Xhc, Offset, Data);
291}
292
301VOID
303 IN PEI_XHC_DEV *Xhc,
304 IN UINT32 Offset,
305 IN UINT32 Bit
306 )
307{
308 UINT32 Data;
309
310 Data = XhcPeiReadRuntimeReg (Xhc, Offset);
311 Data &= ~Bit;
312 XhcPeiWriteRuntimeReg (Xhc, Offset, Data);
313}
314
324BOOLEAN
326 IN PEI_XHC_DEV *Xhc
327 )
328{
329 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);
330}
331
341BOOLEAN
343 IN PEI_XHC_DEV *Xhc
344 )
345{
346 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);
347}
348
361 IN PEI_XHC_DEV *Xhc,
362 IN UINT32 Timeout
363 )
364{
365 EFI_STATUS Status;
366
367 //
368 // Host can only be reset when it is halt. If not so, halt it
369 //
370 if (!XhcPeiIsHalt (Xhc)) {
371 Status = XhcPeiHaltHC (Xhc, Timeout);
372
373 if (EFI_ERROR (Status)) {
374 goto ON_EXIT;
375 }
376 }
377
378 XhcPeiSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
379 //
380 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
381 // Otherwise there may have the timeout case happened.
382 // The below is a workaround to solve such problem.
383 //
384 MicroSecondDelay (1000);
385 Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
386ON_EXIT:
387 DEBUG ((DEBUG_INFO, "XhcPeiResetHC: %r\n", Status));
388 return Status;
389}
390
403 IN PEI_XHC_DEV *Xhc,
404 IN UINT32 Timeout
405 )
406{
407 EFI_STATUS Status;
408
409 XhcPeiClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
410 Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);
411 DEBUG ((DEBUG_INFO, "XhcPeiHaltHC: %r\n", Status));
412 return Status;
413}
414
427 IN PEI_XHC_DEV *Xhc,
428 IN UINT32 Timeout
429 )
430{
431 EFI_STATUS Status;
432
433 XhcPeiSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
434 Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);
435 DEBUG ((DEBUG_INFO, "XhcPeiRunHC: %r\n", Status));
436 return Status;
437}
438
466EFIAPI
468 IN EFI_PEI_SERVICES **PeiServices,
470 IN UINT8 DeviceAddress,
471 IN UINT8 DeviceSpeed,
472 IN UINTN MaximumPacketLength,
473 IN EFI_USB_DEVICE_REQUEST *Request,
474 IN EFI_USB_DATA_DIRECTION TransferDirection,
475 IN OUT VOID *Data,
476 IN OUT UINTN *DataLength,
477 IN UINTN TimeOut,
479 OUT UINT32 *TransferResult
480 )
481{
482 PEI_XHC_DEV *Xhc;
483 URB *Urb;
484 UINT8 Endpoint;
485 UINT8 Index;
486 UINT8 DescriptorType;
487 UINT8 SlotId;
488 UINT8 TTT;
489 UINT8 MTT;
490 UINT32 MaxPacket0;
491 EFI_USB_HUB_DESCRIPTOR *HubDesc;
492 EFI_STATUS Status;
493 EFI_STATUS RecoveryStatus;
494 UINTN MapSize;
495 EFI_USB_PORT_STATUS PortStatus;
496 UINT32 State;
497 EFI_USB_DEVICE_REQUEST ClearPortRequest;
498 UINTN Len;
499
500 //
501 // Validate parameters
502 //
503 if ((Request == NULL) || (TransferResult == NULL)) {
504 return EFI_INVALID_PARAMETER;
505 }
506
507 if ((TransferDirection != EfiUsbDataIn) &&
508 (TransferDirection != EfiUsbDataOut) &&
509 (TransferDirection != EfiUsbNoData))
510 {
511 return EFI_INVALID_PARAMETER;
512 }
513
514 if ((TransferDirection == EfiUsbNoData) &&
515 ((Data != NULL) || (*DataLength != 0)))
516 {
517 return EFI_INVALID_PARAMETER;
518 }
519
520 if ((TransferDirection != EfiUsbNoData) &&
521 ((Data == NULL) || (*DataLength == 0)))
522 {
523 return EFI_INVALID_PARAMETER;
524 }
525
526 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
527 (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&
528 (MaximumPacketLength != 512)
529 )
530 {
531 return EFI_INVALID_PARAMETER;
532 }
533
534 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
535 return EFI_INVALID_PARAMETER;
536 }
537
538 if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {
539 return EFI_INVALID_PARAMETER;
540 }
541
542 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);
543
544 Status = EFI_DEVICE_ERROR;
545 *TransferResult = EFI_USB_ERR_SYSTEM;
546 Len = 0;
547
548 if (XhcPeiIsHalt (Xhc) || XhcPeiIsSysError (Xhc)) {
549 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: HC is halted or has system error\n"));
550 goto ON_EXIT;
551 }
552
553 //
554 // Check if the device is still enabled before every transaction.
555 //
556 SlotId = XhcPeiBusDevAddrToSlotId (Xhc, DeviceAddress);
557 if (SlotId == 0) {
558 goto ON_EXIT;
559 }
560
561 //
562 // Hook the Set_Address request from UsbBus.
563 // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
564 //
565 if ((Request->Request == USB_REQ_SET_ADDRESS) &&
566 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)))
567 {
568 //
569 // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
570 // This way is used to clean the history to avoid using wrong device address afterwards.
571 //
572 for (Index = 0; Index < 255; Index++) {
573 if (!Xhc->UsbDevContext[Index + 1].Enabled &&
574 (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&
575 (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value))
576 {
577 Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
578 }
579 }
580
581 if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {
582 goto ON_EXIT;
583 }
584
585 //
586 // The actual device address has been assigned by XHCI during initializing the device slot.
587 // So we just need establish the mapping relationship between the device address requested from UsbBus
588 // and the actual device address assigned by XHCI. The following invocations through EFI_USB2_HC_PROTOCOL interface
589 // can find out the actual device address by it.
590 //
591 Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;
592 Status = EFI_SUCCESS;
593 goto ON_EXIT;
594 }
595
596 //
597 // Create a new URB, insert it into the asynchronous
598 // schedule list, then poll the execution status.
599 // Note that we encode the direction in address although default control
600 // endpoint is bidirectional. XhcPeiCreateUrb expects this
601 // combination of Ep addr and its direction.
602 //
603 Endpoint = (UINT8)(0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
604 Urb = XhcPeiCreateUrb (
605 Xhc,
606 DeviceAddress,
607 Endpoint,
608 DeviceSpeed,
609 MaximumPacketLength,
610 XHC_CTRL_TRANSFER,
611 Request,
612 Data,
613 *DataLength,
614 NULL,
615 NULL
616 );
617
618 if (Urb == NULL) {
619 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: failed to create URB"));
620 Status = EFI_OUT_OF_RESOURCES;
621 goto ON_EXIT;
622 }
623
624 Status = XhcPeiExecTransfer (Xhc, FALSE, Urb, TimeOut);
625
626 //
627 // Get the status from URB. The result is updated in XhcPeiCheckUrbResult
628 // which is called by XhcPeiExecTransfer
629 //
630 *TransferResult = Urb->Result;
631 *DataLength = Urb->Completed;
632
633 if (Status == EFI_TIMEOUT) {
634 //
635 // The transfer timed out. Abort the transfer by dequeueing of the TD.
636 //
637 RecoveryStatus = XhcPeiDequeueTrbFromEndpoint (Xhc, Urb);
638 if (EFI_ERROR (RecoveryStatus)) {
639 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
640 }
641
642 XhcPeiFreeUrb (Xhc, Urb);
643 goto ON_EXIT;
644 } else {
645 if (*TransferResult == EFI_USB_NOERROR) {
646 Status = EFI_SUCCESS;
647 } else if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {
648 RecoveryStatus = XhcPeiRecoverHaltedEndpoint (Xhc, Urb);
649 if (EFI_ERROR (RecoveryStatus)) {
650 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
651 }
652
653 Status = EFI_DEVICE_ERROR;
654 XhcPeiFreeUrb (Xhc, Urb);
655 goto ON_EXIT;
656 } else {
657 XhcPeiFreeUrb (Xhc, Urb);
658 goto ON_EXIT;
659 }
660 }
661
662 //
663 // Unmap data before consume.
664 //
665 XhcPeiFreeUrb (Xhc, Urb);
666
667 //
668 // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
669 // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
670 // Hook Set_Config request from UsbBus as we need configure device endpoint.
671 //
672 if ((Request->Request == USB_REQ_GET_DESCRIPTOR) &&
673 ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||
674 ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE)))))
675 {
676 DescriptorType = (UINT8)(Request->Value >> 8);
677 if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {
678 ASSERT (Data != NULL);
679 //
680 // Store a copy of device scriptor as hub device need this info to configure endpoint.
681 //
682 CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
683 if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {
684 //
685 // If it's a usb3.0 device, then its max packet size is a 2^n.
686 //
687 MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
688 } else {
689 MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
690 }
691
692 Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
693 if (Xhc->UsbDevContext[SlotId].ConfDesc == NULL) {
694 Status = EFI_OUT_OF_RESOURCES;
695 goto ON_EXIT;
696 }
697
698 if (Xhc->HcCParams.Data.Csz == 0) {
699 Status = XhcPeiEvaluateContext (Xhc, SlotId, MaxPacket0);
700 } else {
701 Status = XhcPeiEvaluateContext64 (Xhc, SlotId, MaxPacket0);
702 }
703 } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
704 ASSERT (Data != NULL);
705 if (*DataLength == ((UINT16 *)Data)[1]) {
706 //
707 // Get configuration value from request, store the configuration descriptor for Configure_Endpoint cmd.
708 //
709 Index = (UINT8)Request->Value;
710 ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
711 Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool (*DataLength);
712 if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] == NULL) {
713 Status = EFI_OUT_OF_RESOURCES;
714 goto ON_EXIT;
715 }
716
717 CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
718 }
719 } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
720 (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2))
721 {
722 ASSERT (Data != NULL);
723 HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;
724 ASSERT (HubDesc->NumPorts <= 15);
725 //
726 // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
727 //
728 TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);
729 if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {
730 //
731 // Don't support multi-TT feature for super speed hub now.
732 //
733 MTT = 0;
734 DEBUG ((DEBUG_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
735 } else {
736 MTT = 0;
737 }
738
739 if (Xhc->HcCParams.Data.Csz == 0) {
740 Status = XhcPeiConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
741 } else {
742 Status = XhcPeiConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
743 }
744 }
745 } else if ((Request->Request == USB_REQ_SET_CONFIG) &&
746 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)))
747 {
748 //
749 // Hook Set_Config request from UsbBus as we need configure device endpoint.
750 //
751 for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
752 if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {
753 if (Xhc->HcCParams.Data.Csz == 0) {
754 Status = XhcPeiSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
755 } else {
756 Status = XhcPeiSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
757 }
758
759 break;
760 }
761 }
762 } else if ((Request->Request == USB_REQ_GET_STATUS) &&
763 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)))
764 {
765 ASSERT (Data != NULL);
766 //
767 // Hook Get_Status request from UsbBus to keep track of the port status change.
768 //
769 State = *(UINT32 *)Data;
770 PortStatus.PortStatus = 0;
771 PortStatus.PortChangeStatus = 0;
772
773 if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
774 //
775 // For super speed hub, its bit10~12 presents the attached device speed.
776 //
777 if ((State & XHC_PORTSC_PS) >> 10 == 0) {
778 PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;
779 }
780 } else {
781 //
782 // For high or full/low speed hub, its bit9~10 presents the attached device speed.
783 //
784 if (XHC_BIT_IS_SET (State, BIT9)) {
785 PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;
786 } else if (XHC_BIT_IS_SET (State, BIT10)) {
787 PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;
788 }
789 }
790
791 //
792 // Convert the XHCI port/port change state to UEFI status
793 //
794 MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);
795 for (Index = 0; Index < MapSize; Index++) {
796 if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {
797 PortStatus.PortStatus = (UINT16)(PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);
798 }
799 }
800
801 MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
802 for (Index = 0; Index < MapSize; Index++) {
803 if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {
804 PortStatus.PortChangeStatus = (UINT16)(PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);
805 }
806 }
807
808 MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
809
810 for (Index = 0; Index < MapSize; Index++) {
811 if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
812 ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
813 ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
814 ClearPortRequest.Request = (UINT8)USB_REQ_CLEAR_FEATURE;
815 ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector;
816 ClearPortRequest.Index = Request->Index;
817 ClearPortRequest.Length = 0;
818
820 PeiServices,
821 This,
822 DeviceAddress,
823 DeviceSpeed,
824 MaximumPacketLength,
825 &ClearPortRequest,
826 EfiUsbNoData,
827 NULL,
828 &Len,
829 TimeOut,
830 Translator,
831 TransferResult
832 );
833 }
834 }
835
836 XhcPeiPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
837
838 *(UINT32 *)Data = *(UINT32 *)&PortStatus;
839 }
840
841ON_EXIT:
842
843 if (EFI_ERROR (Status)) {
844 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
845 }
846
847 return Status;
848}
849
883EFIAPI
885 IN EFI_PEI_SERVICES **PeiServices,
887 IN UINT8 DeviceAddress,
888 IN UINT8 EndPointAddress,
889 IN UINT8 DeviceSpeed,
890 IN UINTN MaximumPacketLength,
891 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
892 IN OUT UINTN *DataLength,
893 IN OUT UINT8 *DataToggle,
894 IN UINTN TimeOut,
896 OUT UINT32 *TransferResult
897 )
898{
899 PEI_XHC_DEV *Xhc;
900 URB *Urb;
901 UINT8 SlotId;
902 EFI_STATUS Status;
903 EFI_STATUS RecoveryStatus;
904
905 //
906 // Validate the parameters
907 //
908 if ((DataLength == NULL) || (*DataLength == 0) ||
909 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL))
910 {
911 return EFI_INVALID_PARAMETER;
912 }
913
914 if ((*DataToggle != 0) && (*DataToggle != 1)) {
915 return EFI_INVALID_PARAMETER;
916 }
917
918 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
919 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
920 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 512)) ||
921 ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength > 1024)))
922 {
923 return EFI_INVALID_PARAMETER;
924 }
925
926 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);
927
928 *TransferResult = EFI_USB_ERR_SYSTEM;
929 Status = EFI_DEVICE_ERROR;
930
931 if (XhcPeiIsHalt (Xhc) || XhcPeiIsSysError (Xhc)) {
932 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: HC is halted or has system error\n"));
933 goto ON_EXIT;
934 }
935
936 //
937 // Check if the device is still enabled before every transaction.
938 //
939 SlotId = XhcPeiBusDevAddrToSlotId (Xhc, DeviceAddress);
940 if (SlotId == 0) {
941 goto ON_EXIT;
942 }
943
944 //
945 // Create a new URB, insert it into the asynchronous
946 // schedule list, then poll the execution status.
947 //
948 Urb = XhcPeiCreateUrb (
949 Xhc,
950 DeviceAddress,
951 EndPointAddress,
952 DeviceSpeed,
953 MaximumPacketLength,
954 XHC_BULK_TRANSFER,
955 NULL,
956 Data[0],
957 *DataLength,
958 NULL,
959 NULL
960 );
961
962 if (Urb == NULL) {
963 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: failed to create URB\n"));
964 Status = EFI_OUT_OF_RESOURCES;
965 goto ON_EXIT;
966 }
967
968 Status = XhcPeiExecTransfer (Xhc, FALSE, Urb, TimeOut);
969
970 *TransferResult = Urb->Result;
971 *DataLength = Urb->Completed;
972
973 if (Status == EFI_TIMEOUT) {
974 //
975 // The transfer timed out. Abort the transfer by dequeueing of the TD.
976 //
977 RecoveryStatus = XhcPeiDequeueTrbFromEndpoint (Xhc, Urb);
978 if (EFI_ERROR (RecoveryStatus)) {
979 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
980 }
981 } else {
982 if (*TransferResult == EFI_USB_NOERROR) {
983 Status = EFI_SUCCESS;
984 } else if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {
985 RecoveryStatus = XhcPeiRecoverHaltedEndpoint (Xhc, Urb);
986 if (EFI_ERROR (RecoveryStatus)) {
987 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
988 }
989
990 Status = EFI_DEVICE_ERROR;
991 }
992 }
993
994 XhcPeiFreeUrb (Xhc, Urb);
995
996ON_EXIT:
997
998 if (EFI_ERROR (Status)) {
999 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1000 }
1001
1002 return Status;
1003}
1004
1018EFIAPI
1020 IN EFI_PEI_SERVICES **PeiServices,
1022 OUT UINT8 *PortNumber
1023 )
1024{
1025 PEI_XHC_DEV *XhcDev;
1026
1027 XhcDev = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);
1028
1029 if (PortNumber == NULL) {
1030 return EFI_INVALID_PARAMETER;
1031 }
1032
1033 *PortNumber = XhcDev->HcSParams1.Data.MaxPorts;
1034 DEBUG ((DEBUG_INFO, "XhcPeiGetRootHubPortNumber: PortNumber = %x\n", *PortNumber));
1035 return EFI_SUCCESS;
1036}
1037
1054EFIAPI
1056 IN EFI_PEI_SERVICES **PeiServices,
1058 IN UINT8 PortNumber,
1059 IN EFI_USB_PORT_FEATURE PortFeature
1060 )
1061{
1062 PEI_XHC_DEV *Xhc;
1063 UINT32 Offset;
1064 UINT32 State;
1065 EFI_STATUS Status;
1066
1067 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);
1068 Status = EFI_SUCCESS;
1069
1070 if (PortNumber >= Xhc->HcSParams1.Data.MaxPorts) {
1071 Status = EFI_INVALID_PARAMETER;
1072 goto ON_EXIT;
1073 }
1074
1075 Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));
1076 State = XhcPeiReadOpReg (Xhc, Offset);
1077 DEBUG ((DEBUG_INFO, "XhcPeiClearRootHubPortFeature: Port: %x State: %x\n", PortNumber, State));
1078
1079 //
1080 // Mask off the port status change bits, these bits are
1081 // write clean bits
1082 //
1083 State &= ~(BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
1084
1085 switch (PortFeature) {
1086 case EfiUsbPortEnable:
1087 //
1088 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
1089 // A port may be disabled by software writing a '1' to this flag.
1090 //
1091 State |= XHC_PORTSC_PED;
1092 State &= ~XHC_PORTSC_RESET;
1093 XhcPeiWriteOpReg (Xhc, Offset, State);
1094 break;
1095
1096 case EfiUsbPortSuspend:
1097 State |= XHC_PORTSC_LWS;
1098 XhcPeiWriteOpReg (Xhc, Offset, State);
1099 State &= ~XHC_PORTSC_PLS;
1100 XhcPeiWriteOpReg (Xhc, Offset, State);
1101 break;
1102
1103 case EfiUsbPortReset:
1104 //
1105 // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
1106 // Register bits indicate status when read, a clear bit may be set by
1107 // writing a '1'. Writing a '0' to RW1S bits has no effect.
1108 //
1109 break;
1110
1111 case EfiUsbPortPower:
1112 if (Xhc->HcCParams.Data.Ppc) {
1113 //
1114 // Port Power Control supported
1115 //
1116 State &= ~XHC_PORTSC_PP;
1117 XhcPeiWriteOpReg (Xhc, Offset, State);
1118 }
1119
1120 break;
1121
1122 case EfiUsbPortOwner:
1123 //
1124 // XHCI root hub port don't has the owner bit, ignore the operation
1125 //
1126 break;
1127
1128 case EfiUsbPortConnectChange:
1129 //
1130 // Clear connect status change
1131 //
1132 State |= XHC_PORTSC_CSC;
1133 XhcPeiWriteOpReg (Xhc, Offset, State);
1134 break;
1135
1136 case EfiUsbPortEnableChange:
1137 //
1138 // Clear enable status change
1139 //
1140 State |= XHC_PORTSC_PEC;
1141 XhcPeiWriteOpReg (Xhc, Offset, State);
1142 break;
1143
1144 case EfiUsbPortOverCurrentChange:
1145 //
1146 // Clear PortOverCurrent change
1147 //
1148 State |= XHC_PORTSC_OCC;
1149 XhcPeiWriteOpReg (Xhc, Offset, State);
1150 break;
1151
1152 case EfiUsbPortResetChange:
1153 //
1154 // Clear Port Reset change
1155 //
1156 State |= XHC_PORTSC_PRC;
1157 XhcPeiWriteOpReg (Xhc, Offset, State);
1158 break;
1159
1160 case EfiUsbPortSuspendChange:
1161 //
1162 // Not supported or not related operation
1163 //
1164 break;
1165
1166 default:
1167 Status = EFI_INVALID_PARAMETER;
1168 break;
1169 }
1170
1171ON_EXIT:
1172 DEBUG ((DEBUG_INFO, "XhcPeiClearRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature, Status));
1173 return Status;
1174}
1175
1190EFIAPI
1192 IN EFI_PEI_SERVICES **PeiServices,
1194 IN UINT8 PortNumber,
1195 IN EFI_USB_PORT_FEATURE PortFeature
1196 )
1197{
1198 PEI_XHC_DEV *Xhc;
1199 UINT32 Offset;
1200 UINT32 State;
1201 EFI_STATUS Status;
1202
1203 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);
1204 Status = EFI_SUCCESS;
1205
1206 if (PortNumber >= Xhc->HcSParams1.Data.MaxPorts) {
1207 Status = EFI_INVALID_PARAMETER;
1208 goto ON_EXIT;
1209 }
1210
1211 Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));
1212 State = XhcPeiReadOpReg (Xhc, Offset);
1213 DEBUG ((DEBUG_INFO, "XhcPeiSetRootHubPortFeature: Port: %x State: %x\n", PortNumber, State));
1214
1215 //
1216 // Mask off the port status change bits, these bits are
1217 // write clean bits
1218 //
1219 State &= ~(BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
1220
1221 switch (PortFeature) {
1222 case EfiUsbPortEnable:
1223 //
1224 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
1225 // A port may be disabled by software writing a '1' to this flag.
1226 //
1227 break;
1228
1229 case EfiUsbPortSuspend:
1230 State |= XHC_PORTSC_LWS;
1231 XhcPeiWriteOpReg (Xhc, Offset, State);
1232 State &= ~XHC_PORTSC_PLS;
1233 State |= (3 << 5);
1234 XhcPeiWriteOpReg (Xhc, Offset, State);
1235 break;
1236
1237 case EfiUsbPortReset:
1238 //
1239 // Make sure Host Controller not halt before reset it
1240 //
1241 if (XhcPeiIsHalt (Xhc)) {
1242 Status = XhcPeiRunHC (Xhc, XHC_GENERIC_TIMEOUT);
1243 if (EFI_ERROR (Status)) {
1244 break;
1245 }
1246 }
1247
1248 //
1249 // 4.3.1 Resetting a Root Hub Port
1250 // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
1251 // 2) Wait for a successful Port Status Change Event for the port, where the Port Reset Change (PRC)
1252 // bit in the PORTSC field is set to '1'.
1253 //
1254 State |= XHC_PORTSC_RESET;
1255 XhcPeiWriteOpReg (Xhc, Offset, State);
1256 XhcPeiWaitOpRegBit (Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
1257 break;
1258
1259 case EfiUsbPortPower:
1260 if (Xhc->HcCParams.Data.Ppc) {
1261 //
1262 // Port Power Control supported
1263 //
1264 State |= XHC_PORTSC_PP;
1265 XhcPeiWriteOpReg (Xhc, Offset, State);
1266 }
1267
1268 break;
1269
1270 case EfiUsbPortOwner:
1271 //
1272 // XHCI root hub port don't has the owner bit, ignore the operation
1273 //
1274 break;
1275
1276 default:
1277 Status = EFI_INVALID_PARAMETER;
1278 }
1279
1280ON_EXIT:
1281 DEBUG ((DEBUG_INFO, "XhcPeiSetRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature, Status));
1282 return Status;
1283}
1284
1299EFIAPI
1301 IN EFI_PEI_SERVICES **PeiServices,
1303 IN UINT8 PortNumber,
1304 OUT EFI_USB_PORT_STATUS *PortStatus
1305 )
1306{
1307 PEI_XHC_DEV *Xhc;
1308 UINT32 Offset;
1309 UINT32 State;
1310 UINTN Index;
1311 UINTN MapSize;
1312 USB_DEV_ROUTE ParentRouteChart;
1313
1314 if (PortStatus == NULL) {
1315 return EFI_INVALID_PARAMETER;
1316 }
1317
1318 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);
1319
1320 if (PortNumber >= Xhc->HcSParams1.Data.MaxPorts) {
1321 return EFI_INVALID_PARAMETER;
1322 }
1323
1324 //
1325 // Clear port status.
1326 //
1327 PortStatus->PortStatus = 0;
1328 PortStatus->PortChangeStatus = 0;
1329
1330 Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));
1331 State = XhcPeiReadOpReg (Xhc, Offset);
1332 DEBUG ((DEBUG_INFO, "XhcPeiGetRootHubPortStatus: Port: %x State: %x\n", PortNumber, State));
1333
1334 //
1335 // According to XHCI 1.1 spec November 2017,
1336 // bit 10~13 of the root port status register identifies the speed of the attached device.
1337 //
1338 switch ((State & XHC_PORTSC_PS) >> 10) {
1339 case 2:
1340 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
1341 break;
1342
1343 case 3:
1344 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
1345 break;
1346
1347 case 4:
1348 case 5:
1349 PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
1350 break;
1351
1352 default:
1353 break;
1354 }
1355
1356 //
1357 // Convert the XHCI port/port change state to UEFI status
1358 //
1359 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
1360
1361 for (Index = 0; Index < MapSize; Index++) {
1362 if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
1363 PortStatus->PortStatus = (UINT16)(PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
1364 }
1365 }
1366
1367 //
1368 // Bit5~8 reflects its current link state.
1369 //
1370 if ((State & XHC_PORTSC_PLS) >> 5 == 3) {
1371 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
1372 }
1373
1374 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
1375
1376 for (Index = 0; Index < MapSize; Index++) {
1377 if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
1378 PortStatus->PortChangeStatus = (UINT16)(PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
1379 }
1380 }
1381
1382 MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
1383
1384 for (Index = 0; Index < MapSize; Index++) {
1385 if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {
1386 XhcPeiClearRootHubPortFeature (PeiServices, This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);
1387 }
1388 }
1389
1390 //
1391 // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
1392 // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
1393 //
1394 ParentRouteChart.Dword = 0;
1395 XhcPeiPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);
1396
1397 DEBUG ((DEBUG_INFO, "XhcPeiGetRootHubPortStatus: PortChangeStatus: %x PortStatus: %x\n", PortStatus->PortChangeStatus, PortStatus->PortStatus));
1398 return EFI_SUCCESS;
1399}
1400
1413EFIAPI
1415 IN EFI_PEI_SERVICES **PeiServices,
1416 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
1417 IN VOID *Ppi
1418 )
1419{
1420 PEI_XHC_DEV *Xhc;
1421
1422 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor);
1423
1424 XhcPeiHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
1425
1426 XhcPeiFreeSched (Xhc);
1427
1428 return EFI_SUCCESS;
1429}
1430
1439EFIAPI
1441 IN EFI_PEI_FILE_HANDLE FileHandle,
1442 IN CONST EFI_PEI_SERVICES **PeiServices
1443 )
1444{
1445 PEI_USB_CONTROLLER_PPI *UsbControllerPpi;
1446 EFI_STATUS Status;
1447 UINT8 Index;
1448 UINTN ControllerType;
1449 UINTN BaseAddress;
1450 UINTN MemPages;
1451 PEI_XHC_DEV *XhcDev;
1452 EFI_PHYSICAL_ADDRESS TempPtr;
1453 UINT32 PageSize;
1454
1455 //
1456 // Shadow this PEIM to run from memory.
1457 //
1458 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1459 return EFI_SUCCESS;
1460 }
1461
1462 Status = PeiServicesLocatePpi (
1463 &gPeiUsbControllerPpiGuid,
1464 0,
1465 NULL,
1466 (VOID **)&UsbControllerPpi
1467 );
1468 if (EFI_ERROR (Status)) {
1469 return EFI_UNSUPPORTED;
1470 }
1471
1472 IoMmuInit ();
1473
1474 Index = 0;
1475 while (TRUE) {
1476 Status = UsbControllerPpi->GetUsbController (
1477 (EFI_PEI_SERVICES **)PeiServices,
1478 UsbControllerPpi,
1479 Index,
1480 &ControllerType,
1481 &BaseAddress
1482 );
1483 //
1484 // When status is error, it means no controller is found.
1485 //
1486 if (EFI_ERROR (Status)) {
1487 break;
1488 }
1489
1490 //
1491 // This PEIM is for XHC type controller.
1492 //
1493 if (ControllerType != PEI_XHCI_CONTROLLER) {
1494 Index++;
1495 continue;
1496 }
1497
1498 MemPages = EFI_SIZE_TO_PAGES (sizeof (PEI_XHC_DEV));
1499 Status = PeiServicesAllocatePages (
1501 MemPages,
1502 &TempPtr
1503 );
1504 if (EFI_ERROR (Status)) {
1505 return EFI_OUT_OF_RESOURCES;
1506 }
1507
1508 ZeroMem ((VOID *)(UINTN)TempPtr, EFI_PAGES_TO_SIZE (MemPages));
1509 XhcDev = (PEI_XHC_DEV *)((UINTN)TempPtr);
1510
1511 XhcDev->Signature = USB_XHC_DEV_SIGNATURE;
1512 XhcDev->UsbHostControllerBaseAddress = (UINT32)BaseAddress;
1513 XhcDev->CapLength = (UINT8)(XhcPeiReadCapRegister (XhcDev, XHC_CAPLENGTH_OFFSET) & 0x0FF);
1514 XhcDev->HcSParams1.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCSPARAMS1_OFFSET);
1515 XhcDev->HcSParams2.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCSPARAMS2_OFFSET);
1516 XhcDev->HcCParams.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCCPARAMS_OFFSET);
1517 XhcDev->DBOff = XhcPeiReadCapRegister (XhcDev, XHC_DBOFF_OFFSET);
1518 XhcDev->RTSOff = XhcPeiReadCapRegister (XhcDev, XHC_RTSOFF_OFFSET);
1519
1520 //
1521 // This PageSize field defines the page size supported by the xHC implementation.
1522 // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
1523 // if bit 0 is Set, the xHC supports 4k byte page sizes.
1524 //
1525 PageSize = XhcPeiReadOpReg (XhcDev, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;
1526 XhcDev->PageSize = 1 << (HighBitSet32 (PageSize) + 12);
1527
1528 DEBUG ((DEBUG_INFO, "XhciPei: UsbHostControllerBaseAddress: %x\n", XhcDev->UsbHostControllerBaseAddress));
1529 DEBUG ((DEBUG_INFO, "XhciPei: CapLength: %x\n", XhcDev->CapLength));
1530 DEBUG ((DEBUG_INFO, "XhciPei: HcSParams1: %x\n", XhcDev->HcSParams1.Dword));
1531 DEBUG ((DEBUG_INFO, "XhciPei: HcSParams2: %x\n", XhcDev->HcSParams2.Dword));
1532 DEBUG ((DEBUG_INFO, "XhciPei: HcCParams: %x\n", XhcDev->HcCParams.Dword));
1533 DEBUG ((DEBUG_INFO, "XhciPei: DBOff: %x\n", XhcDev->DBOff));
1534 DEBUG ((DEBUG_INFO, "XhciPei: RTSOff: %x\n", XhcDev->RTSOff));
1535 DEBUG ((DEBUG_INFO, "XhciPei: PageSize: %x\n", XhcDev->PageSize));
1536
1537 XhcPeiResetHC (XhcDev, XHC_RESET_TIMEOUT);
1538 ASSERT (XhcPeiIsHalt (XhcDev));
1539
1540 //
1541 // Initialize the schedule
1542 //
1543 XhcPeiInitSched (XhcDev);
1544
1545 //
1546 // Start the Host Controller
1547 //
1548 XhcPeiRunHC (XhcDev, XHC_GENERIC_TIMEOUT);
1549
1550 //
1551 // Wait for root port state stable
1552 //
1553 MicroSecondDelay (XHC_ROOT_PORT_STATE_STABLE);
1554
1555 XhcDev->Usb2HostControllerPpi.ControlTransfer = XhcPeiControlTransfer;
1556 XhcDev->Usb2HostControllerPpi.BulkTransfer = XhcPeiBulkTransfer;
1557 XhcDev->Usb2HostControllerPpi.GetRootHubPortNumber = XhcPeiGetRootHubPortNumber;
1558 XhcDev->Usb2HostControllerPpi.GetRootHubPortStatus = XhcPeiGetRootHubPortStatus;
1559 XhcDev->Usb2HostControllerPpi.SetRootHubPortFeature = XhcPeiSetRootHubPortFeature;
1560 XhcDev->Usb2HostControllerPpi.ClearRootHubPortFeature = XhcPeiClearRootHubPortFeature;
1561
1562 XhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
1563 XhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;
1564 XhcDev->PpiDescriptor.Ppi = &XhcDev->Usb2HostControllerPpi;
1565
1566 XhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
1567 XhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;
1568 XhcDev->EndOfPeiNotifyList.Notify = XhcEndOfPei;
1569
1570 PeiServicesInstallPpi (&XhcDev->PpiDescriptor);
1571 PeiServicesNotifyPpi (&XhcDev->EndOfPeiNotifyList);
1572
1573 Index++;
1574 }
1575
1576 return EFI_SUCCESS;
1577}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
EFI_STATUS EFIAPI PeiServicesNotifyPpi(IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList)
EFI_STATUS EFIAPI PeiServicesAllocatePages(IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT EFI_PHYSICAL_ADDRESS *Memory)
EFI_STATUS EFIAPI PeiServicesInstallPpi(IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList)
EFI_STATUS EFIAPI PeiServicesRegisterForShadow(IN EFI_PEI_FILE_HANDLE FileHandle)
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_USB_PORT_FEATURE
#define USB_PORT_STAT_C_CONNECTION
#define EFI_USB_SPEED_SUPER
4.8 Gb/s, USB 3.0 XHCI HC.
#define USB_PORT_STAT_CONNECTION
EFI_USB_DATA_DIRECTION
Definition: UsbIo.h:44
VOID IoMmuInit(OUT EDKII_IOMMU_PPI **IoMmu)
Definition: DmaMem.c:238
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
@ EfiBootServicesData
#define PEI_XHCI_CONTROLLER
Definition: UsbController.h:49
VOID XhcPeiSetOpRegBit(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Bit)
Definition: XhcPeim.c:114
UINT32 XhcPeiReadCapRegister(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset)
Definition: XhcPeim.c:195
BOOLEAN XhcPeiIsHalt(IN PEI_XHC_DEV *Xhc)
Definition: XhcPeim.c:325
EFI_STATUS EFIAPI XhcPeiBulkTransfer(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], IN OUT UINTN *DataLength, IN OUT UINT8 *DataToggle, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: XhcPeim.c:884
VOID XhcPeiClearRuntimeRegBit(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Bit)
Definition: XhcPeim.c:302
UINT32 XhcPeiReadOpReg(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset)
Definition: XhcPeim.c:72
EFI_STATUS EFIAPI XhcPeiGetRootHubPortNumber(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, OUT UINT8 *PortNumber)
Definition: XhcPeim.c:1019
EFI_STATUS XhcPeiRunHC(IN PEI_XHC_DEV *Xhc, IN UINT32 Timeout)
Definition: XhcPeim.c:426
EFI_STATUS XhcPeiHaltHC(IN PEI_XHC_DEV *Xhc, IN UINT32 Timeout)
Definition: XhcPeim.c:402
EFI_STATUS XhcPeiWaitOpRegBit(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Bit, IN BOOLEAN WaitToSet, IN UINT32 Timeout)
Definition: XhcPeim.c:164
BOOLEAN XhcPeiIsSysError(IN PEI_XHC_DEV *Xhc)
Definition: XhcPeim.c:342
EFI_STATUS EFIAPI XhcPeiGetRootHubPortStatus(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 PortNumber, OUT EFI_USB_PORT_STATUS *PortStatus)
Definition: XhcPeim.c:1300
EFI_STATUS EFIAPI XhcPeimEntry(IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices)
Definition: XhcPeim.c:1440
EFI_STATUS EFIAPI XhcPeiClearRootHubPortFeature(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature)
Definition: XhcPeim.c:1055
VOID XhcPeiWriteOpReg(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Data)
Definition: XhcPeim.c:94
EFI_STATUS EFIAPI XhcEndOfPei(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi)
Definition: XhcPeim.c:1414
VOID XhcPeiSetRuntimeRegBit(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Bit)
Definition: XhcPeim.c:280
EFI_STATUS EFIAPI XhcPeiControlTransfer(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 DeviceAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN EFI_USB_DEVICE_REQUEST *Request, IN EFI_USB_DATA_DIRECTION TransferDirection, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: XhcPeim.c:467
UINT32 XhcPeiReadRuntimeReg(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset)
Definition: XhcPeim.c:237
VOID XhcPeiClearOpRegBit(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Bit)
Definition: XhcPeim.c:136
EFI_STATUS XhcPeiResetHC(IN PEI_XHC_DEV *Xhc, IN UINT32 Timeout)
Definition: XhcPeim.c:360
VOID XhcPeiWriteDoorBellReg(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Data)
Definition: XhcPeim.c:216
VOID XhcPeiWriteRuntimeReg(IN PEI_XHC_DEV *Xhc, IN UINT32 Offset, IN UINT32 Data)
Definition: XhcPeim.c:260
EFI_STATUS EFIAPI XhcPeiSetRootHubPortFeature(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature)
Definition: XhcPeim.c:1191
VOID XhcPeiInitSched(IN PEI_XHC_DEV *Xhc)
Definition: XhciSched.c:2882
EFI_STATUS XhcPeiEvaluateContext(IN PEI_XHC_DEV *Xhc, IN UINT8 SlotId, IN UINT32 MaxPacketSize)
Definition: XhciSched.c:2167
EFI_STATUS XhcPeiSetConfigCmd(IN PEI_XHC_DEV *Xhc, IN UINT8 SlotId, IN UINT8 DeviceSpeed, IN USB_CONFIG_DESCRIPTOR *ConfigDesc)
Definition: XhciSched.c:1713
EFI_STATUS XhcPeiSetConfigCmd64(IN PEI_XHC_DEV *Xhc, IN UINT8 SlotId, IN UINT8 DeviceSpeed, IN USB_CONFIG_DESCRIPTOR *ConfigDesc)
Definition: XhciSched.c:1939
EFI_STATUS XhcPeiRecoverHaltedEndpoint(IN PEI_XHC_DEV *Xhc, IN URB *Urb)
Definition: XhciSched.c:472
VOID XhcPeiFreeSched(IN PEI_XHC_DEV *Xhc)
Definition: XhciSched.c:3049
EFI_STATUS XhcPeiConfigHubContext(IN PEI_XHC_DEV *Xhc, IN UINT8 SlotId, IN UINT8 PortNum, IN UINT8 TTT, IN UINT8 MTT)
Definition: XhciSched.c:2279
EFI_STATUS XhcPeiEvaluateContext64(IN PEI_XHC_DEV *Xhc, IN UINT8 SlotId, IN UINT32 MaxPacketSize)
Definition: XhciSched.c:2222
VOID XhcPeiFreeUrb(IN PEI_XHC_DEV *Xhc, IN URB *Urb)
Definition: XhciSched.c:188
EFI_STATUS XhcPeiConfigHubContext64(IN PEI_XHC_DEV *Xhc, IN UINT8 SlotId, IN UINT8 PortNum, IN UINT8 TTT, IN UINT8 MTT)
Definition: XhciSched.c:2348
UINT8 XhcPeiBusDevAddrToSlotId(IN PEI_XHC_DEV *Xhc, IN UINT8 BusDevAddr)
Definition: XhciSched.c:979
URB * XhcPeiCreateUrb(IN PEI_XHC_DEV *Xhc, IN UINT8 BusAddr, IN UINT8 EpAddr, IN UINT8 DevSpeed, IN UINTN MaxPacket, IN UINTN Type, IN EFI_USB_DEVICE_REQUEST *Request, IN VOID *Data, IN UINTN DataLen, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context)
Definition: XhciSched.c:131
EFI_STATUS XhcPeiExecTransfer(IN PEI_XHC_DEV *Xhc, IN BOOLEAN CmdTransfer, IN URB *Urb, IN UINTN Timeout)
Definition: XhciSched.c:797
EFI_STATUS XhcPeiDequeueTrbFromEndpoint(IN PEI_XHC_DEV *Xhc, IN URB *Urb)
Definition: XhciSched.c:532
EFI_STATUS XhcPeiPollPortStatusChange(IN PEI_XHC_DEV *Xhc, IN USB_DEV_ROUTE ParentRouteChart, IN UINT8 Port, IN EFI_USB_PORT_STATUS *PortState)
Definition: XhciSched.c:863
EFI_PEIM_NOTIFY_ENTRY_POINT Notify
Definition: PiPeiCis.h:122
XHC_HCSPARAMS1 HcSParams1
Structural Parameters 1.
Definition: XhcPeim.h:160
UINT32 DBOff
Doorbell Offset.
Definition: XhcPeim.h:163
UINT32 RTSOff
Runtime Register Space Offset.
Definition: XhcPeim.h:164
UINT8 CapLength
Capability Register Length.
Definition: XhcPeim.h:159
XHC_HCSPARAMS2 HcSParams2
Structural Parameters 2.
Definition: XhcPeim.h:161
XHC_HCCPARAMS HcCParams
Capability Parameters.
Definition: XhcPeim.h:162
Definition: EhciUrb.h:200
UINT16 PortChangeStatus
Contains current port status change bitmap.
UINT16 PortStatus
Contains current port status bitmap.