3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 // Two arrays used to translate the EHCI port state (change)
28 // to the UEFI protocol's port state (change).
30 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
31 {PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
32 {PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
33 {PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
34 {PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
35 {PORTSC_RESET
, USB_PORT_STAT_RESET
},
36 {PORTSC_POWER
, USB_PORT_STAT_POWER
},
37 {PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
40 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
41 {PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
42 {PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
43 {PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
48 Retrieves the capablility of root hub ports.
50 @param This This EFI_USB_HC_PROTOCOL instance.
51 @param MaxSpeed Max speed supported by the controller
52 @param PortNumber Number of the root hub ports.
53 @param Is64BitCapable Whether the controller supports 64-bit memory
56 @return EFI_SUCCESS : host controller capability were retrieved successfully.
57 @return EFI_INVALID_PARAMETER : Either of the three capability pointer is NULL
64 IN EFI_USB2_HC_PROTOCOL
*This
,
66 OUT UINT8
*PortNumber
,
67 OUT UINT8
*Is64BitCapable
73 if ((MaxSpeed
== NULL
) || (PortNumber
== NULL
) || (Is64BitCapable
== NULL
)) {
74 return EFI_INVALID_PARAMETER
;
77 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
78 Ehc
= EHC_FROM_THIS (This
);
80 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
81 *PortNumber
= (UINT8
) (Ehc
->HcStructParams
& HCSP_NPORTS
);
82 *Is64BitCapable
= (UINT8
) (Ehc
->HcCapParams
& HCCP_64BIT
);
84 DEBUG ((EFI_D_INFO
, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber
, *Is64BitCapable
));
86 gBS
->RestoreTPL (OldTpl
);
92 Provides software reset for the USB host controller.
94 @param This This EFI_USB2_HC_PROTOCOL instance.
95 @param Attributes A bit mask of the reset operation to perform.
97 @return EFI_SUCCESS : The reset operation succeeded.
98 @return EFI_INVALID_PARAMETER : Attributes is not valid.
99 @return EFI_UNSUPPOURTED : The type of reset specified by Attributes is
100 @return not currently supported by the host controller.
101 @return 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 @return EFI_SUCCESS : Host controller state was returned in State.
178 @return EFI_INVALID_PARAMETER : State is NULL.
179 @return EFI_DEVICE_ERROR : An error was encountered while attempting to
180 @return retrieve the host controller's current state.
187 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
188 OUT EFI_USB_HC_STATE
*State
195 return EFI_INVALID_PARAMETER
;
198 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
199 Ehc
= EHC_FROM_THIS (This
);
201 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
202 *State
= EfiUsbHcStateHalt
;
204 *State
= EfiUsbHcStateOperational
;
207 gBS
->RestoreTPL (OldTpl
);
209 DEBUG ((EFI_D_INFO
, "EhcGetState: current state %d\n", *State
));
215 Sets the USB host controller to a specific state.
217 @param This This EFI_USB2_HC_PROTOCOL instance.
218 @param State The state of the host controller that will be set.
220 @return EFI_SUCCESS : The USB host controller was successfully placed
221 @return in the state specified by State.
222 @return EFI_INVALID_PARAMETER : State is invalid.
223 @return EFI_DEVICE_ERROR : Failed to set the state due to device error.
230 IN EFI_USB2_HC_PROTOCOL
*This
,
231 IN EFI_USB_HC_STATE State
237 EFI_USB_HC_STATE CurState
;
239 Status
= EhcGetState (This
, &CurState
);
241 if (EFI_ERROR (Status
)) {
242 return EFI_DEVICE_ERROR
;
245 if (CurState
== State
) {
249 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
250 Ehc
= EHC_FROM_THIS (This
);
253 case EfiUsbHcStateHalt
:
254 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
257 case EfiUsbHcStateOperational
:
258 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
)) {
259 Status
= EFI_DEVICE_ERROR
;
264 // Software must not write a one to this field unless the host controller
265 // is in the Halted state. Doing so will yield undefined results.
266 // refers to Spec[EHCI1.0-2.3.1]
268 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
269 Status
= EFI_DEVICE_ERROR
;
273 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
276 case EfiUsbHcStateSuspend
:
277 Status
= EFI_UNSUPPORTED
;
281 Status
= EFI_INVALID_PARAMETER
;
284 DEBUG ((EFI_D_INFO
, "EhcSetState: exit status %r\n", Status
));
285 gBS
->RestoreTPL (OldTpl
);
291 Retrieves the current status of a USB root hub port.
293 @param This This EFI_USB2_HC_PROTOCOL instance.
294 @param PortNumber The root hub port to retrieve the state from. This
296 @param PortStatus Variable to receive the port state
298 @return EFI_SUCCESS : The status of the USB root hub port specified
299 @return by PortNumber was returned in PortStatus.
300 @return EFI_INVALID_PARAMETER : PortNumber is invalid.
301 @return EFI_DEVICE_ERROR : Can't read register
307 EhcGetRootHubPortStatus (
308 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
309 IN CONST UINT8 PortNumber
,
310 OUT EFI_USB_PORT_STATUS
*PortStatus
322 if (PortStatus
== NULL
) {
323 return EFI_INVALID_PARAMETER
;
326 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
328 Ehc
= EHC_FROM_THIS (This
);
329 Status
= EFI_SUCCESS
;
331 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
333 if (PortNumber
>= TotalPort
) {
334 Status
= EFI_INVALID_PARAMETER
;
338 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
339 PortStatus
->PortStatus
= 0;
340 PortStatus
->PortChangeStatus
= 0;
342 State
= EhcReadOpReg (Ehc
, Offset
);
345 // Identify device speed. If in K state, it is low speed.
346 // If the port is enabled after reset, the device is of
347 // high speed. The USB bus driver should retrieve the actual
348 // port speed after reset.
350 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
351 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
353 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
354 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
358 // Convert the EHCI port/port change state to UEFI status
360 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
362 for (Index
= 0; Index
< MapSize
; Index
++) {
363 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
364 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
368 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
370 for (Index
= 0; Index
< MapSize
; Index
++) {
371 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
372 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
377 gBS
->RestoreTPL (OldTpl
);
383 Sets a feature for the specified root hub port.
385 @param This This EFI_USB2_HC_PROTOCOL instance.
386 @param PortNumber Root hub port to set.
387 @param PortFeature Feature to set
389 @return EFI_SUCCESS : The feature specified by PortFeature was set
390 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.
391 @return EFI_DEVICE_ERROR : Can't read register
397 EhcSetRootHubPortFeature (
398 IN EFI_USB2_HC_PROTOCOL
*This
,
400 IN EFI_USB_PORT_FEATURE PortFeature
410 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
411 Ehc
= EHC_FROM_THIS (This
);
412 Status
= EFI_SUCCESS
;
414 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
416 if (PortNumber
>= TotalPort
) {
417 Status
= EFI_INVALID_PARAMETER
;
421 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
422 State
= EhcReadOpReg (Ehc
, Offset
);
425 // Mask off the port status change bits, these bits are
428 State
&= ~PORTSC_CHANGE_MASK
;
430 switch (PortFeature
) {
431 case EfiUsbPortEnable
:
433 // Sofeware can't set this bit, Port can only be enable by
434 // EHCI as a part of the reset and enable
436 State
|= PORTSC_ENABLED
;
437 EhcWriteOpReg (Ehc
, Offset
, State
);
440 case EfiUsbPortSuspend
:
441 State
|= PORTSC_SUSPEND
;
442 EhcWriteOpReg (Ehc
, Offset
, State
);
445 case EfiUsbPortReset
:
447 // Make sure Host Controller not halt before reset it
449 if (EhcIsHalt (Ehc
)) {
450 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
452 if (EFI_ERROR (Status
)) {
453 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status
));
459 // Set one to PortReset bit must also set zero to PortEnable bit
461 State
|= PORTSC_RESET
;
462 State
&= ~PORTSC_ENABLED
;
463 EhcWriteOpReg (Ehc
, Offset
, State
);
466 case EfiUsbPortPower
:
468 // Not supported, ignore the operation
470 Status
= EFI_SUCCESS
;
473 case EfiUsbPortOwner
:
474 State
|= PORTSC_OWNER
;
475 EhcWriteOpReg (Ehc
, Offset
, State
);
479 Status
= EFI_INVALID_PARAMETER
;
483 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature: exit status %r\n", Status
));
485 gBS
->RestoreTPL (OldTpl
);
491 Clears a feature for the specified root hub port.
493 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
494 @param PortNumber Specifies the root hub port whose feature is
495 requested to be cleared.
496 @param PortFeature Indicates the feature selector associated with the
497 feature clear request.
499 @return EFI_SUCCESS : The feature specified by PortFeature was cleared
500 @return for the USB root hub port specified by PortNumber.
501 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.
502 @return EFI_DEVICE_ERROR : Can't read register
508 EhcClearRootHubPortFeature (
509 IN EFI_USB2_HC_PROTOCOL
*This
,
511 IN EFI_USB_PORT_FEATURE PortFeature
521 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
522 Ehc
= EHC_FROM_THIS (This
);
523 Status
= EFI_SUCCESS
;
525 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
527 if (PortNumber
>= TotalPort
) {
528 Status
= EFI_INVALID_PARAMETER
;
532 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
533 State
= EhcReadOpReg (Ehc
, Offset
);
534 State
&= ~PORTSC_CHANGE_MASK
;
536 switch (PortFeature
) {
537 case EfiUsbPortEnable
:
539 // Clear PORT_ENABLE feature means disable port.
541 State
&= ~PORTSC_ENABLED
;
542 EhcWriteOpReg (Ehc
, Offset
, State
);
545 case EfiUsbPortSuspend
:
547 // A write of zero to this bit is ignored by the host
548 // controller. The host controller will unconditionally
549 // set this bit to a zero when:
550 // 1. software sets the Forct Port Resume bit to a zero from a one.
551 // 2. software sets the Port Reset bit to a one frome a zero.
553 State
&= ~PORSTSC_RESUME
;
554 EhcWriteOpReg (Ehc
, Offset
, State
);
557 case EfiUsbPortReset
:
559 // Clear PORT_RESET means clear the reset signal.
561 State
&= ~PORTSC_RESET
;
562 EhcWriteOpReg (Ehc
, Offset
, State
);
565 case EfiUsbPortOwner
:
567 // Clear port owner means this port owned by EHC
569 State
&= ~PORTSC_OWNER
;
570 EhcWriteOpReg (Ehc
, Offset
, State
);
573 case EfiUsbPortConnectChange
:
575 // Clear connect status change
577 State
|= PORTSC_CONN_CHANGE
;
578 EhcWriteOpReg (Ehc
, Offset
, State
);
581 case EfiUsbPortEnableChange
:
583 // Clear enable status change
585 State
|= PORTSC_ENABLE_CHANGE
;
586 EhcWriteOpReg (Ehc
, Offset
, State
);
589 case EfiUsbPortOverCurrentChange
:
591 // Clear PortOverCurrent change
593 State
|= PORTSC_OVERCUR_CHANGE
;
594 EhcWriteOpReg (Ehc
, Offset
, State
);
597 case EfiUsbPortPower
:
598 case EfiUsbPortSuspendChange
:
599 case EfiUsbPortResetChange
:
601 // Not supported or not related operation
606 Status
= EFI_INVALID_PARAMETER
;
611 DEBUG ((EFI_D_INFO
, "EhcClearRootHubPortFeature: exit status %r\n", Status
));
612 gBS
->RestoreTPL (OldTpl
);
618 Submits control transfer to a target USB device.
620 @param This This EFI_USB2_HC_PROTOCOL instance.
621 @param DeviceAddress The target device address
622 @param DeviceSpeed Target device speed.
623 @param MaximumPacketLength Maximum packet size the default control transfer
624 endpoint is capable of sending or receiving.
625 @param Request USB device request to send
626 @param TransferDirection Specifies the data direction for the data stage
627 @param Data Data buffer to be transmitted or received from USB
629 @param DataLength The size (in bytes) of the data buffer
630 @param TimeOut Indicates the maximum timeout, in millisecond,
631 @param Translator Transaction translator to be used by this device.
632 @param TransferResult Return the result of this control transfer.
634 @return EFI_SUCCESS : Transfer was completed successfully.
635 @return EFI_OUT_OF_RESOURCES : The transfer failed due to lack of resources.
636 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
637 @return EFI_TIMEOUT : Transfer failed due to timeout.
638 @return EFI_DEVICE_ERROR : Transfer failed due to host controller or device error.
645 IN EFI_USB2_HC_PROTOCOL
*This
,
646 IN UINT8 DeviceAddress
,
647 IN UINT8 DeviceSpeed
,
648 IN UINTN MaximumPacketLength
,
649 IN EFI_USB_DEVICE_REQUEST
*Request
,
650 IN EFI_USB_DATA_DIRECTION TransferDirection
,
652 IN OUT UINTN
*DataLength
,
654 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
655 OUT UINT32
*TransferResult
665 // Validate parameters
667 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
668 return EFI_INVALID_PARAMETER
;
671 if ((TransferDirection
!= EfiUsbDataIn
) &&
672 (TransferDirection
!= EfiUsbDataOut
) &&
673 (TransferDirection
!= EfiUsbNoData
)) {
674 return EFI_INVALID_PARAMETER
;
677 if ((TransferDirection
== EfiUsbNoData
) &&
678 ((Data
!= NULL
) || (*DataLength
!= 0))) {
679 return EFI_INVALID_PARAMETER
;
682 if ((TransferDirection
!= EfiUsbNoData
) &&
683 ((Data
== NULL
) || (*DataLength
== 0))) {
684 return EFI_INVALID_PARAMETER
;
687 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
688 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
689 return EFI_INVALID_PARAMETER
;
692 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
693 return EFI_INVALID_PARAMETER
;
696 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
697 Ehc
= EHC_FROM_THIS (This
);
699 Status
= EFI_DEVICE_ERROR
;
700 *TransferResult
= EFI_USB_ERR_SYSTEM
;
702 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
703 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: HC halted at entrance\n"));
705 EhcAckAllInterrupt (Ehc
);
709 EhcAckAllInterrupt (Ehc
);
712 // Create a new URB, insert it into the asynchronous
713 // schedule list, then poll the execution status.
716 // Encode the direction in address, although default control
717 // endpoint is bidirectional. EhcCreateUrb expects this
718 // combination of Ep addr and its direction.
720 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
739 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: failed to create URB"));
741 Status
= EFI_OUT_OF_RESOURCES
;
745 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
746 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
747 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
750 // Get the status from URB. The result is updated in EhcCheckUrbResult
751 // which is called by EhcExecTransfer
753 *TransferResult
= Urb
->Result
;
754 *DataLength
= Urb
->Completed
;
756 if (*TransferResult
== EFI_USB_NOERROR
) {
757 Status
= EFI_SUCCESS
;
760 EhcAckAllInterrupt (Ehc
);
761 EhcFreeUrb (Ehc
, Urb
);
764 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
765 gBS
->RestoreTPL (OldTpl
);
767 if (EFI_ERROR (Status
)) {
768 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
776 Submits bulk transfer to a bulk endpoint of a USB device.
778 @param This This EFI_USB2_HC_PROTOCOL instance.
779 @param DeviceAddress Target device address
780 @param EndPointAddress Endpoint number and its direction in bit 7. .
781 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
783 @param MaximumPacketLength Maximum packet size the endpoint is capable of
784 sending or receiving.
785 @param DataBuffersNumber Number of data buffers prepared for the transfer.
786 @param Data Array of pointers to the buffers of data to transmit
787 from or receive into.
788 @param DataLength The lenght of the data buffer
789 @param DataToggle On input, the initial data toggle for the transfer;
790 On output, it is updated to to next data toggle to
791 use of the subsequent bulk
793 @param Translator A pointr to the transaction translator data.
794 @param TimeOut Indicates the maximum time, in millisecond, which
795 the transfer is allowed to complete.
796 @param TransferResult A pointer to the detailed result information of the
799 @return EFI_SUCCESS : The transfer was completed successfully.
800 @return EFI_OUT_OF_RESOURCES : The transfer failed due to lack of resource.
801 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
802 @return EFI_TIMEOUT : The transfer failed due to timeout.
803 @return EFI_DEVICE_ERROR : The transfer failed due to host controller error.
810 IN EFI_USB2_HC_PROTOCOL
*This
,
811 IN UINT8 DeviceAddress
,
812 IN UINT8 EndPointAddress
,
813 IN UINT8 DeviceSpeed
,
814 IN UINTN MaximumPacketLength
,
815 IN UINT8 DataBuffersNumber
,
816 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
817 IN OUT UINTN
*DataLength
,
818 IN OUT UINT8
*DataToggle
,
820 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
821 OUT UINT32
*TransferResult
830 // Validate the parameters
832 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
833 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
834 return EFI_INVALID_PARAMETER
;
837 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
838 return EFI_INVALID_PARAMETER
;
841 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
842 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
843 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
844 return EFI_INVALID_PARAMETER
;
847 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
848 Ehc
= EHC_FROM_THIS (This
);
850 *TransferResult
= EFI_USB_ERR_SYSTEM
;
851 Status
= EFI_DEVICE_ERROR
;
853 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
854 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: HC is halted\n"));
856 EhcAckAllInterrupt (Ehc
);
860 EhcAckAllInterrupt (Ehc
);
863 // Create a new URB, insert it into the asynchronous
864 // schedule list, then poll the execution status.
884 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: failed to create URB\n"));
886 Status
= EFI_OUT_OF_RESOURCES
;
890 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
891 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
892 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
894 *TransferResult
= Urb
->Result
;
895 *DataLength
= Urb
->Completed
;
896 *DataToggle
= Urb
->DataToggle
;
898 if (*TransferResult
== EFI_USB_NOERROR
) {
899 Status
= EFI_SUCCESS
;
902 EhcAckAllInterrupt (Ehc
);
903 EhcFreeUrb (Ehc
, Urb
);
906 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
907 gBS
->RestoreTPL (OldTpl
);
909 if (EFI_ERROR (Status
)) {
910 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
918 Submits an asynchronous interrupt transfer to an
919 interrupt endpoint of a USB device.
921 @param This This EFI_USB2_HC_PROTOCOL instance.
922 @param DeviceAddress Target device address
923 @param EndPointAddress Endpoint number and its direction encoded in bit 7
924 @param DeviceSpeed Indicates device speed.
925 @param MaximumPacketLength Maximum packet size the target endpoint is capable
926 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
927 transfer If FALSE, to remove the specified
928 asynchronous interrupt
929 @param DataToggle On input, the initial data toggle to use; on output,
930 it is updated to indicate the next data toggle
931 @param PollingInterval The he interval, in milliseconds, that the transfer
933 @param DataLength The length of data to receive at the rate specified
935 @param Translator Transaction translator to use.
936 @param CallBackFunction Function to call at the rate specified by
938 @param Context Context to CallBackFunction.
940 @return EFI_SUCCESS : The request has been successfully submitted or canceled.
941 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
942 @return EFI_OUT_OF_RESOURCES : The request failed due to a lack of resources.
943 @return EFI_DEVICE_ERROR : The transfer failed due to host controller error.
949 EhcAsyncInterruptTransfer (
950 IN EFI_USB2_HC_PROTOCOL
* This
,
951 IN UINT8 DeviceAddress
,
952 IN UINT8 EndPointAddress
,
953 IN UINT8 DeviceSpeed
,
954 IN UINTN MaximumPacketLength
,
955 IN BOOLEAN IsNewTransfer
,
956 IN OUT UINT8
*DataToggle
,
957 IN UINTN PollingInterval
,
959 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
960 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
961 IN VOID
*Context OPTIONAL
971 // Validate parameters
973 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
974 return EFI_INVALID_PARAMETER
;
978 if (DataLength
== 0) {
979 return EFI_INVALID_PARAMETER
;
982 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
983 return EFI_INVALID_PARAMETER
;
986 if ((PollingInterval
> 255) || (PollingInterval
< 1)) {
987 return EFI_INVALID_PARAMETER
;
991 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
992 Ehc
= EHC_FROM_THIS (This
);
995 // Delete Async interrupt transfer request. DataToggle will return
996 // the next data toggle to use.
998 if (!IsNewTransfer
) {
999 Status
= EhciDelAsyncIntTransfer (Ehc
, DeviceAddress
, EndPointAddress
, DataToggle
);
1001 DEBUG ((EFI_D_INFO
, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status
));
1005 Status
= EFI_SUCCESS
;
1007 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1008 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: HC is halt\n"));
1009 EhcAckAllInterrupt (Ehc
);
1011 Status
= EFI_DEVICE_ERROR
;
1015 EhcAckAllInterrupt (Ehc
);
1017 Data
= AllocatePool (DataLength
);
1020 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1022 Status
= EFI_OUT_OF_RESOURCES
;
1026 Urb
= EhcCreateUrb (
1032 MaximumPacketLength
,
1034 EHC_INT_TRANSFER_ASYNC
,
1044 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1046 gBS
->FreePool (Data
);
1047 Status
= EFI_OUT_OF_RESOURCES
;
1052 // New asynchronous transfer must inserted to the head.
1053 // Check the comments in EhcMoniteAsyncRequests
1055 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1056 InsertHeadList (&Ehc
->AsyncIntTransfers
, &Urb
->UrbList
);
1059 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1060 gBS
->RestoreTPL (OldTpl
);
1067 Submits synchronous interrupt transfer to an interrupt endpoint
1070 @param This This EFI_USB2_HC_PROTOCOL instance.
1071 @param DeviceAddress Target device address
1072 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1073 @param DeviceSpeed Indicates device speed.
1074 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1075 of sending or receiving.
1076 @param Data Buffer of data that will be transmitted to USB
1077 device or received from USB device.
1078 @param DataLength On input, the size, in bytes, of the data buffer; On
1079 output, the number of bytes transferred.
1080 @param DataToggle On input, the initial data toggle to use; on output,
1081 it is updated to indicate the next data toggle
1082 @param TimeOut Maximum time, in second, to complete
1083 @param Translator Transaction translator to use.
1084 @param TransferResult Variable to receive the transfer result
1086 @return EFI_SUCCESS : The transfer was completed successfully.
1087 @return EFI_OUT_OF_RESOURCES : The transfer failed due to lack of resource.
1088 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
1089 @return EFI_TIMEOUT : The transfer failed due to timeout.
1090 @return EFI_DEVICE_ERROR : The failed due to host controller or device error
1096 EhcSyncInterruptTransfer (
1097 IN EFI_USB2_HC_PROTOCOL
*This
,
1098 IN UINT8 DeviceAddress
,
1099 IN UINT8 EndPointAddress
,
1100 IN UINT8 DeviceSpeed
,
1101 IN UINTN MaximumPacketLength
,
1103 IN OUT UINTN
*DataLength
,
1104 IN OUT UINT8
*DataToggle
,
1106 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1107 OUT UINT32
*TransferResult
1116 // Validates parameters
1118 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
1119 (Data
== NULL
) || (TransferResult
== NULL
)) {
1120 return EFI_INVALID_PARAMETER
;
1123 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1124 return EFI_INVALID_PARAMETER
;
1127 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1128 return EFI_INVALID_PARAMETER
;
1131 if (((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) ||
1132 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1133 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 3072))) {
1134 return EFI_INVALID_PARAMETER
;
1137 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1138 Ehc
= EHC_FROM_THIS (This
);
1140 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1141 Status
= EFI_DEVICE_ERROR
;
1143 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1144 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: HC is halt\n"));
1146 EhcAckAllInterrupt (Ehc
);
1150 EhcAckAllInterrupt (Ehc
);
1152 Urb
= EhcCreateUrb (
1158 MaximumPacketLength
,
1160 EHC_INT_TRANSFER_SYNC
,
1170 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: failed to create URB\n"));
1172 Status
= EFI_OUT_OF_RESOURCES
;
1176 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1177 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1178 EhcUnlinkQhFromPeriod (Ehc
, Urb
->Qh
);
1180 *TransferResult
= Urb
->Result
;
1181 *DataLength
= Urb
->Completed
;
1182 *DataToggle
= Urb
->DataToggle
;
1184 if (*TransferResult
== EFI_USB_NOERROR
) {
1185 Status
= EFI_SUCCESS
;
1189 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1190 gBS
->RestoreTPL (OldTpl
);
1192 if (EFI_ERROR (Status
)) {
1193 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1201 Submits isochronous transfer to a target USB device.
1203 @param This This EFI_USB2_HC_PROTOCOL instance.
1204 @param DeviceAddress Target device address
1205 @param EndPointAddress End point address with its direction
1206 @param DeviceSpeed Device speed, Low speed device doesn't support this
1208 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1209 sending or receiving.
1210 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1211 @param Data Array of pointers to the buffers of data that will
1212 be transmitted to USB device or received from USB
1214 @param DataLength The size, in bytes, of the data buffer
1215 @param Translator Transaction translator to use.
1216 @param TransferResult Variable to receive the transfer result
1218 @return EFI_UNSUPPORTED : Isochronous transfer is unsupported.
1224 EhcIsochronousTransfer (
1225 IN EFI_USB2_HC_PROTOCOL
*This
,
1226 IN UINT8 DeviceAddress
,
1227 IN UINT8 EndPointAddress
,
1228 IN UINT8 DeviceSpeed
,
1229 IN UINTN MaximumPacketLength
,
1230 IN UINT8 DataBuffersNumber
,
1231 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1232 IN UINTN DataLength
,
1233 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1234 OUT UINT32
*TransferResult
1237 return EFI_UNSUPPORTED
;
1242 Submits Async isochronous transfer to a target USB device.
1244 @param This This EFI_USB2_HC_PROTOCOL instance.
1245 @param DeviceAddress Target device address
1246 @param EndPointAddress End point address with its direction
1247 @param DeviceSpeed Device speed, Low speed device doesn't support this
1249 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1250 sending or receiving.
1251 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1252 @param Data Array of pointers to the buffers of data that will
1253 be transmitted to USB device or received from USB
1255 @param DataLength The size, in bytes, of the data buffer
1256 @param Translator Transaction translator to use.
1257 @param IsochronousCallBack Function to be called when the transfer complete
1258 @param Context Context passed to the call back function as
1261 @return EFI_UNSUPPORTED : Isochronous transfer isn't supported
1267 EhcAsyncIsochronousTransfer (
1268 IN EFI_USB2_HC_PROTOCOL
*This
,
1269 IN UINT8 DeviceAddress
,
1270 IN UINT8 EndPointAddress
,
1271 IN UINT8 DeviceSpeed
,
1272 IN UINTN MaximumPacketLength
,
1273 IN UINT8 DataBuffersNumber
,
1274 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1275 IN UINTN DataLength
,
1276 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1277 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1281 return EFI_UNSUPPORTED
;
1286 EhcDriverEntryPoint (
1287 IN EFI_HANDLE ImageHandle
,
1288 IN EFI_SYSTEM_TABLE
*SystemTable
1292 Routine Description:
1294 Entry point for EFI drivers.
1298 ImageHandle - EFI_HANDLE
1299 SystemTable - EFI_SYSTEM_TABLE
1304 EFI_DEVICE_ERROR Fail
1308 return EfiLibInstallDriverBindingComponentName2 (
1311 &gEhciDriverBinding
,
1313 &gEhciComponentName
,
1314 &gEhciComponentName2
1320 Test to see if this driver supports ControllerHandle. Any
1321 ControllerHandle that has Usb2HcProtocol installed will
1324 @param This Protocol instance pointer.
1325 @param Controlle Handle of device to test
1326 @param RemainingDevicePath Not used
1328 @return EFI_SUCCESS : This driver supports this device.
1329 @return EFI_UNSUPPORTED : This driver does not support this device.
1334 EhcDriverBindingSupported (
1335 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1336 IN EFI_HANDLE Controller
,
1337 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1341 EFI_PCI_IO_PROTOCOL
*PciIo
;
1342 USB_CLASSC UsbClassCReg
;
1345 // Test whether there is PCI IO Protocol attached on the controller handle.
1347 Status
= gBS
->OpenProtocol (
1349 &gEfiPciIoProtocolGuid
,
1351 This
->DriverBindingHandle
,
1353 EFI_OPEN_PROTOCOL_BY_DRIVER
1356 if (EFI_ERROR (Status
)) {
1357 return EFI_UNSUPPORTED
;
1360 Status
= PciIo
->Pci
.Read (
1364 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1368 if (EFI_ERROR (Status
)) {
1369 Status
= EFI_UNSUPPORTED
;
1374 // Test whether the controller belongs to Ehci type
1376 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1377 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1378 (UsbClassCReg
.PI
!= EHC_PCI_CLASSC_PI
)) {
1380 Status
= EFI_UNSUPPORTED
;
1384 gBS
->CloseProtocol (
1386 &gEfiPciIoProtocolGuid
,
1387 This
->DriverBindingHandle
,
1396 Create and initialize a USB2_HC_DEV
1398 @param PciIo The PciIo on this device
1399 @param OriginalPciAttributes Original PCI attributes
1401 @return The allocated and initialized USB2_HC_DEV structure
1402 @return if created, otherwise NULL.
1408 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1409 IN UINT64 OriginalPciAttributes
1415 Ehc
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
1422 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1424 Ehc
->Signature
= USB2_HC_DEV_SIGNATURE
;
1426 Ehc
->Usb2Hc
.GetCapability
= EhcGetCapability
;
1427 Ehc
->Usb2Hc
.Reset
= EhcReset
;
1428 Ehc
->Usb2Hc
.GetState
= EhcGetState
;
1429 Ehc
->Usb2Hc
.SetState
= EhcSetState
;
1430 Ehc
->Usb2Hc
.ControlTransfer
= EhcControlTransfer
;
1431 Ehc
->Usb2Hc
.BulkTransfer
= EhcBulkTransfer
;
1432 Ehc
->Usb2Hc
.AsyncInterruptTransfer
= EhcAsyncInterruptTransfer
;
1433 Ehc
->Usb2Hc
.SyncInterruptTransfer
= EhcSyncInterruptTransfer
;
1434 Ehc
->Usb2Hc
.IsochronousTransfer
= EhcIsochronousTransfer
;
1435 Ehc
->Usb2Hc
.AsyncIsochronousTransfer
= EhcAsyncIsochronousTransfer
;
1436 Ehc
->Usb2Hc
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1437 Ehc
->Usb2Hc
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1438 Ehc
->Usb2Hc
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1439 Ehc
->Usb2Hc
.MajorRevision
= 0x1;
1440 Ehc
->Usb2Hc
.MinorRevision
= 0x1;
1443 Ehc
->OriginalPciAttributes
= OriginalPciAttributes
;
1445 InitializeListHead (&Ehc
->AsyncIntTransfers
);
1447 Ehc
->HcStructParams
= EhcReadCapRegister (Ehc
, EHC_HCSPARAMS_OFFSET
);
1448 Ehc
->HcCapParams
= EhcReadCapRegister (Ehc
, EHC_HCCPARAMS_OFFSET
);
1449 Ehc
->CapLen
= EhcReadCapRegister (Ehc
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1451 DEBUG ((EFI_D_INFO
, "EhcCreateUsb2Hc: capability length %d\n", Ehc
->CapLen
));
1454 // Create AsyncRequest Polling Timer
1456 Status
= gBS
->CreateEvent (
1457 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1459 EhcMoniteAsyncRequests
,
1464 if (EFI_ERROR (Status
)) {
1465 gBS
->FreePool (Ehc
);
1474 Starting the Usb EHCI Driver
1476 @param This Protocol instance pointer.
1477 @param Controller Handle of device to test
1478 @param RemainingDevicePath Not used
1480 @return EFI_SUCCESS : supports this device.
1481 @return EFI_UNSUPPORTED : do not support this device.
1482 @return EFI_DEVICE_ERROR : cannot be started due to device Error
1483 @return EFI_OUT_OF_RESOURCES : cannot allocate resources
1488 EhcDriverBindingStart (
1489 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1490 IN EFI_HANDLE Controller
,
1491 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1496 EFI_PCI_IO_PROTOCOL
*PciIo
;
1498 UINT64 OriginalPciAttributes
;
1499 BOOLEAN PciAttributesSaved
;
1502 // Open the PciIo Protocol, then enable the USB host controller
1504 Status
= gBS
->OpenProtocol (
1506 &gEfiPciIoProtocolGuid
,
1508 This
->DriverBindingHandle
,
1510 EFI_OPEN_PROTOCOL_BY_DRIVER
1513 if (EFI_ERROR (Status
)) {
1514 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to open PCI_IO\n"));
1515 return EFI_DEVICE_ERROR
;
1518 PciAttributesSaved
= FALSE
;
1520 // Save original PCI attributes
1522 Status
= PciIo
->Attributes (
1524 EfiPciIoAttributeOperationGet
,
1526 &OriginalPciAttributes
1529 if (EFI_ERROR (Status
)) {
1532 PciAttributesSaved
= TRUE
;
1534 Status
= PciIo
->Attributes (
1536 EfiPciIoAttributeOperationSupported
,
1540 if (!EFI_ERROR (Status
)) {
1541 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1542 Status
= PciIo
->Attributes (
1544 EfiPciIoAttributeOperationEnable
,
1550 if (EFI_ERROR (Status
)) {
1551 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to enable controller\n"));
1556 // Create then install USB2_HC_PROTOCOL
1558 Ehc
= EhcCreateUsb2Hc (PciIo
, OriginalPciAttributes
);
1561 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1563 Status
= EFI_OUT_OF_RESOURCES
;
1567 Status
= gBS
->InstallProtocolInterface (
1569 &gEfiUsb2HcProtocolGuid
,
1570 EFI_NATIVE_INTERFACE
,
1574 if (EFI_ERROR (Status
)) {
1575 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1580 // Robustnesss improvement such as for UoL
1581 // Default is not required.
1583 // EhcClearLegacySupport (Ehc);
1584 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1586 Status
= EhcInitHC (Ehc
);
1588 if (EFI_ERROR (Status
)) {
1589 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to init host controller\n"));
1590 goto UNINSTALL_USBHC
;
1594 // Start the asynchronous interrupt monitor
1596 Status
= gBS
->SetTimer (Ehc
->PollTimer
, TimerPeriodic
, EHC_ASYNC_POLL_INTERVAL
);
1598 if (EFI_ERROR (Status
)) {
1599 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1601 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1602 goto UNINSTALL_USBHC
;
1606 // Install the component name protocol, don't fail the start
1607 // because of something for display.
1611 gEhciComponentName
.SupportedLanguages
,
1612 &Ehc
->ControllerNameTable
,
1613 L
"Enhanced Host Controller (USB 2.0)",
1618 gEhciComponentName2
.SupportedLanguages
,
1619 &Ehc
->ControllerNameTable
,
1620 L
"Enhanced Host Controller (USB 2.0)",
1625 DEBUG ((EFI_D_INFO
, "EhcDriverBindingStart: EHCI started for controller @ %x\n", Controller
));
1629 gBS
->UninstallProtocolInterface (
1631 &gEfiUsb2HcProtocolGuid
,
1637 gBS
->CloseEvent (Ehc
->PollTimer
);
1638 gBS
->FreePool (Ehc
);
1641 if (PciAttributesSaved
== TRUE
) {
1643 // Restore original PCI attributes
1647 EfiPciIoAttributeOperationSet
,
1648 OriginalPciAttributes
,
1653 gBS
->CloseProtocol (
1655 &gEfiPciIoProtocolGuid
,
1656 This
->DriverBindingHandle
,
1665 Stop this driver on ControllerHandle. Support stoping any child handles
1666 created by this driver.
1668 @param This Protocol instance pointer.
1669 @param Controller Handle of device to stop driver on
1670 @param NumberOfChildren Number of Children in the ChildHandleBuffer
1671 @param ChildHandleBuffer List of handles for the children we need to stop.
1673 @return EFI_SUCCESS Success
1674 @return EFI_DEVICE_ERROR Fail
1679 EhcDriverBindingStop (
1680 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1681 IN EFI_HANDLE Controller
,
1682 IN UINTN NumberOfChildren
,
1683 IN EFI_HANDLE
*ChildHandleBuffer
1687 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1688 EFI_PCI_IO_PROTOCOL
*PciIo
;
1692 // Test whether the Controller handler passed in is a valid
1693 // Usb controller handle that should be supported, if not,
1694 // return the error status directly
1696 Status
= gBS
->OpenProtocol (
1698 &gEfiUsb2HcProtocolGuid
,
1700 This
->DriverBindingHandle
,
1702 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1705 if (EFI_ERROR (Status
)) {
1709 Ehc
= EHC_FROM_THIS (Usb2Hc
);
1713 // Stop AsyncRequest Polling timer then stop the EHCI driver
1714 // and uninstall the EHCI protocl.
1716 gBS
->SetTimer (Ehc
->PollTimer
, TimerCancel
, EHC_ASYNC_POLL_INTERVAL
);
1717 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1719 Status
= gBS
->UninstallProtocolInterface (
1721 &gEfiUsb2HcProtocolGuid
,
1725 if (EFI_ERROR (Status
)) {
1729 if (Ehc
->PollTimer
!= NULL
) {
1730 gBS
->CloseEvent (Ehc
->PollTimer
);
1735 if (Ehc
->ControllerNameTable
) {
1736 FreeUnicodeStringTable (Ehc
->ControllerNameTable
);
1740 // Restore original PCI attributes
1744 EfiPciIoAttributeOperationSet
,
1745 Ehc
->OriginalPciAttributes
,
1749 gBS
->CloseProtocol (
1751 &gEfiPciIoProtocolGuid
,
1752 This
->DriverBindingHandle
,
1761 EFI_DRIVER_BINDING_PROTOCOL
1762 gEhciDriverBinding
= {
1763 EhcDriverBindingSupported
,
1764 EhcDriverBindingStart
,
1765 EhcDriverBindingStop
,