2 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
3 which is used to enable recovery function from USB Drivers.
5 Copyright (c) 2010 - 2013, 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 EHCI port state (change)
22 // to the UEFI protocol's port state (change).
24 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
25 {PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
26 {PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
27 {PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
28 {PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
29 {PORTSC_RESET
, USB_PORT_STAT_RESET
},
30 {PORTSC_POWER
, USB_PORT_STAT_POWER
},
31 {PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
34 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
35 {PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
36 {PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
37 {PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
41 Read Ehc Operation register.
43 @param Ehc The EHCI device.
44 @param Offset The operation register offset.
46 @retval the register content read.
51 IN PEI_USB2_HC_DEV
*Ehc
,
57 ASSERT (Ehc
->CapLen
!= 0);
59 Data
= MmioRead32 (Ehc
->UsbHostControllerBaseAddress
+ Ehc
->CapLen
+ Offset
);
65 Write the data to the EHCI operation register.
67 @param Ehc The EHCI device.
68 @param Offset EHCI operation register offset.
69 @param Data The data to write.
74 IN PEI_USB2_HC_DEV
*Ehc
,
80 ASSERT (Ehc
->CapLen
!= 0);
82 MmioWrite32(Ehc
->UsbHostControllerBaseAddress
+ Ehc
->CapLen
+ Offset
, Data
);
87 Set one bit of the operational register while keeping other bits.
89 @param Ehc The EHCI device.
90 @param Offset The offset of the operational register.
91 @param Bit The bit mask of the register to set.
96 IN PEI_USB2_HC_DEV
*Ehc
,
103 Data
= EhcReadOpReg (Ehc
, Offset
);
105 EhcWriteOpReg (Ehc
, Offset
, Data
);
109 Clear one bit of the operational register while keeping other bits.
111 @param Ehc The EHCI device.
112 @param Offset The offset of the operational register.
113 @param Bit The bit mask of the register to clear.
118 IN PEI_USB2_HC_DEV
*Ehc
,
125 Data
= EhcReadOpReg (Ehc
, Offset
);
127 EhcWriteOpReg (Ehc
, Offset
, Data
);
131 Wait the operation register's bit as specified by Bit
132 to become set (or clear).
134 @param Ehc The EHCI device.
135 @param Offset The offset of the operational register.
136 @param Bit The bit mask of the register to wait for.
137 @param WaitToSet Wait the bit to set or clear.
138 @param Timeout The time to wait before abort (in millisecond).
140 @retval EFI_SUCCESS The bit successfully changed by host controller.
141 @retval EFI_TIMEOUT The time out occurred.
146 IN PEI_USB2_HC_DEV
*Ehc
,
149 IN BOOLEAN WaitToSet
,
155 for (Index
= 0; Index
< Timeout
/ EHC_SYNC_POLL_INTERVAL
+ 1; Index
++) {
156 if (EHC_REG_BIT_IS_SET (Ehc
, Offset
, Bit
) == WaitToSet
) {
160 MicroSecondDelay (EHC_SYNC_POLL_INTERVAL
);
167 Read EHCI capability register.
169 @param Ehc The EHCI device.
170 @param Offset Capability register address.
172 @retval the register content read.
177 IN PEI_USB2_HC_DEV
*Ehc
,
183 Data
= MmioRead32(Ehc
->UsbHostControllerBaseAddress
+ Offset
);
189 Set door bell and wait it to be ACKed by host controller.
190 This function is used to synchronize with the hardware.
192 @param Ehc The EHCI device.
193 @param Timeout The time to wait before abort (in millisecond, ms).
195 @retval EFI_TIMEOUT Time out happened while waiting door bell to set.
196 @retval EFI_SUCCESS Synchronized with the hardware.
200 EhcSetAndWaitDoorBell (
201 IN PEI_USB2_HC_DEV
*Ehc
,
208 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_IAAD
);
210 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_IAA
, TRUE
, Timeout
);
213 // ACK the IAA bit in USBSTS register. Make sure other
214 // interrupt bits are not ACKed. These bits are WC (Write Clean).
216 Data
= EhcReadOpReg (Ehc
, EHC_USBSTS_OFFSET
);
217 Data
&= ~USBSTS_INTACK_MASK
;
220 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, Data
);
226 Clear all the interrutp status bits, these bits
229 @param Ehc The EHCI device.
234 IN PEI_USB2_HC_DEV
*Ehc
237 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_INTACK_MASK
);
241 Enable the periodic schedule then wait EHC to
244 @param Ehc The EHCI device.
245 @param Timeout The time to wait before abort (in millisecond, ms).
247 @retval EFI_TIMEOUT Time out happened while enabling periodic schedule.
248 @retval EFI_SUCCESS The periodical schedule is enabled.
252 EhcEnablePeriodSchd (
253 IN PEI_USB2_HC_DEV
*Ehc
,
259 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
261 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, TRUE
, Timeout
);
266 Enable asynchrounous schedule.
268 @param Ehc The EHCI device.
269 @param Timeout Time to wait before abort.
271 @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled.
272 @retval Others Failed to enable the asynchronous scheudle.
277 IN PEI_USB2_HC_DEV
*Ehc
,
283 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
285 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, TRUE
, Timeout
);
290 Check whether Ehc is halted.
292 @param Ehc The EHCI device.
294 @retval TRUE The controller is halted.
295 @retval FALSE The controller isn't halted.
300 IN PEI_USB2_HC_DEV
*Ehc
303 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
);
307 Check whether system error occurred.
309 @param Ehc The EHCI device.
311 @retval TRUE System error happened.
312 @retval FALSE No system error.
317 IN PEI_USB2_HC_DEV
*Ehc
320 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
);
324 Reset the host controller.
326 @param Ehc The EHCI device.
327 @param Timeout Time to wait before abort (in millisecond, ms).
329 @retval EFI_TIMEOUT The transfer failed due to time out.
330 @retval Others Failed to reset the host.
335 IN PEI_USB2_HC_DEV
*Ehc
,
342 // Host can only be reset when it is halt. If not so, halt it
344 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
345 Status
= EhcHaltHC (Ehc
, Timeout
);
347 if (EFI_ERROR (Status
)) {
352 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
);
353 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
, FALSE
, Timeout
);
358 Halt the host controller.
360 @param Ehc The EHCI device.
361 @param Timeout Time to wait before abort.
363 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
364 @retval EFI_SUCCESS The EHCI is halt.
369 IN PEI_USB2_HC_DEV
*Ehc
,
375 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
376 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, TRUE
, Timeout
);
383 @param Ehc The EHCI device.
384 @param Timeout Time to wait before abort.
386 @retval EFI_SUCCESS The EHCI is running.
387 @retval Others Failed to set the EHCI to run.
392 IN PEI_USB2_HC_DEV
*Ehc
,
398 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
399 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, FALSE
, Timeout
);
404 Power On All EHCI Ports.
406 @param Ehc The EHCI device.
411 IN PEI_USB2_HC_DEV
*Ehc
417 PortNumber
= (UINT8
)(Ehc
->HcStructParams
& HCSP_NPORTS
);
418 for (Index
= 0; Index
< PortNumber
; Index
++) {
419 EhcSetOpRegBit (Ehc
, EHC_PORT_STAT_OFFSET
+ 4 * Index
, PORTSC_POWER
);
424 Initialize the HC hardware.
425 EHCI spec lists the five things to do to initialize the hardware.
426 1. Program CTRLDSSEGMENT.
427 2. Set USBINTR to enable interrupts.
428 3. Set periodic list base.
429 4. Set USBCMD, interrupt threshold, frame list size etc.
430 5. Write 1 to CONFIGFLAG to route all ports to EHCI.
432 @param Ehc The EHCI device.
434 @retval EFI_SUCCESS The EHCI has come out of halt state.
435 @retval EFI_TIMEOUT Time out happened.
440 IN PEI_USB2_HC_DEV
*Ehc
444 EFI_PHYSICAL_ADDRESS TempPtr
;
447 ASSERT (EhcIsHalt (Ehc
));
450 // Allocate the periodic frame and associated memeory
451 // management facilities if not already done.
453 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
)) {
476 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
478 EhcWriteOpReg (Ehc
, EHC_CTRLDSSEG_OFFSET
, Ehc
->High32bitAddr
);
481 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
483 EhcWriteOpReg (Ehc
, EHC_USBINTR_OFFSET
, 0);
486 // 3. Program periodic frame list, already done in EhcInitSched
487 // 4. Start the Host Controller
489 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
492 // 5. Set all ports routing to EHC
494 EhcSetOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
497 // Wait roothub port power stable
499 MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL
);
501 Status
= EhcEnablePeriodSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
503 if (EFI_ERROR (Status
)) {
507 Status
= EhcEnableAsyncSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
509 if (EFI_ERROR (Status
)) {
517 Submits bulk transfer to a bulk endpoint of a USB device.
519 @param PeiServices The pointer of EFI_PEI_SERVICES.
520 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
521 @param DeviceAddress Target device address.
522 @param EndPointAddress Endpoint number and its direction in bit 7.
523 @param DeviceSpeed Device speed, Low speed device doesn't support
525 @param MaximumPacketLength Maximum packet size the endpoint is capable of
526 sending or receiving.
527 @param Data Array of pointers to the buffers of data to transmit
528 from or receive into.
529 @param DataLength The lenght of the data buffer.
530 @param DataToggle On input, the initial data toggle for the transfer;
531 On output, it is updated to to next data toggle to use of
532 the subsequent bulk transfer.
533 @param TimeOut Indicates the maximum time, in millisecond, which the
534 transfer is allowed to complete.
535 If Timeout is 0, then the caller must wait for the function
536 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
537 @param Translator A pointr to the transaction translator data.
538 @param TransferResult A pointer to the detailed result information of the
541 @retval EFI_SUCCESS The transfer was completed successfully.
542 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
543 @retval EFI_INVALID_PARAMETER Parameters are invalid.
544 @retval EFI_TIMEOUT The transfer failed due to timeout.
545 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
551 IN EFI_PEI_SERVICES
**PeiServices
,
552 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
553 IN UINT8 DeviceAddress
,
554 IN UINT8 EndPointAddress
,
555 IN UINT8 DeviceSpeed
,
556 IN UINTN MaximumPacketLength
,
557 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
558 IN OUT UINTN
*DataLength
,
559 IN OUT UINT8
*DataToggle
,
561 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
562 OUT UINT32
*TransferResult
565 PEI_USB2_HC_DEV
*Ehc
;
570 // Validate the parameters
572 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
573 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
574 return EFI_INVALID_PARAMETER
;
577 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
578 return EFI_INVALID_PARAMETER
;
581 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
582 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
583 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
584 return EFI_INVALID_PARAMETER
;
587 Ehc
=PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This
);
588 *TransferResult
= EFI_USB_ERR_SYSTEM
;
589 Status
= EFI_DEVICE_ERROR
;
591 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
592 EhcAckAllInterrupt (Ehc
);
596 EhcAckAllInterrupt (Ehc
);
599 // Create a new URB, insert it into the asynchronous
600 // schedule list, then poll the execution status.
620 Status
= EFI_OUT_OF_RESOURCES
;
624 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
625 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
626 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
628 *TransferResult
= Urb
->Result
;
629 *DataLength
= Urb
->Completed
;
630 *DataToggle
= Urb
->DataToggle
;
632 if (*TransferResult
== EFI_USB_NOERROR
) {
633 Status
= EFI_SUCCESS
;
636 EhcAckAllInterrupt (Ehc
);
637 EhcFreeUrb (Ehc
, Urb
);
644 Retrieves the number of root hub ports.
646 @param[in] PeiServices The pointer to the PEI Services Table.
647 @param[in] This The pointer to this instance of the
648 PEI_USB2_HOST_CONTROLLER_PPI.
649 @param[out] PortNumber The pointer to the number of the root hub ports.
651 @retval EFI_SUCCESS The port number was retrieved successfully.
652 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
657 EhcGetRootHubPortNumber (
658 IN EFI_PEI_SERVICES
**PeiServices
,
659 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
660 OUT UINT8
*PortNumber
664 PEI_USB2_HC_DEV
*EhcDev
;
665 EhcDev
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
667 if (PortNumber
== NULL
) {
668 return EFI_INVALID_PARAMETER
;
671 *PortNumber
= (UINT8
)(EhcDev
->HcStructParams
& HCSP_NPORTS
);
677 Clears a feature for the specified root hub port.
679 @param PeiServices The pointer of EFI_PEI_SERVICES.
680 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
681 @param PortNumber Specifies the root hub port whose feature
682 is requested to be cleared.
683 @param PortFeature Indicates the feature selector associated with the
684 feature clear request.
686 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
687 for the USB root hub port specified by PortNumber.
688 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
693 EhcClearRootHubPortFeature (
694 IN EFI_PEI_SERVICES
**PeiServices
,
695 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
697 IN EFI_USB_PORT_FEATURE PortFeature
700 PEI_USB2_HC_DEV
*Ehc
;
706 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
707 Status
= EFI_SUCCESS
;
709 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
711 if (PortNumber
>= TotalPort
) {
712 Status
= EFI_INVALID_PARAMETER
;
716 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
717 State
= EhcReadOpReg (Ehc
, Offset
);
718 State
&= ~PORTSC_CHANGE_MASK
;
720 switch (PortFeature
) {
721 case EfiUsbPortEnable
:
723 // Clear PORT_ENABLE feature means disable port.
725 State
&= ~PORTSC_ENABLED
;
726 EhcWriteOpReg (Ehc
, Offset
, State
);
729 case EfiUsbPortSuspend
:
731 // A write of zero to this bit is ignored by the host
732 // controller. The host controller will unconditionally
733 // set this bit to a zero when:
734 // 1. software sets the Forct Port Resume bit to a zero from a one.
735 // 2. software sets the Port Reset bit to a one frome a zero.
737 State
&= ~PORSTSC_RESUME
;
738 EhcWriteOpReg (Ehc
, Offset
, State
);
741 case EfiUsbPortReset
:
743 // Clear PORT_RESET means clear the reset signal.
745 State
&= ~PORTSC_RESET
;
746 EhcWriteOpReg (Ehc
, Offset
, State
);
749 case EfiUsbPortOwner
:
751 // Clear port owner means this port owned by EHC
753 State
&= ~PORTSC_OWNER
;
754 EhcWriteOpReg (Ehc
, Offset
, State
);
757 case EfiUsbPortConnectChange
:
759 // Clear connect status change
761 State
|= PORTSC_CONN_CHANGE
;
762 EhcWriteOpReg (Ehc
, Offset
, State
);
765 case EfiUsbPortEnableChange
:
767 // Clear enable status change
769 State
|= PORTSC_ENABLE_CHANGE
;
770 EhcWriteOpReg (Ehc
, Offset
, State
);
773 case EfiUsbPortOverCurrentChange
:
775 // Clear PortOverCurrent change
777 State
|= PORTSC_OVERCUR_CHANGE
;
778 EhcWriteOpReg (Ehc
, Offset
, State
);
781 case EfiUsbPortPower
:
782 case EfiUsbPortSuspendChange
:
783 case EfiUsbPortResetChange
:
785 // Not supported or not related operation
790 Status
= EFI_INVALID_PARAMETER
;
799 Sets a feature for the specified root hub port.
801 @param PeiServices The pointer of EFI_PEI_SERVICES
802 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI
803 @param PortNumber Root hub port to set.
804 @param PortFeature Feature to set.
806 @retval EFI_SUCCESS The feature specified by PortFeature was set.
807 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
808 @retval EFI_TIMEOUT The time out occurred.
813 EhcSetRootHubPortFeature (
814 IN EFI_PEI_SERVICES
**PeiServices
,
815 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
817 IN EFI_USB_PORT_FEATURE PortFeature
820 PEI_USB2_HC_DEV
*Ehc
;
826 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
827 Status
= EFI_SUCCESS
;
829 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
831 if (PortNumber
>= TotalPort
) {
832 Status
= EFI_INVALID_PARAMETER
;
836 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
837 State
= EhcReadOpReg (Ehc
, Offset
);
840 // Mask off the port status change bits, these bits are
843 State
&= ~PORTSC_CHANGE_MASK
;
845 switch (PortFeature
) {
846 case EfiUsbPortEnable
:
848 // Sofeware can't set this bit, Port can only be enable by
849 // EHCI as a part of the reset and enable
851 State
|= PORTSC_ENABLED
;
852 EhcWriteOpReg (Ehc
, Offset
, State
);
855 case EfiUsbPortSuspend
:
856 State
|= PORTSC_SUSPEND
;
857 EhcWriteOpReg (Ehc
, Offset
, State
);
860 case EfiUsbPortReset
:
862 // Make sure Host Controller not halt before reset it
864 if (EhcIsHalt (Ehc
)) {
865 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
867 if (EFI_ERROR (Status
)) {
873 // Set one to PortReset bit must also set zero to PortEnable bit
875 State
|= PORTSC_RESET
;
876 State
&= ~PORTSC_ENABLED
;
877 EhcWriteOpReg (Ehc
, Offset
, State
);
880 case EfiUsbPortPower
:
882 // Not supported, ignore the operation
884 Status
= EFI_SUCCESS
;
887 case EfiUsbPortOwner
:
888 State
|= PORTSC_OWNER
;
889 EhcWriteOpReg (Ehc
, Offset
, State
);
893 Status
= EFI_INVALID_PARAMETER
;
901 Retrieves the current status of a USB root hub port.
903 @param PeiServices The pointer of EFI_PEI_SERVICES.
904 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
905 @param PortNumber The root hub port to retrieve the state from.
906 @param PortStatus Variable to receive the port state.
908 @retval EFI_SUCCESS The status of the USB root hub port specified.
909 by PortNumber was returned in PortStatus.
910 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
915 EhcGetRootHubPortStatus (
916 IN EFI_PEI_SERVICES
**PeiServices
,
917 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
919 OUT EFI_USB_PORT_STATUS
*PortStatus
922 PEI_USB2_HC_DEV
*Ehc
;
930 if (PortStatus
== NULL
) {
931 return EFI_INVALID_PARAMETER
;
934 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This
);
935 Status
= EFI_SUCCESS
;
937 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
939 if (PortNumber
>= TotalPort
) {
940 Status
= EFI_INVALID_PARAMETER
;
944 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
945 PortStatus
->PortStatus
= 0;
946 PortStatus
->PortChangeStatus
= 0;
948 State
= EhcReadOpReg (Ehc
, Offset
);
951 // Identify device speed. If in K state, it is low speed.
952 // If the port is enabled after reset, the device is of
953 // high speed. The USB bus driver should retrieve the actual
954 // port speed after reset.
956 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
957 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
959 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
960 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
964 // Convert the EHCI port/port change state to UEFI status
966 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
968 for (Index
= 0; Index
< MapSize
; Index
++) {
969 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
970 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
974 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
976 for (Index
= 0; Index
< MapSize
; Index
++) {
977 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
978 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
987 Submits control transfer to a target USB device.
989 @param PeiServices The pointer of EFI_PEI_SERVICES.
990 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
991 @param DeviceAddress The target device address.
992 @param DeviceSpeed Target device speed.
993 @param MaximumPacketLength Maximum packet size the default control transfer
994 endpoint is capable of sending or receiving.
995 @param Request USB device request to send.
996 @param TransferDirection Specifies the data direction for the data stage.
997 @param Data Data buffer to be transmitted or received from USB device.
998 @param DataLength The size (in bytes) of the data buffer.
999 @param TimeOut Indicates the maximum timeout, in millisecond.
1000 If Timeout is 0, then the caller must wait for the function
1001 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
1002 @param Translator Transaction translator to be used by this device.
1003 @param TransferResult Return the result of this control transfer.
1005 @retval EFI_SUCCESS Transfer was completed successfully.
1006 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
1007 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1008 @retval EFI_TIMEOUT Transfer failed due to timeout.
1009 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
1014 EhcControlTransfer (
1015 IN EFI_PEI_SERVICES
**PeiServices
,
1016 IN PEI_USB2_HOST_CONTROLLER_PPI
*This
,
1017 IN UINT8 DeviceAddress
,
1018 IN UINT8 DeviceSpeed
,
1019 IN UINTN MaximumPacketLength
,
1020 IN EFI_USB_DEVICE_REQUEST
*Request
,
1021 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1023 IN OUT UINTN
*DataLength
,
1025 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1026 OUT UINT32
*TransferResult
1029 PEI_USB2_HC_DEV
*Ehc
;
1035 // Validate parameters
1037 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
1038 return EFI_INVALID_PARAMETER
;
1041 if ((TransferDirection
!= EfiUsbDataIn
) &&
1042 (TransferDirection
!= EfiUsbDataOut
) &&
1043 (TransferDirection
!= EfiUsbNoData
)) {
1044 return EFI_INVALID_PARAMETER
;
1047 if ((TransferDirection
== EfiUsbNoData
) &&
1048 ((Data
!= NULL
) || (*DataLength
!= 0))) {
1049 return EFI_INVALID_PARAMETER
;
1052 if ((TransferDirection
!= EfiUsbNoData
) &&
1053 ((Data
== NULL
) || (*DataLength
== 0))) {
1054 return EFI_INVALID_PARAMETER
;
1057 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
1058 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
1059 return EFI_INVALID_PARAMETER
;
1063 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
1064 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1065 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
1066 return EFI_INVALID_PARAMETER
;
1069 Ehc
= PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This
);
1071 Status
= EFI_DEVICE_ERROR
;
1072 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1074 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1075 EhcAckAllInterrupt (Ehc
);
1079 EhcAckAllInterrupt (Ehc
);
1082 // Create a new URB, insert it into the asynchronous
1083 // schedule list, then poll the execution status.
1086 // Encode the direction in address, although default control
1087 // endpoint is bidirectional. EhcCreateUrb expects this
1088 // combination of Ep addr and its direction.
1090 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
1091 Urb
= EhcCreateUrb (
1097 MaximumPacketLength
,
1109 Status
= EFI_OUT_OF_RESOURCES
;
1113 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
1114 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1115 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
1118 // Get the status from URB. The result is updated in EhcCheckUrbResult
1119 // which is called by EhcExecTransfer
1121 *TransferResult
= Urb
->Result
;
1122 *DataLength
= Urb
->Completed
;
1124 if (*TransferResult
== EFI_USB_NOERROR
) {
1125 Status
= EFI_SUCCESS
;
1128 EhcAckAllInterrupt (Ehc
);
1129 EhcFreeUrb (Ehc
, Urb
);
1136 @param FileHandle Handle of the file being invoked.
1137 @param PeiServices Describes the list of possible PEI Services.
1139 @retval EFI_SUCCESS PPI successfully installed.
1145 IN EFI_PEI_FILE_HANDLE FileHandle
,
1146 IN CONST EFI_PEI_SERVICES
**PeiServices
1149 PEI_USB_CONTROLLER_PPI
*ChipSetUsbControllerPpi
;
1152 UINTN ControllerType
;
1155 PEI_USB2_HC_DEV
*EhcDev
;
1156 EFI_PHYSICAL_ADDRESS TempPtr
;
1159 // Shadow this PEIM to run from memory
1161 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1165 Status
= PeiServicesLocatePpi (
1166 &gPeiUsbControllerPpiGuid
,
1169 (VOID
**) &ChipSetUsbControllerPpi
1171 if (EFI_ERROR (Status
)) {
1172 return EFI_UNSUPPORTED
;
1177 Status
= ChipSetUsbControllerPpi
->GetUsbController (
1178 (EFI_PEI_SERVICES
**) PeiServices
,
1179 ChipSetUsbControllerPpi
,
1185 // When status is error, meant no controller is found
1187 if (EFI_ERROR (Status
)) {
1192 // This PEIM is for UHC type controller.
1194 if (ControllerType
!= PEI_EHCI_CONTROLLER
) {
1199 MemPages
= sizeof (PEI_USB2_HC_DEV
) / PAGESIZE
+ 1;
1200 Status
= PeiServicesAllocatePages (
1201 EfiBootServicesCode
,
1205 if (EFI_ERROR (Status
)) {
1206 return EFI_OUT_OF_RESOURCES
;
1209 ZeroMem((VOID
*)(UINTN
)TempPtr
, MemPages
*PAGESIZE
);
1210 EhcDev
= (PEI_USB2_HC_DEV
*) ((UINTN
) TempPtr
);
1212 EhcDev
->Signature
= USB2_HC_DEV_SIGNATURE
;
1214 EhcDev
->UsbHostControllerBaseAddress
= (UINT32
) BaseAddress
;
1217 EhcDev
->HcStructParams
= EhcReadCapRegister (EhcDev
, EHC_HCSPARAMS_OFFSET
);
1218 EhcDev
->HcCapParams
= EhcReadCapRegister (EhcDev
, EHC_HCCPARAMS_OFFSET
);
1219 EhcDev
->CapLen
= EhcReadCapRegister (EhcDev
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1221 // Initialize Uhc's hardware
1223 Status
= InitializeUsbHC (EhcDev
);
1224 if (EFI_ERROR (Status
)) {
1228 EhcDev
->Usb2HostControllerPpi
.ControlTransfer
= EhcControlTransfer
;
1229 EhcDev
->Usb2HostControllerPpi
.BulkTransfer
= EhcBulkTransfer
;
1230 EhcDev
->Usb2HostControllerPpi
.GetRootHubPortNumber
= EhcGetRootHubPortNumber
;
1231 EhcDev
->Usb2HostControllerPpi
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1232 EhcDev
->Usb2HostControllerPpi
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1233 EhcDev
->Usb2HostControllerPpi
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1235 EhcDev
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1236 EhcDev
->PpiDescriptor
.Guid
= &gPeiUsb2HostControllerPpiGuid
;
1237 EhcDev
->PpiDescriptor
.Ppi
= &EhcDev
->Usb2HostControllerPpi
;
1239 Status
= PeiServicesInstallPpi (&EhcDev
->PpiDescriptor
);
1240 if (EFI_ERROR (Status
)) {
1252 @param EhcDev EHCI Device.
1254 @retval EFI_SUCCESS EHCI successfully initialized.
1255 @retval EFI_ABORTED EHCI was failed to be initialized.
1260 IN PEI_USB2_HC_DEV
*EhcDev
1266 EhcResetHC (EhcDev
, EHC_RESET_TIMEOUT
);
1268 Status
= EhcInitHC (EhcDev
);
1270 if (EFI_ERROR (Status
)) {