2 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
3 which is used to enable recovery function from USB Drivers.
5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
14 // Two arrays used to translate the EHCI port state (change)
15 // to the UEFI protocol's port state (change).
17 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
18 { PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
19 { PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
20 { PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
21 { PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
22 { PORTSC_RESET
, USB_PORT_STAT_RESET
},
23 { PORTSC_POWER
, USB_PORT_STAT_POWER
},
24 { PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
27 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
28 { PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
29 { PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
30 { PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
34 Read Ehc Operation register.
36 @param Ehc The EHCI device.
37 @param Offset The operation register offset.
39 @retval the register content read.
44 IN PEI_USB2_HC_DEV
*Ehc
,
50 ASSERT (Ehc
->CapLen
!= 0);
52 Data
= MmioRead32 (Ehc
->UsbHostControllerBaseAddress
+ Ehc
->CapLen
+ Offset
);
58 Write the data to the EHCI operation register.
60 @param Ehc The EHCI device.
61 @param Offset EHCI operation register offset.
62 @param Data The data to write.
67 IN PEI_USB2_HC_DEV
*Ehc
,
72 ASSERT (Ehc
->CapLen
!= 0);
74 MmioWrite32 (Ehc
->UsbHostControllerBaseAddress
+ Ehc
->CapLen
+ Offset
, Data
);
78 Set one bit of the operational register while keeping other bits.
80 @param Ehc The EHCI device.
81 @param Offset The offset of the operational register.
82 @param Bit The bit mask of the register to set.
87 IN PEI_USB2_HC_DEV
*Ehc
,
94 Data
= EhcReadOpReg (Ehc
, Offset
);
96 EhcWriteOpReg (Ehc
, Offset
, Data
);
100 Clear one bit of the operational register while keeping other bits.
102 @param Ehc The EHCI device.
103 @param Offset The offset of the operational register.
104 @param Bit The bit mask of the register to clear.
109 IN PEI_USB2_HC_DEV
*Ehc
,
116 Data
= EhcReadOpReg (Ehc
, Offset
);
118 EhcWriteOpReg (Ehc
, Offset
, Data
);
122 Wait the operation register's bit as specified by Bit
123 to become set (or clear).
125 @param Ehc The EHCI device.
126 @param Offset The offset of the operational register.
127 @param Bit The bit mask of the register to wait for.
128 @param WaitToSet Wait the bit to set or clear.
129 @param Timeout The time to wait before abort (in millisecond).
131 @retval EFI_SUCCESS The bit successfully changed by host controller.
132 @retval EFI_TIMEOUT The time out occurred.
137 IN PEI_USB2_HC_DEV
*Ehc
,
140 IN BOOLEAN WaitToSet
,
146 for (Index
= 0; Index
< Timeout
/ EHC_SYNC_POLL_INTERVAL
+ 1; Index
++) {
147 if (EHC_REG_BIT_IS_SET (Ehc
, Offset
, Bit
) == WaitToSet
) {
151 MicroSecondDelay (EHC_SYNC_POLL_INTERVAL
);
158 Read EHCI capability register.
160 @param Ehc The EHCI device.
161 @param Offset Capability register address.
163 @retval the register content read.
168 IN PEI_USB2_HC_DEV
*Ehc
,
174 Data
= MmioRead32 (Ehc
->UsbHostControllerBaseAddress
+ Offset
);
180 Set door bell and wait it to be ACKed by host controller.
181 This function is used to synchronize with the hardware.
183 @param Ehc The EHCI device.
184 @param Timeout The time to wait before abort (in millisecond, ms).
186 @retval EFI_TIMEOUT Time out happened while waiting door bell to set.
187 @retval EFI_SUCCESS Synchronized with the hardware.
191 EhcSetAndWaitDoorBell (
192 IN PEI_USB2_HC_DEV
*Ehc
,
199 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_IAAD
);
201 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_IAA
, TRUE
, Timeout
);
204 // ACK the IAA bit in USBSTS register. Make sure other
205 // interrupt bits are not ACKed. These bits are WC (Write Clean).
207 Data
= EhcReadOpReg (Ehc
, EHC_USBSTS_OFFSET
);
208 Data
&= ~USBSTS_INTACK_MASK
;
211 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, Data
);
217 Clear all the interrutp status bits, these bits
220 @param Ehc The EHCI device.
225 IN PEI_USB2_HC_DEV
*Ehc
228 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_INTACK_MASK
);
232 Enable the periodic schedule then wait EHC to
235 @param Ehc The EHCI device.
236 @param Timeout The time to wait before abort (in millisecond, ms).
238 @retval EFI_TIMEOUT Time out happened while enabling periodic schedule.
239 @retval EFI_SUCCESS The periodical schedule is enabled.
243 EhcEnablePeriodSchd (
244 IN PEI_USB2_HC_DEV
*Ehc
,
250 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
252 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, TRUE
, Timeout
);
257 Enable asynchrounous schedule.
259 @param Ehc The EHCI device.
260 @param Timeout Time to wait before abort.
262 @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled.
263 @retval Others Failed to enable the asynchronous scheudle.
268 IN PEI_USB2_HC_DEV
*Ehc
,
274 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
276 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, TRUE
, Timeout
);
281 Check whether Ehc is halted.
283 @param Ehc The EHCI device.
285 @retval TRUE The controller is halted.
286 @retval FALSE The controller isn't halted.
291 IN PEI_USB2_HC_DEV
*Ehc
294 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
);
298 Check whether system error occurred.
300 @param Ehc The EHCI device.
302 @retval TRUE System error happened.
303 @retval FALSE No system error.
308 IN PEI_USB2_HC_DEV
*Ehc
311 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
);
315 Reset the host controller.
317 @param Ehc The EHCI device.
318 @param Timeout Time to wait before abort (in millisecond, ms).
320 @retval EFI_TIMEOUT The transfer failed due to time out.
321 @retval Others Failed to reset the host.
326 IN PEI_USB2_HC_DEV
*Ehc
,
333 // Host can only be reset when it is halt. If not so, halt it
335 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
336 Status
= EhcHaltHC (Ehc
, Timeout
);
338 if (EFI_ERROR (Status
)) {
343 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
);
344 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
, FALSE
, Timeout
);
349 Halt the host controller.
351 @param Ehc The EHCI device.
352 @param Timeout Time to wait before abort.
354 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
355 @retval EFI_SUCCESS The EHCI is halt.
360 IN PEI_USB2_HC_DEV
*Ehc
,
366 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
367 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, TRUE
, Timeout
);
374 @param Ehc The EHCI device.
375 @param Timeout Time to wait before abort.
377 @retval EFI_SUCCESS The EHCI is running.
378 @retval Others Failed to set the EHCI to run.
383 IN PEI_USB2_HC_DEV
*Ehc
,
389 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
390 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, FALSE
, Timeout
);
395 Power On All EHCI Ports.
397 @param Ehc The EHCI device.
402 IN PEI_USB2_HC_DEV
*Ehc
409 PortNumber
= (UINT8
)(Ehc
->HcStructParams
& HCSP_NPORTS
);
410 for (Index
= 0; Index
< PortNumber
; Index
++) {
412 // Do not clear port status bits on initialization. Otherwise devices will
413 // not enumerate properly at startup.
415 RegVal
= EhcReadOpReg (Ehc
, EHC_PORT_STAT_OFFSET
+ 4 * Index
);
416 RegVal
&= ~PORTSC_CHANGE_MASK
;
417 RegVal
|= PORTSC_POWER
;
418 EhcWriteOpReg (Ehc
, EHC_PORT_STAT_OFFSET
+ 4 * Index
, RegVal
);
423 Initialize the HC hardware.
424 EHCI spec lists the five things to do to initialize the hardware.
425 1. Program CTRLDSSEGMENT.
426 2. Set USBINTR to enable interrupts.
427 3. Set periodic list base.
428 4. Set USBCMD, interrupt threshold, frame list size etc.
429 5. Write 1 to CONFIGFLAG to route all ports to EHCI.
431 @param Ehc The EHCI device.
433 @retval EFI_SUCCESS The EHCI has come out of halt state.
434 @retval EFI_TIMEOUT Time out happened.
439 IN PEI_USB2_HC_DEV
*Ehc
443 EFI_PHYSICAL_ADDRESS TempPtr
;
446 ASSERT (EhcIsHalt (Ehc
));
449 // Allocate the periodic frame and associated memeory
450 // management facilities if not already done.
452 if (Ehc
->PeriodFrame
!= NULL
) {
456 PageNumber
= sizeof (PEI_URB
)/PAGESIZE
+1;
457 Status
= PeiServicesAllocatePages (
462 Ehc
->Urb
= (PEI_URB
*)((UINTN
)TempPtr
);
463 if (Ehc
->Urb
== NULL
) {
467 EhcPowerOnAllPorts (Ehc
);
468 MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL
);
470 Status
= EhcInitSched (Ehc
);
472 if (EFI_ERROR (Status
)) {
477 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
479 EhcWriteOpReg (Ehc
, EHC_CTRLDSSEG_OFFSET
, Ehc
->High32bitAddr
);
482 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
484 EhcWriteOpReg (Ehc
, EHC_USBINTR_OFFSET
, 0);
487 // 3. Program periodic frame list, already done in EhcInitSched
488 // 4. Start the Host Controller
490 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
493 // 5. Set all ports routing to EHC
495 EhcSetOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
498 // Wait roothub port power stable
500 MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL
);
502 Status
= EhcEnablePeriodSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
504 if (EFI_ERROR (Status
)) {
508 Status
= EhcEnableAsyncSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
510 if (EFI_ERROR (Status
)) {
518 Submits bulk transfer to a bulk endpoint of a USB device.
520 @param PeiServices The pointer of EFI_PEI_SERVICES.
521 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
522 @param DeviceAddress Target device address.
523 @param EndPointAddress Endpoint number and its direction in bit 7.
524 @param DeviceSpeed Device speed, Low speed device doesn't support
526 @param MaximumPacketLength Maximum packet size the endpoint is capable of
527 sending or receiving.
528 @param Data Array of pointers to the buffers of data to transmit
529 from or receive into.
530 @param DataLength The lenght of the data buffer.
531 @param DataToggle On input, the initial data toggle for the transfer;
532 On output, it is updated to to next data toggle to use of
533 the subsequent bulk transfer.
534 @param TimeOut Indicates the maximum time, in millisecond, which the
535 transfer is allowed to complete.
536 If Timeout is 0, then the caller must wait for the function
537 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
538 @param Translator A pointr to the transaction translator data.
539 @param TransferResult A pointer to the detailed result information of the
542 @retval EFI_SUCCESS The transfer was completed successfully.
543 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
544 @retval EFI_INVALID_PARAMETER Parameters are invalid.
545 @retval EFI_TIMEOUT The transfer failed due to timeout.
546 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
552 IN EFI_PEI_SERVICES
**PeiServices
,
553 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
554 IN UINT8 DeviceAddress
,
555 IN UINT8 EndPointAddress
,
556 IN UINT8 DeviceSpeed
,
557 IN UINTN MaximumPacketLength
,
558 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
559 IN OUT UINTN
*DataLength
,
560 IN OUT UINT8
*DataToggle
,
562 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
563 OUT UINT32
*TransferResult
566 PEI_USB2_HC_DEV
*Ehc
;
571 // Validate the parameters
573 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
574 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
))
576 return EFI_INVALID_PARAMETER
;
579 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
580 return EFI_INVALID_PARAMETER
;
583 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
584 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
585 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512)))
587 return EFI_INVALID_PARAMETER
;
590 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
591 *TransferResult
= EFI_USB_ERR_SYSTEM
;
592 Status
= EFI_DEVICE_ERROR
;
594 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
595 EhcAckAllInterrupt (Ehc
);
599 EhcAckAllInterrupt (Ehc
);
602 // Create a new URB, insert it into the asynchronous
603 // schedule list, then poll the execution status.
623 Status
= EFI_OUT_OF_RESOURCES
;
627 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
628 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
629 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
631 *TransferResult
= Urb
->Result
;
632 *DataLength
= Urb
->Completed
;
633 *DataToggle
= Urb
->DataToggle
;
635 if (*TransferResult
== EFI_USB_NOERROR
) {
636 Status
= EFI_SUCCESS
;
639 EhcAckAllInterrupt (Ehc
);
640 EhcFreeUrb (Ehc
, Urb
);
647 Retrieves the number of root hub ports.
649 @param[in] PeiServices The pointer to the PEI Services Table.
650 @param[in] This The pointer to this instance of the
651 PEI_USB2_HOST_CONTROLLER_PPI.
652 @param[out] PortNumber The pointer to the number of the root hub ports.
654 @retval EFI_SUCCESS The port number was retrieved successfully.
655 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
660 EhcGetRootHubPortNumber (
661 IN EFI_PEI_SERVICES
**PeiServices
,
662 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
663 OUT UINT8
*PortNumber
666 PEI_USB2_HC_DEV
*EhcDev
;
668 EhcDev
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
670 if (PortNumber
== NULL
) {
671 return EFI_INVALID_PARAMETER
;
674 *PortNumber
= (UINT8
)(EhcDev
->HcStructParams
& HCSP_NPORTS
);
679 Clears a feature for the specified root hub port.
681 @param PeiServices The pointer of EFI_PEI_SERVICES.
682 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
683 @param PortNumber Specifies the root hub port whose feature
684 is requested to be cleared.
685 @param PortFeature Indicates the feature selector associated with the
686 feature clear request.
688 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
689 for the USB root hub port specified by PortNumber.
690 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
695 EhcClearRootHubPortFeature (
696 IN EFI_PEI_SERVICES
**PeiServices
,
697 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
699 IN EFI_USB_PORT_FEATURE PortFeature
702 PEI_USB2_HC_DEV
*Ehc
;
708 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
709 Status
= EFI_SUCCESS
;
711 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
713 if (PortNumber
>= TotalPort
) {
714 Status
= EFI_INVALID_PARAMETER
;
718 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
719 State
= EhcReadOpReg (Ehc
, Offset
);
720 State
&= ~PORTSC_CHANGE_MASK
;
722 switch (PortFeature
) {
723 case EfiUsbPortEnable
:
725 // Clear PORT_ENABLE feature means disable port.
727 State
&= ~PORTSC_ENABLED
;
728 EhcWriteOpReg (Ehc
, Offset
, State
);
731 case EfiUsbPortSuspend
:
733 // A write of zero to this bit is ignored by the host
734 // controller. The host controller will unconditionally
735 // set this bit to a zero when:
736 // 1. software sets the Forct Port Resume bit to a zero from a one.
737 // 2. software sets the Port Reset bit to a one frome a zero.
739 State
&= ~PORSTSC_RESUME
;
740 EhcWriteOpReg (Ehc
, Offset
, State
);
743 case EfiUsbPortReset
:
745 // Clear PORT_RESET means clear the reset signal.
747 State
&= ~PORTSC_RESET
;
748 EhcWriteOpReg (Ehc
, Offset
, State
);
751 case EfiUsbPortOwner
:
753 // Clear port owner means this port owned by EHC
755 State
&= ~PORTSC_OWNER
;
756 EhcWriteOpReg (Ehc
, Offset
, State
);
759 case EfiUsbPortConnectChange
:
761 // Clear connect status change
763 State
|= PORTSC_CONN_CHANGE
;
764 EhcWriteOpReg (Ehc
, Offset
, State
);
767 case EfiUsbPortEnableChange
:
769 // Clear enable status change
771 State
|= PORTSC_ENABLE_CHANGE
;
772 EhcWriteOpReg (Ehc
, Offset
, State
);
775 case EfiUsbPortOverCurrentChange
:
777 // Clear PortOverCurrent change
779 State
|= PORTSC_OVERCUR_CHANGE
;
780 EhcWriteOpReg (Ehc
, Offset
, State
);
783 case EfiUsbPortPower
:
784 case EfiUsbPortSuspendChange
:
785 case EfiUsbPortResetChange
:
787 // Not supported or not related operation
792 Status
= EFI_INVALID_PARAMETER
;
801 Sets a feature for the specified root hub port.
803 @param PeiServices The pointer of EFI_PEI_SERVICES
804 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI
805 @param PortNumber Root hub port to set.
806 @param PortFeature Feature to set.
808 @retval EFI_SUCCESS The feature specified by PortFeature was set.
809 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
810 @retval EFI_TIMEOUT The time out occurred.
815 EhcSetRootHubPortFeature (
816 IN EFI_PEI_SERVICES
**PeiServices
,
817 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
819 IN EFI_USB_PORT_FEATURE PortFeature
822 PEI_USB2_HC_DEV
*Ehc
;
828 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
829 Status
= EFI_SUCCESS
;
831 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
833 if (PortNumber
>= TotalPort
) {
834 Status
= EFI_INVALID_PARAMETER
;
838 Offset
= (UINT32
)(EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
839 State
= EhcReadOpReg (Ehc
, Offset
);
842 // Mask off the port status change bits, these bits are
845 State
&= ~PORTSC_CHANGE_MASK
;
847 switch (PortFeature
) {
848 case EfiUsbPortEnable
:
850 // Sofeware can't set this bit, Port can only be enable by
851 // EHCI as a part of the reset and enable
853 State
|= PORTSC_ENABLED
;
854 EhcWriteOpReg (Ehc
, Offset
, State
);
857 case EfiUsbPortSuspend
:
858 State
|= PORTSC_SUSPEND
;
859 EhcWriteOpReg (Ehc
, Offset
, State
);
862 case EfiUsbPortReset
:
864 // Make sure Host Controller not halt before reset it
866 if (EhcIsHalt (Ehc
)) {
867 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
869 if (EFI_ERROR (Status
)) {
875 // Set one to PortReset bit must also set zero to PortEnable bit
877 State
|= PORTSC_RESET
;
878 State
&= ~PORTSC_ENABLED
;
879 EhcWriteOpReg (Ehc
, Offset
, State
);
882 case EfiUsbPortPower
:
884 // Not supported, ignore the operation
886 Status
= EFI_SUCCESS
;
889 case EfiUsbPortOwner
:
890 State
|= PORTSC_OWNER
;
891 EhcWriteOpReg (Ehc
, Offset
, State
);
895 Status
= EFI_INVALID_PARAMETER
;
903 Retrieves the current status of a USB root hub port.
905 @param PeiServices The pointer of EFI_PEI_SERVICES.
906 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
907 @param PortNumber The root hub port to retrieve the state from.
908 @param PortStatus Variable to receive the port state.
910 @retval EFI_SUCCESS The status of the USB root hub port specified.
911 by PortNumber was returned in PortStatus.
912 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
917 EhcGetRootHubPortStatus (
918 IN EFI_PEI_SERVICES
**PeiServices
,
919 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
921 OUT EFI_USB_PORT_STATUS
*PortStatus
924 PEI_USB2_HC_DEV
*Ehc
;
932 if (PortStatus
== NULL
) {
933 return EFI_INVALID_PARAMETER
;
936 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
937 Status
= EFI_SUCCESS
;
939 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
941 if (PortNumber
>= TotalPort
) {
942 Status
= EFI_INVALID_PARAMETER
;
946 Offset
= (UINT32
)(EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
947 PortStatus
->PortStatus
= 0;
948 PortStatus
->PortChangeStatus
= 0;
950 State
= EhcReadOpReg (Ehc
, Offset
);
953 // Identify device speed. If in K state, it is low speed.
954 // If the port is enabled after reset, the device is of
955 // high speed. The USB bus driver should retrieve the actual
956 // port speed after reset.
958 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
959 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
960 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
961 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
965 // Convert the EHCI port/port change state to UEFI status
967 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
969 for (Index
= 0; Index
< MapSize
; Index
++) {
970 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
971 PortStatus
->PortStatus
= (UINT16
)(PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
975 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
977 for (Index
= 0; Index
< MapSize
; Index
++) {
978 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
979 PortStatus
->PortChangeStatus
= (UINT16
)(PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
988 Submits control transfer to a target USB device.
990 @param PeiServices The pointer of EFI_PEI_SERVICES.
991 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
992 @param DeviceAddress The target device address.
993 @param DeviceSpeed Target device speed.
994 @param MaximumPacketLength Maximum packet size the default control transfer
995 endpoint is capable of sending or receiving.
996 @param Request USB device request to send.
997 @param TransferDirection Specifies the data direction for the data stage.
998 @param Data Data buffer to be transmitted or received from USB device.
999 @param DataLength The size (in bytes) of the data buffer.
1000 @param TimeOut Indicates the maximum timeout, in millisecond.
1001 If Timeout is 0, then the caller must wait for the function
1002 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
1003 @param Translator Transaction translator to be used by this device.
1004 @param TransferResult Return the result of this control transfer.
1006 @retval EFI_SUCCESS Transfer was completed successfully.
1007 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
1008 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1009 @retval EFI_TIMEOUT Transfer failed due to timeout.
1010 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
1015 EhcControlTransfer (
1016 IN EFI_PEI_SERVICES
**PeiServices
,
1017 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1018 IN UINT8 DeviceAddress
,
1019 IN UINT8 DeviceSpeed
,
1020 IN UINTN MaximumPacketLength
,
1021 IN EFI_USB_DEVICE_REQUEST
*Request
,
1022 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1024 IN OUT UINTN
*DataLength
,
1026 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1027 OUT UINT32
*TransferResult
1030 PEI_USB2_HC_DEV
*Ehc
;
1036 // Validate parameters
1038 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
1039 return EFI_INVALID_PARAMETER
;
1042 if ((TransferDirection
!= EfiUsbDataIn
) &&
1043 (TransferDirection
!= EfiUsbDataOut
) &&
1044 (TransferDirection
!= EfiUsbNoData
))
1046 return EFI_INVALID_PARAMETER
;
1049 if ((TransferDirection
== EfiUsbNoData
) &&
1050 ((Data
!= NULL
) || (*DataLength
!= 0)))
1052 return EFI_INVALID_PARAMETER
;
1055 if ((TransferDirection
!= EfiUsbNoData
) &&
1056 ((Data
== NULL
) || (*DataLength
== 0)))
1058 return EFI_INVALID_PARAMETER
;
1061 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
1062 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64))
1064 return EFI_INVALID_PARAMETER
;
1067 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
1068 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1069 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512)))
1071 return EFI_INVALID_PARAMETER
;
1074 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
1076 Status
= EFI_DEVICE_ERROR
;
1077 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1079 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1080 EhcAckAllInterrupt (Ehc
);
1084 EhcAckAllInterrupt (Ehc
);
1087 // Create a new URB, insert it into the asynchronous
1088 // schedule list, then poll the execution status.
1091 // Encode the direction in address, although default control
1092 // endpoint is bidirectional. EhcCreateUrb expects this
1093 // combination of Ep addr and its direction.
1095 Endpoint
= (UINT8
)(0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
1096 Urb
= EhcCreateUrb (
1102 MaximumPacketLength
,
1114 Status
= EFI_OUT_OF_RESOURCES
;
1118 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
1119 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1120 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
1123 // Get the status from URB. The result is updated in EhcCheckUrbResult
1124 // which is called by EhcExecTransfer
1126 *TransferResult
= Urb
->Result
;
1127 *DataLength
= Urb
->Completed
;
1129 if (*TransferResult
== EFI_USB_NOERROR
) {
1130 Status
= EFI_SUCCESS
;
1133 EhcAckAllInterrupt (Ehc
);
1134 EhcFreeUrb (Ehc
, Urb
);
1141 One notified function to stop the Host Controller at the end of PEI
1143 @param[in] PeiServices Pointer to PEI Services Table.
1144 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification event that
1145 caused this function to execute.
1146 @param[in] Ppi Pointer to the PPI data associated with this function.
1148 @retval EFI_SUCCESS The function completes successfully
1154 IN EFI_PEI_SERVICES
**PeiServices
,
1155 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
1159 PEI_USB2_HC_DEV
*Ehc
;
1161 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor
);
1163 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1171 @param FileHandle Handle of the file being invoked.
1172 @param PeiServices Describes the list of possible PEI Services.
1174 @retval EFI_SUCCESS PPI successfully installed.
1180 IN EFI_PEI_FILE_HANDLE FileHandle
,
1181 IN CONST EFI_PEI_SERVICES
**PeiServices
1184 PEI_USB_CONTROLLER_PPI
*ChipSetUsbControllerPpi
;
1187 UINTN ControllerType
;
1190 PEI_USB2_HC_DEV
*EhcDev
;
1191 EFI_PHYSICAL_ADDRESS TempPtr
;
1194 // Shadow this PEIM to run from memory
1196 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1200 Status
= PeiServicesLocatePpi (
1201 &gPeiUsbControllerPpiGuid
,
1204 (VOID
**)&ChipSetUsbControllerPpi
1206 if (EFI_ERROR (Status
)) {
1207 return EFI_UNSUPPORTED
;
1212 Status
= ChipSetUsbControllerPpi
->GetUsbController (
1213 (EFI_PEI_SERVICES
**)PeiServices
,
1214 ChipSetUsbControllerPpi
,
1220 // When status is error, meant no controller is found
1222 if (EFI_ERROR (Status
)) {
1227 // This PEIM is for UHC type controller.
1229 if (ControllerType
!= PEI_EHCI_CONTROLLER
) {
1234 MemPages
= sizeof (PEI_USB2_HC_DEV
) / PAGESIZE
+ 1;
1235 Status
= PeiServicesAllocatePages (
1236 EfiBootServicesCode
,
1240 if (EFI_ERROR (Status
)) {
1241 return EFI_OUT_OF_RESOURCES
;
1244 ZeroMem ((VOID
*)(UINTN
)TempPtr
, MemPages
*PAGESIZE
);
1245 EhcDev
= (PEI_USB2_HC_DEV
*)((UINTN
)TempPtr
);
1247 EhcDev
->Signature
= USB2_HC_DEV_SIGNATURE
;
1249 IoMmuInit (&EhcDev
->IoMmu
);
1251 EhcDev
->UsbHostControllerBaseAddress
= (UINT32
)BaseAddress
;
1253 EhcDev
->HcStructParams
= EhcReadCapRegister (EhcDev
, EHC_HCSPARAMS_OFFSET
);
1254 EhcDev
->HcCapParams
= EhcReadCapRegister (EhcDev
, EHC_HCCPARAMS_OFFSET
);
1255 EhcDev
->CapLen
= EhcReadCapRegister (EhcDev
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1257 // Initialize Uhc's hardware
1259 Status
= InitializeUsbHC (EhcDev
);
1260 if (EFI_ERROR (Status
)) {
1264 EhcDev
->Usb2HostControllerPpi
.ControlTransfer
= EhcControlTransfer
;
1265 EhcDev
->Usb2HostControllerPpi
.BulkTransfer
= EhcBulkTransfer
;
1266 EhcDev
->Usb2HostControllerPpi
.GetRootHubPortNumber
= EhcGetRootHubPortNumber
;
1267 EhcDev
->Usb2HostControllerPpi
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1268 EhcDev
->Usb2HostControllerPpi
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1269 EhcDev
->Usb2HostControllerPpi
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1271 EhcDev
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1272 EhcDev
->PpiDescriptor
.Guid
= &gPeiUsb2HostControllerPpiGuid
;
1273 EhcDev
->PpiDescriptor
.Ppi
= &EhcDev
->Usb2HostControllerPpi
;
1275 Status
= PeiServicesInstallPpi (&EhcDev
->PpiDescriptor
);
1276 if (EFI_ERROR (Status
)) {
1281 EhcDev
->EndOfPeiNotifyList
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1282 EhcDev
->EndOfPeiNotifyList
.Guid
= &gEfiEndOfPeiSignalPpiGuid
;
1283 EhcDev
->EndOfPeiNotifyList
.Notify
= EhcEndOfPei
;
1285 PeiServicesNotifyPpi (&EhcDev
->EndOfPeiNotifyList
);
1294 @param EhcDev EHCI Device.
1296 @retval EFI_SUCCESS EHCI successfully initialized.
1297 @retval EFI_ABORTED EHCI was failed to be initialized.
1302 IN PEI_USB2_HC_DEV
*EhcDev
1307 EhcResetHC (EhcDev
, EHC_RESET_TIMEOUT
);
1309 Status
= EhcInitHC (EhcDev
);
1311 if (EFI_ERROR (Status
)) {