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
}
41 Retrieves the capablility of root hub ports.
43 @param This This EFI_USB_HC_PROTOCOL instance.
44 @param MaxSpeed Max speed supported by the controller.
45 @param PortNumber Number of the root hub ports.
46 @param Is64BitCapable Whether the controller supports 64-bit memory
49 @retval EFI_SUCCESS Host controller capability were retrieved successfully.
50 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
56 IN EFI_USB2_HC_PROTOCOL
*This
,
58 OUT UINT8
*PortNumber
,
59 OUT UINT8
*Is64BitCapable
65 if ((MaxSpeed
== NULL
) || (PortNumber
== NULL
) || (Is64BitCapable
== NULL
)) {
66 return EFI_INVALID_PARAMETER
;
69 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
70 Ehc
= EHC_FROM_THIS (This
);
72 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
73 *PortNumber
= (UINT8
) (Ehc
->HcStructParams
& HCSP_NPORTS
);
74 *Is64BitCapable
= (UINT8
) (Ehc
->HcCapParams
& HCCP_64BIT
);
76 DEBUG ((EFI_D_INFO
, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber
, *Is64BitCapable
));
78 gBS
->RestoreTPL (OldTpl
);
84 Provides software reset for the USB host controller.
86 @param This This EFI_USB2_HC_PROTOCOL instance.
87 @param Attributes A bit mask of the reset operation to perform.
89 @retval EFI_SUCCESS The reset operation succeeded.
90 @retval EFI_INVALID_PARAMETER Attributes is not valid.
91 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
92 not currently supported by the host controller.
93 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
99 IN EFI_USB2_HC_PROTOCOL
*This
,
107 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
108 Ehc
= EHC_FROM_THIS (This
);
110 switch (Attributes
) {
111 case EFI_USB_HC_RESET_GLOBAL
:
113 // Flow through, same behavior as Host Controller Reset
115 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
117 // Host Controller must be Halt when Reset it
119 if (!EhcIsHalt (Ehc
)) {
120 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
122 if (EFI_ERROR (Status
)) {
123 Status
= EFI_DEVICE_ERROR
;
129 // Clean up the asynchronous transfers, currently only
130 // interrupt supports asynchronous operation.
132 EhciDelAllAsyncIntTransfers (Ehc
);
133 EhcAckAllInterrupt (Ehc
);
136 Status
= EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
138 if (EFI_ERROR (Status
)) {
142 Status
= EhcInitHC (Ehc
);
145 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
:
146 case EFI_USB_HC_RESET_HOST_WITH_DEBUG
:
147 Status
= EFI_UNSUPPORTED
;
151 Status
= EFI_INVALID_PARAMETER
;
155 DEBUG ((EFI_D_INFO
, "EhcReset: exit status %r\n", Status
));
156 gBS
->RestoreTPL (OldTpl
);
162 Retrieve the current state of the USB host controller.
164 @param This This EFI_USB2_HC_PROTOCOL instance.
165 @param State Variable to return the current host controller
168 @retval EFI_SUCCESS Host controller state was returned in State.
169 @retval EFI_INVALID_PARAMETER State is NULL.
170 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
171 retrieve the host controller's current state.
177 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
178 OUT EFI_USB_HC_STATE
*State
185 return EFI_INVALID_PARAMETER
;
188 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
189 Ehc
= EHC_FROM_THIS (This
);
191 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
192 *State
= EfiUsbHcStateHalt
;
194 *State
= EfiUsbHcStateOperational
;
197 gBS
->RestoreTPL (OldTpl
);
199 DEBUG ((EFI_D_INFO
, "EhcGetState: current state %d\n", *State
));
205 Sets the USB host controller to a specific state.
207 @param This This EFI_USB2_HC_PROTOCOL instance.
208 @param State The state of the host controller that will be set.
210 @retval EFI_SUCCESS The USB host controller was successfully placed
211 in the state specified by State.
212 @retval EFI_INVALID_PARAMETER State is invalid.
213 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
219 IN EFI_USB2_HC_PROTOCOL
*This
,
220 IN EFI_USB_HC_STATE State
226 EFI_USB_HC_STATE CurState
;
228 Status
= EhcGetState (This
, &CurState
);
230 if (EFI_ERROR (Status
)) {
231 return EFI_DEVICE_ERROR
;
234 if (CurState
== State
) {
238 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
239 Ehc
= EHC_FROM_THIS (This
);
242 case EfiUsbHcStateHalt
:
243 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
246 case EfiUsbHcStateOperational
:
247 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
)) {
248 Status
= EFI_DEVICE_ERROR
;
253 // Software must not write a one to this field unless the host controller
254 // is in the Halted state. Doing so will yield undefined results.
255 // refers to Spec[EHCI1.0-2.3.1]
257 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
258 Status
= EFI_DEVICE_ERROR
;
262 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
265 case EfiUsbHcStateSuspend
:
266 Status
= EFI_UNSUPPORTED
;
270 Status
= EFI_INVALID_PARAMETER
;
273 DEBUG ((EFI_D_INFO
, "EhcSetState: exit status %r\n", Status
));
274 gBS
->RestoreTPL (OldTpl
);
280 Retrieves the current status of a USB root hub port.
282 @param This This EFI_USB2_HC_PROTOCOL instance.
283 @param PortNumber The root hub port to retrieve the state from.
284 This value is zero-based.
285 @param PortStatus Variable to receive the port state.
287 @retval EFI_SUCCESS The status of the USB root hub port specified.
288 by PortNumber was returned in PortStatus.
289 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
290 @retval EFI_DEVICE_ERROR Can't read register.
295 EhcGetRootHubPortStatus (
296 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
297 IN CONST UINT8 PortNumber
,
298 OUT EFI_USB_PORT_STATUS
*PortStatus
310 if (PortStatus
== NULL
) {
311 return EFI_INVALID_PARAMETER
;
314 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
316 Ehc
= EHC_FROM_THIS (This
);
317 Status
= EFI_SUCCESS
;
319 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
321 if (PortNumber
>= TotalPort
) {
322 Status
= EFI_INVALID_PARAMETER
;
326 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
327 PortStatus
->PortStatus
= 0;
328 PortStatus
->PortChangeStatus
= 0;
330 State
= EhcReadOpReg (Ehc
, Offset
);
333 // Identify device speed. If in K state, it is low speed.
334 // If the port is enabled after reset, the device is of
335 // high speed. The USB bus driver should retrieve the actual
336 // port speed after reset.
338 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
339 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
341 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
342 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
346 // Convert the EHCI port/port change state to UEFI status
348 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
350 for (Index
= 0; Index
< MapSize
; Index
++) {
351 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
352 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
356 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
358 for (Index
= 0; Index
< MapSize
; Index
++) {
359 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
360 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
365 gBS
->RestoreTPL (OldTpl
);
371 Sets a feature for the specified root hub port.
373 @param This This EFI_USB2_HC_PROTOCOL instance.
374 @param PortNumber Root hub port to set.
375 @param PortFeature Feature to set.
377 @retval EFI_SUCCESS The feature specified by PortFeature was set.
378 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
379 @retval EFI_DEVICE_ERROR Can't read register.
384 EhcSetRootHubPortFeature (
385 IN EFI_USB2_HC_PROTOCOL
*This
,
387 IN EFI_USB_PORT_FEATURE PortFeature
397 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
398 Ehc
= EHC_FROM_THIS (This
);
399 Status
= EFI_SUCCESS
;
401 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
403 if (PortNumber
>= TotalPort
) {
404 Status
= EFI_INVALID_PARAMETER
;
408 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
409 State
= EhcReadOpReg (Ehc
, Offset
);
412 // Mask off the port status change bits, these bits are
415 State
&= ~PORTSC_CHANGE_MASK
;
417 switch (PortFeature
) {
418 case EfiUsbPortEnable
:
420 // Sofeware can't set this bit, Port can only be enable by
421 // EHCI as a part of the reset and enable
423 State
|= PORTSC_ENABLED
;
424 EhcWriteOpReg (Ehc
, Offset
, State
);
427 case EfiUsbPortSuspend
:
428 State
|= PORTSC_SUSPEND
;
429 EhcWriteOpReg (Ehc
, Offset
, State
);
432 case EfiUsbPortReset
:
434 // Make sure Host Controller not halt before reset it
436 if (EhcIsHalt (Ehc
)) {
437 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
439 if (EFI_ERROR (Status
)) {
440 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status
));
446 // Set one to PortReset bit must also set zero to PortEnable bit
448 State
|= PORTSC_RESET
;
449 State
&= ~PORTSC_ENABLED
;
450 EhcWriteOpReg (Ehc
, Offset
, State
);
453 case EfiUsbPortPower
:
455 // Not supported, ignore the operation
457 Status
= EFI_SUCCESS
;
460 case EfiUsbPortOwner
:
461 State
|= PORTSC_OWNER
;
462 EhcWriteOpReg (Ehc
, Offset
, State
);
466 Status
= EFI_INVALID_PARAMETER
;
470 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature: exit status %r\n", Status
));
472 gBS
->RestoreTPL (OldTpl
);
478 Clears a feature for the specified root hub port.
480 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
481 @param PortNumber Specifies the root hub port whose feature is
482 requested to be cleared.
483 @param PortFeature Indicates the feature selector associated with the
484 feature clear request.
486 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
487 for the USB root hub port specified by PortNumber.
488 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
489 @retval EFI_DEVICE_ERROR Can't read register.
494 EhcClearRootHubPortFeature (
495 IN EFI_USB2_HC_PROTOCOL
*This
,
497 IN EFI_USB_PORT_FEATURE PortFeature
507 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
508 Ehc
= EHC_FROM_THIS (This
);
509 Status
= EFI_SUCCESS
;
511 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
513 if (PortNumber
>= TotalPort
) {
514 Status
= EFI_INVALID_PARAMETER
;
518 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
519 State
= EhcReadOpReg (Ehc
, Offset
);
520 State
&= ~PORTSC_CHANGE_MASK
;
522 switch (PortFeature
) {
523 case EfiUsbPortEnable
:
525 // Clear PORT_ENABLE feature means disable port.
527 State
&= ~PORTSC_ENABLED
;
528 EhcWriteOpReg (Ehc
, Offset
, State
);
531 case EfiUsbPortSuspend
:
533 // A write of zero to this bit is ignored by the host
534 // controller. The host controller will unconditionally
535 // set this bit to a zero when:
536 // 1. software sets the Forct Port Resume bit to a zero from a one.
537 // 2. software sets the Port Reset bit to a one frome a zero.
539 State
&= ~PORSTSC_RESUME
;
540 EhcWriteOpReg (Ehc
, Offset
, State
);
543 case EfiUsbPortReset
:
545 // Clear PORT_RESET means clear the reset signal.
547 State
&= ~PORTSC_RESET
;
548 EhcWriteOpReg (Ehc
, Offset
, State
);
551 case EfiUsbPortOwner
:
553 // Clear port owner means this port owned by EHC
555 State
&= ~PORTSC_OWNER
;
556 EhcWriteOpReg (Ehc
, Offset
, State
);
559 case EfiUsbPortConnectChange
:
561 // Clear connect status change
563 State
|= PORTSC_CONN_CHANGE
;
564 EhcWriteOpReg (Ehc
, Offset
, State
);
567 case EfiUsbPortEnableChange
:
569 // Clear enable status change
571 State
|= PORTSC_ENABLE_CHANGE
;
572 EhcWriteOpReg (Ehc
, Offset
, State
);
575 case EfiUsbPortOverCurrentChange
:
577 // Clear PortOverCurrent change
579 State
|= PORTSC_OVERCUR_CHANGE
;
580 EhcWriteOpReg (Ehc
, Offset
, State
);
583 case EfiUsbPortPower
:
584 case EfiUsbPortSuspendChange
:
585 case EfiUsbPortResetChange
:
587 // Not supported or not related operation
592 Status
= EFI_INVALID_PARAMETER
;
597 DEBUG ((EFI_D_INFO
, "EhcClearRootHubPortFeature: exit status %r\n", Status
));
598 gBS
->RestoreTPL (OldTpl
);
604 Submits control transfer to a target USB device.
606 @param This This EFI_USB2_HC_PROTOCOL instance.
607 @param DeviceAddress The target device address.
608 @param DeviceSpeed Target device speed.
609 @param MaximumPacketLength Maximum packet size the default control transfer
610 endpoint is capable of sending or receiving.
611 @param Request USB device request to send.
612 @param TransferDirection Specifies the data direction for the data stage
613 @param Data Data buffer to be transmitted or received from USB
615 @param DataLength The size (in bytes) of the data buffer.
616 @param TimeOut Indicates the maximum timeout, in millisecond.
617 @param Translator Transaction translator to be used by this device.
618 @param TransferResult Return the result of this control transfer.
620 @retval EFI_SUCCESS Transfer was completed successfully.
621 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
622 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
623 @retval EFI_TIMEOUT Transfer failed due to timeout.
624 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
630 IN EFI_USB2_HC_PROTOCOL
*This
,
631 IN UINT8 DeviceAddress
,
632 IN UINT8 DeviceSpeed
,
633 IN UINTN MaximumPacketLength
,
634 IN EFI_USB_DEVICE_REQUEST
*Request
,
635 IN EFI_USB_DATA_DIRECTION TransferDirection
,
637 IN OUT UINTN
*DataLength
,
639 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
640 OUT UINT32
*TransferResult
650 // Validate parameters
652 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
653 return EFI_INVALID_PARAMETER
;
656 if ((TransferDirection
!= EfiUsbDataIn
) &&
657 (TransferDirection
!= EfiUsbDataOut
) &&
658 (TransferDirection
!= EfiUsbNoData
)) {
659 return EFI_INVALID_PARAMETER
;
662 if ((TransferDirection
== EfiUsbNoData
) &&
663 ((Data
!= NULL
) || (*DataLength
!= 0))) {
664 return EFI_INVALID_PARAMETER
;
667 if ((TransferDirection
!= EfiUsbNoData
) &&
668 ((Data
== NULL
) || (*DataLength
== 0))) {
669 return EFI_INVALID_PARAMETER
;
672 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
673 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
674 return EFI_INVALID_PARAMETER
;
677 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
678 return EFI_INVALID_PARAMETER
;
681 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
682 Ehc
= EHC_FROM_THIS (This
);
684 Status
= EFI_DEVICE_ERROR
;
685 *TransferResult
= EFI_USB_ERR_SYSTEM
;
687 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
688 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: HC halted at entrance\n"));
690 EhcAckAllInterrupt (Ehc
);
694 EhcAckAllInterrupt (Ehc
);
697 // Create a new URB, insert it into the asynchronous
698 // schedule list, then poll the execution status.
701 // Encode the direction in address, although default control
702 // endpoint is bidirectional. EhcCreateUrb expects this
703 // combination of Ep addr and its direction.
705 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
724 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: failed to create URB"));
726 Status
= EFI_OUT_OF_RESOURCES
;
730 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
731 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
732 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
735 // Get the status from URB. The result is updated in EhcCheckUrbResult
736 // which is called by EhcExecTransfer
738 *TransferResult
= Urb
->Result
;
739 *DataLength
= Urb
->Completed
;
741 if (*TransferResult
== EFI_USB_NOERROR
) {
742 Status
= EFI_SUCCESS
;
745 EhcAckAllInterrupt (Ehc
);
746 EhcFreeUrb (Ehc
, Urb
);
749 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
750 gBS
->RestoreTPL (OldTpl
);
752 if (EFI_ERROR (Status
)) {
753 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
761 Submits bulk transfer to a bulk endpoint of a USB device.
763 @param This This EFI_USB2_HC_PROTOCOL instance.
764 @param DeviceAddress Target device address.
765 @param EndPointAddress Endpoint number and its direction in bit 7.
766 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
768 @param MaximumPacketLength Maximum packet size the endpoint is capable of
769 sending or receiving.
770 @param DataBuffersNumber Number of data buffers prepared for the transfer.
771 @param Data Array of pointers to the buffers of data to transmit
772 from or receive into.
773 @param DataLength The lenght of the data buffer.
774 @param DataToggle On input, the initial data toggle for the transfer;
775 On output, it is updated to to next data toggle to
776 use of the subsequent bulk transfer.
777 @param TimeOut Indicates the maximum time, in millisecond, which
778 the transfer is allowed to complete.
779 @param Translator A pointr to the transaction translator data.
780 @param TransferResult A pointer to the detailed result information of the
783 @retval EFI_SUCCESS The transfer was completed successfully.
784 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
785 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
786 @retval EFI_TIMEOUT The transfer failed due to timeout.
787 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
793 IN EFI_USB2_HC_PROTOCOL
*This
,
794 IN UINT8 DeviceAddress
,
795 IN UINT8 EndPointAddress
,
796 IN UINT8 DeviceSpeed
,
797 IN UINTN MaximumPacketLength
,
798 IN UINT8 DataBuffersNumber
,
799 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
800 IN OUT UINTN
*DataLength
,
801 IN OUT UINT8
*DataToggle
,
803 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
804 OUT UINT32
*TransferResult
813 // Validate the parameters
815 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
816 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
817 return EFI_INVALID_PARAMETER
;
820 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
821 return EFI_INVALID_PARAMETER
;
824 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
825 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
826 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
827 return EFI_INVALID_PARAMETER
;
830 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
831 Ehc
= EHC_FROM_THIS (This
);
833 *TransferResult
= EFI_USB_ERR_SYSTEM
;
834 Status
= EFI_DEVICE_ERROR
;
836 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
837 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: HC is halted\n"));
839 EhcAckAllInterrupt (Ehc
);
843 EhcAckAllInterrupt (Ehc
);
846 // Create a new URB, insert it into the asynchronous
847 // schedule list, then poll the execution status.
867 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: failed to create URB\n"));
869 Status
= EFI_OUT_OF_RESOURCES
;
873 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
874 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
875 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
877 *TransferResult
= Urb
->Result
;
878 *DataLength
= Urb
->Completed
;
879 *DataToggle
= Urb
->DataToggle
;
881 if (*TransferResult
== EFI_USB_NOERROR
) {
882 Status
= EFI_SUCCESS
;
885 EhcAckAllInterrupt (Ehc
);
886 EhcFreeUrb (Ehc
, Urb
);
889 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
890 gBS
->RestoreTPL (OldTpl
);
892 if (EFI_ERROR (Status
)) {
893 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
901 Submits an asynchronous interrupt transfer to an
902 interrupt endpoint of a USB device.
904 @param This This EFI_USB2_HC_PROTOCOL instance.
905 @param DeviceAddress Target device address.
906 @param EndPointAddress Endpoint number and its direction encoded in bit 7
907 @param DeviceSpeed Indicates device speed.
908 @param MaximumPacketLength Maximum packet size the target endpoint is capable
909 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
910 transfer If FALSE, to remove the specified
911 asynchronous interrupt.
912 @param DataToggle On input, the initial data toggle to use; on output,
913 it is updated to indicate the next data toggle.
914 @param PollingInterval The he interval, in milliseconds, that the transfer
916 @param DataLength The length of data to receive at the rate specified
918 @param Translator Transaction translator to use.
919 @param CallBackFunction Function to call at the rate specified by
921 @param Context Context to CallBackFunction.
923 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
924 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
925 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
926 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
931 EhcAsyncInterruptTransfer (
932 IN EFI_USB2_HC_PROTOCOL
* This
,
933 IN UINT8 DeviceAddress
,
934 IN UINT8 EndPointAddress
,
935 IN UINT8 DeviceSpeed
,
936 IN UINTN MaximumPacketLength
,
937 IN BOOLEAN IsNewTransfer
,
938 IN OUT UINT8
*DataToggle
,
939 IN UINTN PollingInterval
,
941 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
942 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
943 IN VOID
*Context OPTIONAL
953 // Validate parameters
955 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
956 return EFI_INVALID_PARAMETER
;
960 if (DataLength
== 0) {
961 return EFI_INVALID_PARAMETER
;
964 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
965 return EFI_INVALID_PARAMETER
;
968 if ((PollingInterval
> 255) || (PollingInterval
< 1)) {
969 return EFI_INVALID_PARAMETER
;
973 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
974 Ehc
= EHC_FROM_THIS (This
);
977 // Delete Async interrupt transfer request. DataToggle will return
978 // the next data toggle to use.
980 if (!IsNewTransfer
) {
981 Status
= EhciDelAsyncIntTransfer (Ehc
, DeviceAddress
, EndPointAddress
, DataToggle
);
983 DEBUG ((EFI_D_INFO
, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status
));
987 Status
= EFI_SUCCESS
;
989 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
990 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: HC is halt\n"));
991 EhcAckAllInterrupt (Ehc
);
993 Status
= EFI_DEVICE_ERROR
;
997 EhcAckAllInterrupt (Ehc
);
999 Data
= AllocatePool (DataLength
);
1002 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1004 Status
= EFI_OUT_OF_RESOURCES
;
1008 Urb
= EhcCreateUrb (
1014 MaximumPacketLength
,
1016 EHC_INT_TRANSFER_ASYNC
,
1026 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1028 gBS
->FreePool (Data
);
1029 Status
= EFI_OUT_OF_RESOURCES
;
1034 // New asynchronous transfer must inserted to the head.
1035 // Check the comments in EhcMoniteAsyncRequests
1037 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1038 InsertHeadList (&Ehc
->AsyncIntTransfers
, &Urb
->UrbList
);
1041 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1042 gBS
->RestoreTPL (OldTpl
);
1049 Submits synchronous interrupt transfer to an interrupt endpoint
1052 @param This This EFI_USB2_HC_PROTOCOL instance.
1053 @param DeviceAddress Target device address.
1054 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1055 @param DeviceSpeed Indicates device speed.
1056 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1057 of sending or receiving.
1058 @param Data Buffer of data that will be transmitted to USB
1059 device or received from USB device.
1060 @param DataLength On input, the size, in bytes, of the data buffer; On
1061 output, the number of bytes transferred.
1062 @param DataToggle On input, the initial data toggle to use; on output,
1063 it is updated to indicate the next data toggle.
1064 @param TimeOut Maximum time, in second, to complete.
1065 @param Translator Transaction translator to use.
1066 @param TransferResult Variable to receive the transfer result.
1068 @return EFI_SUCCESS The transfer was completed successfully.
1069 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1070 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1071 @return EFI_TIMEOUT The transfer failed due to timeout.
1072 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1077 EhcSyncInterruptTransfer (
1078 IN EFI_USB2_HC_PROTOCOL
*This
,
1079 IN UINT8 DeviceAddress
,
1080 IN UINT8 EndPointAddress
,
1081 IN UINT8 DeviceSpeed
,
1082 IN UINTN MaximumPacketLength
,
1084 IN OUT UINTN
*DataLength
,
1085 IN OUT UINT8
*DataToggle
,
1087 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1088 OUT UINT32
*TransferResult
1097 // Validates parameters
1099 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
1100 (Data
== NULL
) || (TransferResult
== NULL
)) {
1101 return EFI_INVALID_PARAMETER
;
1104 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1105 return EFI_INVALID_PARAMETER
;
1108 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1109 return EFI_INVALID_PARAMETER
;
1112 if (((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) ||
1113 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1114 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 3072))) {
1115 return EFI_INVALID_PARAMETER
;
1118 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1119 Ehc
= EHC_FROM_THIS (This
);
1121 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1122 Status
= EFI_DEVICE_ERROR
;
1124 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1125 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: HC is halt\n"));
1127 EhcAckAllInterrupt (Ehc
);
1131 EhcAckAllInterrupt (Ehc
);
1133 Urb
= EhcCreateUrb (
1139 MaximumPacketLength
,
1141 EHC_INT_TRANSFER_SYNC
,
1151 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: failed to create URB\n"));
1153 Status
= EFI_OUT_OF_RESOURCES
;
1157 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1158 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1159 EhcUnlinkQhFromPeriod (Ehc
, Urb
->Qh
);
1161 *TransferResult
= Urb
->Result
;
1162 *DataLength
= Urb
->Completed
;
1163 *DataToggle
= Urb
->DataToggle
;
1165 if (*TransferResult
== EFI_USB_NOERROR
) {
1166 Status
= EFI_SUCCESS
;
1170 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1171 gBS
->RestoreTPL (OldTpl
);
1173 if (EFI_ERROR (Status
)) {
1174 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1182 Submits isochronous transfer to a target USB device.
1184 @param This This EFI_USB2_HC_PROTOCOL instance.
1185 @param DeviceAddress Target device address.
1186 @param EndPointAddress End point address with its direction.
1187 @param DeviceSpeed Device speed, Low speed device doesn't support this
1189 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1190 sending or receiving.
1191 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1192 @param Data Array of pointers to the buffers of data that will
1193 be transmitted to USB device or received from USB
1195 @param DataLength The size, in bytes, of the data buffer.
1196 @param Translator Transaction translator to use.
1197 @param TransferResult Variable to receive the transfer result.
1199 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1204 EhcIsochronousTransfer (
1205 IN EFI_USB2_HC_PROTOCOL
*This
,
1206 IN UINT8 DeviceAddress
,
1207 IN UINT8 EndPointAddress
,
1208 IN UINT8 DeviceSpeed
,
1209 IN UINTN MaximumPacketLength
,
1210 IN UINT8 DataBuffersNumber
,
1211 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1212 IN UINTN DataLength
,
1213 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1214 OUT UINT32
*TransferResult
1217 return EFI_UNSUPPORTED
;
1222 Submits Async isochronous transfer to a target USB device.
1224 @param This This EFI_USB2_HC_PROTOCOL instance.
1225 @param DeviceAddress Target device address.
1226 @param EndPointAddress End point address with its direction.
1227 @param DeviceSpeed Device speed, Low speed device doesn't support this
1229 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1230 sending or receiving.
1231 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1232 @param Data Array of pointers to the buffers of data that will
1233 be transmitted to USB device or received from USB
1235 @param DataLength The size, in bytes, of the data buffer.
1236 @param Translator Transaction translator to use.
1237 @param IsochronousCallBack Function to be called when the transfer complete.
1238 @param Context Context passed to the call back function as
1241 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1246 EhcAsyncIsochronousTransfer (
1247 IN EFI_USB2_HC_PROTOCOL
*This
,
1248 IN UINT8 DeviceAddress
,
1249 IN UINT8 EndPointAddress
,
1250 IN UINT8 DeviceSpeed
,
1251 IN UINTN MaximumPacketLength
,
1252 IN UINT8 DataBuffersNumber
,
1253 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1254 IN UINTN DataLength
,
1255 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1256 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1260 return EFI_UNSUPPORTED
;
1264 Entry point for EFI drivers.
1266 @param ImageHandle EFI_HANDLE.
1267 @param SystemTable EFI_SYSTEM_TABLE.
1269 @return EFI_SUCCESS Success.
1270 EFI_DEVICE_ERROR Fail.
1275 EhcDriverEntryPoint (
1276 IN EFI_HANDLE ImageHandle
,
1277 IN EFI_SYSTEM_TABLE
*SystemTable
1280 return EfiLibInstallDriverBindingComponentName2 (
1283 &gEhciDriverBinding
,
1285 &gEhciComponentName
,
1286 &gEhciComponentName2
1292 Test to see if this driver supports ControllerHandle. Any
1293 ControllerHandle that has Usb2HcProtocol installed will
1296 @param This Protocol instance pointer.
1297 @param Controller Handle of device to test.
1298 @param RemainingDevicePath Not used.
1300 @return EFI_SUCCESS This driver supports this device.
1301 @return EFI_UNSUPPORTED This driver does not support this device.
1306 EhcDriverBindingSupported (
1307 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1308 IN EFI_HANDLE Controller
,
1309 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1313 EFI_PCI_IO_PROTOCOL
*PciIo
;
1314 USB_CLASSC UsbClassCReg
;
1317 // Test whether there is PCI IO Protocol attached on the controller handle.
1319 Status
= gBS
->OpenProtocol (
1321 &gEfiPciIoProtocolGuid
,
1323 This
->DriverBindingHandle
,
1325 EFI_OPEN_PROTOCOL_BY_DRIVER
1328 if (EFI_ERROR (Status
)) {
1329 return EFI_UNSUPPORTED
;
1332 Status
= PciIo
->Pci
.Read (
1336 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1340 if (EFI_ERROR (Status
)) {
1341 Status
= EFI_UNSUPPORTED
;
1346 // Test whether the controller belongs to Ehci type
1348 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1349 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1350 (UsbClassCReg
.PI
!= EHC_PCI_CLASSC_PI
)) {
1352 Status
= EFI_UNSUPPORTED
;
1356 gBS
->CloseProtocol (
1358 &gEfiPciIoProtocolGuid
,
1359 This
->DriverBindingHandle
,
1368 Create and initialize a USB2_HC_DEV.
1370 @param PciIo The PciIo on this device.
1371 @param OriginalPciAttributes Original PCI attributes.
1373 @return The allocated and initialized USB2_HC_DEV structure if created,
1379 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1380 IN UINT64 OriginalPciAttributes
1386 Ehc
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
1393 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1395 Ehc
->Signature
= USB2_HC_DEV_SIGNATURE
;
1397 Ehc
->Usb2Hc
.GetCapability
= EhcGetCapability
;
1398 Ehc
->Usb2Hc
.Reset
= EhcReset
;
1399 Ehc
->Usb2Hc
.GetState
= EhcGetState
;
1400 Ehc
->Usb2Hc
.SetState
= EhcSetState
;
1401 Ehc
->Usb2Hc
.ControlTransfer
= EhcControlTransfer
;
1402 Ehc
->Usb2Hc
.BulkTransfer
= EhcBulkTransfer
;
1403 Ehc
->Usb2Hc
.AsyncInterruptTransfer
= EhcAsyncInterruptTransfer
;
1404 Ehc
->Usb2Hc
.SyncInterruptTransfer
= EhcSyncInterruptTransfer
;
1405 Ehc
->Usb2Hc
.IsochronousTransfer
= EhcIsochronousTransfer
;
1406 Ehc
->Usb2Hc
.AsyncIsochronousTransfer
= EhcAsyncIsochronousTransfer
;
1407 Ehc
->Usb2Hc
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1408 Ehc
->Usb2Hc
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1409 Ehc
->Usb2Hc
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1410 Ehc
->Usb2Hc
.MajorRevision
= 0x2;
1411 Ehc
->Usb2Hc
.MinorRevision
= 0x0;
1414 Ehc
->OriginalPciAttributes
= OriginalPciAttributes
;
1416 InitializeListHead (&Ehc
->AsyncIntTransfers
);
1418 Ehc
->HcStructParams
= EhcReadCapRegister (Ehc
, EHC_HCSPARAMS_OFFSET
);
1419 Ehc
->HcCapParams
= EhcReadCapRegister (Ehc
, EHC_HCCPARAMS_OFFSET
);
1420 Ehc
->CapLen
= EhcReadCapRegister (Ehc
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1422 DEBUG ((EFI_D_INFO
, "EhcCreateUsb2Hc: capability length %d\n", Ehc
->CapLen
));
1425 // Create AsyncRequest Polling Timer
1427 Status
= gBS
->CreateEvent (
1428 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1430 EhcMoniteAsyncRequests
,
1435 if (EFI_ERROR (Status
)) {
1436 gBS
->FreePool (Ehc
);
1445 Starting the Usb EHCI Driver.
1447 @param This Protocol instance pointer.
1448 @param Controller Handle of device to test.
1449 @param RemainingDevicePath Not used.
1451 @return EFI_SUCCESS supports this device.
1452 @return EFI_UNSUPPORTED do not support this device.
1453 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1454 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1459 EhcDriverBindingStart (
1460 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1461 IN EFI_HANDLE Controller
,
1462 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1467 EFI_PCI_IO_PROTOCOL
*PciIo
;
1469 UINT64 OriginalPciAttributes
;
1470 BOOLEAN PciAttributesSaved
;
1473 // Open the PciIo Protocol, then enable the USB host controller
1475 Status
= gBS
->OpenProtocol (
1477 &gEfiPciIoProtocolGuid
,
1479 This
->DriverBindingHandle
,
1481 EFI_OPEN_PROTOCOL_BY_DRIVER
1484 if (EFI_ERROR (Status
)) {
1485 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to open PCI_IO\n"));
1486 return EFI_DEVICE_ERROR
;
1489 PciAttributesSaved
= FALSE
;
1491 // Save original PCI attributes
1493 Status
= PciIo
->Attributes (
1495 EfiPciIoAttributeOperationGet
,
1497 &OriginalPciAttributes
1500 if (EFI_ERROR (Status
)) {
1503 PciAttributesSaved
= TRUE
;
1505 Status
= PciIo
->Attributes (
1507 EfiPciIoAttributeOperationSupported
,
1511 if (!EFI_ERROR (Status
)) {
1512 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1513 Status
= PciIo
->Attributes (
1515 EfiPciIoAttributeOperationEnable
,
1521 if (EFI_ERROR (Status
)) {
1522 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to enable controller\n"));
1527 // Create then install USB2_HC_PROTOCOL
1529 Ehc
= EhcCreateUsb2Hc (PciIo
, OriginalPciAttributes
);
1532 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1534 Status
= EFI_OUT_OF_RESOURCES
;
1538 Status
= gBS
->InstallProtocolInterface (
1540 &gEfiUsb2HcProtocolGuid
,
1541 EFI_NATIVE_INTERFACE
,
1545 if (EFI_ERROR (Status
)) {
1546 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1551 // Robustnesss improvement such as for UoL
1552 // Default is not required.
1554 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1555 EhcClearLegacySupport (Ehc
);
1557 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1559 Status
= EhcInitHC (Ehc
);
1561 if (EFI_ERROR (Status
)) {
1562 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to init host controller\n"));
1563 goto UNINSTALL_USBHC
;
1567 // Start the asynchronous interrupt monitor
1569 Status
= gBS
->SetTimer (Ehc
->PollTimer
, TimerPeriodic
, EHC_ASYNC_POLL_INTERVAL
);
1571 if (EFI_ERROR (Status
)) {
1572 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1574 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1575 goto UNINSTALL_USBHC
;
1579 // Install the component name protocol, don't fail the start
1580 // because of something for display.
1584 gEhciComponentName
.SupportedLanguages
,
1585 &Ehc
->ControllerNameTable
,
1586 L
"Enhanced Host Controller (USB 2.0)",
1591 gEhciComponentName2
.SupportedLanguages
,
1592 &Ehc
->ControllerNameTable
,
1593 L
"Enhanced Host Controller (USB 2.0)",
1598 DEBUG ((EFI_D_INFO
, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller
));
1602 gBS
->UninstallProtocolInterface (
1604 &gEfiUsb2HcProtocolGuid
,
1610 gBS
->CloseEvent (Ehc
->PollTimer
);
1611 gBS
->FreePool (Ehc
);
1614 if (PciAttributesSaved
) {
1616 // Restore original PCI attributes
1620 EfiPciIoAttributeOperationSet
,
1621 OriginalPciAttributes
,
1626 gBS
->CloseProtocol (
1628 &gEfiPciIoProtocolGuid
,
1629 This
->DriverBindingHandle
,
1638 Stop this driver on ControllerHandle. Support stoping any child handles
1639 created by this driver.
1641 @param This Protocol instance pointer.
1642 @param Controller Handle of device to stop driver on.
1643 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1644 @param ChildHandleBuffer List of handles for the children we need to stop.
1646 @return EFI_SUCCESS Success.
1647 @return EFI_DEVICE_ERROR Fail.
1652 EhcDriverBindingStop (
1653 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1654 IN EFI_HANDLE Controller
,
1655 IN UINTN NumberOfChildren
,
1656 IN EFI_HANDLE
*ChildHandleBuffer
1660 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1661 EFI_PCI_IO_PROTOCOL
*PciIo
;
1665 // Test whether the Controller handler passed in is a valid
1666 // Usb controller handle that should be supported, if not,
1667 // return the error status directly
1669 Status
= gBS
->OpenProtocol (
1671 &gEfiUsb2HcProtocolGuid
,
1673 This
->DriverBindingHandle
,
1675 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1678 if (EFI_ERROR (Status
)) {
1682 Ehc
= EHC_FROM_THIS (Usb2Hc
);
1686 // Stop AsyncRequest Polling timer then stop the EHCI driver
1687 // and uninstall the EHCI protocl.
1689 gBS
->SetTimer (Ehc
->PollTimer
, TimerCancel
, EHC_ASYNC_POLL_INTERVAL
);
1690 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1692 Status
= gBS
->UninstallProtocolInterface (
1694 &gEfiUsb2HcProtocolGuid
,
1698 if (EFI_ERROR (Status
)) {
1702 if (Ehc
->PollTimer
!= NULL
) {
1703 gBS
->CloseEvent (Ehc
->PollTimer
);
1708 if (Ehc
->ControllerNameTable
!= NULL
) {
1709 FreeUnicodeStringTable (Ehc
->ControllerNameTable
);
1713 // Restore original PCI attributes
1717 EfiPciIoAttributeOperationSet
,
1718 Ehc
->OriginalPciAttributes
,
1722 gBS
->CloseProtocol (
1724 &gEfiPciIoProtocolGuid
,
1725 This
->DriverBindingHandle
,
1734 EFI_DRIVER_BINDING_PROTOCOL
1735 gEhciDriverBinding
= {
1736 EhcDriverBindingSupported
,
1737 EhcDriverBindingStart
,
1738 EhcDriverBindingStop
,