2 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
3 which is used to enable recovery function from USB Drivers.
5 Copyright (c) 2014 - 2018, 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
);
217 Write the data to the XHCI door bell register.
219 @param Xhc The XHCI device.
220 @param Offset The offset of the door bell register.
221 @param Data The data to write.
225 XhcPeiWriteDoorBellReg (
231 ASSERT (Xhc
->DBOff
!= 0);
233 MmioWrite32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->DBOff
+ Offset
, Data
);
237 Read XHCI runtime register.
239 @param Xhc The XHCI device.
240 @param Offset The offset of the runtime register.
242 @return The register content read
246 XhcPeiReadRuntimeReg (
253 ASSERT (Xhc
->RTSOff
!= 0);
255 Data
= MmioRead32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->RTSOff
+ Offset
);
261 Write the data to the XHCI runtime register.
263 @param Xhc The XHCI device.
264 @param Offset The offset of the runtime register.
265 @param Data The data to write.
269 XhcPeiWriteRuntimeReg (
275 ASSERT (Xhc
->RTSOff
!= 0);
277 MmioWrite32 (Xhc
->UsbHostControllerBaseAddress
+ Xhc
->RTSOff
+ Offset
, Data
);
281 Set one bit of the runtime register while keeping other bits.
283 @param Xhc The XHCI device.
284 @param Offset The offset of the runtime register.
285 @param Bit The bit mask of the register to set.
289 XhcPeiSetRuntimeRegBit (
297 Data
= XhcPeiReadRuntimeReg (Xhc
, Offset
);
299 XhcPeiWriteRuntimeReg (Xhc
, Offset
, Data
);
303 Clear 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 XhcPeiClearRuntimeRegBit (
319 Data
= XhcPeiReadRuntimeReg (Xhc
, Offset
);
321 XhcPeiWriteRuntimeReg (Xhc
, Offset
, Data
);
325 Check whether Xhc is halted.
327 @param Xhc The XHCI device.
329 @retval TRUE The controller is halted.
330 @retval FALSE The controller isn't halted.
338 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
);
342 Check whether system error occurred.
344 @param Xhc The XHCI device.
346 @retval TRUE System error happened.
347 @retval FALSE No system error.
355 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HSE
);
359 Reset the host controller.
361 @param Xhc The XHCI device.
362 @param Timeout Time to wait before abort (in millisecond, ms).
364 @retval EFI_TIMEOUT The transfer failed due to time out.
365 @retval Others Failed to reset the host.
377 // Host can only be reset when it is halt. If not so, halt it
379 if (!XhcPeiIsHalt (Xhc
)) {
380 Status
= XhcPeiHaltHC (Xhc
, Timeout
);
382 if (EFI_ERROR (Status
)) {
387 XhcPeiSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
);
389 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
390 // Otherwise there may have the timeout case happened.
391 // The below is a workaround to solve such problem.
393 MicroSecondDelay (1000);
394 Status
= XhcPeiWaitOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
, FALSE
, Timeout
);
396 DEBUG ((EFI_D_INFO
, "XhcPeiResetHC: %r\n", Status
));
401 Halt the host controller.
403 @param Xhc The XHCI device.
404 @param Timeout Time to wait before abort.
406 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
407 @retval EFI_SUCCESS The XHCI is halt.
418 XhcPeiClearOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
419 Status
= XhcPeiWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, TRUE
, Timeout
);
420 DEBUG ((EFI_D_INFO
, "XhcPeiHaltHC: %r\n", Status
));
427 @param Xhc The XHCI device.
428 @param Timeout Time to wait before abort.
430 @retval EFI_SUCCESS The XHCI is running.
431 @retval Others Failed to set the XHCI to run.
442 XhcPeiSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
443 Status
= XhcPeiWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, FALSE
, Timeout
);
444 DEBUG ((EFI_D_INFO
, "XhcPeiRunHC: %r\n", Status
));
449 Submits control transfer to a target USB device.
451 @param PeiServices The pointer of EFI_PEI_SERVICES.
452 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
453 @param DeviceAddress The target device address.
454 @param DeviceSpeed Target device speed.
455 @param MaximumPacketLength Maximum packet size the default control transfer
456 endpoint is capable of sending or receiving.
457 @param Request USB device request to send.
458 @param TransferDirection Specifies the data direction for the data stage.
459 @param Data Data buffer to be transmitted or received from USB device.
460 @param DataLength The size (in bytes) of the data buffer.
461 @param TimeOut Indicates the maximum timeout, in millisecond.
462 If Timeout is 0, then the caller must wait for the function
463 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
464 @param Translator Transaction translator to be used by this device.
465 @param TransferResult Return the result of this control transfer.
467 @retval EFI_SUCCESS Transfer was completed successfully.
468 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
469 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
470 @retval EFI_TIMEOUT Transfer failed due to timeout.
471 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
476 XhcPeiControlTransfer (
477 IN EFI_PEI_SERVICES
**PeiServices
,
478 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
479 IN UINT8 DeviceAddress
,
480 IN UINT8 DeviceSpeed
,
481 IN UINTN MaximumPacketLength
,
482 IN EFI_USB_DEVICE_REQUEST
*Request
,
483 IN EFI_USB_DATA_DIRECTION TransferDirection
,
485 IN OUT UINTN
*DataLength
,
487 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
488 OUT UINT32
*TransferResult
495 UINT8 DescriptorType
;
500 EFI_USB_HUB_DESCRIPTOR
*HubDesc
;
502 EFI_STATUS RecoveryStatus
;
504 EFI_USB_PORT_STATUS PortStatus
;
506 EFI_USB_DEVICE_REQUEST ClearPortRequest
;
510 // Validate parameters
512 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
513 return EFI_INVALID_PARAMETER
;
516 if ((TransferDirection
!= EfiUsbDataIn
) &&
517 (TransferDirection
!= EfiUsbDataOut
) &&
518 (TransferDirection
!= EfiUsbNoData
)) {
519 return EFI_INVALID_PARAMETER
;
522 if ((TransferDirection
== EfiUsbNoData
) &&
523 ((Data
!= NULL
) || (*DataLength
!= 0))) {
524 return EFI_INVALID_PARAMETER
;
527 if ((TransferDirection
!= EfiUsbNoData
) &&
528 ((Data
== NULL
) || (*DataLength
== 0))) {
529 return EFI_INVALID_PARAMETER
;
532 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
533 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64) &&
534 (MaximumPacketLength
!= 512)
536 return EFI_INVALID_PARAMETER
;
539 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
540 return EFI_INVALID_PARAMETER
;
543 if ((DeviceSpeed
== EFI_USB_SPEED_SUPER
) && (MaximumPacketLength
!= 512)) {
544 return EFI_INVALID_PARAMETER
;
547 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
549 Status
= EFI_DEVICE_ERROR
;
550 *TransferResult
= EFI_USB_ERR_SYSTEM
;
553 if (XhcPeiIsHalt (Xhc
) || XhcPeiIsSysError (Xhc
)) {
554 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: HC is halted or has system error\n"));
559 // Check if the device is still enabled before every transaction.
561 SlotId
= XhcPeiBusDevAddrToSlotId (Xhc
, DeviceAddress
);
567 // Hook the Set_Address request from UsbBus.
568 // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
570 if ((Request
->Request
== USB_REQ_SET_ADDRESS
) &&
571 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, USB_TARGET_DEVICE
))) {
573 // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
574 // This way is used to clean the history to avoid using wrong device address afterwards.
576 for (Index
= 0; Index
< 255; Index
++) {
577 if (!Xhc
->UsbDevContext
[Index
+ 1].Enabled
&&
578 (Xhc
->UsbDevContext
[Index
+ 1].SlotId
== 0) &&
579 (Xhc
->UsbDevContext
[Index
+ 1].BusDevAddr
== (UINT8
) Request
->Value
)) {
580 Xhc
->UsbDevContext
[Index
+ 1].BusDevAddr
= 0;
584 if (Xhc
->UsbDevContext
[SlotId
].XhciDevAddr
== 0) {
588 // The actual device address has been assigned by XHCI during initializing the device slot.
589 // So we just need establish the mapping relationship between the device address requested from UsbBus
590 // and the actual device address assigned by XHCI. The following invocations through EFI_USB2_HC_PROTOCOL interface
591 // can find out the actual device address by it.
593 Xhc
->UsbDevContext
[SlotId
].BusDevAddr
= (UINT8
) Request
->Value
;
594 Status
= EFI_SUCCESS
;
599 // Create a new URB, insert it into the asynchronous
600 // schedule list, then poll the execution status.
601 // Note that we encode the direction in address although default control
602 // endpoint is bidirectional. XhcPeiCreateUrb expects this
603 // combination of Ep addr and its direction.
605 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
606 Urb
= XhcPeiCreateUrb (
621 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: failed to create URB"));
622 Status
= EFI_OUT_OF_RESOURCES
;
626 Status
= XhcPeiExecTransfer (Xhc
, FALSE
, Urb
, TimeOut
);
629 // Get the status from URB. The result is updated in XhcPeiCheckUrbResult
630 // which is called by XhcPeiExecTransfer
632 *TransferResult
= Urb
->Result
;
633 *DataLength
= Urb
->Completed
;
635 if (Status
== EFI_TIMEOUT
) {
637 // The transfer timed out. Abort the transfer by dequeueing of the TD.
639 RecoveryStatus
= XhcPeiDequeueTrbFromEndpoint(Xhc
, Urb
);
640 if (EFI_ERROR(RecoveryStatus
)) {
641 DEBUG((EFI_D_ERROR
, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
643 XhcPeiFreeUrb (Xhc
, Urb
);
646 if (*TransferResult
== EFI_USB_NOERROR
) {
647 Status
= EFI_SUCCESS
;
648 } else if ((*TransferResult
== EFI_USB_ERR_STALL
) || (*TransferResult
== EFI_USB_ERR_BABBLE
)) {
649 RecoveryStatus
= XhcPeiRecoverHaltedEndpoint(Xhc
, Urb
);
650 if (EFI_ERROR (RecoveryStatus
)) {
651 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
653 Status
= EFI_DEVICE_ERROR
;
654 XhcPeiFreeUrb (Xhc
, Urb
);
657 XhcPeiFreeUrb (Xhc
, Urb
);
662 // Unmap data before consume.
664 XhcPeiFreeUrb (Xhc
, Urb
);
667 // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
668 // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
669 // Hook Set_Config request from UsbBus as we need configure device endpoint.
671 if ((Request
->Request
== USB_REQ_GET_DESCRIPTOR
) &&
672 ((Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbDataIn
, USB_REQ_TYPE_STANDARD
, USB_TARGET_DEVICE
)) ||
673 ((Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbDataIn
, USB_REQ_TYPE_CLASS
, USB_TARGET_DEVICE
))))) {
674 DescriptorType
= (UINT8
) (Request
->Value
>> 8);
675 if ((DescriptorType
== USB_DESC_TYPE_DEVICE
) && ((*DataLength
== sizeof (EFI_USB_DEVICE_DESCRIPTOR
)) || ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (*DataLength
== 8)))) {
676 ASSERT (Data
!= NULL
);
678 // Store a copy of device scriptor as hub device need this info to configure endpoint.
680 CopyMem (&Xhc
->UsbDevContext
[SlotId
].DevDesc
, Data
, *DataLength
);
681 if (Xhc
->UsbDevContext
[SlotId
].DevDesc
.BcdUSB
>= 0x0300) {
683 // If it's a usb3.0 device, then its max packet size is a 2^n.
685 MaxPacket0
= 1 << Xhc
->UsbDevContext
[SlotId
].DevDesc
.MaxPacketSize0
;
687 MaxPacket0
= Xhc
->UsbDevContext
[SlotId
].DevDesc
.MaxPacketSize0
;
689 Xhc
->UsbDevContext
[SlotId
].ConfDesc
= AllocateZeroPool (Xhc
->UsbDevContext
[SlotId
].DevDesc
.NumConfigurations
* sizeof (EFI_USB_CONFIG_DESCRIPTOR
*));
690 if (Xhc
->UsbDevContext
[SlotId
].ConfDesc
== NULL
) {
691 Status
= EFI_OUT_OF_RESOURCES
;
694 if (Xhc
->HcCParams
.Data
.Csz
== 0) {
695 Status
= XhcPeiEvaluateContext (Xhc
, SlotId
, MaxPacket0
);
697 Status
= XhcPeiEvaluateContext64 (Xhc
, SlotId
, MaxPacket0
);
699 } else if (DescriptorType
== USB_DESC_TYPE_CONFIG
) {
700 ASSERT (Data
!= NULL
);
701 if (*DataLength
== ((UINT16
*) Data
)[1]) {
703 // Get configuration value from request, store the configuration descriptor for Configure_Endpoint cmd.
705 Index
= (UINT8
) Request
->Value
;
706 ASSERT (Index
< Xhc
->UsbDevContext
[SlotId
].DevDesc
.NumConfigurations
);
707 Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
] = AllocateZeroPool (*DataLength
);
708 if (Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
] == NULL
) {
709 Status
= EFI_OUT_OF_RESOURCES
;
712 CopyMem (Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
], Data
, *DataLength
);
714 } else if (((DescriptorType
== USB_DESC_TYPE_HUB
) ||
715 (DescriptorType
== USB_DESC_TYPE_HUB_SUPER_SPEED
)) && (*DataLength
> 2)) {
716 ASSERT (Data
!= NULL
);
717 HubDesc
= (EFI_USB_HUB_DESCRIPTOR
*) Data
;
718 ASSERT (HubDesc
->NumPorts
<= 15);
720 // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
722 TTT
= (UINT8
) ((HubDesc
->HubCharacter
& (BIT5
| BIT6
)) >> 5);
723 if (Xhc
->UsbDevContext
[SlotId
].DevDesc
.DeviceProtocol
== 2) {
725 // Don't support multi-TT feature for super speed hub now.
728 DEBUG ((EFI_D_ERROR
, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
733 if (Xhc
->HcCParams
.Data
.Csz
== 0) {
734 Status
= XhcPeiConfigHubContext (Xhc
, SlotId
, HubDesc
->NumPorts
, TTT
, MTT
);
736 Status
= XhcPeiConfigHubContext64 (Xhc
, SlotId
, HubDesc
->NumPorts
, TTT
, MTT
);
739 } else if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
740 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, USB_TARGET_DEVICE
))) {
742 // Hook Set_Config request from UsbBus as we need configure device endpoint.
744 for (Index
= 0; Index
< Xhc
->UsbDevContext
[SlotId
].DevDesc
.NumConfigurations
; Index
++) {
745 if (Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
]->ConfigurationValue
== (UINT8
)Request
->Value
) {
746 if (Xhc
->HcCParams
.Data
.Csz
== 0) {
747 Status
= XhcPeiSetConfigCmd (Xhc
, SlotId
, DeviceSpeed
, Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
]);
749 Status
= XhcPeiSetConfigCmd64 (Xhc
, SlotId
, DeviceSpeed
, Xhc
->UsbDevContext
[SlotId
].ConfDesc
[Index
]);
754 } else if ((Request
->Request
== USB_REQ_GET_STATUS
) &&
755 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbDataIn
, USB_REQ_TYPE_CLASS
, USB_TARGET_OTHER
))) {
756 ASSERT (Data
!= NULL
);
758 // Hook Get_Status request from UsbBus to keep track of the port status change.
760 State
= *(UINT32
*) Data
;
761 PortStatus
.PortStatus
= 0;
762 PortStatus
.PortChangeStatus
= 0;
764 if (DeviceSpeed
== EFI_USB_SPEED_SUPER
) {
766 // For super speed hub, its bit10~12 presents the attached device speed.
768 if ((State
& XHC_PORTSC_PS
) >> 10 == 0) {
769 PortStatus
.PortStatus
|= USB_PORT_STAT_SUPER_SPEED
;
773 // For high or full/low speed hub, its bit9~10 presents the attached device speed.
775 if (XHC_BIT_IS_SET (State
, BIT9
)) {
776 PortStatus
.PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
777 } else if (XHC_BIT_IS_SET (State
, BIT10
)) {
778 PortStatus
.PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
783 // Convert the XHCI port/port change state to UEFI status
785 MapSize
= sizeof (mUsbHubPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
786 for (Index
= 0; Index
< MapSize
; Index
++) {
787 if (XHC_BIT_IS_SET (State
, mUsbHubPortStateMap
[Index
].HwState
)) {
788 PortStatus
.PortStatus
= (UINT16
) (PortStatus
.PortStatus
| mUsbHubPortStateMap
[Index
].UefiState
);
792 MapSize
= sizeof (mUsbHubPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
793 for (Index
= 0; Index
< MapSize
; Index
++) {
794 if (XHC_BIT_IS_SET (State
, mUsbHubPortChangeMap
[Index
].HwState
)) {
795 PortStatus
.PortChangeStatus
= (UINT16
) (PortStatus
.PortChangeStatus
| mUsbHubPortChangeMap
[Index
].UefiState
);
799 MapSize
= sizeof (mUsbHubClearPortChangeMap
) / sizeof (USB_CLEAR_PORT_MAP
);
801 for (Index
= 0; Index
< MapSize
; Index
++) {
802 if (XHC_BIT_IS_SET (State
, mUsbHubClearPortChangeMap
[Index
].HwState
)) {
803 ZeroMem (&ClearPortRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
804 ClearPortRequest
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_CLASS
, USB_TARGET_OTHER
);
805 ClearPortRequest
.Request
= (UINT8
) USB_REQ_CLEAR_FEATURE
;
806 ClearPortRequest
.Value
= mUsbHubClearPortChangeMap
[Index
].Selector
;
807 ClearPortRequest
.Index
= Request
->Index
;
808 ClearPortRequest
.Length
= 0;
810 XhcPeiControlTransfer (
827 XhcPeiPollPortStatusChange (Xhc
, Xhc
->UsbDevContext
[SlotId
].RouteString
, (UINT8
)Request
->Index
, &PortStatus
);
829 *(UINT32
*) Data
= *(UINT32
*) &PortStatus
;
834 if (EFI_ERROR (Status
)) {
835 DEBUG ((EFI_D_ERROR
, "XhcPeiControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
842 Submits bulk transfer to a bulk endpoint of a USB device.
844 @param PeiServices The pointer of EFI_PEI_SERVICES.
845 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
846 @param DeviceAddress Target device address.
847 @param EndPointAddress Endpoint number and its direction in bit 7.
848 @param DeviceSpeed Device speed, Low speed device doesn't support
850 @param MaximumPacketLength Maximum packet size the endpoint is capable of
851 sending or receiving.
852 @param Data Array of pointers to the buffers of data to transmit
853 from or receive into.
854 @param DataLength The lenght of the data buffer.
855 @param DataToggle On input, the initial data toggle for the transfer;
856 On output, it is updated to to next data toggle to use of
857 the subsequent bulk transfer.
858 @param TimeOut Indicates the maximum time, in millisecond, which the
859 transfer is allowed to complete.
860 If Timeout is 0, then the caller must wait for the function
861 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
862 @param Translator A pointr to the transaction translator data.
863 @param TransferResult A pointer to the detailed result information of the
866 @retval EFI_SUCCESS The transfer was completed successfully.
867 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
868 @retval EFI_INVALID_PARAMETER Parameters are invalid.
869 @retval EFI_TIMEOUT The transfer failed due to timeout.
870 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
876 IN EFI_PEI_SERVICES
**PeiServices
,
877 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
878 IN UINT8 DeviceAddress
,
879 IN UINT8 EndPointAddress
,
880 IN UINT8 DeviceSpeed
,
881 IN UINTN MaximumPacketLength
,
882 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
883 IN OUT UINTN
*DataLength
,
884 IN OUT UINT8
*DataToggle
,
886 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
887 OUT UINT32
*TransferResult
894 EFI_STATUS RecoveryStatus
;
897 // Validate the parameters
899 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
900 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
901 return EFI_INVALID_PARAMETER
;
904 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
905 return EFI_INVALID_PARAMETER
;
908 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
909 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
910 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 512)) ||
911 ((DeviceSpeed
== EFI_USB_SPEED_SUPER
) && (MaximumPacketLength
> 1024))) {
912 return EFI_INVALID_PARAMETER
;
915 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
917 *TransferResult
= EFI_USB_ERR_SYSTEM
;
918 Status
= EFI_DEVICE_ERROR
;
920 if (XhcPeiIsHalt (Xhc
) || XhcPeiIsSysError (Xhc
)) {
921 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: HC is halted or has system error\n"));
926 // Check if the device is still enabled before every transaction.
928 SlotId
= XhcPeiBusDevAddrToSlotId (Xhc
, DeviceAddress
);
934 // Create a new URB, insert it into the asynchronous
935 // schedule list, then poll the execution status.
937 Urb
= XhcPeiCreateUrb (
952 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: failed to create URB\n"));
953 Status
= EFI_OUT_OF_RESOURCES
;
957 Status
= XhcPeiExecTransfer (Xhc
, FALSE
, Urb
, TimeOut
);
959 *TransferResult
= Urb
->Result
;
960 *DataLength
= Urb
->Completed
;
962 if (Status
== EFI_TIMEOUT
) {
964 // The transfer timed out. Abort the transfer by dequeueing of the TD.
966 RecoveryStatus
= XhcPeiDequeueTrbFromEndpoint(Xhc
, Urb
);
967 if (EFI_ERROR(RecoveryStatus
)) {
968 DEBUG((EFI_D_ERROR
, "XhcPeiBulkTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
971 if (*TransferResult
== EFI_USB_NOERROR
) {
972 Status
= EFI_SUCCESS
;
973 } else if ((*TransferResult
== EFI_USB_ERR_STALL
) || (*TransferResult
== EFI_USB_ERR_BABBLE
)) {
974 RecoveryStatus
= XhcPeiRecoverHaltedEndpoint(Xhc
, Urb
);
975 if (EFI_ERROR (RecoveryStatus
)) {
976 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
978 Status
= EFI_DEVICE_ERROR
;
982 XhcPeiFreeUrb (Xhc
, Urb
);
986 if (EFI_ERROR (Status
)) {
987 DEBUG ((EFI_D_ERROR
, "XhcPeiBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
994 Retrieves the number of root hub ports.
996 @param[in] PeiServices The pointer to the PEI Services Table.
997 @param[in] This The pointer to this instance of the
998 PEI_USB2_HOST_CONTROLLER_PPI.
999 @param[out] PortNumber The pointer to the number of the root hub ports.
1001 @retval EFI_SUCCESS The port number was retrieved successfully.
1002 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
1007 XhcPeiGetRootHubPortNumber (
1008 IN EFI_PEI_SERVICES
**PeiServices
,
1009 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1010 OUT UINT8
*PortNumber
1013 PEI_XHC_DEV
*XhcDev
;
1014 XhcDev
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1016 if (PortNumber
== NULL
) {
1017 return EFI_INVALID_PARAMETER
;
1020 *PortNumber
= XhcDev
->HcSParams1
.Data
.MaxPorts
;
1021 DEBUG ((EFI_D_INFO
, "XhcPeiGetRootHubPortNumber: PortNumber = %x\n", *PortNumber
));
1026 Clears a feature for the specified root hub port.
1028 @param PeiServices The pointer of EFI_PEI_SERVICES.
1029 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
1030 @param PortNumber Specifies the root hub port whose feature
1031 is requested to be cleared.
1032 @param PortFeature Indicates the feature selector associated with the
1033 feature clear request.
1035 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
1036 for the USB root hub port specified by PortNumber.
1037 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1042 XhcPeiClearRootHubPortFeature (
1043 IN EFI_PEI_SERVICES
**PeiServices
,
1044 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1045 IN UINT8 PortNumber
,
1046 IN EFI_USB_PORT_FEATURE PortFeature
1054 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1055 Status
= EFI_SUCCESS
;
1057 if (PortNumber
>= Xhc
->HcSParams1
.Data
.MaxPorts
) {
1058 Status
= EFI_INVALID_PARAMETER
;
1062 Offset
= (UINT32
) (XHC_PORTSC_OFFSET
+ (0x10 * PortNumber
));
1063 State
= XhcPeiReadOpReg (Xhc
, Offset
);
1064 DEBUG ((EFI_D_INFO
, "XhcPeiClearRootHubPortFeature: Port: %x State: %x\n", PortNumber
, State
));
1067 // Mask off the port status change bits, these bits are
1070 State
&= ~ (BIT1
| BIT17
| BIT18
| BIT19
| BIT20
| BIT21
| BIT22
| BIT23
);
1072 switch (PortFeature
) {
1073 case EfiUsbPortEnable
:
1075 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
1076 // A port may be disabled by software writing a '1' to this flag.
1078 State
|= XHC_PORTSC_PED
;
1079 State
&= ~XHC_PORTSC_RESET
;
1080 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1083 case EfiUsbPortSuspend
:
1084 State
|= XHC_PORTSC_LWS
;
1085 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1086 State
&= ~XHC_PORTSC_PLS
;
1087 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1090 case EfiUsbPortReset
:
1092 // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
1093 // Register bits indicate status when read, a clear bit may be set by
1094 // writing a '1'. Writing a '0' to RW1S bits has no effect.
1098 case EfiUsbPortPower
:
1099 if (Xhc
->HcCParams
.Data
.Ppc
) {
1101 // Port Power Control supported
1103 State
&= ~XHC_PORTSC_PP
;
1104 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1108 case EfiUsbPortOwner
:
1110 // XHCI root hub port don't has the owner bit, ignore the operation
1114 case EfiUsbPortConnectChange
:
1116 // Clear connect status change
1118 State
|= XHC_PORTSC_CSC
;
1119 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1122 case EfiUsbPortEnableChange
:
1124 // Clear enable status change
1126 State
|= XHC_PORTSC_PEC
;
1127 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1130 case EfiUsbPortOverCurrentChange
:
1132 // Clear PortOverCurrent change
1134 State
|= XHC_PORTSC_OCC
;
1135 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1138 case EfiUsbPortResetChange
:
1140 // Clear Port Reset change
1142 State
|= XHC_PORTSC_PRC
;
1143 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1146 case EfiUsbPortSuspendChange
:
1148 // Not supported or not related operation
1153 Status
= EFI_INVALID_PARAMETER
;
1158 DEBUG ((EFI_D_INFO
, "XhcPeiClearRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature
, Status
));
1163 Sets a feature for the specified root hub port.
1165 @param PeiServices The pointer of EFI_PEI_SERVICES
1166 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI
1167 @param PortNumber Root hub port to set.
1168 @param PortFeature Feature to set.
1170 @retval EFI_SUCCESS The feature specified by PortFeature was set.
1171 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1172 @retval EFI_TIMEOUT The time out occurred.
1177 XhcPeiSetRootHubPortFeature (
1178 IN EFI_PEI_SERVICES
**PeiServices
,
1179 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1180 IN UINT8 PortNumber
,
1181 IN EFI_USB_PORT_FEATURE PortFeature
1189 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1190 Status
= EFI_SUCCESS
;
1192 if (PortNumber
>= Xhc
->HcSParams1
.Data
.MaxPorts
) {
1193 Status
= EFI_INVALID_PARAMETER
;
1197 Offset
= (UINT32
) (XHC_PORTSC_OFFSET
+ (0x10 * PortNumber
));
1198 State
= XhcPeiReadOpReg (Xhc
, Offset
);
1199 DEBUG ((EFI_D_INFO
, "XhcPeiSetRootHubPortFeature: Port: %x State: %x\n", PortNumber
, State
));
1202 // Mask off the port status change bits, these bits are
1205 State
&= ~ (BIT1
| BIT17
| BIT18
| BIT19
| BIT20
| BIT21
| BIT22
| BIT23
);
1207 switch (PortFeature
) {
1208 case EfiUsbPortEnable
:
1210 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
1211 // A port may be disabled by software writing a '1' to this flag.
1215 case EfiUsbPortSuspend
:
1216 State
|= XHC_PORTSC_LWS
;
1217 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1218 State
&= ~XHC_PORTSC_PLS
;
1220 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1223 case EfiUsbPortReset
:
1225 // Make sure Host Controller not halt before reset it
1227 if (XhcPeiIsHalt (Xhc
)) {
1228 Status
= XhcPeiRunHC (Xhc
, XHC_GENERIC_TIMEOUT
);
1229 if (EFI_ERROR (Status
)) {
1235 // 4.3.1 Resetting a Root Hub Port
1236 // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
1237 // 2) Wait for a successful Port Status Change Event for the port, where the Port Reset Change (PRC)
1238 // bit in the PORTSC field is set to '1'.
1240 State
|= XHC_PORTSC_RESET
;
1241 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1242 XhcPeiWaitOpRegBit(Xhc
, Offset
, XHC_PORTSC_PRC
, TRUE
, XHC_GENERIC_TIMEOUT
);
1245 case EfiUsbPortPower
:
1246 if (Xhc
->HcCParams
.Data
.Ppc
) {
1248 // Port Power Control supported
1250 State
|= XHC_PORTSC_PP
;
1251 XhcPeiWriteOpReg (Xhc
, Offset
, State
);
1255 case EfiUsbPortOwner
:
1257 // XHCI root hub port don't has the owner bit, ignore the operation
1262 Status
= EFI_INVALID_PARAMETER
;
1266 DEBUG ((EFI_D_INFO
, "XhcPeiSetRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature
, Status
));
1271 Retrieves the current status of a USB root hub port.
1273 @param PeiServices The pointer of EFI_PEI_SERVICES.
1274 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
1275 @param PortNumber The root hub port to retrieve the state from.
1276 @param PortStatus Variable to receive the port state.
1278 @retval EFI_SUCCESS The status of the USB root hub port specified.
1279 by PortNumber was returned in PortStatus.
1280 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
1285 XhcPeiGetRootHubPortStatus (
1286 IN EFI_PEI_SERVICES
**PeiServices
,
1287 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1288 IN UINT8 PortNumber
,
1289 OUT EFI_USB_PORT_STATUS
*PortStatus
1297 USB_DEV_ROUTE ParentRouteChart
;
1299 if (PortStatus
== NULL
) {
1300 return EFI_INVALID_PARAMETER
;
1303 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This
);
1305 if (PortNumber
>= Xhc
->HcSParams1
.Data
.MaxPorts
) {
1306 return EFI_INVALID_PARAMETER
;
1310 // Clear port status.
1312 PortStatus
->PortStatus
= 0;
1313 PortStatus
->PortChangeStatus
= 0;
1315 Offset
= (UINT32
) (XHC_PORTSC_OFFSET
+ (0x10 * PortNumber
));
1316 State
= XhcPeiReadOpReg (Xhc
, Offset
);
1317 DEBUG ((EFI_D_INFO
, "XhcPeiGetRootHubPortStatus: Port: %x State: %x\n", PortNumber
, State
));
1320 // According to XHCI 1.1 spec November 2017,
1321 // bit 10~13 of the root port status register identifies the speed of the attached device.
1323 switch ((State
& XHC_PORTSC_PS
) >> 10) {
1325 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1329 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
1334 PortStatus
->PortStatus
|= USB_PORT_STAT_SUPER_SPEED
;
1342 // Convert the XHCI port/port change state to UEFI status
1344 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
1346 for (Index
= 0; Index
< MapSize
; Index
++) {
1347 if (XHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
1348 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
1352 // Bit5~8 reflects its current link state.
1354 if ((State
& XHC_PORTSC_PLS
) >> 5 == 3) {
1355 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1358 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
1360 for (Index
= 0; Index
< MapSize
; Index
++) {
1361 if (XHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
1362 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
1366 MapSize
= sizeof (mUsbClearPortChangeMap
) / sizeof (USB_CLEAR_PORT_MAP
);
1368 for (Index
= 0; Index
< MapSize
; Index
++) {
1369 if (XHC_BIT_IS_SET (State
, mUsbClearPortChangeMap
[Index
].HwState
)) {
1370 XhcPeiClearRootHubPortFeature (PeiServices
, This
, PortNumber
, (EFI_USB_PORT_FEATURE
)mUsbClearPortChangeMap
[Index
].Selector
);
1375 // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
1376 // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
1378 ParentRouteChart
.Dword
= 0;
1379 XhcPeiPollPortStatusChange (Xhc
, ParentRouteChart
, PortNumber
, PortStatus
);
1381 DEBUG ((EFI_D_INFO
, "XhcPeiGetRootHubPortStatus: PortChangeStatus: %x PortStatus: %x\n", PortStatus
->PortChangeStatus
, PortStatus
->PortStatus
));
1386 One notified function to stop the Host Controller at the end of PEI
1388 @param[in] PeiServices Pointer to PEI Services Table.
1389 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification event that
1390 caused this function to execute.
1391 @param[in] Ppi Pointer to the PPI data associated with this function.
1393 @retval EFI_SUCCESS The function completes successfully
1399 IN EFI_PEI_SERVICES
**PeiServices
,
1400 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
1406 Xhc
= PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY(NotifyDescriptor
);
1408 XhcPeiHaltHC (Xhc
, XHC_GENERIC_TIMEOUT
);
1410 XhcPeiFreeSched (Xhc
);
1416 @param FileHandle Handle of the file being invoked.
1417 @param PeiServices Describes the list of possible PEI Services.
1419 @retval EFI_SUCCESS PPI successfully installed.
1425 IN EFI_PEI_FILE_HANDLE FileHandle
,
1426 IN CONST EFI_PEI_SERVICES
**PeiServices
1429 PEI_USB_CONTROLLER_PPI
*UsbControllerPpi
;
1432 UINTN ControllerType
;
1435 PEI_XHC_DEV
*XhcDev
;
1436 EFI_PHYSICAL_ADDRESS TempPtr
;
1440 // Shadow this PEIM to run from memory.
1442 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1446 Status
= PeiServicesLocatePpi (
1447 &gPeiUsbControllerPpiGuid
,
1450 (VOID
**) &UsbControllerPpi
1452 if (EFI_ERROR (Status
)) {
1453 return EFI_UNSUPPORTED
;
1460 Status
= UsbControllerPpi
->GetUsbController (
1461 (EFI_PEI_SERVICES
**) PeiServices
,
1468 // When status is error, it means no controller is found.
1470 if (EFI_ERROR (Status
)) {
1475 // This PEIM is for XHC type controller.
1477 if (ControllerType
!= PEI_XHCI_CONTROLLER
) {
1482 MemPages
= EFI_SIZE_TO_PAGES (sizeof (PEI_XHC_DEV
));
1483 Status
= PeiServicesAllocatePages (
1484 EfiBootServicesData
,
1488 if (EFI_ERROR (Status
)) {
1489 return EFI_OUT_OF_RESOURCES
;
1491 ZeroMem ((VOID
*) (UINTN
) TempPtr
, EFI_PAGES_TO_SIZE (MemPages
));
1492 XhcDev
= (PEI_XHC_DEV
*) ((UINTN
) TempPtr
);
1494 XhcDev
->Signature
= USB_XHC_DEV_SIGNATURE
;
1495 XhcDev
->UsbHostControllerBaseAddress
= (UINT32
) BaseAddress
;
1496 XhcDev
->CapLength
= (UINT8
) (XhcPeiReadCapRegister (XhcDev
, XHC_CAPLENGTH_OFFSET
) & 0x0FF);
1497 XhcDev
->HcSParams1
.Dword
= XhcPeiReadCapRegister (XhcDev
, XHC_HCSPARAMS1_OFFSET
);
1498 XhcDev
->HcSParams2
.Dword
= XhcPeiReadCapRegister (XhcDev
, XHC_HCSPARAMS2_OFFSET
);
1499 XhcDev
->HcCParams
.Dword
= XhcPeiReadCapRegister (XhcDev
, XHC_HCCPARAMS_OFFSET
);
1500 XhcDev
->DBOff
= XhcPeiReadCapRegister (XhcDev
, XHC_DBOFF_OFFSET
);
1501 XhcDev
->RTSOff
= XhcPeiReadCapRegister (XhcDev
, XHC_RTSOFF_OFFSET
);
1504 // This PageSize field defines the page size supported by the xHC implementation.
1505 // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
1506 // if bit 0 is Set, the xHC supports 4k byte page sizes.
1508 PageSize
= XhcPeiReadOpReg (XhcDev
, XHC_PAGESIZE_OFFSET
) & XHC_PAGESIZE_MASK
;
1509 XhcDev
->PageSize
= 1 << (HighBitSet32 (PageSize
) + 12);
1511 DEBUG ((EFI_D_INFO
, "XhciPei: UsbHostControllerBaseAddress: %x\n", XhcDev
->UsbHostControllerBaseAddress
));
1512 DEBUG ((EFI_D_INFO
, "XhciPei: CapLength: %x\n", XhcDev
->CapLength
));
1513 DEBUG ((EFI_D_INFO
, "XhciPei: HcSParams1: %x\n", XhcDev
->HcSParams1
.Dword
));
1514 DEBUG ((EFI_D_INFO
, "XhciPei: HcSParams2: %x\n", XhcDev
->HcSParams2
.Dword
));
1515 DEBUG ((EFI_D_INFO
, "XhciPei: HcCParams: %x\n", XhcDev
->HcCParams
.Dword
));
1516 DEBUG ((EFI_D_INFO
, "XhciPei: DBOff: %x\n", XhcDev
->DBOff
));
1517 DEBUG ((EFI_D_INFO
, "XhciPei: RTSOff: %x\n", XhcDev
->RTSOff
));
1518 DEBUG ((EFI_D_INFO
, "XhciPei: PageSize: %x\n", XhcDev
->PageSize
));
1520 XhcPeiResetHC (XhcDev
, XHC_RESET_TIMEOUT
);
1521 ASSERT (XhcPeiIsHalt (XhcDev
));
1524 // Initialize the schedule
1526 XhcPeiInitSched (XhcDev
);
1529 // Start the Host Controller
1531 XhcPeiRunHC (XhcDev
, XHC_GENERIC_TIMEOUT
);
1534 // Wait for root port state stable
1536 MicroSecondDelay (XHC_ROOT_PORT_STATE_STABLE
);
1538 XhcDev
->Usb2HostControllerPpi
.ControlTransfer
= XhcPeiControlTransfer
;
1539 XhcDev
->Usb2HostControllerPpi
.BulkTransfer
= XhcPeiBulkTransfer
;
1540 XhcDev
->Usb2HostControllerPpi
.GetRootHubPortNumber
= XhcPeiGetRootHubPortNumber
;
1541 XhcDev
->Usb2HostControllerPpi
.GetRootHubPortStatus
= XhcPeiGetRootHubPortStatus
;
1542 XhcDev
->Usb2HostControllerPpi
.SetRootHubPortFeature
= XhcPeiSetRootHubPortFeature
;
1543 XhcDev
->Usb2HostControllerPpi
.ClearRootHubPortFeature
= XhcPeiClearRootHubPortFeature
;
1545 XhcDev
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1546 XhcDev
->PpiDescriptor
.Guid
= &gPeiUsb2HostControllerPpiGuid
;
1547 XhcDev
->PpiDescriptor
.Ppi
= &XhcDev
->Usb2HostControllerPpi
;
1549 XhcDev
->EndOfPeiNotifyList
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1550 XhcDev
->EndOfPeiNotifyList
.Guid
= &gEfiEndOfPeiSignalPpiGuid
;
1551 XhcDev
->EndOfPeiNotifyList
.Notify
= XhcEndOfPei
;
1553 PeiServicesInstallPpi (&XhcDev
->PpiDescriptor
);
1554 PeiServicesNotifyPpi (&XhcDev
->EndOfPeiNotifyList
);