3 The Ehci controller driver.
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // Two arrays used to translate the EHCI port state (change)
21 // to the UEFI protocol's port state (change).
23 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
24 {PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
25 {PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
26 {PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
27 {PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
28 {PORTSC_RESET
, USB_PORT_STAT_RESET
},
29 {PORTSC_POWER
, USB_PORT_STAT_POWER
},
30 {PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
33 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
34 {PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
35 {PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
36 {PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
39 EFI_DRIVER_BINDING_PROTOCOL
40 gEhciDriverBinding
= {
41 EhcDriverBindingSupported
,
42 EhcDriverBindingStart
,
50 Retrieves the capablility of root hub ports.
52 @param This This EFI_USB_HC_PROTOCOL instance.
53 @param MaxSpeed Max speed supported by the controller.
54 @param PortNumber Number of the root hub ports.
55 @param Is64BitCapable Whether the controller supports 64-bit memory
58 @retval EFI_SUCCESS Host controller capability were retrieved successfully.
59 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
65 IN EFI_USB2_HC_PROTOCOL
*This
,
67 OUT UINT8
*PortNumber
,
68 OUT UINT8
*Is64BitCapable
74 if ((MaxSpeed
== NULL
) || (PortNumber
== NULL
) || (Is64BitCapable
== NULL
)) {
75 return EFI_INVALID_PARAMETER
;
78 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
79 Ehc
= EHC_FROM_THIS (This
);
81 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
82 *PortNumber
= (UINT8
) (Ehc
->HcStructParams
& HCSP_NPORTS
);
83 *Is64BitCapable
= (UINT8
) (Ehc
->HcCapParams
& HCCP_64BIT
);
85 DEBUG ((EFI_D_INFO
, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber
, *Is64BitCapable
));
87 gBS
->RestoreTPL (OldTpl
);
93 Provides software reset for the USB host controller.
95 @param This This EFI_USB2_HC_PROTOCOL instance.
96 @param Attributes A bit mask of the reset operation to perform.
98 @retval EFI_SUCCESS The reset operation succeeded.
99 @retval EFI_INVALID_PARAMETER Attributes is not valid.
100 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
101 not currently supported by the host controller.
102 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
108 IN EFI_USB2_HC_PROTOCOL
*This
,
116 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
117 Ehc
= EHC_FROM_THIS (This
);
119 switch (Attributes
) {
120 case EFI_USB_HC_RESET_GLOBAL
:
122 // Flow through, same behavior as Host Controller Reset
124 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
126 // Host Controller must be Halt when Reset it
128 if (!EhcIsHalt (Ehc
)) {
129 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
131 if (EFI_ERROR (Status
)) {
132 Status
= EFI_DEVICE_ERROR
;
138 // Clean up the asynchronous transfers, currently only
139 // interrupt supports asynchronous operation.
141 EhciDelAllAsyncIntTransfers (Ehc
);
142 EhcAckAllInterrupt (Ehc
);
145 Status
= EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
147 if (EFI_ERROR (Status
)) {
151 Status
= EhcInitHC (Ehc
);
154 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
:
155 case EFI_USB_HC_RESET_HOST_WITH_DEBUG
:
156 Status
= EFI_UNSUPPORTED
;
160 Status
= EFI_INVALID_PARAMETER
;
164 DEBUG ((EFI_D_INFO
, "EhcReset: exit status %r\n", Status
));
165 gBS
->RestoreTPL (OldTpl
);
171 Retrieve the current state of the USB host controller.
173 @param This This EFI_USB2_HC_PROTOCOL instance.
174 @param State Variable to return the current host controller
177 @retval EFI_SUCCESS Host controller state was returned in State.
178 @retval EFI_INVALID_PARAMETER State is NULL.
179 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
180 retrieve the host controller's current state.
186 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
187 OUT EFI_USB_HC_STATE
*State
194 return EFI_INVALID_PARAMETER
;
197 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
198 Ehc
= EHC_FROM_THIS (This
);
200 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
201 *State
= EfiUsbHcStateHalt
;
203 *State
= EfiUsbHcStateOperational
;
206 gBS
->RestoreTPL (OldTpl
);
208 DEBUG ((EFI_D_INFO
, "EhcGetState: current state %d\n", *State
));
214 Sets the USB host controller to a specific state.
216 @param This This EFI_USB2_HC_PROTOCOL instance.
217 @param State The state of the host controller that will be set.
219 @retval EFI_SUCCESS The USB host controller was successfully placed
220 in the state specified by State.
221 @retval EFI_INVALID_PARAMETER State is invalid.
222 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
228 IN EFI_USB2_HC_PROTOCOL
*This
,
229 IN EFI_USB_HC_STATE State
235 EFI_USB_HC_STATE CurState
;
237 Status
= EhcGetState (This
, &CurState
);
239 if (EFI_ERROR (Status
)) {
240 return EFI_DEVICE_ERROR
;
243 if (CurState
== State
) {
247 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
248 Ehc
= EHC_FROM_THIS (This
);
251 case EfiUsbHcStateHalt
:
252 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
255 case EfiUsbHcStateOperational
:
256 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
)) {
257 Status
= EFI_DEVICE_ERROR
;
262 // Software must not write a one to this field unless the host controller
263 // is in the Halted state. Doing so will yield undefined results.
264 // refers to Spec[EHCI1.0-2.3.1]
266 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
267 Status
= EFI_DEVICE_ERROR
;
271 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
274 case EfiUsbHcStateSuspend
:
275 Status
= EFI_UNSUPPORTED
;
279 Status
= EFI_INVALID_PARAMETER
;
282 DEBUG ((EFI_D_INFO
, "EhcSetState: exit status %r\n", Status
));
283 gBS
->RestoreTPL (OldTpl
);
289 Retrieves the current status of a USB root hub port.
291 @param This This EFI_USB2_HC_PROTOCOL instance.
292 @param PortNumber The root hub port to retrieve the state from.
293 This value is zero-based.
294 @param PortStatus Variable to receive the port state.
296 @retval EFI_SUCCESS The status of the USB root hub port specified.
297 by PortNumber was returned in PortStatus.
298 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
299 @retval EFI_DEVICE_ERROR Can't read register.
304 EhcGetRootHubPortStatus (
305 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
306 IN CONST UINT8 PortNumber
,
307 OUT EFI_USB_PORT_STATUS
*PortStatus
319 if (PortStatus
== NULL
) {
320 return EFI_INVALID_PARAMETER
;
323 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
325 Ehc
= EHC_FROM_THIS (This
);
326 Status
= EFI_SUCCESS
;
328 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
330 if (PortNumber
>= TotalPort
) {
331 Status
= EFI_INVALID_PARAMETER
;
335 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
336 PortStatus
->PortStatus
= 0;
337 PortStatus
->PortChangeStatus
= 0;
339 State
= EhcReadOpReg (Ehc
, Offset
);
342 // Identify device speed. If in K state, it is low speed.
343 // If the port is enabled after reset, the device is of
344 // high speed. The USB bus driver should retrieve the actual
345 // port speed after reset.
347 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
348 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
350 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
351 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
355 // Convert the EHCI port/port change state to UEFI status
357 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
359 for (Index
= 0; Index
< MapSize
; Index
++) {
360 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
361 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
365 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
367 for (Index
= 0; Index
< MapSize
; Index
++) {
368 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
369 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
374 gBS
->RestoreTPL (OldTpl
);
380 Sets a feature for the specified root hub port.
382 @param This This EFI_USB2_HC_PROTOCOL instance.
383 @param PortNumber Root hub port to set.
384 @param PortFeature Feature to set.
386 @retval EFI_SUCCESS The feature specified by PortFeature was set.
387 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
388 @retval EFI_DEVICE_ERROR Can't read register.
393 EhcSetRootHubPortFeature (
394 IN EFI_USB2_HC_PROTOCOL
*This
,
396 IN EFI_USB_PORT_FEATURE PortFeature
406 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
407 Ehc
= EHC_FROM_THIS (This
);
408 Status
= EFI_SUCCESS
;
410 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
412 if (PortNumber
>= TotalPort
) {
413 Status
= EFI_INVALID_PARAMETER
;
417 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
418 State
= EhcReadOpReg (Ehc
, Offset
);
421 // Mask off the port status change bits, these bits are
424 State
&= ~PORTSC_CHANGE_MASK
;
426 switch (PortFeature
) {
427 case EfiUsbPortEnable
:
429 // Sofeware can't set this bit, Port can only be enable by
430 // EHCI as a part of the reset and enable
432 State
|= PORTSC_ENABLED
;
433 EhcWriteOpReg (Ehc
, Offset
, State
);
436 case EfiUsbPortSuspend
:
437 State
|= PORTSC_SUSPEND
;
438 EhcWriteOpReg (Ehc
, Offset
, State
);
441 case EfiUsbPortReset
:
443 // Make sure Host Controller not halt before reset it
445 if (EhcIsHalt (Ehc
)) {
446 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
448 if (EFI_ERROR (Status
)) {
449 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status
));
455 // Set one to PortReset bit must also set zero to PortEnable bit
457 State
|= PORTSC_RESET
;
458 State
&= ~PORTSC_ENABLED
;
459 EhcWriteOpReg (Ehc
, Offset
, State
);
462 case EfiUsbPortPower
:
464 // Not supported, ignore the operation
466 Status
= EFI_SUCCESS
;
469 case EfiUsbPortOwner
:
470 State
|= PORTSC_OWNER
;
471 EhcWriteOpReg (Ehc
, Offset
, State
);
475 Status
= EFI_INVALID_PARAMETER
;
479 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature: exit status %r\n", Status
));
481 gBS
->RestoreTPL (OldTpl
);
487 Clears a feature for the specified root hub port.
489 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
490 @param PortNumber Specifies the root hub port whose feature is
491 requested to be cleared.
492 @param PortFeature Indicates the feature selector associated with the
493 feature clear request.
495 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
496 for the USB root hub port specified by PortNumber.
497 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
498 @retval EFI_DEVICE_ERROR Can't read register.
503 EhcClearRootHubPortFeature (
504 IN EFI_USB2_HC_PROTOCOL
*This
,
506 IN EFI_USB_PORT_FEATURE PortFeature
516 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
517 Ehc
= EHC_FROM_THIS (This
);
518 Status
= EFI_SUCCESS
;
520 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
522 if (PortNumber
>= TotalPort
) {
523 Status
= EFI_INVALID_PARAMETER
;
527 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
528 State
= EhcReadOpReg (Ehc
, Offset
);
529 State
&= ~PORTSC_CHANGE_MASK
;
531 switch (PortFeature
) {
532 case EfiUsbPortEnable
:
534 // Clear PORT_ENABLE feature means disable port.
536 State
&= ~PORTSC_ENABLED
;
537 EhcWriteOpReg (Ehc
, Offset
, State
);
540 case EfiUsbPortSuspend
:
542 // A write of zero to this bit is ignored by the host
543 // controller. The host controller will unconditionally
544 // set this bit to a zero when:
545 // 1. software sets the Forct Port Resume bit to a zero from a one.
546 // 2. software sets the Port Reset bit to a one frome a zero.
548 State
&= ~PORSTSC_RESUME
;
549 EhcWriteOpReg (Ehc
, Offset
, State
);
552 case EfiUsbPortReset
:
554 // Clear PORT_RESET means clear the reset signal.
556 State
&= ~PORTSC_RESET
;
557 EhcWriteOpReg (Ehc
, Offset
, State
);
560 case EfiUsbPortOwner
:
562 // Clear port owner means this port owned by EHC
564 State
&= ~PORTSC_OWNER
;
565 EhcWriteOpReg (Ehc
, Offset
, State
);
568 case EfiUsbPortConnectChange
:
570 // Clear connect status change
572 State
|= PORTSC_CONN_CHANGE
;
573 EhcWriteOpReg (Ehc
, Offset
, State
);
576 case EfiUsbPortEnableChange
:
578 // Clear enable status change
580 State
|= PORTSC_ENABLE_CHANGE
;
581 EhcWriteOpReg (Ehc
, Offset
, State
);
584 case EfiUsbPortOverCurrentChange
:
586 // Clear PortOverCurrent change
588 State
|= PORTSC_OVERCUR_CHANGE
;
589 EhcWriteOpReg (Ehc
, Offset
, State
);
592 case EfiUsbPortPower
:
593 case EfiUsbPortSuspendChange
:
594 case EfiUsbPortResetChange
:
596 // Not supported or not related operation
601 Status
= EFI_INVALID_PARAMETER
;
606 DEBUG ((EFI_D_INFO
, "EhcClearRootHubPortFeature: exit status %r\n", Status
));
607 gBS
->RestoreTPL (OldTpl
);
613 Submits control transfer to a target USB device.
615 @param This This EFI_USB2_HC_PROTOCOL instance.
616 @param DeviceAddress The target device address.
617 @param DeviceSpeed Target device speed.
618 @param MaximumPacketLength Maximum packet size the default control transfer
619 endpoint is capable of sending or receiving.
620 @param Request USB device request to send.
621 @param TransferDirection Specifies the data direction for the data stage
622 @param Data Data buffer to be transmitted or received from USB
624 @param DataLength The size (in bytes) of the data buffer.
625 @param TimeOut Indicates the maximum timeout, in millisecond.
626 @param Translator Transaction translator to be used by this device.
627 @param TransferResult Return the result of this control transfer.
629 @retval EFI_SUCCESS Transfer was completed successfully.
630 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
631 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
632 @retval EFI_TIMEOUT Transfer failed due to timeout.
633 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
639 IN EFI_USB2_HC_PROTOCOL
*This
,
640 IN UINT8 DeviceAddress
,
641 IN UINT8 DeviceSpeed
,
642 IN UINTN MaximumPacketLength
,
643 IN EFI_USB_DEVICE_REQUEST
*Request
,
644 IN EFI_USB_DATA_DIRECTION TransferDirection
,
646 IN OUT UINTN
*DataLength
,
648 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
649 OUT UINT32
*TransferResult
659 // Validate parameters
661 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
662 return EFI_INVALID_PARAMETER
;
665 if ((TransferDirection
!= EfiUsbDataIn
) &&
666 (TransferDirection
!= EfiUsbDataOut
) &&
667 (TransferDirection
!= EfiUsbNoData
)) {
668 return EFI_INVALID_PARAMETER
;
671 if ((TransferDirection
== EfiUsbNoData
) &&
672 ((Data
!= NULL
) || (*DataLength
!= 0))) {
673 return EFI_INVALID_PARAMETER
;
676 if ((TransferDirection
!= EfiUsbNoData
) &&
677 ((Data
== NULL
) || (*DataLength
== 0))) {
678 return EFI_INVALID_PARAMETER
;
681 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
682 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
683 return EFI_INVALID_PARAMETER
;
686 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
687 return EFI_INVALID_PARAMETER
;
690 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
691 Ehc
= EHC_FROM_THIS (This
);
693 Status
= EFI_DEVICE_ERROR
;
694 *TransferResult
= EFI_USB_ERR_SYSTEM
;
696 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
697 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: HC halted at entrance\n"));
699 EhcAckAllInterrupt (Ehc
);
703 EhcAckAllInterrupt (Ehc
);
706 // Create a new URB, insert it into the asynchronous
707 // schedule list, then poll the execution status.
710 // Encode the direction in address, although default control
711 // endpoint is bidirectional. EhcCreateUrb expects this
712 // combination of Ep addr and its direction.
714 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
733 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: failed to create URB"));
735 Status
= EFI_OUT_OF_RESOURCES
;
739 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
740 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
741 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
744 // Get the status from URB. The result is updated in EhcCheckUrbResult
745 // which is called by EhcExecTransfer
747 *TransferResult
= Urb
->Result
;
748 *DataLength
= Urb
->Completed
;
750 if (*TransferResult
== EFI_USB_NOERROR
) {
751 Status
= EFI_SUCCESS
;
754 EhcAckAllInterrupt (Ehc
);
755 EhcFreeUrb (Ehc
, Urb
);
758 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
759 gBS
->RestoreTPL (OldTpl
);
761 if (EFI_ERROR (Status
)) {
762 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
770 Submits bulk transfer to a bulk endpoint of a USB device.
772 @param This This EFI_USB2_HC_PROTOCOL instance.
773 @param DeviceAddress Target device address.
774 @param EndPointAddress Endpoint number and its direction in bit 7.
775 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
777 @param MaximumPacketLength Maximum packet size the endpoint is capable of
778 sending or receiving.
779 @param DataBuffersNumber Number of data buffers prepared for the transfer.
780 @param Data Array of pointers to the buffers of data to transmit
781 from or receive into.
782 @param DataLength The lenght of the data buffer.
783 @param DataToggle On input, the initial data toggle for the transfer;
784 On output, it is updated to to next data toggle to
785 use of the subsequent bulk transfer.
786 @param TimeOut Indicates the maximum time, in millisecond, which
787 the transfer is allowed to complete.
788 @param Translator A pointr to the transaction translator data.
789 @param TransferResult A pointer to the detailed result information of the
792 @retval EFI_SUCCESS The transfer was completed successfully.
793 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
794 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
795 @retval EFI_TIMEOUT The transfer failed due to timeout.
796 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
802 IN EFI_USB2_HC_PROTOCOL
*This
,
803 IN UINT8 DeviceAddress
,
804 IN UINT8 EndPointAddress
,
805 IN UINT8 DeviceSpeed
,
806 IN UINTN MaximumPacketLength
,
807 IN UINT8 DataBuffersNumber
,
808 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
809 IN OUT UINTN
*DataLength
,
810 IN OUT UINT8
*DataToggle
,
812 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
813 OUT UINT32
*TransferResult
822 // Validate the parameters
824 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
825 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
826 return EFI_INVALID_PARAMETER
;
829 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
830 return EFI_INVALID_PARAMETER
;
833 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
834 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
835 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
836 return EFI_INVALID_PARAMETER
;
839 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
840 Ehc
= EHC_FROM_THIS (This
);
842 *TransferResult
= EFI_USB_ERR_SYSTEM
;
843 Status
= EFI_DEVICE_ERROR
;
845 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
846 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: HC is halted\n"));
848 EhcAckAllInterrupt (Ehc
);
852 EhcAckAllInterrupt (Ehc
);
855 // Create a new URB, insert it into the asynchronous
856 // schedule list, then poll the execution status.
876 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: failed to create URB\n"));
878 Status
= EFI_OUT_OF_RESOURCES
;
882 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
883 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
884 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
886 *TransferResult
= Urb
->Result
;
887 *DataLength
= Urb
->Completed
;
888 *DataToggle
= Urb
->DataToggle
;
890 if (*TransferResult
== EFI_USB_NOERROR
) {
891 Status
= EFI_SUCCESS
;
894 EhcAckAllInterrupt (Ehc
);
895 EhcFreeUrb (Ehc
, Urb
);
898 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
899 gBS
->RestoreTPL (OldTpl
);
901 if (EFI_ERROR (Status
)) {
902 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
910 Submits an asynchronous interrupt transfer to an
911 interrupt endpoint of a USB device.
913 @param This This EFI_USB2_HC_PROTOCOL instance.
914 @param DeviceAddress Target device address.
915 @param EndPointAddress Endpoint number and its direction encoded in bit 7
916 @param DeviceSpeed Indicates device speed.
917 @param MaximumPacketLength Maximum packet size the target endpoint is capable
918 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
919 transfer If FALSE, to remove the specified
920 asynchronous interrupt.
921 @param DataToggle On input, the initial data toggle to use; on output,
922 it is updated to indicate the next data toggle.
923 @param PollingInterval The he interval, in milliseconds, that the transfer
925 @param DataLength The length of data to receive at the rate specified
927 @param Translator Transaction translator to use.
928 @param CallBackFunction Function to call at the rate specified by
930 @param Context Context to CallBackFunction.
932 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
933 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
934 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
935 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
940 EhcAsyncInterruptTransfer (
941 IN EFI_USB2_HC_PROTOCOL
* This
,
942 IN UINT8 DeviceAddress
,
943 IN UINT8 EndPointAddress
,
944 IN UINT8 DeviceSpeed
,
945 IN UINTN MaximumPacketLength
,
946 IN BOOLEAN IsNewTransfer
,
947 IN OUT UINT8
*DataToggle
,
948 IN UINTN PollingInterval
,
950 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
951 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
952 IN VOID
*Context OPTIONAL
962 // Validate parameters
964 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
965 return EFI_INVALID_PARAMETER
;
969 if (DataLength
== 0) {
970 return EFI_INVALID_PARAMETER
;
973 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
974 return EFI_INVALID_PARAMETER
;
977 if ((PollingInterval
> 255) || (PollingInterval
< 1)) {
978 return EFI_INVALID_PARAMETER
;
982 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
983 Ehc
= EHC_FROM_THIS (This
);
986 // Delete Async interrupt transfer request. DataToggle will return
987 // the next data toggle to use.
989 if (!IsNewTransfer
) {
990 Status
= EhciDelAsyncIntTransfer (Ehc
, DeviceAddress
, EndPointAddress
, DataToggle
);
992 DEBUG ((EFI_D_INFO
, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status
));
996 Status
= EFI_SUCCESS
;
998 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
999 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: HC is halt\n"));
1000 EhcAckAllInterrupt (Ehc
);
1002 Status
= EFI_DEVICE_ERROR
;
1006 EhcAckAllInterrupt (Ehc
);
1008 Data
= AllocatePool (DataLength
);
1011 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1013 Status
= EFI_OUT_OF_RESOURCES
;
1017 Urb
= EhcCreateUrb (
1023 MaximumPacketLength
,
1025 EHC_INT_TRANSFER_ASYNC
,
1035 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1037 gBS
->FreePool (Data
);
1038 Status
= EFI_OUT_OF_RESOURCES
;
1043 // New asynchronous transfer must inserted to the head.
1044 // Check the comments in EhcMoniteAsyncRequests
1046 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1047 InsertHeadList (&Ehc
->AsyncIntTransfers
, &Urb
->UrbList
);
1050 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1051 gBS
->RestoreTPL (OldTpl
);
1058 Submits synchronous interrupt transfer to an interrupt endpoint
1061 @param This This EFI_USB2_HC_PROTOCOL instance.
1062 @param DeviceAddress Target device address.
1063 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1064 @param DeviceSpeed Indicates device speed.
1065 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1066 of sending or receiving.
1067 @param Data Buffer of data that will be transmitted to USB
1068 device or received from USB device.
1069 @param DataLength On input, the size, in bytes, of the data buffer; On
1070 output, the number of bytes transferred.
1071 @param DataToggle On input, the initial data toggle to use; on output,
1072 it is updated to indicate the next data toggle.
1073 @param TimeOut Maximum time, in second, to complete.
1074 @param Translator Transaction translator to use.
1075 @param TransferResult Variable to receive the transfer result.
1077 @return EFI_SUCCESS The transfer was completed successfully.
1078 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1079 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1080 @return EFI_TIMEOUT The transfer failed due to timeout.
1081 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1086 EhcSyncInterruptTransfer (
1087 IN EFI_USB2_HC_PROTOCOL
*This
,
1088 IN UINT8 DeviceAddress
,
1089 IN UINT8 EndPointAddress
,
1090 IN UINT8 DeviceSpeed
,
1091 IN UINTN MaximumPacketLength
,
1093 IN OUT UINTN
*DataLength
,
1094 IN OUT UINT8
*DataToggle
,
1096 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1097 OUT UINT32
*TransferResult
1106 // Validates parameters
1108 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
1109 (Data
== NULL
) || (TransferResult
== NULL
)) {
1110 return EFI_INVALID_PARAMETER
;
1113 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1114 return EFI_INVALID_PARAMETER
;
1117 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1118 return EFI_INVALID_PARAMETER
;
1121 if (((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) ||
1122 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1123 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 3072))) {
1124 return EFI_INVALID_PARAMETER
;
1127 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1128 Ehc
= EHC_FROM_THIS (This
);
1130 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1131 Status
= EFI_DEVICE_ERROR
;
1133 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1134 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: HC is halt\n"));
1136 EhcAckAllInterrupt (Ehc
);
1140 EhcAckAllInterrupt (Ehc
);
1142 Urb
= EhcCreateUrb (
1148 MaximumPacketLength
,
1150 EHC_INT_TRANSFER_SYNC
,
1160 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: failed to create URB\n"));
1162 Status
= EFI_OUT_OF_RESOURCES
;
1166 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1167 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1168 EhcUnlinkQhFromPeriod (Ehc
, Urb
->Qh
);
1170 *TransferResult
= Urb
->Result
;
1171 *DataLength
= Urb
->Completed
;
1172 *DataToggle
= Urb
->DataToggle
;
1174 if (*TransferResult
== EFI_USB_NOERROR
) {
1175 Status
= EFI_SUCCESS
;
1179 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1180 gBS
->RestoreTPL (OldTpl
);
1182 if (EFI_ERROR (Status
)) {
1183 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1191 Submits isochronous transfer to a target USB device.
1193 @param This This EFI_USB2_HC_PROTOCOL instance.
1194 @param DeviceAddress Target device address.
1195 @param EndPointAddress End point address with its direction.
1196 @param DeviceSpeed Device speed, Low speed device doesn't support this
1198 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1199 sending or receiving.
1200 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1201 @param Data Array of pointers to the buffers of data that will
1202 be transmitted to USB device or received from USB
1204 @param DataLength The size, in bytes, of the data buffer.
1205 @param Translator Transaction translator to use.
1206 @param TransferResult Variable to receive the transfer result.
1208 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1213 EhcIsochronousTransfer (
1214 IN EFI_USB2_HC_PROTOCOL
*This
,
1215 IN UINT8 DeviceAddress
,
1216 IN UINT8 EndPointAddress
,
1217 IN UINT8 DeviceSpeed
,
1218 IN UINTN MaximumPacketLength
,
1219 IN UINT8 DataBuffersNumber
,
1220 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1221 IN UINTN DataLength
,
1222 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1223 OUT UINT32
*TransferResult
1226 return EFI_UNSUPPORTED
;
1231 Submits Async isochronous transfer to a target USB device.
1233 @param This This EFI_USB2_HC_PROTOCOL instance.
1234 @param DeviceAddress Target device address.
1235 @param EndPointAddress End point address with its direction.
1236 @param DeviceSpeed Device speed, Low speed device doesn't support this
1238 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1239 sending or receiving.
1240 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1241 @param Data Array of pointers to the buffers of data that will
1242 be transmitted to USB device or received from USB
1244 @param DataLength The size, in bytes, of the data buffer.
1245 @param Translator Transaction translator to use.
1246 @param IsochronousCallBack Function to be called when the transfer complete.
1247 @param Context Context passed to the call back function as
1250 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1255 EhcAsyncIsochronousTransfer (
1256 IN EFI_USB2_HC_PROTOCOL
*This
,
1257 IN UINT8 DeviceAddress
,
1258 IN UINT8 EndPointAddress
,
1259 IN UINT8 DeviceSpeed
,
1260 IN UINTN MaximumPacketLength
,
1261 IN UINT8 DataBuffersNumber
,
1262 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1263 IN UINTN DataLength
,
1264 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1265 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1269 return EFI_UNSUPPORTED
;
1273 Entry point for EFI drivers.
1275 @param ImageHandle EFI_HANDLE.
1276 @param SystemTable EFI_SYSTEM_TABLE.
1278 @return EFI_SUCCESS Success.
1279 EFI_DEVICE_ERROR Fail.
1284 EhcDriverEntryPoint (
1285 IN EFI_HANDLE ImageHandle
,
1286 IN EFI_SYSTEM_TABLE
*SystemTable
1289 return EfiLibInstallDriverBindingComponentName2 (
1292 &gEhciDriverBinding
,
1294 &gEhciComponentName
,
1295 &gEhciComponentName2
1301 Test to see if this driver supports ControllerHandle. Any
1302 ControllerHandle that has Usb2HcProtocol installed will
1305 @param This Protocol instance pointer.
1306 @param Controller Handle of device to test.
1307 @param RemainingDevicePath Not used.
1309 @return EFI_SUCCESS This driver supports this device.
1310 @return EFI_UNSUPPORTED This driver does not support this device.
1315 EhcDriverBindingSupported (
1316 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1317 IN EFI_HANDLE Controller
,
1318 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1322 EFI_PCI_IO_PROTOCOL
*PciIo
;
1323 USB_CLASSC UsbClassCReg
;
1326 // Test whether there is PCI IO Protocol attached on the controller handle.
1328 Status
= gBS
->OpenProtocol (
1330 &gEfiPciIoProtocolGuid
,
1332 This
->DriverBindingHandle
,
1334 EFI_OPEN_PROTOCOL_BY_DRIVER
1337 if (EFI_ERROR (Status
)) {
1338 return EFI_UNSUPPORTED
;
1341 Status
= PciIo
->Pci
.Read (
1345 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1349 if (EFI_ERROR (Status
)) {
1350 Status
= EFI_UNSUPPORTED
;
1355 // Test whether the controller belongs to Ehci type
1357 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1358 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1359 (UsbClassCReg
.PI
!= EHC_PCI_CLASSC_PI
)) {
1361 Status
= EFI_UNSUPPORTED
;
1365 gBS
->CloseProtocol (
1367 &gEfiPciIoProtocolGuid
,
1368 This
->DriverBindingHandle
,
1377 Create and initialize a USB2_HC_DEV.
1379 @param PciIo The PciIo on this device.
1380 @param OriginalPciAttributes Original PCI attributes.
1382 @return The allocated and initialized USB2_HC_DEV structure if created,
1388 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1389 IN UINT64 OriginalPciAttributes
1395 Ehc
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
1402 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1404 Ehc
->Signature
= USB2_HC_DEV_SIGNATURE
;
1406 Ehc
->Usb2Hc
.GetCapability
= EhcGetCapability
;
1407 Ehc
->Usb2Hc
.Reset
= EhcReset
;
1408 Ehc
->Usb2Hc
.GetState
= EhcGetState
;
1409 Ehc
->Usb2Hc
.SetState
= EhcSetState
;
1410 Ehc
->Usb2Hc
.ControlTransfer
= EhcControlTransfer
;
1411 Ehc
->Usb2Hc
.BulkTransfer
= EhcBulkTransfer
;
1412 Ehc
->Usb2Hc
.AsyncInterruptTransfer
= EhcAsyncInterruptTransfer
;
1413 Ehc
->Usb2Hc
.SyncInterruptTransfer
= EhcSyncInterruptTransfer
;
1414 Ehc
->Usb2Hc
.IsochronousTransfer
= EhcIsochronousTransfer
;
1415 Ehc
->Usb2Hc
.AsyncIsochronousTransfer
= EhcAsyncIsochronousTransfer
;
1416 Ehc
->Usb2Hc
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1417 Ehc
->Usb2Hc
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1418 Ehc
->Usb2Hc
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1419 Ehc
->Usb2Hc
.MajorRevision
= 0x2;
1420 Ehc
->Usb2Hc
.MinorRevision
= 0x0;
1423 Ehc
->OriginalPciAttributes
= OriginalPciAttributes
;
1425 InitializeListHead (&Ehc
->AsyncIntTransfers
);
1427 Ehc
->HcStructParams
= EhcReadCapRegister (Ehc
, EHC_HCSPARAMS_OFFSET
);
1428 Ehc
->HcCapParams
= EhcReadCapRegister (Ehc
, EHC_HCCPARAMS_OFFSET
);
1429 Ehc
->CapLen
= EhcReadCapRegister (Ehc
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1431 DEBUG ((EFI_D_INFO
, "EhcCreateUsb2Hc: capability length %d\n", Ehc
->CapLen
));
1434 // Create AsyncRequest Polling Timer
1436 Status
= gBS
->CreateEvent (
1437 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1439 EhcMoniteAsyncRequests
,
1444 if (EFI_ERROR (Status
)) {
1445 gBS
->FreePool (Ehc
);
1454 Starting the Usb EHCI Driver.
1456 @param This Protocol instance pointer.
1457 @param Controller Handle of device to test.
1458 @param RemainingDevicePath Not used.
1460 @return EFI_SUCCESS supports this device.
1461 @return EFI_UNSUPPORTED do not support this device.
1462 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1463 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1468 EhcDriverBindingStart (
1469 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1470 IN EFI_HANDLE Controller
,
1471 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1476 EFI_PCI_IO_PROTOCOL
*PciIo
;
1478 UINT64 OriginalPciAttributes
;
1479 BOOLEAN PciAttributesSaved
;
1482 // Open the PciIo Protocol, then enable the USB host controller
1484 Status
= gBS
->OpenProtocol (
1486 &gEfiPciIoProtocolGuid
,
1488 This
->DriverBindingHandle
,
1490 EFI_OPEN_PROTOCOL_BY_DRIVER
1493 if (EFI_ERROR (Status
)) {
1494 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to open PCI_IO\n"));
1495 return EFI_DEVICE_ERROR
;
1498 PciAttributesSaved
= FALSE
;
1500 // Save original PCI attributes
1502 Status
= PciIo
->Attributes (
1504 EfiPciIoAttributeOperationGet
,
1506 &OriginalPciAttributes
1509 if (EFI_ERROR (Status
)) {
1512 PciAttributesSaved
= TRUE
;
1514 Status
= PciIo
->Attributes (
1516 EfiPciIoAttributeOperationSupported
,
1520 if (!EFI_ERROR (Status
)) {
1521 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1522 Status
= PciIo
->Attributes (
1524 EfiPciIoAttributeOperationEnable
,
1530 if (EFI_ERROR (Status
)) {
1531 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to enable controller\n"));
1536 // Create then install USB2_HC_PROTOCOL
1538 Ehc
= EhcCreateUsb2Hc (PciIo
, OriginalPciAttributes
);
1541 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1543 Status
= EFI_OUT_OF_RESOURCES
;
1547 Status
= gBS
->InstallProtocolInterface (
1549 &gEfiUsb2HcProtocolGuid
,
1550 EFI_NATIVE_INTERFACE
,
1554 if (EFI_ERROR (Status
)) {
1555 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1560 // Robustnesss improvement such as for UoL
1561 // Default is not required.
1563 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1564 EhcClearLegacySupport (Ehc
);
1566 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1568 Status
= EhcInitHC (Ehc
);
1570 if (EFI_ERROR (Status
)) {
1571 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to init host controller\n"));
1572 goto UNINSTALL_USBHC
;
1576 // Start the asynchronous interrupt monitor
1578 Status
= gBS
->SetTimer (Ehc
->PollTimer
, TimerPeriodic
, EHC_ASYNC_POLL_INTERVAL
);
1580 if (EFI_ERROR (Status
)) {
1581 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1583 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1584 goto UNINSTALL_USBHC
;
1588 // Install the component name protocol, don't fail the start
1589 // because of something for display.
1593 gEhciComponentName
.SupportedLanguages
,
1594 &Ehc
->ControllerNameTable
,
1595 L
"Enhanced Host Controller (USB 2.0)",
1600 gEhciComponentName2
.SupportedLanguages
,
1601 &Ehc
->ControllerNameTable
,
1602 L
"Enhanced Host Controller (USB 2.0)",
1607 DEBUG ((EFI_D_INFO
, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller
));
1611 gBS
->UninstallProtocolInterface (
1613 &gEfiUsb2HcProtocolGuid
,
1619 gBS
->CloseEvent (Ehc
->PollTimer
);
1620 gBS
->FreePool (Ehc
);
1623 if (PciAttributesSaved
) {
1625 // Restore original PCI attributes
1629 EfiPciIoAttributeOperationSet
,
1630 OriginalPciAttributes
,
1635 gBS
->CloseProtocol (
1637 &gEfiPciIoProtocolGuid
,
1638 This
->DriverBindingHandle
,
1647 Stop this driver on ControllerHandle. Support stoping any child handles
1648 created by this driver.
1650 @param This Protocol instance pointer.
1651 @param Controller Handle of device to stop driver on.
1652 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1653 @param ChildHandleBuffer List of handles for the children we need to stop.
1655 @return EFI_SUCCESS Success.
1656 @return EFI_DEVICE_ERROR Fail.
1661 EhcDriverBindingStop (
1662 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1663 IN EFI_HANDLE Controller
,
1664 IN UINTN NumberOfChildren
,
1665 IN EFI_HANDLE
*ChildHandleBuffer
1669 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1670 EFI_PCI_IO_PROTOCOL
*PciIo
;
1674 // Test whether the Controller handler passed in is a valid
1675 // Usb controller handle that should be supported, if not,
1676 // return the error status directly
1678 Status
= gBS
->OpenProtocol (
1680 &gEfiUsb2HcProtocolGuid
,
1682 This
->DriverBindingHandle
,
1684 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1687 if (EFI_ERROR (Status
)) {
1691 Ehc
= EHC_FROM_THIS (Usb2Hc
);
1695 // Stop AsyncRequest Polling timer then stop the EHCI driver
1696 // and uninstall the EHCI protocl.
1698 gBS
->SetTimer (Ehc
->PollTimer
, TimerCancel
, EHC_ASYNC_POLL_INTERVAL
);
1699 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1701 Status
= gBS
->UninstallProtocolInterface (
1703 &gEfiUsb2HcProtocolGuid
,
1707 if (EFI_ERROR (Status
)) {
1711 if (Ehc
->PollTimer
!= NULL
) {
1712 gBS
->CloseEvent (Ehc
->PollTimer
);
1717 if (Ehc
->ControllerNameTable
!= NULL
) {
1718 FreeUnicodeStringTable (Ehc
->ControllerNameTable
);
1722 // Restore original PCI attributes
1726 EfiPciIoAttributeOperationSet
,
1727 Ehc
->OriginalPciAttributes
,
1731 gBS
->CloseProtocol (
1733 &gEfiPciIoProtocolGuid
,
1734 This
->DriverBindingHandle
,