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 the UHCI driver attaches to the companion UHCI controller.
10 This way avoids the control transfer on a shared port between EHCI and companion host
11 controller when UHCI gets attached earlier than EHCI and a USB 2.0 device inserts.
13 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28 // Two arrays used to translate the EHCI port state (change)
29 // to the UEFI protocol's port state (change).
31 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
32 {PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
33 {PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
34 {PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
35 {PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
36 {PORTSC_RESET
, USB_PORT_STAT_RESET
},
37 {PORTSC_POWER
, USB_PORT_STAT_POWER
},
38 {PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
41 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
42 {PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
43 {PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
44 {PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
47 EFI_DRIVER_BINDING_PROTOCOL
48 gEhciDriverBinding
= {
49 EhcDriverBindingSupported
,
50 EhcDriverBindingStart
,
58 Retrieves the capability of root hub ports.
60 @param This This EFI_USB_HC_PROTOCOL instance.
61 @param MaxSpeed Max speed supported by the controller.
62 @param PortNumber Number of the root hub ports.
63 @param Is64BitCapable Whether the controller supports 64-bit memory
66 @retval EFI_SUCCESS Host controller capability were retrieved successfully.
67 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
73 IN EFI_USB2_HC_PROTOCOL
*This
,
75 OUT UINT8
*PortNumber
,
76 OUT UINT8
*Is64BitCapable
82 if ((MaxSpeed
== NULL
) || (PortNumber
== NULL
) || (Is64BitCapable
== NULL
)) {
83 return EFI_INVALID_PARAMETER
;
86 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
87 Ehc
= EHC_FROM_THIS (This
);
89 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
90 *PortNumber
= (UINT8
) (Ehc
->HcStructParams
& HCSP_NPORTS
);
91 *Is64BitCapable
= (UINT8
) (Ehc
->HcCapParams
& HCCP_64BIT
);
93 DEBUG ((EFI_D_INFO
, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber
, *Is64BitCapable
));
95 gBS
->RestoreTPL (OldTpl
);
101 Provides software reset for the USB host controller.
103 @param This This EFI_USB2_HC_PROTOCOL instance.
104 @param Attributes A bit mask of the reset operation to perform.
106 @retval EFI_SUCCESS The reset operation succeeded.
107 @retval EFI_INVALID_PARAMETER Attributes is not valid.
108 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
109 not currently supported by the host controller.
110 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
116 IN EFI_USB2_HC_PROTOCOL
*This
,
123 UINT32 DbgCtrlStatus
;
125 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
126 Ehc
= EHC_FROM_THIS (This
);
128 switch (Attributes
) {
129 case EFI_USB_HC_RESET_GLOBAL
:
131 // Flow through, same behavior as Host Controller Reset
133 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
135 // Host Controller must be Halt when Reset it
137 if (Ehc
->DebugPortNum
!= 0) {
138 DbgCtrlStatus
= EhcReadDbgRegister(Ehc
, 0);
139 if ((DbgCtrlStatus
& (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) == (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) {
140 Status
= EFI_SUCCESS
;
145 if (!EhcIsHalt (Ehc
)) {
146 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
148 if (EFI_ERROR (Status
)) {
149 Status
= EFI_DEVICE_ERROR
;
155 // Clean up the asynchronous transfers, currently only
156 // interrupt supports asynchronous operation.
158 EhciDelAllAsyncIntTransfers (Ehc
);
159 EhcAckAllInterrupt (Ehc
);
162 Status
= EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
164 if (EFI_ERROR (Status
)) {
168 Status
= EhcInitHC (Ehc
);
171 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
:
172 case EFI_USB_HC_RESET_HOST_WITH_DEBUG
:
173 Status
= EFI_UNSUPPORTED
;
177 Status
= EFI_INVALID_PARAMETER
;
181 DEBUG ((EFI_D_INFO
, "EhcReset: exit status %r\n", Status
));
182 gBS
->RestoreTPL (OldTpl
);
188 Retrieve the current state of the USB host controller.
190 @param This This EFI_USB2_HC_PROTOCOL instance.
191 @param State Variable to return the current host controller
194 @retval EFI_SUCCESS Host controller state was returned in State.
195 @retval EFI_INVALID_PARAMETER State is NULL.
196 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
197 retrieve the host controller's current state.
203 IN EFI_USB2_HC_PROTOCOL
*This
,
204 OUT EFI_USB_HC_STATE
*State
211 return EFI_INVALID_PARAMETER
;
214 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
215 Ehc
= EHC_FROM_THIS (This
);
217 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
218 *State
= EfiUsbHcStateHalt
;
220 *State
= EfiUsbHcStateOperational
;
223 gBS
->RestoreTPL (OldTpl
);
225 DEBUG ((EFI_D_INFO
, "EhcGetState: current state %d\n", *State
));
231 Sets the USB host controller to a specific state.
233 @param This This EFI_USB2_HC_PROTOCOL instance.
234 @param State The state of the host controller that will be set.
236 @retval EFI_SUCCESS The USB host controller was successfully placed
237 in the state specified by State.
238 @retval EFI_INVALID_PARAMETER State is invalid.
239 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
245 IN EFI_USB2_HC_PROTOCOL
*This
,
246 IN EFI_USB_HC_STATE State
252 EFI_USB_HC_STATE CurState
;
254 Status
= EhcGetState (This
, &CurState
);
256 if (EFI_ERROR (Status
)) {
257 return EFI_DEVICE_ERROR
;
260 if (CurState
== State
) {
264 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
265 Ehc
= EHC_FROM_THIS (This
);
268 case EfiUsbHcStateHalt
:
269 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
272 case EfiUsbHcStateOperational
:
273 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
)) {
274 Status
= EFI_DEVICE_ERROR
;
279 // Software must not write a one to this field unless the host controller
280 // is in the Halted state. Doing so will yield undefined results.
281 // refers to Spec[EHCI1.0-2.3.1]
283 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
284 Status
= EFI_DEVICE_ERROR
;
288 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
291 case EfiUsbHcStateSuspend
:
292 Status
= EFI_UNSUPPORTED
;
296 Status
= EFI_INVALID_PARAMETER
;
299 DEBUG ((EFI_D_INFO
, "EhcSetState: exit status %r\n", Status
));
300 gBS
->RestoreTPL (OldTpl
);
306 Retrieves the current status of a USB root hub port.
308 @param This This EFI_USB2_HC_PROTOCOL instance.
309 @param PortNumber The root hub port to retrieve the state from.
310 This value is zero-based.
311 @param PortStatus Variable to receive the port state.
313 @retval EFI_SUCCESS The status of the USB root hub port specified.
314 by PortNumber was returned in PortStatus.
315 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
316 @retval EFI_DEVICE_ERROR Can't read register.
321 EhcGetRootHubPortStatus (
322 IN EFI_USB2_HC_PROTOCOL
*This
,
324 OUT EFI_USB_PORT_STATUS
*PortStatus
335 UINT32 DbgCtrlStatus
;
337 if (PortStatus
== NULL
) {
338 return EFI_INVALID_PARAMETER
;
341 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
343 Ehc
= EHC_FROM_THIS (This
);
344 Status
= EFI_SUCCESS
;
346 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
348 if (PortNumber
>= TotalPort
) {
349 Status
= EFI_INVALID_PARAMETER
;
353 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
354 PortStatus
->PortStatus
= 0;
355 PortStatus
->PortChangeStatus
= 0;
357 if ((Ehc
->DebugPortNum
!= 0) && (PortNumber
== (Ehc
->DebugPortNum
- 1))) {
358 DbgCtrlStatus
= EhcReadDbgRegister(Ehc
, 0);
359 if ((DbgCtrlStatus
& (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) == (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) {
364 State
= EhcReadOpReg (Ehc
, Offset
);
367 // Identify device speed. If in K state, it is low speed.
368 // If the port is enabled after reset, the device is of
369 // high speed. The USB bus driver should retrieve the actual
370 // port speed after reset.
372 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
373 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
375 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
376 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
380 // Convert the EHCI port/port change state to UEFI status
382 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
384 for (Index
= 0; Index
< MapSize
; Index
++) {
385 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
386 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
390 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
392 for (Index
= 0; Index
< MapSize
; Index
++) {
393 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
394 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
399 gBS
->RestoreTPL (OldTpl
);
405 Sets a feature for the specified root hub port.
407 @param This This EFI_USB2_HC_PROTOCOL instance.
408 @param PortNumber Root hub port to set.
409 @param PortFeature Feature to set.
411 @retval EFI_SUCCESS The feature specified by PortFeature was set.
412 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
413 @retval EFI_DEVICE_ERROR Can't read register.
418 EhcSetRootHubPortFeature (
419 IN EFI_USB2_HC_PROTOCOL
*This
,
421 IN EFI_USB_PORT_FEATURE PortFeature
431 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
432 Ehc
= EHC_FROM_THIS (This
);
433 Status
= EFI_SUCCESS
;
435 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
437 if (PortNumber
>= TotalPort
) {
438 Status
= EFI_INVALID_PARAMETER
;
442 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
443 State
= EhcReadOpReg (Ehc
, Offset
);
446 // Mask off the port status change bits, these bits are
449 State
&= ~PORTSC_CHANGE_MASK
;
451 switch (PortFeature
) {
452 case EfiUsbPortEnable
:
454 // Sofeware can't set this bit, Port can only be enable by
455 // EHCI as a part of the reset and enable
457 State
|= PORTSC_ENABLED
;
458 EhcWriteOpReg (Ehc
, Offset
, State
);
461 case EfiUsbPortSuspend
:
462 State
|= PORTSC_SUSPEND
;
463 EhcWriteOpReg (Ehc
, Offset
, State
);
466 case EfiUsbPortReset
:
468 // Make sure Host Controller not halt before reset it
470 if (EhcIsHalt (Ehc
)) {
471 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
473 if (EFI_ERROR (Status
)) {
474 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status
));
480 // Set one to PortReset bit must also set zero to PortEnable bit
482 State
|= PORTSC_RESET
;
483 State
&= ~PORTSC_ENABLED
;
484 EhcWriteOpReg (Ehc
, Offset
, State
);
487 case EfiUsbPortPower
:
489 // Set port power bit when PPC is 1
491 if ((Ehc
->HcCapParams
& HCSP_PPC
) == HCSP_PPC
) {
492 State
|= PORTSC_POWER
;
493 EhcWriteOpReg (Ehc
, Offset
, State
);
497 case EfiUsbPortOwner
:
498 State
|= PORTSC_OWNER
;
499 EhcWriteOpReg (Ehc
, Offset
, State
);
503 Status
= EFI_INVALID_PARAMETER
;
507 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature: exit status %r\n", Status
));
509 gBS
->RestoreTPL (OldTpl
);
515 Clears a feature for the specified root hub port.
517 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
518 @param PortNumber Specifies the root hub port whose feature is
519 requested to be cleared.
520 @param PortFeature Indicates the feature selector associated with the
521 feature clear request.
523 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
524 for the USB root hub port specified by PortNumber.
525 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
526 @retval EFI_DEVICE_ERROR Can't read register.
531 EhcClearRootHubPortFeature (
532 IN EFI_USB2_HC_PROTOCOL
*This
,
534 IN EFI_USB_PORT_FEATURE PortFeature
544 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
545 Ehc
= EHC_FROM_THIS (This
);
546 Status
= EFI_SUCCESS
;
548 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
550 if (PortNumber
>= TotalPort
) {
551 Status
= EFI_INVALID_PARAMETER
;
555 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
556 State
= EhcReadOpReg (Ehc
, Offset
);
557 State
&= ~PORTSC_CHANGE_MASK
;
559 switch (PortFeature
) {
560 case EfiUsbPortEnable
:
562 // Clear PORT_ENABLE feature means disable port.
564 State
&= ~PORTSC_ENABLED
;
565 EhcWriteOpReg (Ehc
, Offset
, State
);
568 case EfiUsbPortSuspend
:
570 // A write of zero to this bit is ignored by the host
571 // controller. The host controller will unconditionally
572 // set this bit to a zero when:
573 // 1. software sets the Forct Port Resume bit to a zero from a one.
574 // 2. software sets the Port Reset bit to a one frome a zero.
576 State
&= ~PORSTSC_RESUME
;
577 EhcWriteOpReg (Ehc
, Offset
, State
);
580 case EfiUsbPortReset
:
582 // Clear PORT_RESET means clear the reset signal.
584 State
&= ~PORTSC_RESET
;
585 EhcWriteOpReg (Ehc
, Offset
, State
);
588 case EfiUsbPortOwner
:
590 // Clear port owner means this port owned by EHC
592 State
&= ~PORTSC_OWNER
;
593 EhcWriteOpReg (Ehc
, Offset
, State
);
596 case EfiUsbPortConnectChange
:
598 // Clear connect status change
600 State
|= PORTSC_CONN_CHANGE
;
601 EhcWriteOpReg (Ehc
, Offset
, State
);
604 case EfiUsbPortEnableChange
:
606 // Clear enable status change
608 State
|= PORTSC_ENABLE_CHANGE
;
609 EhcWriteOpReg (Ehc
, Offset
, State
);
612 case EfiUsbPortOverCurrentChange
:
614 // Clear PortOverCurrent change
616 State
|= PORTSC_OVERCUR_CHANGE
;
617 EhcWriteOpReg (Ehc
, Offset
, State
);
620 case EfiUsbPortPower
:
622 // Clear port power bit when PPC is 1
624 if ((Ehc
->HcCapParams
& HCSP_PPC
) == HCSP_PPC
) {
625 State
&= ~PORTSC_POWER
;
626 EhcWriteOpReg (Ehc
, Offset
, State
);
629 case EfiUsbPortSuspendChange
:
630 case EfiUsbPortResetChange
:
632 // Not supported or not related operation
637 Status
= EFI_INVALID_PARAMETER
;
642 DEBUG ((EFI_D_INFO
, "EhcClearRootHubPortFeature: exit status %r\n", Status
));
643 gBS
->RestoreTPL (OldTpl
);
649 Submits control transfer to a target USB device.
651 @param This This EFI_USB2_HC_PROTOCOL instance.
652 @param DeviceAddress The target device address.
653 @param DeviceSpeed Target device speed.
654 @param MaximumPacketLength Maximum packet size the default control transfer
655 endpoint is capable of sending or receiving.
656 @param Request USB device request to send.
657 @param TransferDirection Specifies the data direction for the data stage
658 @param Data Data buffer to be transmitted or received from USB
660 @param DataLength The size (in bytes) of the data buffer.
661 @param TimeOut Indicates the maximum timeout, in millisecond.
662 @param Translator Transaction translator to be used by this device.
663 @param TransferResult Return the result of this control transfer.
665 @retval EFI_SUCCESS Transfer was completed successfully.
666 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
667 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
668 @retval EFI_TIMEOUT Transfer failed due to timeout.
669 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
675 IN EFI_USB2_HC_PROTOCOL
*This
,
676 IN UINT8 DeviceAddress
,
677 IN UINT8 DeviceSpeed
,
678 IN UINTN MaximumPacketLength
,
679 IN EFI_USB_DEVICE_REQUEST
*Request
,
680 IN EFI_USB_DATA_DIRECTION TransferDirection
,
682 IN OUT UINTN
*DataLength
,
684 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
685 OUT UINT32
*TransferResult
695 // Validate parameters
697 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
698 return EFI_INVALID_PARAMETER
;
701 if ((TransferDirection
!= EfiUsbDataIn
) &&
702 (TransferDirection
!= EfiUsbDataOut
) &&
703 (TransferDirection
!= EfiUsbNoData
)) {
704 return EFI_INVALID_PARAMETER
;
707 if ((TransferDirection
== EfiUsbNoData
) &&
708 ((Data
!= NULL
) || (*DataLength
!= 0))) {
709 return EFI_INVALID_PARAMETER
;
712 if ((TransferDirection
!= EfiUsbNoData
) &&
713 ((Data
== NULL
) || (*DataLength
== 0))) {
714 return EFI_INVALID_PARAMETER
;
717 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
718 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
719 return EFI_INVALID_PARAMETER
;
722 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
723 return EFI_INVALID_PARAMETER
;
726 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
727 Ehc
= EHC_FROM_THIS (This
);
729 Status
= EFI_DEVICE_ERROR
;
730 *TransferResult
= EFI_USB_ERR_SYSTEM
;
732 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
733 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: HC halted at entrance\n"));
735 EhcAckAllInterrupt (Ehc
);
739 EhcAckAllInterrupt (Ehc
);
742 // Create a new URB, insert it into the asynchronous
743 // schedule list, then poll the execution status.
746 // Encode the direction in address, although default control
747 // endpoint is bidirectional. EhcCreateUrb expects this
748 // combination of Ep addr and its direction.
750 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
769 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: failed to create URB"));
771 Status
= EFI_OUT_OF_RESOURCES
;
775 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
776 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
777 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
780 // Get the status from URB. The result is updated in EhcCheckUrbResult
781 // which is called by EhcExecTransfer
783 *TransferResult
= Urb
->Result
;
784 *DataLength
= Urb
->Completed
;
786 if (*TransferResult
== EFI_USB_NOERROR
) {
787 Status
= EFI_SUCCESS
;
790 EhcAckAllInterrupt (Ehc
);
791 EhcFreeUrb (Ehc
, Urb
);
794 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
795 gBS
->RestoreTPL (OldTpl
);
797 if (EFI_ERROR (Status
)) {
798 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
806 Submits bulk transfer to a bulk endpoint of a USB device.
808 @param This This EFI_USB2_HC_PROTOCOL instance.
809 @param DeviceAddress Target device address.
810 @param EndPointAddress Endpoint number and its direction in bit 7.
811 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
813 @param MaximumPacketLength Maximum packet size the endpoint is capable of
814 sending or receiving.
815 @param DataBuffersNumber Number of data buffers prepared for the transfer.
816 @param Data Array of pointers to the buffers of data to transmit
817 from or receive into.
818 @param DataLength The lenght of the data buffer.
819 @param DataToggle On input, the initial data toggle for the transfer;
820 On output, it is updated to to next data toggle to
821 use of the subsequent bulk transfer.
822 @param TimeOut Indicates the maximum time, in millisecond, which
823 the transfer is allowed to complete.
824 @param Translator A pointr to the transaction translator data.
825 @param TransferResult A pointer to the detailed result information of the
828 @retval EFI_SUCCESS The transfer was completed successfully.
829 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
830 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
831 @retval EFI_TIMEOUT The transfer failed due to timeout.
832 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
838 IN EFI_USB2_HC_PROTOCOL
*This
,
839 IN UINT8 DeviceAddress
,
840 IN UINT8 EndPointAddress
,
841 IN UINT8 DeviceSpeed
,
842 IN UINTN MaximumPacketLength
,
843 IN UINT8 DataBuffersNumber
,
844 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
845 IN OUT UINTN
*DataLength
,
846 IN OUT UINT8
*DataToggle
,
848 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
849 OUT UINT32
*TransferResult
858 // Validate the parameters
860 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
861 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
862 return EFI_INVALID_PARAMETER
;
865 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
866 return EFI_INVALID_PARAMETER
;
869 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
870 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
871 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
872 return EFI_INVALID_PARAMETER
;
875 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
876 Ehc
= EHC_FROM_THIS (This
);
878 *TransferResult
= EFI_USB_ERR_SYSTEM
;
879 Status
= EFI_DEVICE_ERROR
;
881 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
882 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: HC is halted\n"));
884 EhcAckAllInterrupt (Ehc
);
888 EhcAckAllInterrupt (Ehc
);
891 // Create a new URB, insert it into the asynchronous
892 // schedule list, then poll the execution status.
912 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: failed to create URB\n"));
914 Status
= EFI_OUT_OF_RESOURCES
;
918 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
919 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
920 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
922 *TransferResult
= Urb
->Result
;
923 *DataLength
= Urb
->Completed
;
924 *DataToggle
= Urb
->DataToggle
;
926 if (*TransferResult
== EFI_USB_NOERROR
) {
927 Status
= EFI_SUCCESS
;
930 EhcAckAllInterrupt (Ehc
);
931 EhcFreeUrb (Ehc
, Urb
);
934 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
935 gBS
->RestoreTPL (OldTpl
);
937 if (EFI_ERROR (Status
)) {
938 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
946 Submits an asynchronous interrupt transfer to an
947 interrupt endpoint of a USB device.
949 @param This This EFI_USB2_HC_PROTOCOL instance.
950 @param DeviceAddress Target device address.
951 @param EndPointAddress Endpoint number and its direction encoded in bit 7
952 @param DeviceSpeed Indicates device speed.
953 @param MaximumPacketLength Maximum packet size the target endpoint is capable
954 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
955 transfer If FALSE, to remove the specified
956 asynchronous interrupt.
957 @param DataToggle On input, the initial data toggle to use; on output,
958 it is updated to indicate the next data toggle.
959 @param PollingInterval The he interval, in milliseconds, that the transfer
961 @param DataLength The length of data to receive at the rate specified
963 @param Translator Transaction translator to use.
964 @param CallBackFunction Function to call at the rate specified by
966 @param Context Context to CallBackFunction.
968 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
969 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
970 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
971 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
976 EhcAsyncInterruptTransfer (
977 IN EFI_USB2_HC_PROTOCOL
* This
,
978 IN UINT8 DeviceAddress
,
979 IN UINT8 EndPointAddress
,
980 IN UINT8 DeviceSpeed
,
981 IN UINTN MaximumPacketLength
,
982 IN BOOLEAN IsNewTransfer
,
983 IN OUT UINT8
*DataToggle
,
984 IN UINTN PollingInterval
,
986 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
987 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
988 IN VOID
*Context OPTIONAL
998 // Validate parameters
1000 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1001 return EFI_INVALID_PARAMETER
;
1004 if (IsNewTransfer
) {
1005 if (DataLength
== 0) {
1006 return EFI_INVALID_PARAMETER
;
1009 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1010 return EFI_INVALID_PARAMETER
;
1013 if ((PollingInterval
> 255) || (PollingInterval
< 1)) {
1014 return EFI_INVALID_PARAMETER
;
1018 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1019 Ehc
= EHC_FROM_THIS (This
);
1022 // Delete Async interrupt transfer request. DataToggle will return
1023 // the next data toggle to use.
1025 if (!IsNewTransfer
) {
1026 Status
= EhciDelAsyncIntTransfer (Ehc
, DeviceAddress
, EndPointAddress
, DataToggle
);
1028 DEBUG ((EFI_D_INFO
, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status
));
1032 Status
= EFI_SUCCESS
;
1034 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1035 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: HC is halt\n"));
1036 EhcAckAllInterrupt (Ehc
);
1038 Status
= EFI_DEVICE_ERROR
;
1042 EhcAckAllInterrupt (Ehc
);
1044 Data
= AllocatePool (DataLength
);
1047 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1049 Status
= EFI_OUT_OF_RESOURCES
;
1053 Urb
= EhcCreateUrb (
1059 MaximumPacketLength
,
1061 EHC_INT_TRANSFER_ASYNC
,
1071 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1073 gBS
->FreePool (Data
);
1074 Status
= EFI_OUT_OF_RESOURCES
;
1079 // New asynchronous transfer must inserted to the head.
1080 // Check the comments in EhcMoniteAsyncRequests
1082 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1083 InsertHeadList (&Ehc
->AsyncIntTransfers
, &Urb
->UrbList
);
1086 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1087 gBS
->RestoreTPL (OldTpl
);
1094 Submits synchronous interrupt transfer to an interrupt endpoint
1097 @param This This EFI_USB2_HC_PROTOCOL instance.
1098 @param DeviceAddress Target device address.
1099 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1100 @param DeviceSpeed Indicates device speed.
1101 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1102 of sending or receiving.
1103 @param Data Buffer of data that will be transmitted to USB
1104 device or received from USB device.
1105 @param DataLength On input, the size, in bytes, of the data buffer; On
1106 output, the number of bytes transferred.
1107 @param DataToggle On input, the initial data toggle to use; on output,
1108 it is updated to indicate the next data toggle.
1109 @param TimeOut Maximum time, in second, to complete.
1110 @param Translator Transaction translator to use.
1111 @param TransferResult Variable to receive the transfer result.
1113 @return EFI_SUCCESS The transfer was completed successfully.
1114 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1115 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1116 @return EFI_TIMEOUT The transfer failed due to timeout.
1117 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1122 EhcSyncInterruptTransfer (
1123 IN EFI_USB2_HC_PROTOCOL
*This
,
1124 IN UINT8 DeviceAddress
,
1125 IN UINT8 EndPointAddress
,
1126 IN UINT8 DeviceSpeed
,
1127 IN UINTN MaximumPacketLength
,
1129 IN OUT UINTN
*DataLength
,
1130 IN OUT UINT8
*DataToggle
,
1132 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1133 OUT UINT32
*TransferResult
1142 // Validates parameters
1144 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
1145 (Data
== NULL
) || (TransferResult
== NULL
)) {
1146 return EFI_INVALID_PARAMETER
;
1149 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1150 return EFI_INVALID_PARAMETER
;
1153 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1154 return EFI_INVALID_PARAMETER
;
1157 if (((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) ||
1158 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1159 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 3072))) {
1160 return EFI_INVALID_PARAMETER
;
1163 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1164 Ehc
= EHC_FROM_THIS (This
);
1166 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1167 Status
= EFI_DEVICE_ERROR
;
1169 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1170 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: HC is halt\n"));
1172 EhcAckAllInterrupt (Ehc
);
1176 EhcAckAllInterrupt (Ehc
);
1178 Urb
= EhcCreateUrb (
1184 MaximumPacketLength
,
1186 EHC_INT_TRANSFER_SYNC
,
1196 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: failed to create URB\n"));
1198 Status
= EFI_OUT_OF_RESOURCES
;
1202 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1203 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1204 EhcUnlinkQhFromPeriod (Ehc
, Urb
->Qh
);
1206 *TransferResult
= Urb
->Result
;
1207 *DataLength
= Urb
->Completed
;
1208 *DataToggle
= Urb
->DataToggle
;
1210 if (*TransferResult
== EFI_USB_NOERROR
) {
1211 Status
= EFI_SUCCESS
;
1215 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1216 gBS
->RestoreTPL (OldTpl
);
1218 if (EFI_ERROR (Status
)) {
1219 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1227 Submits isochronous transfer to a target USB device.
1229 @param This This EFI_USB2_HC_PROTOCOL instance.
1230 @param DeviceAddress Target device address.
1231 @param EndPointAddress End point address with its direction.
1232 @param DeviceSpeed Device speed, Low speed device doesn't support this
1234 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1235 sending or receiving.
1236 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1237 @param Data Array of pointers to the buffers of data that will
1238 be transmitted to USB device or received from USB
1240 @param DataLength The size, in bytes, of the data buffer.
1241 @param Translator Transaction translator to use.
1242 @param TransferResult Variable to receive the transfer result.
1244 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1249 EhcIsochronousTransfer (
1250 IN EFI_USB2_HC_PROTOCOL
*This
,
1251 IN UINT8 DeviceAddress
,
1252 IN UINT8 EndPointAddress
,
1253 IN UINT8 DeviceSpeed
,
1254 IN UINTN MaximumPacketLength
,
1255 IN UINT8 DataBuffersNumber
,
1256 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1257 IN UINTN DataLength
,
1258 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1259 OUT UINT32
*TransferResult
1262 return EFI_UNSUPPORTED
;
1267 Submits Async isochronous transfer to a target USB device.
1269 @param This This EFI_USB2_HC_PROTOCOL instance.
1270 @param DeviceAddress Target device address.
1271 @param EndPointAddress End point address with its direction.
1272 @param DeviceSpeed Device speed, Low speed device doesn't support this
1274 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1275 sending or receiving.
1276 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1277 @param Data Array of pointers to the buffers of data that will
1278 be transmitted to USB device or received from USB
1280 @param DataLength The size, in bytes, of the data buffer.
1281 @param Translator Transaction translator to use.
1282 @param IsochronousCallBack Function to be called when the transfer complete.
1283 @param Context Context passed to the call back function as
1286 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1291 EhcAsyncIsochronousTransfer (
1292 IN EFI_USB2_HC_PROTOCOL
*This
,
1293 IN UINT8 DeviceAddress
,
1294 IN UINT8 EndPointAddress
,
1295 IN UINT8 DeviceSpeed
,
1296 IN UINTN MaximumPacketLength
,
1297 IN UINT8 DataBuffersNumber
,
1298 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1299 IN UINTN DataLength
,
1300 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1301 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1305 return EFI_UNSUPPORTED
;
1309 Entry point for EFI drivers.
1311 @param ImageHandle EFI_HANDLE.
1312 @param SystemTable EFI_SYSTEM_TABLE.
1314 @return EFI_SUCCESS Success.
1315 EFI_DEVICE_ERROR Fail.
1320 EhcDriverEntryPoint (
1321 IN EFI_HANDLE ImageHandle
,
1322 IN EFI_SYSTEM_TABLE
*SystemTable
1325 return EfiLibInstallDriverBindingComponentName2 (
1328 &gEhciDriverBinding
,
1330 &gEhciComponentName
,
1331 &gEhciComponentName2
1337 Test to see if this driver supports ControllerHandle. Any
1338 ControllerHandle that has Usb2HcProtocol installed will
1341 @param This Protocol instance pointer.
1342 @param Controller Handle of device to test.
1343 @param RemainingDevicePath Not used.
1345 @return EFI_SUCCESS This driver supports this device.
1346 @return EFI_UNSUPPORTED This driver does not support this device.
1351 EhcDriverBindingSupported (
1352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1353 IN EFI_HANDLE Controller
,
1354 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1358 EFI_PCI_IO_PROTOCOL
*PciIo
;
1359 USB_CLASSC UsbClassCReg
;
1362 // Test whether there is PCI IO Protocol attached on the controller handle.
1364 Status
= gBS
->OpenProtocol (
1366 &gEfiPciIoProtocolGuid
,
1368 This
->DriverBindingHandle
,
1370 EFI_OPEN_PROTOCOL_BY_DRIVER
1373 if (EFI_ERROR (Status
)) {
1374 return EFI_UNSUPPORTED
;
1377 Status
= PciIo
->Pci
.Read (
1380 PCI_CLASSCODE_OFFSET
,
1381 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1385 if (EFI_ERROR (Status
)) {
1386 Status
= EFI_UNSUPPORTED
;
1391 // Test whether the controller belongs to Ehci type
1393 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) || (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
)
1394 || ((UsbClassCReg
.ProgInterface
!= PCI_IF_EHCI
) && (UsbClassCReg
.ProgInterface
!=PCI_IF_UHCI
))) {
1396 Status
= EFI_UNSUPPORTED
;
1400 gBS
->CloseProtocol (
1402 &gEfiPciIoProtocolGuid
,
1403 This
->DriverBindingHandle
,
1411 Get the usb debug port related information.
1413 @param Ehc The EHCI device.
1415 @retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
1416 @retval Others The usb host controller does not supported usb debug port capability.
1420 EhcGetUsbDebugPortInfo (
1424 EFI_PCI_IO_PROTOCOL
*PciIo
;
1426 UINT8 CapabilityPtr
;
1431 ASSERT (Ehc
->PciIo
!= NULL
);
1435 // Detect if the EHCI host controller support Capaility Pointer.
1437 Status
= PciIo
->Pci
.Read (
1440 PCI_PRIMARY_STATUS_OFFSET
,
1445 if (EFI_ERROR (Status
)) {
1449 if ((PciStatus
& EFI_PCI_STATUS_CAPABILITY
) == 0) {
1451 // The Pci Device Doesn't Support Capability Pointer.
1453 return EFI_UNSUPPORTED
;
1457 // Get Pointer To Capability List
1459 Status
= PciIo
->Pci
.Read (
1462 PCI_CAPBILITY_POINTER_OFFSET
,
1467 if (EFI_ERROR (Status
)) {
1472 // Find Capability ID 0xA, Which Is For Debug Port
1474 while (CapabilityPtr
!= 0) {
1475 Status
= PciIo
->Pci
.Read (
1483 if (EFI_ERROR (Status
)) {
1487 if (CapabilityId
== EHC_DEBUG_PORT_CAP_ID
) {
1491 Status
= PciIo
->Pci
.Read (
1499 if (EFI_ERROR (Status
)) {
1505 // No Debug Port Capability Found
1507 if (CapabilityPtr
== 0) {
1508 return EFI_UNSUPPORTED
;
1512 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1514 Status
= PciIo
->Pci
.Read (
1522 if (EFI_ERROR (Status
)) {
1526 Ehc
->DebugPortOffset
= DebugPort
& 0x1FFF;
1527 Ehc
->DebugPortBarNum
= (DebugPort
>> 13) - 1;
1528 Ehc
->DebugPortNum
= (UINT8
)((Ehc
->HcStructParams
& 0x00F00000) >> 20);
1535 Create and initialize a USB2_HC_DEV.
1537 @param PciIo The PciIo on this device.
1538 @param OriginalPciAttributes Original PCI attributes.
1540 @return The allocated and initialized USB2_HC_DEV structure if created,
1546 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1547 IN UINT64 OriginalPciAttributes
1553 Ehc
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
1560 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1562 Ehc
->Signature
= USB2_HC_DEV_SIGNATURE
;
1564 Ehc
->Usb2Hc
.GetCapability
= EhcGetCapability
;
1565 Ehc
->Usb2Hc
.Reset
= EhcReset
;
1566 Ehc
->Usb2Hc
.GetState
= EhcGetState
;
1567 Ehc
->Usb2Hc
.SetState
= EhcSetState
;
1568 Ehc
->Usb2Hc
.ControlTransfer
= EhcControlTransfer
;
1569 Ehc
->Usb2Hc
.BulkTransfer
= EhcBulkTransfer
;
1570 Ehc
->Usb2Hc
.AsyncInterruptTransfer
= EhcAsyncInterruptTransfer
;
1571 Ehc
->Usb2Hc
.SyncInterruptTransfer
= EhcSyncInterruptTransfer
;
1572 Ehc
->Usb2Hc
.IsochronousTransfer
= EhcIsochronousTransfer
;
1573 Ehc
->Usb2Hc
.AsyncIsochronousTransfer
= EhcAsyncIsochronousTransfer
;
1574 Ehc
->Usb2Hc
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1575 Ehc
->Usb2Hc
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1576 Ehc
->Usb2Hc
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1577 Ehc
->Usb2Hc
.MajorRevision
= 0x2;
1578 Ehc
->Usb2Hc
.MinorRevision
= 0x0;
1581 Ehc
->OriginalPciAttributes
= OriginalPciAttributes
;
1583 InitializeListHead (&Ehc
->AsyncIntTransfers
);
1585 Ehc
->HcStructParams
= EhcReadCapRegister (Ehc
, EHC_HCSPARAMS_OFFSET
);
1586 Ehc
->HcCapParams
= EhcReadCapRegister (Ehc
, EHC_HCCPARAMS_OFFSET
);
1587 Ehc
->CapLen
= EhcReadCapRegister (Ehc
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1589 DEBUG ((EFI_D_INFO
, "EhcCreateUsb2Hc: capability length %d\n", Ehc
->CapLen
));
1592 // EHCI Controllers with a CapLen of 0 are ignored.
1594 if (Ehc
->CapLen
== 0) {
1595 gBS
->FreePool (Ehc
);
1599 EhcGetUsbDebugPortInfo (Ehc
);
1602 // Create AsyncRequest Polling Timer
1604 Status
= gBS
->CreateEvent (
1605 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1607 EhcMonitorAsyncRequests
,
1612 if (EFI_ERROR (Status
)) {
1613 gBS
->FreePool (Ehc
);
1621 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1623 @param Event Pointer to this event
1624 @param Context Event hanlder private data
1629 EhcExitBootService (
1637 Ehc
= (USB2_HC_DEV
*) Context
;
1640 // Reset the Host Controller
1642 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1647 Starting the Usb EHCI Driver.
1649 @param This Protocol instance pointer.
1650 @param Controller Handle of device to test.
1651 @param RemainingDevicePath Not used.
1653 @return EFI_SUCCESS supports this device.
1654 @return EFI_UNSUPPORTED do not support this device.
1655 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1656 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1661 EhcDriverBindingStart (
1662 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1663 IN EFI_HANDLE Controller
,
1664 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1669 EFI_PCI_IO_PROTOCOL
*PciIo
;
1670 EFI_PCI_IO_PROTOCOL
*Instance
;
1672 UINT64 OriginalPciAttributes
;
1673 BOOLEAN PciAttributesSaved
;
1674 USB_CLASSC UsbClassCReg
;
1675 EFI_HANDLE
*HandleBuffer
;
1676 UINTN NumberOfHandles
;
1678 UINTN UhciSegmentNumber
;
1679 UINTN UhciBusNumber
;
1680 UINTN UhciDeviceNumber
;
1681 UINTN UhciFunctionNumber
;
1682 UINTN EhciSegmentNumber
;
1683 UINTN EhciBusNumber
;
1684 UINTN EhciDeviceNumber
;
1685 UINTN EhciFunctionNumber
;
1689 // Open the PciIo Protocol, then enable the USB host controller
1691 Status
= gBS
->OpenProtocol (
1693 &gEfiPciIoProtocolGuid
,
1695 This
->DriverBindingHandle
,
1697 EFI_OPEN_PROTOCOL_BY_DRIVER
1700 if (EFI_ERROR (Status
)) {
1704 PciAttributesSaved
= FALSE
;
1706 // Save original PCI attributes
1708 Status
= PciIo
->Attributes (
1710 EfiPciIoAttributeOperationGet
,
1712 &OriginalPciAttributes
1715 if (EFI_ERROR (Status
)) {
1718 PciAttributesSaved
= TRUE
;
1720 Status
= PciIo
->Attributes (
1722 EfiPciIoAttributeOperationSupported
,
1726 if (!EFI_ERROR (Status
)) {
1727 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1728 Status
= PciIo
->Attributes (
1730 EfiPciIoAttributeOperationEnable
,
1736 if (EFI_ERROR (Status
)) {
1737 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to enable controller\n"));
1742 // Get the Pci device class code.
1744 Status
= PciIo
->Pci
.Read (
1747 PCI_CLASSCODE_OFFSET
,
1748 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1752 if (EFI_ERROR (Status
)) {
1753 Status
= EFI_UNSUPPORTED
;
1757 // determine if the device is UHCI host controller or not. If yes, then find out the
1758 // companion usb ehci host controller and force EHCI driver get attached to it before
1759 // UHCI driver attaches to UHCI host controller.
1761 if ((UsbClassCReg
.ProgInterface
== PCI_IF_UHCI
) &&
1762 (UsbClassCReg
.BaseCode
== PCI_CLASS_SERIAL
) &&
1763 (UsbClassCReg
.SubClassCode
== PCI_CLASS_SERIAL_USB
)) {
1764 Status
= PciIo
->GetLocation (
1771 if (EFI_ERROR (Status
)) {
1775 Status
= gBS
->LocateHandleBuffer (
1777 &gEfiPciIoProtocolGuid
,
1782 if (EFI_ERROR (Status
)) {
1786 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
1788 // Get the device path on this handle
1790 Status
= gBS
->HandleProtocol (
1791 HandleBuffer
[Index
],
1792 &gEfiPciIoProtocolGuid
,
1795 ASSERT_EFI_ERROR (Status
);
1797 Status
= Instance
->Pci
.Read (
1800 PCI_CLASSCODE_OFFSET
,
1801 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1805 if (EFI_ERROR (Status
)) {
1806 Status
= EFI_UNSUPPORTED
;
1810 if ((UsbClassCReg
.ProgInterface
== PCI_IF_EHCI
) &&
1811 (UsbClassCReg
.BaseCode
== PCI_CLASS_SERIAL
) &&
1812 (UsbClassCReg
.SubClassCode
== PCI_CLASS_SERIAL_USB
)) {
1813 Status
= Instance
->GetLocation (
1820 if (EFI_ERROR (Status
)) {
1824 // Currently, the judgment on the companion usb host controller is through the
1825 // same bus number, which may vary on different platform.
1827 if (EhciBusNumber
== UhciBusNumber
) {
1828 gBS
->CloseProtocol (
1830 &gEfiPciIoProtocolGuid
,
1831 This
->DriverBindingHandle
,
1834 EhcDriverBindingStart(This
, HandleBuffer
[Index
], NULL
);
1838 Status
= EFI_NOT_FOUND
;
1843 // Create then install USB2_HC_PROTOCOL
1845 Ehc
= EhcCreateUsb2Hc (PciIo
, OriginalPciAttributes
);
1848 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1850 Status
= EFI_OUT_OF_RESOURCES
;
1854 Status
= gBS
->InstallProtocolInterface (
1856 &gEfiUsb2HcProtocolGuid
,
1857 EFI_NATIVE_INTERFACE
,
1861 if (EFI_ERROR (Status
)) {
1862 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1867 // Robustnesss improvement such as for Duet platform
1868 // Default is not required.
1870 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1871 EhcClearLegacySupport (Ehc
);
1874 if (Ehc
->DebugPortNum
!= 0) {
1875 State
= EhcReadDbgRegister(Ehc
, 0);
1876 if ((State
& (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) != (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) {
1877 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1881 Status
= EhcInitHC (Ehc
);
1883 if (EFI_ERROR (Status
)) {
1884 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to init host controller\n"));
1885 goto UNINSTALL_USBHC
;
1889 // Start the asynchronous interrupt monitor
1891 Status
= gBS
->SetTimer (Ehc
->PollTimer
, TimerPeriodic
, EHC_ASYNC_POLL_INTERVAL
);
1893 if (EFI_ERROR (Status
)) {
1894 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1896 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1897 goto UNINSTALL_USBHC
;
1901 // Create event to stop the HC when exit boot service.
1903 Status
= gBS
->CreateEventEx (
1908 &gEfiEventExitBootServicesGuid
,
1909 &Ehc
->ExitBootServiceEvent
1911 if (EFI_ERROR (Status
)) {
1912 goto UNINSTALL_USBHC
;
1916 // Install the component name protocol, don't fail the start
1917 // because of something for display.
1921 gEhciComponentName
.SupportedLanguages
,
1922 &Ehc
->ControllerNameTable
,
1923 L
"Enhanced Host Controller (USB 2.0)",
1928 gEhciComponentName2
.SupportedLanguages
,
1929 &Ehc
->ControllerNameTable
,
1930 L
"Enhanced Host Controller (USB 2.0)",
1935 DEBUG ((EFI_D_INFO
, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller
));
1939 gBS
->UninstallProtocolInterface (
1941 &gEfiUsb2HcProtocolGuid
,
1947 gBS
->CloseEvent (Ehc
->PollTimer
);
1948 gBS
->FreePool (Ehc
);
1951 if (PciAttributesSaved
) {
1953 // Restore original PCI attributes
1957 EfiPciIoAttributeOperationSet
,
1958 OriginalPciAttributes
,
1963 gBS
->CloseProtocol (
1965 &gEfiPciIoProtocolGuid
,
1966 This
->DriverBindingHandle
,
1975 Stop this driver on ControllerHandle. Support stoping any child handles
1976 created by this driver.
1978 @param This Protocol instance pointer.
1979 @param Controller Handle of device to stop driver on.
1980 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1981 @param ChildHandleBuffer List of handles for the children we need to stop.
1983 @return EFI_SUCCESS Success.
1984 @return EFI_DEVICE_ERROR Fail.
1989 EhcDriverBindingStop (
1990 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1991 IN EFI_HANDLE Controller
,
1992 IN UINTN NumberOfChildren
,
1993 IN EFI_HANDLE
*ChildHandleBuffer
1997 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1998 EFI_PCI_IO_PROTOCOL
*PciIo
;
2002 // Test whether the Controller handler passed in is a valid
2003 // Usb controller handle that should be supported, if not,
2004 // return the error status directly
2006 Status
= gBS
->OpenProtocol (
2008 &gEfiUsb2HcProtocolGuid
,
2010 This
->DriverBindingHandle
,
2012 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2015 if (EFI_ERROR (Status
)) {
2019 Ehc
= EHC_FROM_THIS (Usb2Hc
);
2023 // Stop AsyncRequest Polling timer then stop the EHCI driver
2024 // and uninstall the EHCI protocl.
2026 gBS
->SetTimer (Ehc
->PollTimer
, TimerCancel
, EHC_ASYNC_POLL_INTERVAL
);
2027 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
2029 Status
= gBS
->UninstallProtocolInterface (
2031 &gEfiUsb2HcProtocolGuid
,
2035 if (EFI_ERROR (Status
)) {
2039 if (Ehc
->PollTimer
!= NULL
) {
2040 gBS
->CloseEvent (Ehc
->PollTimer
);
2043 if (Ehc
->ExitBootServiceEvent
!= NULL
) {
2044 gBS
->CloseEvent (Ehc
->ExitBootServiceEvent
);
2049 if (Ehc
->ControllerNameTable
!= NULL
) {
2050 FreeUnicodeStringTable (Ehc
->ControllerNameTable
);
2054 // Disable routing of all ports to EHCI controller, so all ports are
2055 // routed back to the UHCI controller.
2057 EhcClearOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
2060 // Restore original PCI attributes
2064 EfiPciIoAttributeOperationSet
,
2065 Ehc
->OriginalPciAttributes
,
2069 gBS
->CloseProtocol (
2071 &gEfiPciIoProtocolGuid
,
2072 This
->DriverBindingHandle
,