2 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
3 which is used to enable recovery function from USB Drivers.
5 Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 // Two arrays used to translate the XHCI port state (change)
22 // to the UEFI protocol's port state (change).
24 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
25 {XHC_PORTSC_CCS
, USB_PORT_STAT_CONNECTION
},
26 {XHC_PORTSC_PED
, USB_PORT_STAT_ENABLE
},
27 {XHC_PORTSC_OCA
, USB_PORT_STAT_OVERCURRENT
},
28 {XHC_PORTSC_PP
, USB_PORT_STAT_POWER
},
29 {XHC_PORTSC_RESET
, USB_PORT_STAT_RESET
}
32 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
33 {XHC_PORTSC_CSC
, USB_PORT_STAT_C_CONNECTION
},
34 {XHC_PORTSC_PEC
, USB_PORT_STAT_C_ENABLE
},
35 {XHC_PORTSC_OCC
, USB_PORT_STAT_C_OVERCURRENT
},
36 {XHC_PORTSC_PRC
, USB_PORT_STAT_C_RESET
}
39 USB_CLEAR_PORT_MAP mUsbClearPortChangeMap
[] = {
40 {XHC_PORTSC_CSC
, EfiUsbPortConnectChange
},
41 {XHC_PORTSC_PEC
, EfiUsbPortEnableChange
},
42 {XHC_PORTSC_OCC
, EfiUsbPortOverCurrentChange
},
43 {XHC_PORTSC_PRC
, EfiUsbPortResetChange
}
46 USB_PORT_STATE_MAP mUsbHubPortStateMap
[] = {
47 {XHC_HUB_PORTSC_CCS
, USB_PORT_STAT_CONNECTION
},
48 {XHC_HUB_PORTSC_PED
, USB_PORT_STAT_ENABLE
},
49 {XHC_HUB_PORTSC_OCA
, USB_PORT_STAT_OVERCURRENT
},
50 {XHC_HUB_PORTSC_PP
, USB_PORT_STAT_POWER
},
51 {XHC_HUB_PORTSC_RESET
, USB_PORT_STAT_RESET
}
54 USB_PORT_STATE_MAP mUsbHubPortChangeMap
[] = {
55 {XHC_HUB_PORTSC_CSC
, USB_PORT_STAT_C_CONNECTION
},
56 {XHC_HUB_PORTSC_PEC
, USB_PORT_STAT_C_ENABLE
},
57 {XHC_HUB_PORTSC_OCC
, USB_PORT_STAT_C_OVERCURRENT
},
58 {XHC_HUB_PORTSC_PRC
, USB_PORT_STAT_C_RESET
}
61 USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap
[] = {
62 {XHC_HUB_PORTSC_CSC
, EfiUsbPortConnectChange
},
63 {XHC_HUB_PORTSC_PEC
, EfiUsbPortEnableChange
},
64 {XHC_HUB_PORTSC_OCC
, EfiUsbPortOverCurrentChange
},
65 {XHC_HUB_PORTSC_PRC
, EfiUsbPortResetChange
},
66 {XHC_HUB_PORTSC_BHRC
, Usb3PortBHPortResetChange
}
70 Read XHCI Operation register.
72 @param Xhc The XHCI device.
73 @param Offset The operation register offset.
75 @retval the register content read.
86 ASSERT (Xhc
->CapLength
!= 0);
88 Data
= MmioRead32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->CapLength
+ Offset
);
93 Write the data to the XHCI operation register.
95 @param Xhc The XHCI device.
96 @param Offset The operation register offset.
97 @param Data The data to write.
107 ASSERT (Xhc
->CapLength
!= 0);
109 MmioWrite32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->CapLength
+ Offset
, Data
);
113 Set one bit of the operational register while keeping other bits.
115 @param Xhc The XHCI device.
116 @param Offset The offset of the operational register.
117 @param Bit The bit mask of the register to set.
129 Data
= XhcPeiReadOpReg (Xhc
, Offset
);
131 XhcPeiWriteOpReg (Xhc
, Offset
, Data
);
135 Clear one bit of the operational register while keeping other bits.
137 @param Xhc The XHCI device.
138 @param Offset The offset of the operational register.
139 @param Bit The bit mask of the register to clear.
143 XhcPeiClearOpRegBit (
151 Data
= XhcPeiReadOpReg (Xhc
, Offset
);
153 XhcPeiWriteOpReg (Xhc
, Offset
, Data
);
157 Wait the operation register's bit as specified by Bit
158 to become set (or clear).
160 @param Xhc The XHCI device.
161 @param Offset The offset of the operational register.
162 @param Bit The bit mask of the register to wait for.
163 @param WaitToSet Wait the bit to set or clear.
164 @param Timeout The time to wait before abort (in millisecond, ms).
166 @retval EFI_SUCCESS The bit successfully changed by host controller.
167 @retval EFI_TIMEOUT The time out occurred.
175 IN BOOLEAN WaitToSet
,
181 for (Index
= 0; Index
< Timeout
* XHC_1_MILLISECOND
; Index
++) {
182 if (XHC_REG_BIT_IS_SET (Xhc
, Offset
, Bit
) == WaitToSet
) {
186 MicroSecondDelay (XHC_1_MICROSECOND
);
193 Read XHCI capability register.
195 @param Xhc The XHCI device.
196 @param Offset Capability register address.
198 @retval the register content read.
202 XhcPeiReadCapRegister (
209 Data
= MmioRead32 (Xhc
->UsbHostControllerBaseAddress
+ Offset
);
215 Read XHCI door bell register.
217 @param Xhc The XHCI device.
218 @param Offset The offset of the door bell register.
220 @return The register content read
224 XhcPeiReadDoorBellReg (
231 ASSERT (Xhc
->DBOff
!= 0);
233 Data
= MmioRead32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->DBOff
+ Offset
);
239 Write the data to the XHCI door bell register.
241 @param Xhc The XHCI device.
242 @param Offset The offset of the door bell register.
243 @param Data The data to write.
247 XhcPeiWriteDoorBellReg (
253 ASSERT (Xhc
->DBOff
!= 0);
255 MmioWrite32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->DBOff
+ Offset
, Data
);
259 Read XHCI runtime register.
261 @param Xhc The XHCI device.
262 @param Offset The offset of the runtime register.
264 @return The register content read
268 XhcPeiReadRuntimeReg (
275 ASSERT (Xhc
->RTSOff
!= 0);
277 Data
= MmioRead32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->RTSOff
+ Offset
);
283 Write the data to the XHCI runtime register.
285 @param Xhc The XHCI device.
286 @param Offset The offset of the runtime register.
287 @param Data The data to write.
291 XhcPeiWriteRuntimeReg (
297 ASSERT (Xhc
->RTSOff
!= 0);
299 MmioWrite32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->RTSOff
+ Offset
, Data
);
303 Set one bit of the runtime register while keeping other bits.
305 @param Xhc The XHCI device.
306 @param Offset The offset of the runtime register.
307 @param Bit The bit mask of the register to set.
311 XhcPeiSetRuntimeRegBit (
319 Data
= XhcPeiReadRuntimeReg (Xhc
, Offset
);
321 XhcPeiWriteRuntimeReg (Xhc
, Offset
, Data
);
325 Clear one bit of the runtime register while keeping other bits.
327 @param Xhc The XHCI device.
328 @param Offset The offset of the runtime register.
329 @param Bit The bit mask of the register to set.
333 XhcPeiClearRuntimeRegBit (
341 Data
= XhcPeiReadRuntimeReg (Xhc
, Offset
);
343 XhcPeiWriteRuntimeReg (Xhc
, Offset
, Data
);
347 Check whether Xhc is halted.
349 @param Xhc The XHCI device.
351 @retval TRUE The controller is halted.
352 @retval FALSE The controller isn't halted.
360 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
);
364 Check whether system error occurred.
366 @param Xhc The XHCI device.
368 @retval TRUE System error happened.
369 @retval FALSE No system error.
377 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HSE
);
381 Reset the host controller.
383 @param Xhc The XHCI device.
384 @param Timeout Time to wait before abort (in millisecond, ms).
386 @retval EFI_TIMEOUT The transfer failed due to time out.
387 @retval Others Failed to reset the host.
399 // Host can only be reset when it is halt. If not so, halt it
401 if (!XhcPeiIsHalt (Xhc
)) {
402 Status
= XhcPeiHaltHC (Xhc
, Timeout
);
404 if (EFI_ERROR (Status
)) {
409 XhcPeiSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
);
411 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
412 // Otherwise there may have the timeout case happened.
413 // The below is a workaround to solve such problem.
415 MicroSecondDelay (1000);
416 Status
= XhcPeiWaitOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
, FALSE
, Timeout
);
418 DEBUG ((EFI_D_INFO
, "XhcPeiResetHC: %r\n", Status
));
423 Halt the host controller.
425 @param Xhc The XHCI device.
426 @param Timeout Time to wait before abort.
428 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
429 @retval EFI_SUCCESS The XHCI is halt.
440 XhcPeiClearOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
441 Status
= XhcPeiWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, TRUE
, Timeout
);
442 DEBUG ((EFI_D_INFO
, "XhcPeiHaltHC: %r\n", Status
));
449 @param Xhc The XHCI device.
450 @param Timeout Time to wait before abort.
452 @retval EFI_SUCCESS The XHCI is running.
453 @retval Others Failed to set the XHCI to run.
464 XhcPeiSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
465 Status
= XhcPeiWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, FALSE
, Timeout
);
466 DEBUG ((EFI_D_INFO
, "XhcPeiRunHC: %r\n", Status
));
471 Submits control transfer to a target USB device.
473 @param PeiServices The pointer of EFI_PEI_SERVICES.
474 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
475 @param DeviceAddress The target device address.
476 @param DeviceSpeed Target device speed.
477 @param MaximumPacketLength Maximum packet size the default control transfer
478 endpoint is capable of sending or receiving.
479 @param Request USB device request to send.
480 @param TransferDirection Specifies the data direction for the data stage.
481 @param Data Data buffer to be transmitted or received from USB device.
482 @param DataLength The size (in bytes) of the data buffer.
483 @param TimeOut Indicates the maximum timeout, in millisecond.
484 If Timeout is 0, then the caller must wait for the function
485 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
486 @param Translator Transaction translator to be used by this device.
487 @param TransferResult Return the result of this control transfer.
489 @retval EFI_SUCCESS Transfer was completed successfully.
490 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
491 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
492 @retval EFI_TIMEOUT Transfer failed due to timeout.
493 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
498 XhcPeiControlTransfer (
499 IN EFI_PEI_SERVICES
**PeiServices
,
500 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
501 IN UINT8 DeviceAddress
,
502 IN UINT8 DeviceSpeed
,
503 IN UINTN MaximumPacketLength
,
504 IN EFI_USB_DEVICE_REQUEST
*Request
,
505 IN EFI_USB_DATA_DIRECTION TransferDirection
,
507 IN OUT UINTN
*DataLength
,
509 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
510 OUT UINT32
*TransferResult
517 UINT8 DescriptorType
;
522 EFI_USB_HUB_DESCRIPTOR
*HubDesc
;
524 EFI_STATUS RecoveryStatus
;
526 EFI_USB_PORT_STATUS PortStatus
;
528 EFI_USB_DEVICE_REQUEST ClearPortRequest
;
532 // Validate parameters
534 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
535 return EFI_INVALID_PARAMETER
;
538 if ((TransferDirection
!= EfiUsbDataIn
) &&
539 (TransferDirection
!= EfiUsbDataOut
) &&
540 (TransferDirection
!= EfiUsbNoData
)) {
541 return EFI_INVALID_PARAMETER
;
544 if ((TransferDirection
== EfiUsbNoData
) &&
545 ((Data
!= NULL
) || (*DataLength
!= 0))) {
546 return EFI_INVALID_PARAMETER
;
549 if ((TransferDirection
!= EfiUsbNoData
) &&
550 ((Data
== NULL
) || (*DataLength
== 0))) {
551 return EFI_INVALID_PARAMETER
;
554 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
555 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64) &&
556 (MaximumPacketLength
!= 512)
558 return EFI_INVALID_PARAMETER
;
561 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
562 return EFI_INVALID_PARAMETER
;
565 if ((DeviceSpeed
== EFI_USB_SPEED_SUPER
) && (MaximumPacketLength
!= 512)) {
566 return EFI_INVALID_PARAMETER
;
569 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
571 Status
= EFI_DEVICE_ERROR
;
572 *TransferResult
= EFI_USB_ERR_SYSTEM
;
575 if (XhcPeiIsHalt (Xhc
) || XhcPeiIsSysError (Xhc
)) {
576 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: HC is halted or has system error\n"));
581 // Check if the device is still enabled before every transaction.
583 SlotId
= XhcPeiBusDevAddrToSlotId (Xhc
, DeviceAddress
);
589 // Hook the Set_Address request from UsbBus.
590 // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
592 if ((Request
->Request
== USB_REQ_SET_ADDRESS
) &&
593 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, USB_TARGET_DEVICE
))) {
595 // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
596 // This way is used to clean the history to avoid using wrong device address afterwards.
598 for (Index
= 0; Index
< 255; Index
++) {
599 if (!Xhc
->UsbDevContext
[Index
+ 1].Enabled
&&
600 (Xhc
->UsbDevContext
[Index
+ 1].SlotId
== 0) &&
601 (Xhc
->UsbDevContext
[Index
+ 1].BusDevAddr
== (UINT8
) Request
->Value
)) {
602 Xhc
->UsbDevContext
[Index
+ 1].BusDevAddr
= 0;
606 if (Xhc
->UsbDevContext
[SlotId
].XhciDevAddr
== 0) {
610 // The actual device address has been assigned by XHCI during initializing the device slot.
611 // So we just need establish the mapping relationship between the device address requested from UsbBus
612 // and the actual device address assigned by XHCI. The following invocations through EFI_USB2_HC_PROTOCOL interface
613 // can find out the actual device address by it.
615 Xhc
->UsbDevContext
[SlotId
].BusDevAddr
= (UINT8
) Request
->Value
;
616 Status
= EFI_SUCCESS
;
621 // Create a new URB, insert it into the asynchronous
622 // schedule list, then poll the execution status.
623 // Note that we encode the direction in address although default control
624 // endpoint is bidirectional. XhcPeiCreateUrb expects this
625 // combination of Ep addr and its direction.
627 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
628 Urb
= XhcPeiCreateUrb (
643 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: failed to create URB"));
644 Status
= EFI_OUT_OF_RESOURCES
;
648 Status
= XhcPeiExecTransfer (Xhc
, FALSE
, Urb
, TimeOut
);
651 // Get the status from URB. The result is updated in XhcPeiCheckUrbResult
652 // which is called by XhcPeiExecTransfer
654 *TransferResult
= Urb
->Result
;
655 *DataLength
= Urb
->Completed
;
657 if (Status
== EFI_TIMEOUT
) {
659 // The transfer timed out. Abort the transfer by dequeueing of the TD.
661 RecoveryStatus
= XhcPeiDequeueTrbFromEndpoint(Xhc
, Urb
);
662 if (EFI_ERROR(RecoveryStatus
)) {
663 DEBUG((EFI_D_ERROR
, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
667 if (*TransferResult
== EFI_USB_NOERROR
) {
668 Status
= EFI_SUCCESS
;
669 } else if ((*TransferResult
== EFI_USB_ERR_STALL
) || (*TransferResult
== EFI_USB_ERR_BABBLE
)) {
670 RecoveryStatus
= XhcPeiRecoverHaltedEndpoint(Xhc
, Urb
);
671 if (EFI_ERROR (RecoveryStatus
)) {
672 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
674 Status
= EFI_DEVICE_ERROR
;
682 // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
683 // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
684 // Hook Set_Config request from UsbBus as we need configure device endpoint.
686 if ((Request
->Request
== USB_REQ_GET_DESCRIPTOR
) &&
687 ((Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbDataIn
, USB_REQ_TYPE_STANDARD
, USB_TARGET_DEVICE
)) ||
688 ((Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbDataIn
, USB_REQ_TYPE_CLASS
, USB_TARGET_DEVICE
))))) {
689 DescriptorType
= (UINT8
) (Request
->Value
>> 8);
690 if ((DescriptorType
== USB_DESC_TYPE_DEVICE
) && ((*DataLength
== sizeof (EFI_USB_DEVICE_DESCRIPTOR
)) || ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (*DataLength
== 8)))) {
691 ASSERT (Data
!= NULL
);
693 // Store a copy of device scriptor as hub device need this info to configure endpoint.
695 CopyMem (&Xhc
->UsbDevContext
[SlotId
].DevDesc
, Data
, *DataLength
);
696 if (Xhc
->UsbDevContext
[SlotId
].DevDesc
.BcdUSB
>= 0x0300) {
698 // If it's a usb3.0 device, then its max packet size is a 2^n.
700 MaxPacket0
= 1 << Xhc
->UsbDevContext
[SlotId
].DevDesc
.MaxPacketSize0
;
702 MaxPacket0
= Xhc
->UsbDevContext
[SlotId
].DevDesc
.MaxPacketSize0
;
704 Xhc
->UsbDevContext
[SlotId
].ConfDesc
= AllocateZeroPool (Xhc
->UsbDevContext
[SlotId
].DevDesc
.NumConfigurations
* sizeof (EFI_USB_CONFIG_DESCRIPTOR
*));
705 if (Xhc
->UsbDevContext
[SlotId
].ConfDesc
== NULL
) {
706 Status
= EFI_OUT_OF_RESOURCES
;
709 if (Xhc
->HcCParams
.Data
.Csz
== 0) {
710 Status
= XhcPeiEvaluateContext (Xhc
, SlotId
, MaxPacket0
);
712 Status
= XhcPeiEvaluateContext64 (Xhc
, SlotId
, MaxPacket0
);
714 } else if (DescriptorType
== USB_DESC_TYPE_CONFIG
) {
715 ASSERT (Data
!= NULL
);
716 if (*DataLength
== ((UINT16
*) Data
)[1]) {
718 // Get configuration value from request, store the configuration descriptor for Configure_Endpoint cmd.
720 Index
= (UINT8
) Request
->Value
;
721 ASSERT (Index
< Xhc
->UsbDevContext
[SlotId
].DevDesc
.NumConfigurations
);
722 Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
] = AllocateZeroPool (*DataLength
);
723 if (Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
] == NULL
) {
724 Status
= EFI_OUT_OF_RESOURCES
;
727 CopyMem (Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
], Data
, *DataLength
);
729 } else if (((DescriptorType
== USB_DESC_TYPE_HUB
) ||
730 (DescriptorType
== USB_DESC_TYPE_HUB_SUPER_SPEED
)) && (*DataLength
> 2)) {
731 ASSERT (Data
!= NULL
);
732 HubDesc
= (EFI_USB_HUB_DESCRIPTOR
*) Data
;
733 ASSERT (HubDesc
->NumPorts
<= 15);
735 // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
737 TTT
= (UINT8
) ((HubDesc
->HubCharacter
& (BIT5
| BIT6
)) >> 5);
738 if (Xhc
->UsbDevContext
[SlotId
].DevDesc
.DeviceProtocol
== 2) {
740 // Don't support multi-TT feature for super speed hub now.
743 DEBUG ((EFI_D_ERROR
, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
748 if (Xhc
->HcCParams
.Data
.Csz
== 0) {
749 Status
= XhcPeiConfigHubContext (Xhc
, SlotId
, HubDesc
->NumPorts
, TTT
, MTT
);
751 Status
= XhcPeiConfigHubContext64 (Xhc
, SlotId
, HubDesc
->NumPorts
, TTT
, MTT
);
754 } else if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
755 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, USB_TARGET_DEVICE
))) {
757 // Hook Set_Config request from UsbBus as we need configure device endpoint.
759 for (Index
= 0; Index
< Xhc
->UsbDevContext
[SlotId
].DevDesc
.NumConfigurations
; Index
++) {
760 if (Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
]->ConfigurationValue
== (UINT8
)Request
->Value
) {
761 if (Xhc
->HcCParams
.Data
.Csz
== 0) {
762 Status
= XhcPeiSetConfigCmd (Xhc
, SlotId
, DeviceSpeed
, Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
]);
764 Status
= XhcPeiSetConfigCmd64 (Xhc
, SlotId
, DeviceSpeed
, Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
]);
769 } else if ((Request
->Request
== USB_REQ_GET_STATUS
) &&
770 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbDataIn
, USB_REQ_TYPE_CLASS
, USB_TARGET_OTHER
))) {
771 ASSERT (Data
!= NULL
);
773 // Hook Get_Status request from UsbBus to keep track of the port status change.
775 State
= *(UINT32
*) Data
;
776 PortStatus
.PortStatus
= 0;
777 PortStatus
.PortChangeStatus
= 0;
779 if (DeviceSpeed
== EFI_USB_SPEED_SUPER
) {
781 // For super speed hub, its bit10~12 presents the attached device speed.
783 if ((State
& XHC_PORTSC_PS
) >> 10 == 0) {
784 PortStatus
.PortStatus
|= USB_PORT_STAT_SUPER_SPEED
;
788 // For high or full/low speed hub, its bit9~10 presents the attached device speed.
790 if (XHC_BIT_IS_SET (State
, BIT9
)) {
791 PortStatus
.PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
792 } else if (XHC_BIT_IS_SET (State
, BIT10
)) {
793 PortStatus
.PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
798 // Convert the XHCI port/port change state to UEFI status
800 MapSize
= sizeof (mUsbHubPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
801 for (Index
= 0; Index
< MapSize
; Index
++) {
802 if (XHC_BIT_IS_SET (State
, mUsbHubPortStateMap
[Index
].HwState
)) {
803 PortStatus
.PortStatus
= (UINT16
) (PortStatus
.PortStatus
| mUsbHubPortStateMap
[Index
].UefiState
);
807 MapSize
= sizeof (mUsbHubPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
808 for (Index
= 0; Index
< MapSize
; Index
++) {
809 if (XHC_BIT_IS_SET (State
, mUsbHubPortChangeMap
[Index
].HwState
)) {
810 PortStatus
.PortChangeStatus
= (UINT16
) (PortStatus
.PortChangeStatus
| mUsbHubPortChangeMap
[Index
].UefiState
);
814 MapSize
= sizeof (mUsbHubClearPortChangeMap
) / sizeof (USB_CLEAR_PORT_MAP
);
816 for (Index
= 0; Index
< MapSize
; Index
++) {
817 if (XHC_BIT_IS_SET (State
, mUsbHubClearPortChangeMap
[Index
].HwState
)) {
818 ZeroMem (&ClearPortRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
819 ClearPortRequest
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_CLASS
, USB_TARGET_OTHER
);
820 ClearPortRequest
.Request
= (UINT8
) USB_REQ_CLEAR_FEATURE
;
821 ClearPortRequest
.Value
= mUsbHubClearPortChangeMap
[Index
].Selector
;
822 ClearPortRequest
.Index
= Request
->Index
;
823 ClearPortRequest
.Length
= 0;
825 XhcPeiControlTransfer (
842 XhcPeiPollPortStatusChange (Xhc
, Xhc
->UsbDevContext
[SlotId
].RouteString
, (UINT8
)Request
->Index
, &PortStatus
);
844 *(UINT32
*) Data
= *(UINT32
*) &PortStatus
;
848 XhcPeiFreeUrb (Xhc
, Urb
);
852 if (EFI_ERROR (Status
)) {
853 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
860 Submits bulk transfer to a bulk endpoint of a USB device.
862 @param PeiServices The pointer of EFI_PEI_SERVICES.
863 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
864 @param DeviceAddress Target device address.
865 @param EndPointAddress Endpoint number and its direction in bit 7.
866 @param DeviceSpeed Device speed, Low speed device doesn't support
868 @param MaximumPacketLength Maximum packet size the endpoint is capable of
869 sending or receiving.
870 @param Data Array of pointers to the buffers of data to transmit
871 from or receive into.
872 @param DataLength The lenght of the data buffer.
873 @param DataToggle On input, the initial data toggle for the transfer;
874 On output, it is updated to to next data toggle to use of
875 the subsequent bulk transfer.
876 @param TimeOut Indicates the maximum time, in millisecond, which the
877 transfer is allowed to complete.
878 If Timeout is 0, then the caller must wait for the function
879 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
880 @param Translator A pointr to the transaction translator data.
881 @param TransferResult A pointer to the detailed result information of the
884 @retval EFI_SUCCESS The transfer was completed successfully.
885 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
886 @retval EFI_INVALID_PARAMETER Parameters are invalid.
887 @retval EFI_TIMEOUT The transfer failed due to timeout.
888 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
894 IN EFI_PEI_SERVICES
**PeiServices
,
895 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
896 IN UINT8 DeviceAddress
,
897 IN UINT8 EndPointAddress
,
898 IN UINT8 DeviceSpeed
,
899 IN UINTN MaximumPacketLength
,
900 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
901 IN OUT UINTN
*DataLength
,
902 IN OUT UINT8
*DataToggle
,
904 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
905 OUT UINT32
*TransferResult
912 EFI_STATUS RecoveryStatus
;
915 // Validate the parameters
917 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
918 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
919 return EFI_INVALID_PARAMETER
;
922 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
923 return EFI_INVALID_PARAMETER
;
926 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
927 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
928 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 512)) ||
929 ((DeviceSpeed
== EFI_USB_SPEED_SUPER
) && (MaximumPacketLength
> 1024))) {
930 return EFI_INVALID_PARAMETER
;
933 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
935 *TransferResult
= EFI_USB_ERR_SYSTEM
;
936 Status
= EFI_DEVICE_ERROR
;
938 if (XhcPeiIsHalt (Xhc
) || XhcPeiIsSysError (Xhc
)) {
939 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: HC is halted or has system error\n"));
944 // Check if the device is still enabled before every transaction.
946 SlotId
= XhcPeiBusDevAddrToSlotId (Xhc
, DeviceAddress
);
952 // Create a new URB, insert it into the asynchronous
953 // schedule list, then poll the execution status.
955 Urb
= XhcPeiCreateUrb (
970 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: failed to create URB\n"));
971 Status
= EFI_OUT_OF_RESOURCES
;
975 Status
= XhcPeiExecTransfer (Xhc
, FALSE
, Urb
, TimeOut
);
977 *TransferResult
= Urb
->Result
;
978 *DataLength
= Urb
->Completed
;
980 if (Status
== EFI_TIMEOUT
) {
982 // The transfer timed out. Abort the transfer by dequeueing of the TD.
984 RecoveryStatus
= XhcPeiDequeueTrbFromEndpoint(Xhc
, Urb
);
985 if (EFI_ERROR(RecoveryStatus
)) {
986 DEBUG((EFI_D_ERROR
, "XhcPeiBulkTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
989 if (*TransferResult
== EFI_USB_NOERROR
) {
990 Status
= EFI_SUCCESS
;
991 } else if ((*TransferResult
== EFI_USB_ERR_STALL
) || (*TransferResult
== EFI_USB_ERR_BABBLE
)) {
992 RecoveryStatus
= XhcPeiRecoverHaltedEndpoint(Xhc
, Urb
);
993 if (EFI_ERROR (RecoveryStatus
)) {
994 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
996 Status
= EFI_DEVICE_ERROR
;
1000 XhcPeiFreeUrb (Xhc
, Urb
);
1004 if (EFI_ERROR (Status
)) {
1005 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1012 Retrieves the number of root hub ports.
1014 @param[in] PeiServices The pointer to the PEI Services Table.
1015 @param[in] This The pointer to this instance of the
1016 PEI_USB2_HOST_CONTROLLER_PPI.
1017 @param[out] PortNumber The pointer to the number of the root hub ports.
1019 @retval EFI_SUCCESS The port number was retrieved successfully.
1020 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
1025 XhcPeiGetRootHubPortNumber (
1026 IN EFI_PEI_SERVICES
**PeiServices
,
1027 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1028 OUT UINT8
*PortNumber
1031 PEI_XHC_DEV
*XhcDev
;
1032 XhcDev
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1034 if (PortNumber
== NULL
) {
1035 return EFI_INVALID_PARAMETER
;
1038 *PortNumber
= XhcDev
->HcSParams1
.Data
.MaxPorts
;
1039 DEBUG ((EFI_D_INFO
, "XhcPeiGetRootHubPortNumber: PortNumber = %x\n", *PortNumber
));
1044 Clears a feature for the specified root hub port.
1046 @param PeiServices The pointer of EFI_PEI_SERVICES.
1047 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
1048 @param PortNumber Specifies the root hub port whose feature
1049 is requested to be cleared.
1050 @param PortFeature Indicates the feature selector associated with the
1051 feature clear request.
1053 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
1054 for the USB root hub port specified by PortNumber.
1055 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1060 XhcPeiClearRootHubPortFeature (
1061 IN EFI_PEI_SERVICES
**PeiServices
,
1062 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1063 IN UINT8 PortNumber
,
1064 IN EFI_USB_PORT_FEATURE PortFeature
1072 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1073 Status
= EFI_SUCCESS
;
1075 if (PortNumber
>= Xhc
->HcSParams1
.Data
.MaxPorts
) {
1076 Status
= EFI_INVALID_PARAMETER
;
1080 Offset
= (UINT32
) (XHC_PORTSC_OFFSET
+ (0x10 * PortNumber
));
1081 State
= XhcPeiReadOpReg (Xhc
, Offset
);
1082 DEBUG ((EFI_D_INFO
, "XhcPeiClearRootHubPortFeature: Port: %x State: %x\n", PortNumber
, State
));
1085 // Mask off the port status change bits, these bits are
1088 State
&= ~ (BIT1
| BIT17
| BIT18
| BIT19
| BIT20
| BIT21
| BIT22
| BIT23
);
1090 switch (PortFeature
) {
1091 case EfiUsbPortEnable
:
1093 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
1094 // A port may be disabled by software writing a '1' to this flag.
1096 State
|= XHC_PORTSC_PED
;
1097 State
&= ~XHC_PORTSC_RESET
;
1098 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1101 case EfiUsbPortSuspend
:
1102 State
|= XHC_PORTSC_LWS
;
1103 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1104 State
&= ~XHC_PORTSC_PLS
;
1105 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1108 case EfiUsbPortReset
:
1110 // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
1111 // Register bits indicate status when read, a clear bit may be set by
1112 // writing a '1'. Writing a '0' to RW1S bits has no effect.
1116 case EfiUsbPortPower
:
1117 if (Xhc
->HcCParams
.Data
.Ppc
) {
1119 // Port Power Control supported
1121 State
&= ~XHC_PORTSC_PP
;
1122 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1126 case EfiUsbPortOwner
:
1128 // XHCI root hub port don't has the owner bit, ignore the operation
1132 case EfiUsbPortConnectChange
:
1134 // Clear connect status change
1136 State
|= XHC_PORTSC_CSC
;
1137 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1140 case EfiUsbPortEnableChange
:
1142 // Clear enable status change
1144 State
|= XHC_PORTSC_PEC
;
1145 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1148 case EfiUsbPortOverCurrentChange
:
1150 // Clear PortOverCurrent change
1152 State
|= XHC_PORTSC_OCC
;
1153 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1156 case EfiUsbPortResetChange
:
1158 // Clear Port Reset change
1160 State
|= XHC_PORTSC_PRC
;
1161 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1164 case EfiUsbPortSuspendChange
:
1166 // Not supported or not related operation
1171 Status
= EFI_INVALID_PARAMETER
;
1176 DEBUG ((EFI_D_INFO
, "XhcPeiClearRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature
, Status
));
1181 Sets a feature for the specified root hub port.
1183 @param PeiServices The pointer of EFI_PEI_SERVICES
1184 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI
1185 @param PortNumber Root hub port to set.
1186 @param PortFeature Feature to set.
1188 @retval EFI_SUCCESS The feature specified by PortFeature was set.
1189 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1190 @retval EFI_TIMEOUT The time out occurred.
1195 XhcPeiSetRootHubPortFeature (
1196 IN EFI_PEI_SERVICES
**PeiServices
,
1197 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1198 IN UINT8 PortNumber
,
1199 IN EFI_USB_PORT_FEATURE PortFeature
1207 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1208 Status
= EFI_SUCCESS
;
1210 if (PortNumber
>= Xhc
->HcSParams1
.Data
.MaxPorts
) {
1211 Status
= EFI_INVALID_PARAMETER
;
1215 Offset
= (UINT32
) (XHC_PORTSC_OFFSET
+ (0x10 * PortNumber
));
1216 State
= XhcPeiReadOpReg (Xhc
, Offset
);
1217 DEBUG ((EFI_D_INFO
, "XhcPeiSetRootHubPortFeature: Port: %x State: %x\n", PortNumber
, State
));
1220 // Mask off the port status change bits, these bits are
1223 State
&= ~ (BIT1
| BIT17
| BIT18
| BIT19
| BIT20
| BIT21
| BIT22
| BIT23
);
1225 switch (PortFeature
) {
1226 case EfiUsbPortEnable
:
1228 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
1229 // A port may be disabled by software writing a '1' to this flag.
1233 case EfiUsbPortSuspend
:
1234 State
|= XHC_PORTSC_LWS
;
1235 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1236 State
&= ~XHC_PORTSC_PLS
;
1238 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1241 case EfiUsbPortReset
:
1243 // Make sure Host Controller not halt before reset it
1245 if (XhcPeiIsHalt (Xhc
)) {
1246 Status
= XhcPeiRunHC (Xhc
, XHC_GENERIC_TIMEOUT
);
1247 if (EFI_ERROR (Status
)) {
1253 // 4.3.1 Resetting a Root Hub Port
1254 // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
1255 // 2) Wait for a successful Port Status Change Event for the port, where the Port Reset Change (PRC)
1256 // bit in the PORTSC field is set to '1'.
1258 State
|= XHC_PORTSC_RESET
;
1259 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1260 XhcPeiWaitOpRegBit(Xhc
, Offset
, XHC_PORTSC_PRC
, TRUE
, XHC_GENERIC_TIMEOUT
);
1263 case EfiUsbPortPower
:
1264 if (Xhc
->HcCParams
.Data
.Ppc
) {
1266 // Port Power Control supported
1268 State
|= XHC_PORTSC_PP
;
1269 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1273 case EfiUsbPortOwner
:
1275 // XHCI root hub port don't has the owner bit, ignore the operation
1280 Status
= EFI_INVALID_PARAMETER
;
1284 DEBUG ((EFI_D_INFO
, "XhcPeiSetRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature
, Status
));
1289 Retrieves the current status of a USB root hub port.
1291 @param PeiServices The pointer of EFI_PEI_SERVICES.
1292 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
1293 @param PortNumber The root hub port to retrieve the state from.
1294 @param PortStatus Variable to receive the port state.
1296 @retval EFI_SUCCESS The status of the USB root hub port specified.
1297 by PortNumber was returned in PortStatus.
1298 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
1303 XhcPeiGetRootHubPortStatus (
1304 IN EFI_PEI_SERVICES
**PeiServices
,
1305 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1306 IN UINT8 PortNumber
,
1307 OUT EFI_USB_PORT_STATUS
*PortStatus
1315 USB_DEV_ROUTE ParentRouteChart
;
1317 if (PortStatus
== NULL
) {
1318 return EFI_INVALID_PARAMETER
;
1321 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1323 if (PortNumber
>= Xhc
->HcSParams1
.Data
.MaxPorts
) {
1324 return EFI_INVALID_PARAMETER
;
1328 // Clear port status.
1330 PortStatus
->PortStatus
= 0;
1331 PortStatus
->PortChangeStatus
= 0;
1333 Offset
= (UINT32
) (XHC_PORTSC_OFFSET
+ (0x10 * PortNumber
));
1334 State
= XhcPeiReadOpReg (Xhc
, Offset
);
1335 DEBUG ((EFI_D_INFO
, "XhcPeiGetRootHubPortStatus: Port: %x State: %x\n", PortNumber
, State
));
1338 // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.
1340 switch ((State
& XHC_PORTSC_PS
) >> 10) {
1342 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1346 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
1350 PortStatus
->PortStatus
|= USB_PORT_STAT_SUPER_SPEED
;
1358 // Convert the XHCI port/port change state to UEFI status
1360 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
1362 for (Index
= 0; Index
< MapSize
; Index
++) {
1363 if (XHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
1364 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
1368 // Bit5~8 reflects its current link state.
1370 if ((State
& XHC_PORTSC_PLS
) >> 5 == 3) {
1371 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1374 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
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
);
1382 MapSize
= sizeof (mUsbClearPortChangeMap
) / sizeof (USB_CLEAR_PORT_MAP
);
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
);
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.
1394 ParentRouteChart
.Dword
= 0;
1395 XhcPeiPollPortStatusChange (Xhc
, ParentRouteChart
, PortNumber
, PortStatus
);
1397 DEBUG ((EFI_D_INFO
, "XhcPeiGetRootHubPortStatus: PortChangeStatus: %x PortStatus: %x\n", PortStatus
->PortChangeStatus
, PortStatus
->PortStatus
));
1402 @param FileHandle Handle of the file being invoked.
1403 @param PeiServices Describes the list of possible PEI Services.
1405 @retval EFI_SUCCESS PPI successfully installed.
1411 IN EFI_PEI_FILE_HANDLE FileHandle
,
1412 IN CONST EFI_PEI_SERVICES
**PeiServices
1415 PEI_USB_CONTROLLER_PPI
*UsbControllerPpi
;
1418 UINTN ControllerType
;
1421 PEI_XHC_DEV
*XhcDev
;
1422 EFI_PHYSICAL_ADDRESS TempPtr
;
1426 // Shadow this PEIM to run from memory.
1428 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1432 Status
= PeiServicesLocatePpi (
1433 &gPeiUsbControllerPpiGuid
,
1436 (VOID
**) &UsbControllerPpi
1438 if (EFI_ERROR (Status
)) {
1439 return EFI_UNSUPPORTED
;
1444 Status
= UsbControllerPpi
->GetUsbController (
1445 (EFI_PEI_SERVICES
**) PeiServices
,
1452 // When status is error, it means no controller is found.
1454 if (EFI_ERROR (Status
)) {
1459 // This PEIM is for XHC type controller.
1461 if (ControllerType
!= PEI_XHCI_CONTROLLER
) {
1466 MemPages
= EFI_SIZE_TO_PAGES (sizeof (PEI_XHC_DEV
));
1467 Status
= PeiServicesAllocatePages (
1468 EfiBootServicesData
,
1472 if (EFI_ERROR (Status
)) {
1473 return EFI_OUT_OF_RESOURCES
;
1475 ZeroMem ((VOID
*) (UINTN
) TempPtr
, EFI_PAGES_TO_SIZE (MemPages
));
1476 XhcDev
= (PEI_XHC_DEV
*) ((UINTN
) TempPtr
);
1478 XhcDev
->Signature
= USB_XHC_DEV_SIGNATURE
;
1479 XhcDev
->UsbHostControllerBaseAddress
= (UINT32
) BaseAddress
;
1480 XhcDev
->CapLength
= (UINT8
) (XhcPeiReadCapRegister (XhcDev
, XHC_CAPLENGTH_OFFSET
) & 0x0FF);
1481 XhcDev
->HcSParams1
.Dword
= XhcPeiReadCapRegister (XhcDev
, XHC_HCSPARAMS1_OFFSET
);
1482 XhcDev
->HcSParams2
.Dword
= XhcPeiReadCapRegister (XhcDev
, XHC_HCSPARAMS2_OFFSET
);
1483 XhcDev
->HcCParams
.Dword
= XhcPeiReadCapRegister (XhcDev
, XHC_HCCPARAMS_OFFSET
);
1484 XhcDev
->DBOff
= XhcPeiReadCapRegister (XhcDev
, XHC_DBOFF_OFFSET
);
1485 XhcDev
->RTSOff
= XhcPeiReadCapRegister (XhcDev
, XHC_RTSOFF_OFFSET
);
1488 // This PageSize field defines the page size supported by the xHC implementation.
1489 // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
1490 // if bit 0 is Set, the xHC supports 4k byte page sizes.
1492 PageSize
= XhcPeiReadOpReg (XhcDev
, XHC_PAGESIZE_OFFSET
) & XHC_PAGESIZE_MASK
;
1493 XhcDev
->PageSize
= 1 << (HighBitSet32 (PageSize
) + 12);
1495 DEBUG ((EFI_D_INFO
, "XhciPei: UsbHostControllerBaseAddress: %x\n", XhcDev
->UsbHostControllerBaseAddress
));
1496 DEBUG ((EFI_D_INFO
, "XhciPei: CapLength: %x\n", XhcDev
->CapLength
));
1497 DEBUG ((EFI_D_INFO
, "XhciPei: HcSParams1: %x\n", XhcDev
->HcSParams1
.Dword
));
1498 DEBUG ((EFI_D_INFO
, "XhciPei: HcSParams2: %x\n", XhcDev
->HcSParams2
.Dword
));
1499 DEBUG ((EFI_D_INFO
, "XhciPei: HcCParams: %x\n", XhcDev
->HcCParams
.Dword
));
1500 DEBUG ((EFI_D_INFO
, "XhciPei: DBOff: %x\n", XhcDev
->DBOff
));
1501 DEBUG ((EFI_D_INFO
, "XhciPei: RTSOff: %x\n", XhcDev
->RTSOff
));
1502 DEBUG ((EFI_D_INFO
, "XhciPei: PageSize: %x\n", XhcDev
->PageSize
));
1504 XhcPeiResetHC (XhcDev
, XHC_RESET_TIMEOUT
);
1505 ASSERT (XhcPeiIsHalt (XhcDev
));
1508 // Initialize the schedule
1510 XhcPeiInitSched (XhcDev
);
1513 // Start the Host Controller
1515 XhcPeiRunHC (XhcDev
, XHC_GENERIC_TIMEOUT
);
1518 // Wait for root port state stable
1520 MicroSecondDelay (XHC_ROOT_PORT_STATE_STABLE
);
1522 XhcDev
->Usb2HostControllerPpi
.ControlTransfer
= XhcPeiControlTransfer
;
1523 XhcDev
->Usb2HostControllerPpi
.BulkTransfer
= XhcPeiBulkTransfer
;
1524 XhcDev
->Usb2HostControllerPpi
.GetRootHubPortNumber
= XhcPeiGetRootHubPortNumber
;
1525 XhcDev
->Usb2HostControllerPpi
.GetRootHubPortStatus
= XhcPeiGetRootHubPortStatus
;
1526 XhcDev
->Usb2HostControllerPpi
.SetRootHubPortFeature
= XhcPeiSetRootHubPortFeature
;
1527 XhcDev
->Usb2HostControllerPpi
.ClearRootHubPortFeature
= XhcPeiClearRootHubPortFeature
;
1529 XhcDev
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1530 XhcDev
->PpiDescriptor
.Guid
= &gPeiUsb2HostControllerPpiGuid
;
1531 XhcDev
->PpiDescriptor
.Ppi
= &XhcDev
->Usb2HostControllerPpi
;
1533 PeiServicesInstallPpi (&XhcDev
->PpiDescriptor
);