2 The Ehci controller driver.
4 EhciDxe driver is responsible for managing the behavior of EHCI controller.
5 It implements the interfaces of monitoring the status of all ports and transferring
6 Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.
8 Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
9 to the EHCI controller before a UHCI or OHCI driver attaches to the companion UHCI or
10 OHCI controller. This way avoids the control transfer on a shared port between EHCI
11 and companion host controller when UHCI or OHCI gets attached earlier than EHCI and a
12 USB 2.0 device inserts.
14 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
15 SPDX-License-Identifier: BSD-2-Clause-Patent
23 // Two arrays used to translate the EHCI port state (change)
24 // to the UEFI protocol's port state (change).
26 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
27 {PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
28 {PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
29 {PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
30 {PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
31 {PORTSC_RESET
, USB_PORT_STAT_RESET
},
32 {PORTSC_POWER
, USB_PORT_STAT_POWER
},
33 {PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
36 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
37 {PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
38 {PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
39 {PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
42 EFI_DRIVER_BINDING_PROTOCOL
43 gEhciDriverBinding
= {
44 EhcDriverBindingSupported
,
45 EhcDriverBindingStart
,
53 Retrieves the capability of root hub ports.
55 @param This This EFI_USB_HC_PROTOCOL instance.
56 @param MaxSpeed Max speed supported by the controller.
57 @param PortNumber Number of the root hub ports.
58 @param Is64BitCapable Whether the controller supports 64-bit memory
61 @retval EFI_SUCCESS Host controller capability were retrieved successfully.
62 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
68 IN EFI_USB2_HC_PROTOCOL
*This
,
70 OUT UINT8
*PortNumber
,
71 OUT UINT8
*Is64BitCapable
77 if ((MaxSpeed
== NULL
) || (PortNumber
== NULL
) || (Is64BitCapable
== NULL
)) {
78 return EFI_INVALID_PARAMETER
;
81 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
82 Ehc
= EHC_FROM_THIS (This
);
84 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
85 *PortNumber
= (UINT8
) (Ehc
->HcStructParams
& HCSP_NPORTS
);
86 *Is64BitCapable
= (UINT8
) Ehc
->Support64BitDma
;
88 DEBUG ((EFI_D_INFO
, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber
, *Is64BitCapable
));
90 gBS
->RestoreTPL (OldTpl
);
96 Provides software reset for the USB host controller.
98 @param This This EFI_USB2_HC_PROTOCOL instance.
99 @param Attributes A bit mask of the reset operation to perform.
101 @retval EFI_SUCCESS The reset operation succeeded.
102 @retval EFI_INVALID_PARAMETER Attributes is not valid.
103 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
104 not currently supported by the host controller.
105 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
111 IN EFI_USB2_HC_PROTOCOL
*This
,
119 Ehc
= EHC_FROM_THIS (This
);
121 if (Ehc
->DevicePath
!= NULL
) {
123 // Report Status Code to indicate reset happens
125 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
127 (EFI_IO_BUS_USB
| EFI_IOB_PC_RESET
),
132 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
134 switch (Attributes
) {
135 case EFI_USB_HC_RESET_GLOBAL
:
137 // Flow through, same behavior as Host Controller Reset
139 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
141 // Host Controller must be Halt when Reset it
143 if (EhcIsDebugPortInUse (Ehc
, NULL
)) {
144 Status
= EFI_SUCCESS
;
148 if (!EhcIsHalt (Ehc
)) {
149 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
151 if (EFI_ERROR (Status
)) {
152 Status
= EFI_DEVICE_ERROR
;
158 // Clean up the asynchronous transfers, currently only
159 // interrupt supports asynchronous operation.
161 EhciDelAllAsyncIntTransfers (Ehc
);
162 EhcAckAllInterrupt (Ehc
);
165 Status
= EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
167 if (EFI_ERROR (Status
)) {
171 Status
= EhcInitHC (Ehc
);
174 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
:
175 case EFI_USB_HC_RESET_HOST_WITH_DEBUG
:
176 Status
= EFI_UNSUPPORTED
;
180 Status
= EFI_INVALID_PARAMETER
;
184 DEBUG ((EFI_D_INFO
, "EhcReset: exit status %r\n", Status
));
185 gBS
->RestoreTPL (OldTpl
);
191 Retrieve the current state of the USB host controller.
193 @param This This EFI_USB2_HC_PROTOCOL instance.
194 @param State Variable to return the current host controller
197 @retval EFI_SUCCESS Host controller state was returned in State.
198 @retval EFI_INVALID_PARAMETER State is NULL.
199 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
200 retrieve the host controller's current state.
206 IN EFI_USB2_HC_PROTOCOL
*This
,
207 OUT EFI_USB_HC_STATE
*State
214 return EFI_INVALID_PARAMETER
;
217 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
218 Ehc
= EHC_FROM_THIS (This
);
220 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
221 *State
= EfiUsbHcStateHalt
;
223 *State
= EfiUsbHcStateOperational
;
226 gBS
->RestoreTPL (OldTpl
);
228 DEBUG ((EFI_D_INFO
, "EhcGetState: current state %d\n", *State
));
234 Sets the USB host controller to a specific state.
236 @param This This EFI_USB2_HC_PROTOCOL instance.
237 @param State The state of the host controller that will be set.
239 @retval EFI_SUCCESS The USB host controller was successfully placed
240 in the state specified by State.
241 @retval EFI_INVALID_PARAMETER State is invalid.
242 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
248 IN EFI_USB2_HC_PROTOCOL
*This
,
249 IN EFI_USB_HC_STATE State
255 EFI_USB_HC_STATE CurState
;
257 Status
= EhcGetState (This
, &CurState
);
259 if (EFI_ERROR (Status
)) {
260 return EFI_DEVICE_ERROR
;
263 if (CurState
== State
) {
267 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
268 Ehc
= EHC_FROM_THIS (This
);
271 case EfiUsbHcStateHalt
:
272 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
275 case EfiUsbHcStateOperational
:
276 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
)) {
277 Status
= EFI_DEVICE_ERROR
;
282 // Software must not write a one to this field unless the host controller
283 // is in the Halted state. Doing so will yield undefined results.
284 // refers to Spec[EHCI1.0-2.3.1]
286 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
287 Status
= EFI_DEVICE_ERROR
;
291 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
294 case EfiUsbHcStateSuspend
:
295 Status
= EFI_UNSUPPORTED
;
299 Status
= EFI_INVALID_PARAMETER
;
302 DEBUG ((EFI_D_INFO
, "EhcSetState: exit status %r\n", Status
));
303 gBS
->RestoreTPL (OldTpl
);
309 Retrieves the current status of a USB root hub port.
311 @param This This EFI_USB2_HC_PROTOCOL instance.
312 @param PortNumber The root hub port to retrieve the state from.
313 This value is zero-based.
314 @param PortStatus Variable to receive the port state.
316 @retval EFI_SUCCESS The status of the USB root hub port specified.
317 by PortNumber was returned in PortStatus.
318 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
319 @retval EFI_DEVICE_ERROR Can't read register.
324 EhcGetRootHubPortStatus (
325 IN EFI_USB2_HC_PROTOCOL
*This
,
327 OUT EFI_USB_PORT_STATUS
*PortStatus
339 if (PortStatus
== NULL
) {
340 return EFI_INVALID_PARAMETER
;
343 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
345 Ehc
= EHC_FROM_THIS (This
);
346 Status
= EFI_SUCCESS
;
348 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
350 if (PortNumber
>= TotalPort
) {
351 Status
= EFI_INVALID_PARAMETER
;
355 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
356 PortStatus
->PortStatus
= 0;
357 PortStatus
->PortChangeStatus
= 0;
359 if (EhcIsDebugPortInUse (Ehc
, &PortNumber
)) {
363 State
= EhcReadOpReg (Ehc
, Offset
);
366 // Identify device speed. If in K state, it is low speed.
367 // If the port is enabled after reset, the device is of
368 // high speed. The USB bus driver should retrieve the actual
369 // port speed after reset.
371 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
372 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
374 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
375 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
379 // Convert the EHCI port/port change state to UEFI status
381 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
383 for (Index
= 0; Index
< MapSize
; Index
++) {
384 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
385 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
389 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
391 for (Index
= 0; Index
< MapSize
; Index
++) {
392 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
393 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
398 gBS
->RestoreTPL (OldTpl
);
404 Sets a feature for the specified root hub port.
406 @param This This EFI_USB2_HC_PROTOCOL instance.
407 @param PortNumber Root hub port to set.
408 @param PortFeature Feature to set.
410 @retval EFI_SUCCESS The feature specified by PortFeature was set.
411 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
412 @retval EFI_DEVICE_ERROR Can't read register.
417 EhcSetRootHubPortFeature (
418 IN EFI_USB2_HC_PROTOCOL
*This
,
420 IN EFI_USB_PORT_FEATURE PortFeature
430 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
431 Ehc
= EHC_FROM_THIS (This
);
432 Status
= EFI_SUCCESS
;
434 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
436 if (PortNumber
>= TotalPort
) {
437 Status
= EFI_INVALID_PARAMETER
;
441 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
442 State
= EhcReadOpReg (Ehc
, Offset
);
445 // Mask off the port status change bits, these bits are
448 State
&= ~PORTSC_CHANGE_MASK
;
450 switch (PortFeature
) {
451 case EfiUsbPortEnable
:
453 // Sofeware can't set this bit, Port can only be enable by
454 // EHCI as a part of the reset and enable
456 State
|= PORTSC_ENABLED
;
457 EhcWriteOpReg (Ehc
, Offset
, State
);
460 case EfiUsbPortSuspend
:
461 State
|= PORTSC_SUSPEND
;
462 EhcWriteOpReg (Ehc
, Offset
, State
);
465 case EfiUsbPortReset
:
467 // Make sure Host Controller not halt before reset it
469 if (EhcIsHalt (Ehc
)) {
470 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
472 if (EFI_ERROR (Status
)) {
473 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status
));
479 // Set one to PortReset bit must also set zero to PortEnable bit
481 State
|= PORTSC_RESET
;
482 State
&= ~PORTSC_ENABLED
;
483 EhcWriteOpReg (Ehc
, Offset
, State
);
486 case EfiUsbPortPower
:
488 // Set port power bit when PPC is 1
490 if ((Ehc
->HcCapParams
& HCSP_PPC
) == HCSP_PPC
) {
491 State
|= PORTSC_POWER
;
492 EhcWriteOpReg (Ehc
, Offset
, State
);
496 case EfiUsbPortOwner
:
497 State
|= PORTSC_OWNER
;
498 EhcWriteOpReg (Ehc
, Offset
, State
);
502 Status
= EFI_INVALID_PARAMETER
;
506 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature: exit status %r\n", Status
));
508 gBS
->RestoreTPL (OldTpl
);
514 Clears a feature for the specified root hub port.
516 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
517 @param PortNumber Specifies the root hub port whose feature is
518 requested to be cleared.
519 @param PortFeature Indicates the feature selector associated with the
520 feature clear request.
522 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
523 for the USB root hub port specified by PortNumber.
524 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
525 @retval EFI_DEVICE_ERROR Can't read register.
530 EhcClearRootHubPortFeature (
531 IN EFI_USB2_HC_PROTOCOL
*This
,
533 IN EFI_USB_PORT_FEATURE PortFeature
543 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
544 Ehc
= EHC_FROM_THIS (This
);
545 Status
= EFI_SUCCESS
;
547 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
549 if (PortNumber
>= TotalPort
) {
550 Status
= EFI_INVALID_PARAMETER
;
554 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
555 State
= EhcReadOpReg (Ehc
, Offset
);
556 State
&= ~PORTSC_CHANGE_MASK
;
558 switch (PortFeature
) {
559 case EfiUsbPortEnable
:
561 // Clear PORT_ENABLE feature means disable port.
563 State
&= ~PORTSC_ENABLED
;
564 EhcWriteOpReg (Ehc
, Offset
, State
);
567 case EfiUsbPortSuspend
:
569 // A write of zero to this bit is ignored by the host
570 // controller. The host controller will unconditionally
571 // set this bit to a zero when:
572 // 1. software sets the Forct Port Resume bit to a zero from a one.
573 // 2. software sets the Port Reset bit to a one frome a zero.
575 State
&= ~PORSTSC_RESUME
;
576 EhcWriteOpReg (Ehc
, Offset
, State
);
579 case EfiUsbPortReset
:
581 // Clear PORT_RESET means clear the reset signal.
583 State
&= ~PORTSC_RESET
;
584 EhcWriteOpReg (Ehc
, Offset
, State
);
587 case EfiUsbPortOwner
:
589 // Clear port owner means this port owned by EHC
591 State
&= ~PORTSC_OWNER
;
592 EhcWriteOpReg (Ehc
, Offset
, State
);
595 case EfiUsbPortConnectChange
:
597 // Clear connect status change
599 State
|= PORTSC_CONN_CHANGE
;
600 EhcWriteOpReg (Ehc
, Offset
, State
);
603 case EfiUsbPortEnableChange
:
605 // Clear enable status change
607 State
|= PORTSC_ENABLE_CHANGE
;
608 EhcWriteOpReg (Ehc
, Offset
, State
);
611 case EfiUsbPortOverCurrentChange
:
613 // Clear PortOverCurrent change
615 State
|= PORTSC_OVERCUR_CHANGE
;
616 EhcWriteOpReg (Ehc
, Offset
, State
);
619 case EfiUsbPortPower
:
621 // Clear port power bit when PPC is 1
623 if ((Ehc
->HcCapParams
& HCSP_PPC
) == HCSP_PPC
) {
624 State
&= ~PORTSC_POWER
;
625 EhcWriteOpReg (Ehc
, Offset
, State
);
628 case EfiUsbPortSuspendChange
:
629 case EfiUsbPortResetChange
:
631 // Not supported or not related operation
636 Status
= EFI_INVALID_PARAMETER
;
641 DEBUG ((EFI_D_INFO
, "EhcClearRootHubPortFeature: exit status %r\n", Status
));
642 gBS
->RestoreTPL (OldTpl
);
648 Submits control transfer to a target USB device.
650 @param This This EFI_USB2_HC_PROTOCOL instance.
651 @param DeviceAddress The target device address.
652 @param DeviceSpeed Target device speed.
653 @param MaximumPacketLength Maximum packet size the default control transfer
654 endpoint is capable of sending or receiving.
655 @param Request USB device request to send.
656 @param TransferDirection Specifies the data direction for the data stage
657 @param Data Data buffer to be transmitted or received from USB
659 @param DataLength The size (in bytes) of the data buffer.
660 @param TimeOut Indicates the maximum timeout, in millisecond.
661 @param Translator Transaction translator to be used by this device.
662 @param TransferResult Return the result of this control transfer.
664 @retval EFI_SUCCESS Transfer was completed successfully.
665 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
666 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
667 @retval EFI_TIMEOUT Transfer failed due to timeout.
668 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
674 IN EFI_USB2_HC_PROTOCOL
*This
,
675 IN UINT8 DeviceAddress
,
676 IN UINT8 DeviceSpeed
,
677 IN UINTN MaximumPacketLength
,
678 IN EFI_USB_DEVICE_REQUEST
*Request
,
679 IN EFI_USB_DATA_DIRECTION TransferDirection
,
681 IN OUT UINTN
*DataLength
,
683 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
684 OUT UINT32
*TransferResult
694 // Validate parameters
696 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
697 return EFI_INVALID_PARAMETER
;
700 if ((TransferDirection
!= EfiUsbDataIn
) &&
701 (TransferDirection
!= EfiUsbDataOut
) &&
702 (TransferDirection
!= EfiUsbNoData
)) {
703 return EFI_INVALID_PARAMETER
;
706 if ((TransferDirection
== EfiUsbNoData
) &&
707 ((Data
!= NULL
) || (*DataLength
!= 0))) {
708 return EFI_INVALID_PARAMETER
;
711 if ((TransferDirection
!= EfiUsbNoData
) &&
712 ((Data
== NULL
) || (*DataLength
== 0))) {
713 return EFI_INVALID_PARAMETER
;
716 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
717 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
718 return EFI_INVALID_PARAMETER
;
721 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
722 return EFI_INVALID_PARAMETER
;
725 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
726 Ehc
= EHC_FROM_THIS (This
);
728 Status
= EFI_DEVICE_ERROR
;
729 *TransferResult
= EFI_USB_ERR_SYSTEM
;
731 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
732 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: HC halted at entrance\n"));
734 EhcAckAllInterrupt (Ehc
);
738 EhcAckAllInterrupt (Ehc
);
741 // Create a new URB, insert it into the asynchronous
742 // schedule list, then poll the execution status.
745 // Encode the direction in address, although default control
746 // endpoint is bidirectional. EhcCreateUrb expects this
747 // combination of Ep addr and its direction.
749 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
768 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: failed to create URB"));
770 Status
= EFI_OUT_OF_RESOURCES
;
774 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
775 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
776 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
779 // Get the status from URB. The result is updated in EhcCheckUrbResult
780 // which is called by EhcExecTransfer
782 *TransferResult
= Urb
->Result
;
783 *DataLength
= Urb
->Completed
;
785 if (*TransferResult
== EFI_USB_NOERROR
) {
786 Status
= EFI_SUCCESS
;
789 EhcAckAllInterrupt (Ehc
);
790 EhcFreeUrb (Ehc
, Urb
);
793 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
794 gBS
->RestoreTPL (OldTpl
);
796 if (EFI_ERROR (Status
)) {
797 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
805 Submits bulk transfer to a bulk endpoint of a USB device.
807 @param This This EFI_USB2_HC_PROTOCOL instance.
808 @param DeviceAddress Target device address.
809 @param EndPointAddress Endpoint number and its direction in bit 7.
810 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
812 @param MaximumPacketLength Maximum packet size the endpoint is capable of
813 sending or receiving.
814 @param DataBuffersNumber Number of data buffers prepared for the transfer.
815 @param Data Array of pointers to the buffers of data to transmit
816 from or receive into.
817 @param DataLength The lenght of the data buffer.
818 @param DataToggle On input, the initial data toggle for the transfer;
819 On output, it is updated to to next data toggle to
820 use of the subsequent bulk transfer.
821 @param TimeOut Indicates the maximum time, in millisecond, which
822 the transfer is allowed to complete.
823 @param Translator A pointr to the transaction translator data.
824 @param TransferResult A pointer to the detailed result information of the
827 @retval EFI_SUCCESS The transfer was completed successfully.
828 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
829 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
830 @retval EFI_TIMEOUT The transfer failed due to timeout.
831 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
837 IN EFI_USB2_HC_PROTOCOL
*This
,
838 IN UINT8 DeviceAddress
,
839 IN UINT8 EndPointAddress
,
840 IN UINT8 DeviceSpeed
,
841 IN UINTN MaximumPacketLength
,
842 IN UINT8 DataBuffersNumber
,
843 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
844 IN OUT UINTN
*DataLength
,
845 IN OUT UINT8
*DataToggle
,
847 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
848 OUT UINT32
*TransferResult
857 // Validate the parameters
859 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
860 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
861 return EFI_INVALID_PARAMETER
;
864 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
865 return EFI_INVALID_PARAMETER
;
868 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
869 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
870 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
871 return EFI_INVALID_PARAMETER
;
874 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
875 Ehc
= EHC_FROM_THIS (This
);
877 *TransferResult
= EFI_USB_ERR_SYSTEM
;
878 Status
= EFI_DEVICE_ERROR
;
880 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
881 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: HC is halted\n"));
883 EhcAckAllInterrupt (Ehc
);
887 EhcAckAllInterrupt (Ehc
);
890 // Create a new URB, insert it into the asynchronous
891 // schedule list, then poll the execution status.
911 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: failed to create URB\n"));
913 Status
= EFI_OUT_OF_RESOURCES
;
917 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
918 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
919 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
921 *TransferResult
= Urb
->Result
;
922 *DataLength
= Urb
->Completed
;
923 *DataToggle
= Urb
->DataToggle
;
925 if (*TransferResult
== EFI_USB_NOERROR
) {
926 Status
= EFI_SUCCESS
;
929 EhcAckAllInterrupt (Ehc
);
930 EhcFreeUrb (Ehc
, Urb
);
933 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
934 gBS
->RestoreTPL (OldTpl
);
936 if (EFI_ERROR (Status
)) {
937 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
945 Submits an asynchronous interrupt transfer to an
946 interrupt endpoint of a USB device.
948 @param This This EFI_USB2_HC_PROTOCOL instance.
949 @param DeviceAddress Target device address.
950 @param EndPointAddress Endpoint number and its direction encoded in bit 7
951 @param DeviceSpeed Indicates device speed.
952 @param MaximumPacketLength Maximum packet size the target endpoint is capable
953 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
954 transfer If FALSE, to remove the specified
955 asynchronous interrupt.
956 @param DataToggle On input, the initial data toggle to use; on output,
957 it is updated to indicate the next data toggle.
958 @param PollingInterval The he interval, in milliseconds, that the transfer
960 @param DataLength The length of data to receive at the rate specified
962 @param Translator Transaction translator to use.
963 @param CallBackFunction Function to call at the rate specified by
965 @param Context Context to CallBackFunction.
967 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
968 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
969 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
970 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
975 EhcAsyncInterruptTransfer (
976 IN EFI_USB2_HC_PROTOCOL
* This
,
977 IN UINT8 DeviceAddress
,
978 IN UINT8 EndPointAddress
,
979 IN UINT8 DeviceSpeed
,
980 IN UINTN MaximumPacketLength
,
981 IN BOOLEAN IsNewTransfer
,
982 IN OUT UINT8
*DataToggle
,
983 IN UINTN PollingInterval
,
985 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
986 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
987 IN VOID
*Context OPTIONAL
996 // Validate parameters
998 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
999 return EFI_INVALID_PARAMETER
;
1002 if (IsNewTransfer
) {
1003 if (DataLength
== 0) {
1004 return EFI_INVALID_PARAMETER
;
1007 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1008 return EFI_INVALID_PARAMETER
;
1011 if ((PollingInterval
> 255) || (PollingInterval
< 1)) {
1012 return EFI_INVALID_PARAMETER
;
1016 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1017 Ehc
= EHC_FROM_THIS (This
);
1020 // Delete Async interrupt transfer request. DataToggle will return
1021 // the next data toggle to use.
1023 if (!IsNewTransfer
) {
1024 Status
= EhciDelAsyncIntTransfer (Ehc
, DeviceAddress
, EndPointAddress
, DataToggle
);
1026 DEBUG ((EFI_D_INFO
, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status
));
1030 Status
= EFI_SUCCESS
;
1032 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1033 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: HC is halt\n"));
1034 EhcAckAllInterrupt (Ehc
);
1036 Status
= EFI_DEVICE_ERROR
;
1040 EhcAckAllInterrupt (Ehc
);
1042 Urb
= EhciInsertAsyncIntTransfer (
1048 MaximumPacketLength
,
1057 Status
= EFI_OUT_OF_RESOURCES
;
1062 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1063 gBS
->RestoreTPL (OldTpl
);
1070 Submits synchronous interrupt transfer to an interrupt endpoint
1073 @param This This EFI_USB2_HC_PROTOCOL instance.
1074 @param DeviceAddress Target device address.
1075 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1076 @param DeviceSpeed Indicates device speed.
1077 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1078 of sending or receiving.
1079 @param Data Buffer of data that will be transmitted to USB
1080 device or received from USB device.
1081 @param DataLength On input, the size, in bytes, of the data buffer; On
1082 output, the number of bytes transferred.
1083 @param DataToggle On input, the initial data toggle to use; on output,
1084 it is updated to indicate the next data toggle.
1085 @param TimeOut Maximum time, in second, to complete.
1086 @param Translator Transaction translator to use.
1087 @param TransferResult Variable to receive the transfer result.
1089 @return EFI_SUCCESS The transfer was completed successfully.
1090 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1091 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1092 @return EFI_TIMEOUT The transfer failed due to timeout.
1093 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1098 EhcSyncInterruptTransfer (
1099 IN EFI_USB2_HC_PROTOCOL
*This
,
1100 IN UINT8 DeviceAddress
,
1101 IN UINT8 EndPointAddress
,
1102 IN UINT8 DeviceSpeed
,
1103 IN UINTN MaximumPacketLength
,
1105 IN OUT UINTN
*DataLength
,
1106 IN OUT UINT8
*DataToggle
,
1108 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1109 OUT UINT32
*TransferResult
1118 // Validates parameters
1120 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
1121 (Data
== NULL
) || (TransferResult
== NULL
)) {
1122 return EFI_INVALID_PARAMETER
;
1125 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1126 return EFI_INVALID_PARAMETER
;
1129 if (((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) ||
1130 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1131 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 3072))) {
1132 return EFI_INVALID_PARAMETER
;
1135 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1136 Ehc
= EHC_FROM_THIS (This
);
1138 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1139 Status
= EFI_DEVICE_ERROR
;
1141 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1142 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: HC is halt\n"));
1144 EhcAckAllInterrupt (Ehc
);
1148 EhcAckAllInterrupt (Ehc
);
1150 Urb
= EhcCreateUrb (
1156 MaximumPacketLength
,
1158 EHC_INT_TRANSFER_SYNC
,
1168 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: failed to create URB\n"));
1170 Status
= EFI_OUT_OF_RESOURCES
;
1174 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1175 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1176 EhcUnlinkQhFromPeriod (Ehc
, Urb
->Qh
);
1178 *TransferResult
= Urb
->Result
;
1179 *DataLength
= Urb
->Completed
;
1180 *DataToggle
= Urb
->DataToggle
;
1182 if (*TransferResult
== EFI_USB_NOERROR
) {
1183 Status
= EFI_SUCCESS
;
1186 EhcFreeUrb (Ehc
, Urb
);
1188 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1189 gBS
->RestoreTPL (OldTpl
);
1191 if (EFI_ERROR (Status
)) {
1192 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1200 Submits isochronous transfer to a target USB device.
1202 @param This This EFI_USB2_HC_PROTOCOL instance.
1203 @param DeviceAddress Target device address.
1204 @param EndPointAddress End point address with its direction.
1205 @param DeviceSpeed Device speed, Low speed device doesn't support this
1207 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1208 sending or receiving.
1209 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1210 @param Data Array of pointers to the buffers of data that will
1211 be transmitted to USB device or received from USB
1213 @param DataLength The size, in bytes, of the data buffer.
1214 @param Translator Transaction translator to use.
1215 @param TransferResult Variable to receive the transfer result.
1217 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1222 EhcIsochronousTransfer (
1223 IN EFI_USB2_HC_PROTOCOL
*This
,
1224 IN UINT8 DeviceAddress
,
1225 IN UINT8 EndPointAddress
,
1226 IN UINT8 DeviceSpeed
,
1227 IN UINTN MaximumPacketLength
,
1228 IN UINT8 DataBuffersNumber
,
1229 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1230 IN UINTN DataLength
,
1231 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1232 OUT UINT32
*TransferResult
1235 return EFI_UNSUPPORTED
;
1240 Submits Async isochronous transfer to a target USB device.
1242 @param This This EFI_USB2_HC_PROTOCOL instance.
1243 @param DeviceAddress Target device address.
1244 @param EndPointAddress End point address with its direction.
1245 @param DeviceSpeed Device speed, Low speed device doesn't support this
1247 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1248 sending or receiving.
1249 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1250 @param Data Array of pointers to the buffers of data that will
1251 be transmitted to USB device or received from USB
1253 @param DataLength The size, in bytes, of the data buffer.
1254 @param Translator Transaction translator to use.
1255 @param IsochronousCallBack Function to be called when the transfer complete.
1256 @param Context Context passed to the call back function as
1259 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1264 EhcAsyncIsochronousTransfer (
1265 IN EFI_USB2_HC_PROTOCOL
*This
,
1266 IN UINT8 DeviceAddress
,
1267 IN UINT8 EndPointAddress
,
1268 IN UINT8 DeviceSpeed
,
1269 IN UINTN MaximumPacketLength
,
1270 IN UINT8 DataBuffersNumber
,
1271 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1272 IN UINTN DataLength
,
1273 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1274 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1278 return EFI_UNSUPPORTED
;
1282 Entry point for EFI drivers.
1284 @param ImageHandle EFI_HANDLE.
1285 @param SystemTable EFI_SYSTEM_TABLE.
1287 @return EFI_SUCCESS Success.
1288 EFI_DEVICE_ERROR Fail.
1293 EhcDriverEntryPoint (
1294 IN EFI_HANDLE ImageHandle
,
1295 IN EFI_SYSTEM_TABLE
*SystemTable
1298 return EfiLibInstallDriverBindingComponentName2 (
1301 &gEhciDriverBinding
,
1303 &gEhciComponentName
,
1304 &gEhciComponentName2
1310 Test to see if this driver supports ControllerHandle. Any
1311 ControllerHandle that has Usb2HcProtocol installed will
1314 @param This Protocol instance pointer.
1315 @param Controller Handle of device to test.
1316 @param RemainingDevicePath Not used.
1318 @return EFI_SUCCESS This driver supports this device.
1319 @return EFI_UNSUPPORTED This driver does not support this device.
1324 EhcDriverBindingSupported (
1325 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1326 IN EFI_HANDLE Controller
,
1327 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1331 EFI_PCI_IO_PROTOCOL
*PciIo
;
1332 USB_CLASSC UsbClassCReg
;
1335 // Test whether there is PCI IO Protocol attached on the controller handle.
1337 Status
= gBS
->OpenProtocol (
1339 &gEfiPciIoProtocolGuid
,
1341 This
->DriverBindingHandle
,
1343 EFI_OPEN_PROTOCOL_BY_DRIVER
1346 if (EFI_ERROR (Status
)) {
1347 return EFI_UNSUPPORTED
;
1350 Status
= PciIo
->Pci
.Read (
1353 PCI_CLASSCODE_OFFSET
,
1354 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1358 if (EFI_ERROR (Status
)) {
1359 Status
= EFI_UNSUPPORTED
;
1364 // Test whether the controller belongs to Ehci type
1366 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) || (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
)
1367 || ((UsbClassCReg
.ProgInterface
!= PCI_IF_EHCI
) && (UsbClassCReg
.ProgInterface
!= PCI_IF_UHCI
) && (UsbClassCReg
.ProgInterface
!= PCI_IF_OHCI
))) {
1369 Status
= EFI_UNSUPPORTED
;
1373 gBS
->CloseProtocol (
1375 &gEfiPciIoProtocolGuid
,
1376 This
->DriverBindingHandle
,
1384 Get the usb debug port related information.
1386 @param Ehc The EHCI device.
1388 @retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
1389 @retval Others The usb host controller does not supported usb debug port capability.
1393 EhcGetUsbDebugPortInfo (
1397 EFI_PCI_IO_PROTOCOL
*PciIo
;
1399 UINT8 CapabilityPtr
;
1404 ASSERT (Ehc
->PciIo
!= NULL
);
1408 // Detect if the EHCI host controller support Capaility Pointer.
1410 Status
= PciIo
->Pci
.Read (
1413 PCI_PRIMARY_STATUS_OFFSET
,
1418 if (EFI_ERROR (Status
)) {
1422 if ((PciStatus
& EFI_PCI_STATUS_CAPABILITY
) == 0) {
1424 // The Pci Device Doesn't Support Capability Pointer.
1426 return EFI_UNSUPPORTED
;
1430 // Get Pointer To Capability List
1432 Status
= PciIo
->Pci
.Read (
1435 PCI_CAPBILITY_POINTER_OFFSET
,
1440 if (EFI_ERROR (Status
)) {
1445 // Find Capability ID 0xA, Which Is For Debug Port
1447 while (CapabilityPtr
!= 0) {
1448 Status
= PciIo
->Pci
.Read (
1456 if (EFI_ERROR (Status
)) {
1460 if (CapabilityId
== EHC_DEBUG_PORT_CAP_ID
) {
1464 Status
= PciIo
->Pci
.Read (
1472 if (EFI_ERROR (Status
)) {
1478 // No Debug Port Capability Found
1480 if (CapabilityPtr
== 0) {
1481 return EFI_UNSUPPORTED
;
1485 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1487 Status
= PciIo
->Pci
.Read (
1495 if (EFI_ERROR (Status
)) {
1499 Ehc
->DebugPortOffset
= DebugPort
& 0x1FFF;
1500 Ehc
->DebugPortBarNum
= (UINT8
)((DebugPort
>> 13) - 1);
1501 Ehc
->DebugPortNum
= (UINT8
)((Ehc
->HcStructParams
& 0x00F00000) >> 20);
1508 Create and initialize a USB2_HC_DEV.
1510 @param PciIo The PciIo on this device.
1511 @param DevicePath The device path of host controller.
1512 @param OriginalPciAttributes Original PCI attributes.
1514 @return The allocated and initialized USB2_HC_DEV structure if created,
1520 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1521 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1522 IN UINT64 OriginalPciAttributes
1528 Ehc
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
1535 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1537 Ehc
->Signature
= USB2_HC_DEV_SIGNATURE
;
1539 Ehc
->Usb2Hc
.GetCapability
= EhcGetCapability
;
1540 Ehc
->Usb2Hc
.Reset
= EhcReset
;
1541 Ehc
->Usb2Hc
.GetState
= EhcGetState
;
1542 Ehc
->Usb2Hc
.SetState
= EhcSetState
;
1543 Ehc
->Usb2Hc
.ControlTransfer
= EhcControlTransfer
;
1544 Ehc
->Usb2Hc
.BulkTransfer
= EhcBulkTransfer
;
1545 Ehc
->Usb2Hc
.AsyncInterruptTransfer
= EhcAsyncInterruptTransfer
;
1546 Ehc
->Usb2Hc
.SyncInterruptTransfer
= EhcSyncInterruptTransfer
;
1547 Ehc
->Usb2Hc
.IsochronousTransfer
= EhcIsochronousTransfer
;
1548 Ehc
->Usb2Hc
.AsyncIsochronousTransfer
= EhcAsyncIsochronousTransfer
;
1549 Ehc
->Usb2Hc
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1550 Ehc
->Usb2Hc
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1551 Ehc
->Usb2Hc
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1552 Ehc
->Usb2Hc
.MajorRevision
= 0x2;
1553 Ehc
->Usb2Hc
.MinorRevision
= 0x0;
1556 Ehc
->DevicePath
= DevicePath
;
1557 Ehc
->OriginalPciAttributes
= OriginalPciAttributes
;
1559 InitializeListHead (&Ehc
->AsyncIntTransfers
);
1561 Ehc
->HcStructParams
= EhcReadCapRegister (Ehc
, EHC_HCSPARAMS_OFFSET
);
1562 Ehc
->HcCapParams
= EhcReadCapRegister (Ehc
, EHC_HCCPARAMS_OFFSET
);
1563 Ehc
->CapLen
= EhcReadCapRegister (Ehc
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1565 DEBUG ((EFI_D_INFO
, "EhcCreateUsb2Hc: capability length %d\n", Ehc
->CapLen
));
1568 // EHCI Controllers with a CapLen of 0 are ignored.
1570 if (Ehc
->CapLen
== 0) {
1571 gBS
->FreePool (Ehc
);
1575 EhcGetUsbDebugPortInfo (Ehc
);
1578 // Create AsyncRequest Polling Timer
1580 Status
= gBS
->CreateEvent (
1581 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1583 EhcMonitorAsyncRequests
,
1588 if (EFI_ERROR (Status
)) {
1589 gBS
->FreePool (Ehc
);
1597 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1599 @param Event Pointer to this event
1600 @param Context Event handler private data
1605 EhcExitBootService (
1613 Ehc
= (USB2_HC_DEV
*) Context
;
1616 // Reset the Host Controller
1618 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1623 Starting the Usb EHCI Driver.
1625 @param This Protocol instance pointer.
1626 @param Controller Handle of device to test.
1627 @param RemainingDevicePath Not used.
1629 @return EFI_SUCCESS supports this device.
1630 @return EFI_UNSUPPORTED do not support this device.
1631 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1632 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1637 EhcDriverBindingStart (
1638 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1639 IN EFI_HANDLE Controller
,
1640 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1645 EFI_PCI_IO_PROTOCOL
*PciIo
;
1646 EFI_PCI_IO_PROTOCOL
*Instance
;
1648 UINT64 OriginalPciAttributes
;
1649 BOOLEAN PciAttributesSaved
;
1650 USB_CLASSC UsbClassCReg
;
1651 EFI_HANDLE
*HandleBuffer
;
1652 UINTN NumberOfHandles
;
1654 UINTN CompanionSegmentNumber
;
1655 UINTN CompanionBusNumber
;
1656 UINTN CompanionDeviceNumber
;
1657 UINTN CompanionFunctionNumber
;
1658 UINTN EhciSegmentNumber
;
1659 UINTN EhciBusNumber
;
1660 UINTN EhciDeviceNumber
;
1661 UINTN EhciFunctionNumber
;
1662 EFI_DEVICE_PATH_PROTOCOL
*HcDevicePath
;
1665 // Open the PciIo Protocol, then enable the USB host controller
1667 Status
= gBS
->OpenProtocol (
1669 &gEfiPciIoProtocolGuid
,
1671 This
->DriverBindingHandle
,
1673 EFI_OPEN_PROTOCOL_BY_DRIVER
1676 if (EFI_ERROR (Status
)) {
1681 // Open Device Path Protocol for on USB host controller
1683 HcDevicePath
= NULL
;
1684 Status
= gBS
->OpenProtocol (
1686 &gEfiDevicePathProtocolGuid
,
1687 (VOID
**) &HcDevicePath
,
1688 This
->DriverBindingHandle
,
1690 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1693 PciAttributesSaved
= FALSE
;
1695 // Save original PCI attributes
1697 Status
= PciIo
->Attributes (
1699 EfiPciIoAttributeOperationGet
,
1701 &OriginalPciAttributes
1704 if (EFI_ERROR (Status
)) {
1707 PciAttributesSaved
= TRUE
;
1709 Status
= PciIo
->Attributes (
1711 EfiPciIoAttributeOperationSupported
,
1715 if (!EFI_ERROR (Status
)) {
1716 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
1717 Status
= PciIo
->Attributes (
1719 EfiPciIoAttributeOperationEnable
,
1725 if (EFI_ERROR (Status
)) {
1726 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to enable controller\n"));
1731 // Get the Pci device class code.
1733 Status
= PciIo
->Pci
.Read (
1736 PCI_CLASSCODE_OFFSET
,
1737 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1741 if (EFI_ERROR (Status
)) {
1742 Status
= EFI_UNSUPPORTED
;
1746 // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the
1747 // companion usb ehci host controller and force EHCI driver get attached to it before
1748 // UHCI or OHCI driver attaches to UHCI or OHCI host controller.
1750 if ((UsbClassCReg
.ProgInterface
== PCI_IF_UHCI
|| UsbClassCReg
.ProgInterface
== PCI_IF_OHCI
) &&
1751 (UsbClassCReg
.BaseCode
== PCI_CLASS_SERIAL
) &&
1752 (UsbClassCReg
.SubClassCode
== PCI_CLASS_SERIAL_USB
)) {
1753 Status
= PciIo
->GetLocation (
1755 &CompanionSegmentNumber
,
1756 &CompanionBusNumber
,
1757 &CompanionDeviceNumber
,
1758 &CompanionFunctionNumber
1760 if (EFI_ERROR (Status
)) {
1764 Status
= gBS
->LocateHandleBuffer (
1766 &gEfiPciIoProtocolGuid
,
1771 if (EFI_ERROR (Status
)) {
1775 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
1777 // Get the device path on this handle
1779 Status
= gBS
->HandleProtocol (
1780 HandleBuffer
[Index
],
1781 &gEfiPciIoProtocolGuid
,
1784 ASSERT_EFI_ERROR (Status
);
1786 Status
= Instance
->Pci
.Read (
1789 PCI_CLASSCODE_OFFSET
,
1790 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1794 if (EFI_ERROR (Status
)) {
1795 Status
= EFI_UNSUPPORTED
;
1799 if ((UsbClassCReg
.ProgInterface
== PCI_IF_EHCI
) &&
1800 (UsbClassCReg
.BaseCode
== PCI_CLASS_SERIAL
) &&
1801 (UsbClassCReg
.SubClassCode
== PCI_CLASS_SERIAL_USB
)) {
1802 Status
= Instance
->GetLocation (
1809 if (EFI_ERROR (Status
)) {
1813 // Currently, the judgment on the companion usb host controller is through the
1814 // same bus number, which may vary on different platform.
1816 if (EhciBusNumber
== CompanionBusNumber
) {
1817 gBS
->CloseProtocol (
1819 &gEfiPciIoProtocolGuid
,
1820 This
->DriverBindingHandle
,
1823 EhcDriverBindingStart(This
, HandleBuffer
[Index
], NULL
);
1827 Status
= EFI_NOT_FOUND
;
1832 // Create then install USB2_HC_PROTOCOL
1834 Ehc
= EhcCreateUsb2Hc (PciIo
, HcDevicePath
, OriginalPciAttributes
);
1837 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1839 Status
= EFI_OUT_OF_RESOURCES
;
1844 // Enable 64-bit DMA support in the PCI layer if this controller
1847 if (EHC_BIT_IS_SET (Ehc
->HcCapParams
, HCCP_64BIT
)) {
1848 Status
= PciIo
->Attributes (
1850 EfiPciIoAttributeOperationEnable
,
1851 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
1854 if (!EFI_ERROR (Status
)) {
1855 Ehc
->Support64BitDma
= TRUE
;
1858 "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",
1859 __FUNCTION__
, Controller
, Status
));
1863 Status
= gBS
->InstallProtocolInterface (
1865 &gEfiUsb2HcProtocolGuid
,
1866 EFI_NATIVE_INTERFACE
,
1870 if (EFI_ERROR (Status
)) {
1871 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1876 // Robustnesss improvement such as for Duet platform
1877 // Default is not required.
1879 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1880 EhcClearLegacySupport (Ehc
);
1883 if (!EhcIsDebugPortInUse (Ehc
, NULL
)) {
1884 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1887 Status
= EhcInitHC (Ehc
);
1889 if (EFI_ERROR (Status
)) {
1890 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to init host controller\n"));
1891 goto UNINSTALL_USBHC
;
1895 // Start the asynchronous interrupt monitor
1897 Status
= gBS
->SetTimer (Ehc
->PollTimer
, TimerPeriodic
, EHC_ASYNC_POLL_INTERVAL
);
1899 if (EFI_ERROR (Status
)) {
1900 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1902 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1903 goto UNINSTALL_USBHC
;
1907 // Create event to stop the HC when exit boot service.
1909 Status
= gBS
->CreateEventEx (
1914 &gEfiEventExitBootServicesGuid
,
1915 &Ehc
->ExitBootServiceEvent
1917 if (EFI_ERROR (Status
)) {
1918 goto UNINSTALL_USBHC
;
1922 // Install the component name protocol, don't fail the start
1923 // because of something for display.
1927 gEhciComponentName
.SupportedLanguages
,
1928 &Ehc
->ControllerNameTable
,
1929 L
"Enhanced Host Controller (USB 2.0)",
1934 gEhciComponentName2
.SupportedLanguages
,
1935 &Ehc
->ControllerNameTable
,
1936 L
"Enhanced Host Controller (USB 2.0)",
1941 DEBUG ((EFI_D_INFO
, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller
));
1945 gBS
->UninstallProtocolInterface (
1947 &gEfiUsb2HcProtocolGuid
,
1953 gBS
->CloseEvent (Ehc
->PollTimer
);
1954 gBS
->FreePool (Ehc
);
1957 if (PciAttributesSaved
) {
1959 // Restore original PCI attributes
1963 EfiPciIoAttributeOperationSet
,
1964 OriginalPciAttributes
,
1969 gBS
->CloseProtocol (
1971 &gEfiPciIoProtocolGuid
,
1972 This
->DriverBindingHandle
,
1981 Stop this driver on ControllerHandle. Support stopping any child handles
1982 created by this driver.
1984 @param This Protocol instance pointer.
1985 @param Controller Handle of device to stop driver on.
1986 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1987 @param ChildHandleBuffer List of handles for the children we need to stop.
1989 @return EFI_SUCCESS Success.
1990 @return EFI_DEVICE_ERROR Fail.
1995 EhcDriverBindingStop (
1996 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1997 IN EFI_HANDLE Controller
,
1998 IN UINTN NumberOfChildren
,
1999 IN EFI_HANDLE
*ChildHandleBuffer
2003 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
2004 EFI_PCI_IO_PROTOCOL
*PciIo
;
2008 // Test whether the Controller handler passed in is a valid
2009 // Usb controller handle that should be supported, if not,
2010 // return the error status directly
2012 Status
= gBS
->OpenProtocol (
2014 &gEfiUsb2HcProtocolGuid
,
2016 This
->DriverBindingHandle
,
2018 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2021 if (EFI_ERROR (Status
)) {
2025 Ehc
= EHC_FROM_THIS (Usb2Hc
);
2028 Status
= gBS
->UninstallProtocolInterface (
2030 &gEfiUsb2HcProtocolGuid
,
2034 if (EFI_ERROR (Status
)) {
2039 // Stop AsyncRequest Polling timer then stop the EHCI driver
2040 // and uninstall the EHCI protocl.
2042 gBS
->SetTimer (Ehc
->PollTimer
, TimerCancel
, EHC_ASYNC_POLL_INTERVAL
);
2043 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
2045 if (Ehc
->PollTimer
!= NULL
) {
2046 gBS
->CloseEvent (Ehc
->PollTimer
);
2049 if (Ehc
->ExitBootServiceEvent
!= NULL
) {
2050 gBS
->CloseEvent (Ehc
->ExitBootServiceEvent
);
2055 if (Ehc
->ControllerNameTable
!= NULL
) {
2056 FreeUnicodeStringTable (Ehc
->ControllerNameTable
);
2060 // Disable routing of all ports to EHCI controller, so all ports are
2061 // routed back to the UHCI or OHCI controller.
2063 EhcClearOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
2066 // Restore original PCI attributes
2070 EfiPciIoAttributeOperationSet
,
2071 Ehc
->OriginalPciAttributes
,
2075 gBS
->CloseProtocol (
2077 &gEfiPciIoProtocolGuid
,
2078 This
->DriverBindingHandle
,