3 Copyright (c) 2004 - 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.
18 The UHCI driver model and HC protocol routines.
28 Provides software reset for the USB host controller according to UEFI 2.0 spec.
30 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
31 @param Attributes A bit mask of the reset operation to perform. See
32 below for a list of the supported bit mask values.
34 @return EFI_SUCCESS : The reset operation succeeded.
35 @return EFI_INVALID_PARAMETER : Attributes is not valid.
36 @return EFI_UNSUPPORTED : This type of reset is not currently supported
37 @return EFI_DEVICE_ERROR : Other errors
44 IN EFI_USB2_HC_PROTOCOL
*This
,
51 if ((Attributes
== EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
) ||
52 (Attributes
== EFI_USB_HC_RESET_HOST_WITH_DEBUG
)) {
53 return EFI_UNSUPPORTED
;
56 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
58 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
61 case EFI_USB_HC_RESET_GLOBAL
:
63 // Stop schedule and set the Global Reset bit in the command register
65 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
66 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_GRESET
);
68 gBS
->Stall (UHC_ROOT_PORT_RESET_STALL
);
71 // Clear the Global Reset bit to zero.
73 UhciClearRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_GRESET
);
75 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
78 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
80 // Stop schedule and set Host Controller Reset bit to 1
82 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
83 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_HCRESET
);
85 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
89 goto ON_INVAILD_PARAMETER
;
93 // Delete all old transactions on the USB bus, then
94 // reinitialize the frame list
96 UhciFreeAllAsyncReq (Uhc
);
97 UhciDestoryFrameList (Uhc
);
98 UhciInitFrameList (Uhc
);
100 gBS
->RestoreTPL (OldTpl
);
104 ON_INVAILD_PARAMETER
:
106 gBS
->RestoreTPL (OldTpl
);
108 return EFI_INVALID_PARAMETER
;
113 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
115 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
116 @param State Variable to receive current device state
118 @return EFI_SUCCESS : The state is returned
119 @return EFI_INVALID_PARAMETER : State is not valid.
120 @return EFI_DEVICE_ERROR : Other errors2006
127 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
128 OUT EFI_USB_HC_STATE
*State
136 return EFI_INVALID_PARAMETER
;
139 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
141 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
142 UsbSts
= UhciReadReg (Uhc
->PciIo
, USBSTS_OFFSET
);
144 if (UsbCmd
& USBCMD_EGSM
) {
145 *State
= EfiUsbHcStateSuspend
;
147 } else if ((UsbSts
& USBSTS_HCH
) != 0) {
148 *State
= EfiUsbHcStateHalt
;
151 *State
= EfiUsbHcStateOperational
;
159 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
161 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
162 @param State Indicates the state of the host controller that will
165 @return EFI_SUCCESS : Host controller was successfully placed in the state
166 @return EFI_INVALID_PARAMETER : State is invalid.
167 @return EFI_DEVICE_ERROR : Failed to set the state
174 IN EFI_USB2_HC_PROTOCOL
*This
,
175 IN EFI_USB_HC_STATE State
178 EFI_USB_HC_STATE CurState
;
184 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
185 Status
= Uhci2GetState (This
, &CurState
);
187 if (EFI_ERROR (Status
)) {
188 return EFI_DEVICE_ERROR
;
191 if (CurState
== State
) {
195 Status
= EFI_SUCCESS
;
196 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
199 case EfiUsbHcStateHalt
:
200 Status
= UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
203 case EfiUsbHcStateOperational
:
204 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
206 if (CurState
== EfiUsbHcStateHalt
) {
208 // Set Run/Stop bit to 1, also set the bandwidht reclamation
211 UsbCmd
|= USBCMD_RS
| USBCMD_MAXP
;
212 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
214 } else if (CurState
== EfiUsbHcStateSuspend
) {
216 // If FGR(Force Global Resume) bit is 0, set it
218 if ((UsbCmd
& USBCMD_FGR
) == 0) {
219 UsbCmd
|= USBCMD_FGR
;
220 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
224 // wait 20ms to let resume complete (20ms is specified by UHCI spec)
226 gBS
->Stall (UHC_FORCE_GLOBAL_RESUME_STALL
);
229 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
231 UsbCmd
&= ~USBCMD_FGR
;
232 UsbCmd
&= ~USBCMD_EGSM
;
234 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
239 case EfiUsbHcStateSuspend
:
240 Status
= Uhci2SetState (This
, EfiUsbHcStateHalt
);
242 if (EFI_ERROR (Status
)) {
243 Status
= EFI_DEVICE_ERROR
;
248 // Set Enter Global Suspend Mode bit to 1.
250 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
251 UsbCmd
|= USBCMD_EGSM
;
252 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
256 Status
= EFI_INVALID_PARAMETER
;
261 gBS
->RestoreTPL (OldTpl
);
266 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
268 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance
269 @param MaxSpeed A pointer to the max speed USB host controller
271 @param PortNumber A pointer to the number of root hub ports.
272 @param Is64BitCapable A pointer to an integer to show whether USB host
273 controller supports 64-bit memory addressing.
275 @return EFI_SUCCESS : capabilities were retrieved successfully.
276 @return EFI_INVALID_PARAMETER : MaxSpeed or PortNumber or Is64BitCapable is NULL.
277 @return EFI_DEVICE_ERROR : An error was encountered
284 IN EFI_USB2_HC_PROTOCOL
*This
,
286 OUT UINT8
*PortNumber
,
287 OUT UINT8
*Is64BitCapable
295 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
297 if ((NULL
== MaxSpeed
) || (NULL
== PortNumber
) || (NULL
== Is64BitCapable
)) {
298 return EFI_INVALID_PARAMETER
;
301 *MaxSpeed
= EFI_USB_SPEED_FULL
;
302 *Is64BitCapable
= (UINT8
) FALSE
;
306 for (Index
= 0; Index
< USB_MAX_ROOTHUB_PORT
; Index
++) {
307 Offset
= USBPORTSC_OFFSET
+ Index
* 2;
308 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
311 // Port status's bit 7 is reserved and always returns 1 if
312 // the port number is valid. Intel's UHCI (in EHCI controller)
313 // returns 0 in this bit if port number is invalid. Also, if
314 // PciIo IoRead returns error, 0xFFFF is returned to caller.
316 if (((PortSC
& 0x80) != 0) && (PortSC
!= 0xFFFF)) {
321 Uhc
->RootPorts
= *PortNumber
;
323 DEBUG ((EFI_D_INFO
, "Uhci2GetCapability: %d ports\n", Uhc
->RootPorts
));
329 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
331 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
332 @param PortNumber The port to get status
333 @param PortStatus A pointer to the current port status bits and port
336 @return EFI_SUCCESS : status of the USB root hub port was returned in PortStatus.
337 @return EFI_INVALID_PARAMETER : PortNumber is invalid.
338 @return EFI_DEVICE_ERROR : Can't read register
344 Uhci2GetRootHubPortStatus (
345 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
346 IN CONST UINT8 PortNumber
,
347 OUT EFI_USB_PORT_STATUS
*PortStatus
354 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
356 if (PortStatus
== NULL
) {
357 return EFI_INVALID_PARAMETER
;
360 if (PortNumber
>= Uhc
->RootPorts
) {
361 return EFI_INVALID_PARAMETER
;
364 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
365 PortStatus
->PortStatus
= 0;
366 PortStatus
->PortChangeStatus
= 0;
368 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
370 if (PortSC
& USBPORTSC_CCS
) {
371 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
374 if (PortSC
& USBPORTSC_PED
) {
375 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
378 if (PortSC
& USBPORTSC_SUSP
) {
379 DEBUG ((EFI_D_INFO
, "Uhci2GetRootHubPortStatus: port %d is suspended\n", PortNumber
));
380 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
383 if (PortSC
& USBPORTSC_PR
) {
384 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
387 if (PortSC
& USBPORTSC_LSDA
) {
388 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
392 // CHC will always return one in port owner bit
394 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
396 if (PortSC
& USBPORTSC_CSC
) {
397 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
400 if (PortSC
& USBPORTSC_PEDC
) {
401 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
409 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
411 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
412 @param PortNumber Specifies the root hub port whose feature is
414 @param PortFeature Indicates the feature selector associated with the
417 @return EFI_SUCCESS : PortFeature was set for the root port
418 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.
419 @return EFI_DEVICE_ERROR : Can't read register
425 Uhci2SetRootHubPortFeature (
426 IN EFI_USB2_HC_PROTOCOL
*This
,
428 IN EFI_USB_PORT_FEATURE PortFeature
437 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
439 if (PortNumber
>= Uhc
->RootPorts
) {
440 return EFI_INVALID_PARAMETER
;
443 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
445 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
446 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
448 switch (PortFeature
) {
449 case EfiUsbPortSuspend
:
450 Command
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
451 if (!(Command
& USBCMD_EGSM
)) {
453 // if global suspend is not active, can set port suspend
456 PortSC
|= USBPORTSC_SUSP
;
460 case EfiUsbPortReset
:
462 PortSC
|= USBPORTSC_PR
;
465 case EfiUsbPortPower
:
471 case EfiUsbPortEnable
:
473 PortSC
|= USBPORTSC_PED
;
477 gBS
->RestoreTPL (OldTpl
);
478 return EFI_INVALID_PARAMETER
;
481 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
482 gBS
->RestoreTPL (OldTpl
);
489 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
491 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
492 @param PortNumber Specifies the root hub port whose feature is
493 requested to be cleared.
494 @param PortFeature Indicates the feature selector associated with the
495 feature clear request.
497 @return EFI_SUCCESS : PortFeature was cleared for the USB root hub port
498 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.
499 @return EFI_DEVICE_ERROR : Can't read register
505 Uhci2ClearRootHubPortFeature (
506 IN EFI_USB2_HC_PROTOCOL
*This
,
508 IN EFI_USB_PORT_FEATURE PortFeature
516 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
518 if (PortNumber
>= Uhc
->RootPorts
) {
519 return EFI_INVALID_PARAMETER
;
522 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
524 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
525 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
527 switch (PortFeature
) {
528 case EfiUsbPortEnable
:
530 PortSC
&= ~USBPORTSC_PED
;
533 case EfiUsbPortSuspend
:
535 // Cause a resume on the specified port if in suspend mode.
538 PortSC
&= ~USBPORTSC_SUSP
;
541 case EfiUsbPortPower
:
547 case EfiUsbPortReset
:
549 PortSC
&= ~USBPORTSC_PR
;
552 case EfiUsbPortConnectChange
:
554 PortSC
|= USBPORTSC_CSC
;
557 case EfiUsbPortEnableChange
:
559 PortSC
|= USBPORTSC_PEDC
;
562 case EfiUsbPortSuspendChange
:
564 // Root hub does not support this
568 case EfiUsbPortOverCurrentChange
:
570 // Root hub does not support this
574 case EfiUsbPortResetChange
:
576 // Root hub does not support this
581 gBS
->RestoreTPL (OldTpl
);
582 return EFI_INVALID_PARAMETER
;
585 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
586 gBS
->RestoreTPL (OldTpl
);
593 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..
595 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.
596 DeviceAddress : Target device address
597 DeviceSpeed : Device speed
598 MaximumPacketLength : Maximum packet size of the target endpoint
599 Request : USB device request to send
600 TransferDirection : Data direction of the Data stage in control transfer
601 Data : Data to transmit/receive in data stage
602 DataLength : Length of the data
603 TimeOut : Maximum time, in microseconds, for transfer to complete.
604 TransferResult : Variable to receive the transfer result
606 @return EFI_SUCCESS : The control transfer was completed successfully.
607 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.
608 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
609 @return EFI_TIMEOUT : Failed due to timeout.
610 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.
616 Uhci2ControlTransfer (
617 IN EFI_USB2_HC_PROTOCOL
*This
,
618 IN UINT8 DeviceAddress
,
619 IN UINT8 DeviceSpeed
,
620 IN UINTN MaximumPacketLength
,
621 IN EFI_USB_DEVICE_REQUEST
*Request
,
622 IN EFI_USB_DATA_DIRECTION TransferDirection
,
624 IN OUT UINTN
*DataLength
,
626 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
627 OUT UINT32
*TransferResult
634 UHCI_QH_RESULT QhResult
;
640 BOOLEAN IsSlowDevice
;
642 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
649 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
652 // Parameters Checking
654 if (Request
== NULL
|| TransferResult
== NULL
) {
655 return EFI_INVALID_PARAMETER
;
658 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
659 return EFI_INVALID_PARAMETER
;
662 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
663 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
665 return EFI_INVALID_PARAMETER
;
668 if ((TransferDirection
!= EfiUsbNoData
) && (DataLength
== NULL
)) {
669 return EFI_INVALID_PARAMETER
;
672 *TransferResult
= EFI_USB_ERR_SYSTEM
;
673 Status
= EFI_DEVICE_ERROR
;
676 // If errors exist that cause host controller halt,
677 // clear status then return EFI_DEVICE_ERROR.
679 UhciAckAllInterrupt (Uhc
);
681 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
682 return EFI_DEVICE_ERROR
;
685 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
688 // Map the Request and data for bus master access,
689 // then create a list of TD for this transfer
691 Status
= UhciMapUserRequest (Uhc
, Request
, &RequestPhy
, &RequestMap
);
693 if (EFI_ERROR (Status
)) {
697 Status
= UhciMapUserData (Uhc
, TransferDirection
, Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
699 if (EFI_ERROR (Status
)) {
700 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
704 TDs
= UhciCreateCtrlTds (
711 (UINT8
) MaximumPacketLength
,
716 Status
= EFI_OUT_OF_RESOURCES
;
721 // According to the speed of the end point, link
722 // the TD to corrosponding queue head, then check
723 // the execution result
725 UhciLinkTdToQh (Uhc
->CtrlQh
, TDs
);
726 Status
= UhciExecuteTransfer (Uhc
, Uhc
->CtrlQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
727 UhciUnlinkTdFromQh (Uhc
->CtrlQh
, TDs
);
729 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
731 *TransferResult
= QhResult
.Result
;
733 if (DataLength
!= NULL
) {
734 *DataLength
= QhResult
.Complete
;
737 UhciDestoryTds (Uhc
, TDs
);
740 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
741 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
744 gBS
->RestoreTPL (OldTpl
);
751 Submits bulk transfer to a bulk endpoint of a USB device
753 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.
754 DeviceAddress : Target device address
755 EndPointAddress : Endpoint number and direction
756 DeviceSpeed : Device speed
757 MaximumPacketLength : Maximum packet size of the target endpoint
758 DataBuffersNumber : Number of data buffers prepared for the transfer.
759 Data : Array of pointers to the buffers of data
760 DataLength : On input, size of the data buffer, On output,
761 actually transferred data size.
762 DataToggle : On input, data toggle to use; On output, next data toggle
763 Translator : A pointr to the transaction translator data.
764 TimeOut : Maximum time out, in microseconds
765 TransferResult : Variable to receive transfer result
767 @return EFI_SUCCESS : The bulk transfer was completed successfully.
768 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.
769 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
770 @return EFI_TIMEOUT : Failed due to timeout.
771 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.
778 IN EFI_USB2_HC_PROTOCOL
*This
,
779 IN UINT8 DeviceAddress
,
780 IN UINT8 EndPointAddress
,
781 IN UINT8 DeviceSpeed
,
782 IN UINTN MaximumPacketLength
,
783 IN UINT8 DataBuffersNumber
,
784 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
785 IN OUT UINTN
*DataLength
,
786 IN OUT UINT8
*DataToggle
,
788 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
789 OUT UINT32
*TransferResult
792 EFI_USB_DATA_DIRECTION Direction
;
797 UHCI_QH_RESULT QhResult
;
803 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
807 if (DeviceSpeed
== EFI_USB_SPEED_LOW
) {
808 return EFI_INVALID_PARAMETER
;
811 if ((DataLength
== NULL
) || (Data
== NULL
) || (TransferResult
== NULL
)) {
812 return EFI_INVALID_PARAMETER
;
815 if (*DataLength
== 0) {
816 return EFI_INVALID_PARAMETER
;
819 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
820 return EFI_INVALID_PARAMETER
;
823 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
824 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
825 return EFI_INVALID_PARAMETER
;
828 *TransferResult
= EFI_USB_ERR_SYSTEM
;
829 Status
= EFI_OUT_OF_RESOURCES
;
832 // If has errors that cause host controller halt,
833 // then return EFI_DEVICE_ERROR directly.
835 UhciAckAllInterrupt (Uhc
);
837 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
838 return EFI_DEVICE_ERROR
;
841 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
844 // Map the source data buffer for bus master access,
845 // then create a list of TDs
847 if (EndPointAddress
& 0x80) {
848 Direction
= EfiUsbDataIn
;
850 Direction
= EfiUsbDataOut
;
853 Status
= UhciMapUserData (Uhc
, Direction
, *Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
855 if (EFI_ERROR (Status
)) {
859 Status
= EFI_OUT_OF_RESOURCES
;
860 TDs
= UhciCreateBulkOrIntTds (
868 (UINT8
) MaximumPacketLength
,
873 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
879 // Link the TDs to bulk queue head. According to the platfore
880 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
881 // to do full speed bandwidth reclamation or not.
883 BulkQh
= Uhc
->BulkQh
;
885 UhciLinkTdToQh (BulkQh
, TDs
);
886 Status
= UhciExecuteTransfer (Uhc
, BulkQh
, TDs
, TimeOut
, FALSE
, &QhResult
);
887 UhciUnlinkTdFromQh (BulkQh
, TDs
);
889 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
891 *TransferResult
= QhResult
.Result
;
892 *DataToggle
= QhResult
.NextToggle
;
893 *DataLength
= QhResult
.Complete
;
895 UhciDestoryTds (Uhc
, TDs
);
896 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
899 gBS
->RestoreTPL (OldTpl
);
905 Submits an asynchronous interrupt transfer to an
906 interrupt endpoint of a USB device according to UEFI 2.0 spec.
908 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.
909 DeviceAddress : Target device address
910 EndPointAddress : Endpoint number and direction
911 DeviceSpeed : Device speed
912 MaximumPacketLength : Maximum packet size of the target endpoint
913 IsNewTransfer : If TRUE, submit a new transfer, if FALSE cancel old transfer
914 DataToggle : On input, data toggle to use; On output, next data toggle
915 PollingInterval : Interrupt poll rate in milliseconds
916 DataLength : On input, size of the data buffer, On output,
917 actually transferred data size.
918 Translator : A pointr to the transaction translator data.
919 CallBackFunction : Function to call periodically
920 Context : User context
922 @return EFI_SUCCESS : Transfer was submitted
923 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
924 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.
925 @return EFI_DEVICE_ERROR : Can't read register
931 Uhci2AsyncInterruptTransfer (
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
,
947 BOOLEAN IsSlowDevice
;
957 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
964 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
966 if ((EndPointAddress
& 0x80) == 0) {
967 return EFI_INVALID_PARAMETER
;
971 // Delete Async interrupt transfer request
973 if (!IsNewTransfer
) {
974 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
975 Status
= UhciRemoveAsyncReq (Uhc
, DeviceAddress
, EndPointAddress
, DataToggle
);
977 gBS
->RestoreTPL (OldTpl
);
981 if (PollingInterval
< 1 || PollingInterval
> 255) {
982 return EFI_INVALID_PARAMETER
;
985 if (DataLength
== 0) {
986 return EFI_INVALID_PARAMETER
;
989 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
990 return EFI_INVALID_PARAMETER
;
994 // If has errors that cause host controller halt,
995 // then return EFI_DEVICE_ERROR directly.
997 UhciAckAllInterrupt (Uhc
);
999 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1000 return EFI_DEVICE_ERROR
;
1004 // Allocate and map source data buffer for bus master access.
1006 DataPtr
= AllocatePool (DataLength
);
1008 if (DataPtr
== NULL
) {
1009 return EFI_OUT_OF_RESOURCES
;
1012 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1015 // Map the user data then create a queue head and
1016 // list of TD for it.
1018 Status
= UhciMapUserData (
1028 if (EFI_ERROR (Status
)) {
1032 Qh
= UhciCreateQh (Uhc
, PollingInterval
);
1035 Status
= EFI_OUT_OF_RESOURCES
;
1039 IntTds
= UhciCreateBulkOrIntTds (
1047 (UINT8
) MaximumPacketLength
,
1051 if (IntTds
== NULL
) {
1052 Status
= EFI_OUT_OF_RESOURCES
;
1056 UhciLinkTdToQh (Qh
, IntTds
);
1059 // Save QH-TD structures to async Interrupt transfer list,
1060 // for monitor interrupt transfer execution routine use.
1062 Status
= UhciCreateAsyncReq (
1077 if (EFI_ERROR (Status
)) {
1081 UhciLinkQhToFrameList (Uhc
->FrameBase
, Qh
);
1083 gBS
->RestoreTPL (OldTpl
);
1087 UsbHcFreeMem (Uhc
->MemPool
, Qh
, sizeof (UHCI_QH_SW
));
1090 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1093 gBS
->FreePool (DataPtr
);
1094 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1096 gBS
->RestoreTPL (OldTpl
);
1101 Submits synchronous interrupt transfer to an interrupt endpoint
1102 of a USB device according to UEFI 2.0 spec.
1104 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.
1105 DeviceAddress : Target device address
1106 EndPointAddress : Endpoint number and direction
1107 DeviceSpeed : Device speed
1108 MaximumPacketLength : Maximum packet size of the target endpoint
1109 DataBuffersNumber : Number of data buffers prepared for the transfer.
1110 Data : Array of pointers to the buffers of data
1111 DataLength : On input, size of the data buffer, On output,
1112 actually transferred data size.
1113 DataToggle : On input, data toggle to use; On output, next data toggle
1114 TimeOut : Maximum time out, in microseconds
1115 Translator : A pointr to the transaction translator data.
1116 TransferResult : Variable to receive transfer result
1118 @return EFI_SUCCESS : The transfer was completed successfully.
1119 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.
1120 @return EFI_INVALID_PARAMETER : Some parameters are invalid.
1121 @return EFI_TIMEOUT : Failed due to timeout.
1122 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.
1128 Uhci2SyncInterruptTransfer (
1129 IN EFI_USB2_HC_PROTOCOL
*This
,
1130 IN UINT8 DeviceAddress
,
1131 IN UINT8 EndPointAddress
,
1132 IN UINT8 DeviceSpeed
,
1133 IN UINTN MaximumPacketLength
,
1135 IN OUT UINTN
*DataLength
,
1136 IN OUT UINT8
*DataToggle
,
1138 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1139 OUT UINT32
*TransferResult
1145 UHCI_QH_RESULT QhResult
;
1150 BOOLEAN IsSlowDevice
;
1152 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1157 if (DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
1158 return EFI_INVALID_PARAMETER
;
1161 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
1163 if ((DataLength
== NULL
) || (Data
== NULL
) || (TransferResult
== NULL
)) {
1164 return EFI_INVALID_PARAMETER
;
1167 if ((EndPointAddress
& 0x80) == 0) {
1168 return EFI_INVALID_PARAMETER
;
1171 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1172 return EFI_INVALID_PARAMETER
;
1175 if ((*DataLength
== 0) || (MaximumPacketLength
> 64)) {
1176 return EFI_INVALID_PARAMETER
;
1179 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
1180 return EFI_INVALID_PARAMETER
;
1183 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1184 Status
= EFI_DEVICE_ERROR
;
1187 UhciAckAllInterrupt (Uhc
);
1189 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1193 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1196 // Map the source data buffer for bus master access.
1197 // Create Tds list, then link it to the UHC's interrupt list
1199 Status
= UhciMapUserData (
1209 if (EFI_ERROR (Status
)) {
1213 TDs
= UhciCreateBulkOrIntTds (
1221 (UINT8
) MaximumPacketLength
,
1226 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1228 Status
= EFI_OUT_OF_RESOURCES
;
1233 UhciLinkTdToQh (Uhc
->SyncIntQh
, TDs
);
1235 Status
= UhciExecuteTransfer (Uhc
, Uhc
->SyncIntQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
1237 UhciUnlinkTdFromQh (Uhc
->SyncIntQh
, TDs
);
1238 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1240 *TransferResult
= QhResult
.Result
;
1241 *DataToggle
= QhResult
.NextToggle
;
1242 *DataLength
= QhResult
.Complete
;
1244 UhciDestoryTds (Uhc
, TDs
);
1245 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1248 gBS
->RestoreTPL (OldTpl
);
1254 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
1256 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.
1257 DeviceAddress : Target device address
1258 EndPointAddress : Endpoint number and direction
1259 DeviceSpeed : Device speed
1260 MaximumPacketLength : Maximum packet size of the target endpoint
1261 DataBuffersNumber : Number of data buffers prepared for the transfer.
1262 Data : Array of pointers to the buffers of data
1263 DataLength : On input, size of the data buffer, On output,
1264 actually transferred data size.
1265 Translator : A pointr to the transaction translator data.
1266 TransferResult : Variable to receive transfer result
1268 @return EFI_UNSUPPORTED
1274 Uhci2IsochronousTransfer (
1275 IN EFI_USB2_HC_PROTOCOL
*This
,
1276 IN UINT8 DeviceAddress
,
1277 IN UINT8 EndPointAddress
,
1278 IN UINT8 DeviceSpeed
,
1279 IN UINTN MaximumPacketLength
,
1280 IN UINT8 DataBuffersNumber
,
1281 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1282 IN UINTN DataLength
,
1283 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1284 OUT UINT32
*TransferResult
1287 return EFI_UNSUPPORTED
;
1292 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
1294 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.
1295 DeviceAddress : Target device address
1296 EndPointAddress : Endpoint number and direction
1297 DeviceSpeed : Device speed
1298 MaximumPacketLength : Maximum packet size of the target endpoint
1299 DataBuffersNumber : Number of data buffers prepared for the transfer.
1300 Data : Array of pointers to the buffers of data
1301 Translator : A pointr to the transaction translator data.
1302 IsochronousCallBack : Function to call when the transfer complete
1303 Context : Pass to the call back function as parameter
1305 @return EFI_UNSUPPORTED
1311 Uhci2AsyncIsochronousTransfer (
1312 IN EFI_USB2_HC_PROTOCOL
*This
,
1313 IN UINT8 DeviceAddress
,
1314 IN UINT8 EndPointAddress
,
1315 IN UINT8 DeviceSpeed
,
1316 IN UINTN MaximumPacketLength
,
1317 IN UINT8 DataBuffersNumber
,
1318 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1319 IN UINTN DataLength
,
1320 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1321 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1325 return EFI_UNSUPPORTED
;
1330 UhciDriverEntryPoint (
1331 IN EFI_HANDLE ImageHandle
,
1332 IN EFI_SYSTEM_TABLE
*SystemTable
1336 Routine Description:
1338 Entry point for EFI drivers.
1342 ImageHandle - EFI_HANDLE
1343 SystemTable - EFI_SYSTEM_TABLE
1347 EFI_SUCCESS : Driver is successfully loaded
1352 return EfiLibInstallDriverBindingComponentName2 (
1355 &gUhciDriverBinding
,
1357 &gUhciComponentName
,
1358 &gUhciComponentName2
1364 Test to see if this driver supports ControllerHandle. Any
1365 ControllerHandle that has UsbHcProtocol installed will be supported.
1367 @param This Protocol instance pointer.
1368 @param Controller Handle of device to test
1369 @param RemainingDevicePath Not used
1371 @return EFI_SUCCESS : This driver supports this device.
1372 @return EFI_UNSUPPORTED : This driver does not support this device.
1377 UhciDriverBindingSupported (
1378 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1379 IN EFI_HANDLE Controller
,
1380 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1383 EFI_STATUS OpenStatus
;
1385 EFI_PCI_IO_PROTOCOL
*PciIo
;
1386 USB_CLASSC UsbClassCReg
;
1389 // Test whether there is PCI IO Protocol attached on the controller handle.
1391 OpenStatus
= gBS
->OpenProtocol (
1393 &gEfiPciIoProtocolGuid
,
1395 This
->DriverBindingHandle
,
1397 EFI_OPEN_PROTOCOL_BY_DRIVER
1400 if (EFI_ERROR (OpenStatus
)) {
1404 Status
= PciIo
->Pci
.Read (
1408 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1412 if (EFI_ERROR (Status
)) {
1413 Status
= EFI_UNSUPPORTED
;
1418 // Test whether the controller belongs to UHCI type
1420 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1421 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1422 (UsbClassCReg
.PI
!= PCI_CLASSC_PI_UHCI
)
1425 Status
= EFI_UNSUPPORTED
;
1429 gBS
->CloseProtocol (
1431 &gEfiPciIoProtocolGuid
,
1432 This
->DriverBindingHandle
,
1442 Allocate and initialize the empty UHCI device
1444 @param PciIo The PCIIO to use
1446 @return Allocated UHCI device
1452 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1453 IN UINT64 OriginalPciAttributes
1459 Uhc
= AllocateZeroPool (sizeof (USB_HC_DEV
));
1466 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
1467 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
1469 Uhc
->Signature
= USB_HC_DEV_SIGNATURE
;
1470 Uhc
->Usb2Hc
.GetCapability
= Uhci2GetCapability
;
1471 Uhc
->Usb2Hc
.Reset
= Uhci2Reset
;
1472 Uhc
->Usb2Hc
.GetState
= Uhci2GetState
;
1473 Uhc
->Usb2Hc
.SetState
= Uhci2SetState
;
1474 Uhc
->Usb2Hc
.ControlTransfer
= Uhci2ControlTransfer
;
1475 Uhc
->Usb2Hc
.BulkTransfer
= Uhci2BulkTransfer
;
1476 Uhc
->Usb2Hc
.AsyncInterruptTransfer
= Uhci2AsyncInterruptTransfer
;
1477 Uhc
->Usb2Hc
.SyncInterruptTransfer
= Uhci2SyncInterruptTransfer
;
1478 Uhc
->Usb2Hc
.IsochronousTransfer
= Uhci2IsochronousTransfer
;
1479 Uhc
->Usb2Hc
.AsyncIsochronousTransfer
= Uhci2AsyncIsochronousTransfer
;
1480 Uhc
->Usb2Hc
.GetRootHubPortStatus
= Uhci2GetRootHubPortStatus
;
1481 Uhc
->Usb2Hc
.SetRootHubPortFeature
= Uhci2SetRootHubPortFeature
;
1482 Uhc
->Usb2Hc
.ClearRootHubPortFeature
= Uhci2ClearRootHubPortFeature
;
1483 Uhc
->Usb2Hc
.MajorRevision
= 0x1;
1484 Uhc
->Usb2Hc
.MinorRevision
= 0x1;
1487 Uhc
->OriginalPciAttributes
= OriginalPciAttributes
;
1488 Uhc
->MemPool
= UsbHcInitMemPool (PciIo
, TRUE
, 0);
1490 if (Uhc
->MemPool
== NULL
) {
1491 Status
= EFI_OUT_OF_RESOURCES
;
1495 InitializeListHead (&Uhc
->AsyncIntList
);
1497 Status
= gBS
->CreateEvent (
1498 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1500 UhciMonitorAsyncReqList
,
1502 &Uhc
->AsyncIntMonitor
1505 if (EFI_ERROR (Status
)) {
1506 UsbHcFreeMemPool (Uhc
->MemPool
);
1513 gBS
->FreePool (Uhc
);
1519 Free the UHCI device and release its associated resources
1521 @param Uhc The UHCI device to release
1532 if (Uhc
->AsyncIntMonitor
!= NULL
) {
1533 gBS
->CloseEvent (Uhc
->AsyncIntMonitor
);
1536 if (Uhc
->MemPool
!= NULL
) {
1537 UsbHcFreeMemPool (Uhc
->MemPool
);
1540 if (Uhc
->CtrlNameTable
) {
1541 FreeUnicodeStringTable (Uhc
->CtrlNameTable
);
1544 gBS
->FreePool (Uhc
);
1549 Uninstall all Uhci Interface
1551 @param Controller Controller handle
1552 @param This Protocol instance pointer.
1560 IN EFI_HANDLE Controller
,
1561 IN EFI_USB2_HC_PROTOCOL
*This
1567 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
1569 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1570 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1572 gBS
->UninstallProtocolInterface (
1574 &gEfiUsb2HcProtocolGuid
,
1578 UhciFreeAllAsyncReq (Uhc
);
1579 UhciDestoryFrameList (Uhc
);
1582 // Restore original PCI attributes
1584 Uhc
->PciIo
->Attributes (
1586 EfiPciIoAttributeOperationSet
,
1587 Uhc
->OriginalPciAttributes
,
1596 Starting the Usb UHCI Driver
1598 @param This Protocol instance pointer.
1599 @param Controller Handle of device to test
1600 @param RemainingDevicePath Not used
1602 @retval EFI_SUCCESS This driver supports this device.
1603 @retval EFI_UNSUPPORTED This driver does not support this device.
1604 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error
1605 EFI_OUT_OF_RESOURCES- Failed due to resource
1611 UhciDriverBindingStart (
1612 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1613 IN EFI_HANDLE Controller
,
1614 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1618 EFI_PCI_IO_PROTOCOL
*PciIo
;
1621 UINT64 OriginalPciAttributes
;
1622 BOOLEAN PciAttributesSaved
;
1625 // Open PCIIO, then enable the EHC device and turn off emulation
1628 Status
= gBS
->OpenProtocol (
1630 &gEfiPciIoProtocolGuid
,
1632 This
->DriverBindingHandle
,
1634 EFI_OPEN_PROTOCOL_BY_DRIVER
1637 if (EFI_ERROR (Status
)) {
1641 PciAttributesSaved
= FALSE
;
1643 // Save original PCI attributes
1645 Status
= PciIo
->Attributes (
1647 EfiPciIoAttributeOperationGet
,
1649 &OriginalPciAttributes
1652 if (EFI_ERROR (Status
)) {
1655 PciAttributesSaved
= TRUE
;
1658 // Robustnesss improvement such as for UoL
1659 // Default is not required.
1661 // UhciTurnOffUsbEmulation (PciIo);
1663 Status
= PciIo
->Attributes (
1665 EfiPciIoAttributeOperationSupported
,
1669 if (!EFI_ERROR (Status
)) {
1670 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1671 Status
= PciIo
->Attributes (
1673 EfiPciIoAttributeOperationEnable
,
1679 if (EFI_ERROR (Status
)) {
1683 Uhc
= UhciAllocateDev (PciIo
, OriginalPciAttributes
);
1686 Status
= EFI_OUT_OF_RESOURCES
;
1691 // Allocate and Init Host Controller's Frame List Entry
1693 Status
= UhciInitFrameList (Uhc
);
1695 if (EFI_ERROR (Status
)) {
1696 Status
= EFI_OUT_OF_RESOURCES
;
1700 Status
= gBS
->SetTimer (
1701 Uhc
->AsyncIntMonitor
,
1703 UHC_ASYNC_POLL_INTERVAL
1706 if (EFI_ERROR (Status
)) {
1711 // Install USB2_HC_PROTOCOL
1713 Status
= gBS
->InstallMultipleProtocolInterfaces (
1715 &gEfiUsb2HcProtocolGuid
,
1720 if (EFI_ERROR (Status
)) {
1725 // Install the component name protocol
1727 Uhc
->CtrlNameTable
= NULL
;
1731 gUhciComponentName
.SupportedLanguages
,
1732 &Uhc
->CtrlNameTable
,
1733 L
"Usb Universal Host Controller",
1738 gUhciComponentName2
.SupportedLanguages
,
1739 &Uhc
->CtrlNameTable
,
1740 L
"Usb Universal Host Controller",
1746 // Start the UHCI hardware, also set its reclamation point to 64 bytes
1748 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_RS
| USBCMD_MAXP
);
1756 if (PciAttributesSaved
== TRUE
) {
1758 // Restore original PCI attributes
1762 EfiPciIoAttributeOperationSet
,
1763 OriginalPciAttributes
,
1768 gBS
->CloseProtocol (
1770 &gEfiPciIoProtocolGuid
,
1771 This
->DriverBindingHandle
,
1780 Stop this driver on ControllerHandle. Support stoping any child handles
1781 created by this driver.
1783 @param This Protocol instance pointer.
1784 @param Controller Handle of device to stop driver on
1785 @param NumberOfChildren Number of Children in the ChildHandleBuffer
1786 @param ChildHandleBuffer List of handles for the children we need to stop.
1794 UhciDriverBindingStop (
1795 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1796 IN EFI_HANDLE Controller
,
1797 IN UINTN NumberOfChildren
,
1798 IN EFI_HANDLE
*ChildHandleBuffer
1801 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1804 Status
= gBS
->OpenProtocol (
1806 &gEfiUsb2HcProtocolGuid
,
1808 This
->DriverBindingHandle
,
1810 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1814 // Test whether the Controller handler passed in is a valid
1815 // Usb controller handle that should be supported, if not,
1816 // return the error status directly
1818 if (EFI_ERROR (Status
)) {
1822 UhciCleanDevUp (Controller
, Usb2Hc
);
1824 gBS
->CloseProtocol (
1826 &gEfiPciIoProtocolGuid
,
1827 This
->DriverBindingHandle
,
1834 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding
= {
1835 UhciDriverBindingSupported
,
1836 UhciDriverBindingStart
,
1837 UhciDriverBindingStop
,