3 The UHCI driver model and HC protocol routines.
5 Copyright (c) 2004 - 2010, 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.
19 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding
= {
20 UhciDriverBindingSupported
,
21 UhciDriverBindingStart
,
22 UhciDriverBindingStop
,
29 Provides software reset for the USB host controller according to UEFI 2.0 spec.
31 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
32 @param Attributes A bit mask of the reset operation to perform. See
33 below for a list of the supported bit mask values.
35 @return EFI_SUCCESS The reset operation succeeded.
36 @return EFI_INVALID_PARAMETER Attributes is not valid.
37 @return EFI_UNSUPPORTED This type of reset is not currently supported.
38 @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 errors.
126 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
127 OUT EFI_USB_HC_STATE
*State
135 return EFI_INVALID_PARAMETER
;
138 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
140 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
141 UsbSts
= UhciReadReg (Uhc
->PciIo
, USBSTS_OFFSET
);
143 if ((UsbCmd
& USBCMD_EGSM
) !=0 ) {
144 *State
= EfiUsbHcStateSuspend
;
146 } else if ((UsbSts
& USBSTS_HCH
) != 0) {
147 *State
= EfiUsbHcStateHalt
;
150 *State
= EfiUsbHcStateOperational
;
158 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
160 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
161 @param State Indicates the state of the host controller that will
164 @return EFI_SUCCESS Host controller was successfully placed in the state.
165 @return EFI_INVALID_PARAMETER State is invalid.
166 @return EFI_DEVICE_ERROR Failed to set the state.
172 IN EFI_USB2_HC_PROTOCOL
*This
,
173 IN EFI_USB_HC_STATE State
176 EFI_USB_HC_STATE CurState
;
182 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
183 Status
= Uhci2GetState (This
, &CurState
);
185 if (EFI_ERROR (Status
)) {
186 return EFI_DEVICE_ERROR
;
189 if (CurState
== State
) {
193 Status
= EFI_SUCCESS
;
194 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
197 case EfiUsbHcStateHalt
:
198 Status
= UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
201 case EfiUsbHcStateOperational
:
202 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
204 if (CurState
== EfiUsbHcStateHalt
) {
206 // Set Run/Stop bit to 1, also set the bandwidht reclamation
209 UsbCmd
|= USBCMD_RS
| USBCMD_MAXP
;
210 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
212 } else if (CurState
== EfiUsbHcStateSuspend
) {
214 // If FGR(Force Global Resume) bit is 0, set it
216 if ((UsbCmd
& USBCMD_FGR
) == 0) {
217 UsbCmd
|= USBCMD_FGR
;
218 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
222 // wait 20ms to let resume complete (20ms is specified by UHCI spec)
224 gBS
->Stall (UHC_FORCE_GLOBAL_RESUME_STALL
);
227 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
229 UsbCmd
&= ~USBCMD_FGR
;
230 UsbCmd
&= ~USBCMD_EGSM
;
232 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
237 case EfiUsbHcStateSuspend
:
238 Status
= Uhci2SetState (This
, EfiUsbHcStateHalt
);
240 if (EFI_ERROR (Status
)) {
241 Status
= EFI_DEVICE_ERROR
;
246 // Set Enter Global Suspend Mode bit to 1.
248 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
249 UsbCmd
|= USBCMD_EGSM
;
250 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
254 Status
= EFI_INVALID_PARAMETER
;
259 gBS
->RestoreTPL (OldTpl
);
264 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
266 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
267 @param MaxSpeed A pointer to the max speed USB host controller
269 @param PortNumber A pointer to the number of root hub ports.
270 @param Is64BitCapable A pointer to an integer to show whether USB host
271 controller supports 64-bit memory addressing.
273 @return EFI_SUCCESS capabilities were retrieved successfully.
274 @return EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.
275 @return EFI_DEVICE_ERROR An error was encountered.
281 IN EFI_USB2_HC_PROTOCOL
*This
,
283 OUT UINT8
*PortNumber
,
284 OUT UINT8
*Is64BitCapable
292 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
294 if ((NULL
== MaxSpeed
) || (NULL
== PortNumber
) || (NULL
== Is64BitCapable
)) {
295 return EFI_INVALID_PARAMETER
;
298 *MaxSpeed
= EFI_USB_SPEED_FULL
;
299 *Is64BitCapable
= (UINT8
) FALSE
;
303 for (Index
= 0; Index
< USB_MAX_ROOTHUB_PORT
; Index
++) {
304 Offset
= USBPORTSC_OFFSET
+ Index
* 2;
305 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
308 // Port status's bit 7 is reserved and always returns 1 if
309 // the port number is valid. Intel's UHCI (in EHCI controller)
310 // returns 0 in this bit if port number is invalid. Also, if
311 // PciIo IoRead returns error, 0xFFFF is returned to caller.
313 if (((PortSC
& 0x80) == 0) || (PortSC
== 0xFFFF)) {
319 Uhc
->RootPorts
= *PortNumber
;
321 DEBUG ((EFI_D_INFO
, "Uhci2GetCapability: %d ports\n", (UINT32
)Uhc
->RootPorts
));
327 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
329 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
330 @param PortNumber The port to get status.
331 @param PortStatus A pointer to the current port status bits and port
334 @return EFI_SUCCESS status of the USB root hub port was returned in PortStatus.
335 @return EFI_INVALID_PARAMETER PortNumber is invalid.
336 @return EFI_DEVICE_ERROR Can't read register.
341 Uhci2GetRootHubPortStatus (
342 IN CONST EFI_USB2_HC_PROTOCOL
*This
,
343 IN CONST UINT8 PortNumber
,
344 OUT EFI_USB_PORT_STATUS
*PortStatus
351 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
353 if (PortStatus
== NULL
) {
354 return EFI_INVALID_PARAMETER
;
357 if (PortNumber
>= Uhc
->RootPorts
) {
358 return EFI_INVALID_PARAMETER
;
361 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
362 PortStatus
->PortStatus
= 0;
363 PortStatus
->PortChangeStatus
= 0;
365 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
367 if ((PortSC
& USBPORTSC_CCS
) != 0) {
368 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
371 if ((PortSC
& USBPORTSC_PED
) != 0) {
372 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
375 if ((PortSC
& USBPORTSC_SUSP
) != 0) {
376 DEBUG ((EFI_D_INFO
, "Uhci2GetRootHubPortStatus: port %d is suspended\n", PortNumber
));
377 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
380 if ((PortSC
& USBPORTSC_PR
) != 0) {
381 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
384 if ((PortSC
& USBPORTSC_LSDA
) != 0) {
385 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
389 // CHC will always return one in port owner bit
391 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
393 if ((PortSC
& USBPORTSC_CSC
) != 0) {
394 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
397 if ((PortSC
& USBPORTSC_PEDC
) != 0) {
398 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
406 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
408 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
409 @param PortNumber Specifies the root hub port whose feature is
411 @param PortFeature Indicates the feature selector associated with the
414 @return EFI_SUCCESS PortFeature was set for the root port.
415 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
416 @return EFI_DEVICE_ERROR Can't read register.
421 Uhci2SetRootHubPortFeature (
422 IN EFI_USB2_HC_PROTOCOL
*This
,
424 IN EFI_USB_PORT_FEATURE PortFeature
433 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
435 if (PortNumber
>= Uhc
->RootPorts
) {
436 return EFI_INVALID_PARAMETER
;
439 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
441 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
442 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
444 switch (PortFeature
) {
445 case EfiUsbPortSuspend
:
446 Command
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
447 if ((Command
& USBCMD_EGSM
) == 0) {
449 // if global suspend is not active, can set port suspend
452 PortSC
|= USBPORTSC_SUSP
;
456 case EfiUsbPortReset
:
458 PortSC
|= USBPORTSC_PR
;
461 case EfiUsbPortPower
:
467 case EfiUsbPortEnable
:
469 PortSC
|= USBPORTSC_PED
;
473 gBS
->RestoreTPL (OldTpl
);
474 return EFI_INVALID_PARAMETER
;
477 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
478 gBS
->RestoreTPL (OldTpl
);
485 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
487 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
488 @param PortNumber Specifies the root hub port whose feature is
489 requested to be cleared.
490 @param PortFeature Indicates the feature selector associated with the
491 feature clear request.
493 @return EFI_SUCCESS PortFeature was cleared for the USB root hub port.
494 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
495 @return EFI_DEVICE_ERROR Can't read register.
500 Uhci2ClearRootHubPortFeature (
501 IN EFI_USB2_HC_PROTOCOL
*This
,
503 IN EFI_USB_PORT_FEATURE PortFeature
511 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
513 if (PortNumber
>= Uhc
->RootPorts
) {
514 return EFI_INVALID_PARAMETER
;
517 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
519 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
520 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
522 switch (PortFeature
) {
523 case EfiUsbPortEnable
:
525 PortSC
&= ~USBPORTSC_PED
;
528 case EfiUsbPortSuspend
:
530 // Cause a resume on the specified port if in suspend mode.
533 PortSC
&= ~USBPORTSC_SUSP
;
536 case EfiUsbPortPower
:
542 case EfiUsbPortReset
:
544 PortSC
&= ~USBPORTSC_PR
;
547 case EfiUsbPortConnectChange
:
549 PortSC
|= USBPORTSC_CSC
;
552 case EfiUsbPortEnableChange
:
554 PortSC
|= USBPORTSC_PEDC
;
557 case EfiUsbPortSuspendChange
:
559 // Root hub does not support this
563 case EfiUsbPortOverCurrentChange
:
565 // Root hub does not support this
569 case EfiUsbPortResetChange
:
571 // Root hub does not support this
576 gBS
->RestoreTPL (OldTpl
);
577 return EFI_INVALID_PARAMETER
;
580 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
581 gBS
->RestoreTPL (OldTpl
);
588 Submits control transfer to a target USB device accroding to UEFI 2.0 spec.
590 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
591 @param DeviceAddress Target device address.
592 @param DeviceSpeed Device speed.
593 @param MaximumPacketLength Maximum packet size of the target endpoint.
594 @param Request USB device request to send.
595 @param TransferDirection Data direction of the Data stage in control transfer.
596 @param Data Data to transmit/receive in data stage.
597 @param DataLength Length of the data.
598 @param TimeOut Maximum time, in microseconds, for transfer to complete.
599 @param Translator Transaction translator to be used by this device.
600 @param TransferResult Variable to receive the transfer result.
602 @return EFI_SUCCESS The control transfer was completed successfully.
603 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
604 @return EFI_INVALID_PARAMETER Some parameters are invalid.
605 @return EFI_TIMEOUT Failed due to timeout.
606 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
611 Uhci2ControlTransfer (
612 IN EFI_USB2_HC_PROTOCOL
*This
,
613 IN UINT8 DeviceAddress
,
614 IN UINT8 DeviceSpeed
,
615 IN UINTN MaximumPacketLength
,
616 IN EFI_USB_DEVICE_REQUEST
*Request
,
617 IN EFI_USB_DATA_DIRECTION TransferDirection
,
619 IN OUT UINTN
*DataLength
,
621 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
622 OUT UINT32
*TransferResult
629 UHCI_QH_RESULT QhResult
;
635 BOOLEAN IsSlowDevice
;
636 UINTN TransferDataLength
;
638 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
645 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
648 // Parameters Checking
650 if (Request
== NULL
|| TransferResult
== NULL
) {
651 return EFI_INVALID_PARAMETER
;
654 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
655 return EFI_INVALID_PARAMETER
;
658 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
659 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
661 return EFI_INVALID_PARAMETER
;
664 if ((TransferDirection
!= EfiUsbNoData
) && (Data
== NULL
|| DataLength
== NULL
)) {
665 return EFI_INVALID_PARAMETER
;
668 if (TransferDirection
== EfiUsbNoData
) {
669 TransferDataLength
= 0;
671 TransferDataLength
= *DataLength
;
674 *TransferResult
= EFI_USB_ERR_SYSTEM
;
675 Status
= EFI_DEVICE_ERROR
;
678 // If errors exist that cause host controller halt,
679 // clear status then return EFI_DEVICE_ERROR.
681 UhciAckAllInterrupt (Uhc
);
683 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
684 return EFI_DEVICE_ERROR
;
687 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
690 // Map the Request and data for bus master access,
691 // then create a list of TD for this transfer
693 Status
= UhciMapUserRequest (Uhc
, Request
, &RequestPhy
, &RequestMap
);
695 if (EFI_ERROR (Status
)) {
699 Status
= UhciMapUserData (Uhc
, TransferDirection
, Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
701 if (EFI_ERROR (Status
)) {
702 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
706 TDs
= UhciCreateCtrlTds (
715 (UINT8
) MaximumPacketLength
,
720 Status
= EFI_OUT_OF_RESOURCES
;
725 // According to the speed of the end point, link
726 // the TD to corrosponding queue head, then check
727 // the execution result
729 UhciLinkTdToQh (Uhc
, Uhc
->CtrlQh
, TDs
);
730 Status
= UhciExecuteTransfer (Uhc
, Uhc
->CtrlQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
731 UhciUnlinkTdFromQh (Uhc
->CtrlQh
, TDs
);
733 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
735 *TransferResult
= QhResult
.Result
;
737 if (DataLength
!= NULL
) {
738 *DataLength
= QhResult
.Complete
;
741 UhciDestoryTds (Uhc
, TDs
);
744 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
745 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
748 gBS
->RestoreTPL (OldTpl
);
754 Submits bulk transfer to a bulk endpoint of a USB device.
756 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
757 @param DeviceAddress Target device address.
758 @param EndPointAddress Endpoint number and direction.
759 @param DeviceSpeed Device speed.
760 @param MaximumPacketLength Maximum packet size of the target endpoint.
761 @param DataBuffersNumber Number of data buffers prepared for the transfer.
762 @param Data Array of pointers to the buffers of data.
763 @param DataLength On input, size of the data buffer, On output,
764 actually transferred data size.
765 @param DataToggle On input, data toggle to use; On output, next data toggle.
766 @param TimeOut Maximum time out, in microseconds.
767 @param Translator A pointr to the transaction translator data.
768 @param TransferResult Variable to receive transfer result.
770 @return EFI_SUCCESS The bulk transfer was completed successfully.
771 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
772 @return EFI_INVALID_PARAMETER Some parameters are invalid.
773 @return EFI_TIMEOUT Failed due to timeout.
774 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
780 IN EFI_USB2_HC_PROTOCOL
*This
,
781 IN UINT8 DeviceAddress
,
782 IN UINT8 EndPointAddress
,
783 IN UINT8 DeviceSpeed
,
784 IN UINTN MaximumPacketLength
,
785 IN UINT8 DataBuffersNumber
,
786 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
787 IN OUT UINTN
*DataLength
,
788 IN OUT UINT8
*DataToggle
,
790 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
791 OUT UINT32
*TransferResult
794 EFI_USB_DATA_DIRECTION Direction
;
799 UHCI_QH_RESULT QhResult
;
805 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
809 if (DeviceSpeed
== EFI_USB_SPEED_LOW
) {
810 return EFI_INVALID_PARAMETER
;
813 if ((DataLength
== NULL
) || (*DataLength
== 0) || (Data
== NULL
) || (TransferResult
== NULL
)) {
814 return EFI_INVALID_PARAMETER
;
817 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
818 return EFI_INVALID_PARAMETER
;
821 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
822 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
823 return EFI_INVALID_PARAMETER
;
826 *TransferResult
= EFI_USB_ERR_SYSTEM
;
827 Status
= EFI_OUT_OF_RESOURCES
;
830 // If has errors that cause host controller halt,
831 // then return EFI_DEVICE_ERROR directly.
833 UhciAckAllInterrupt (Uhc
);
835 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
836 return EFI_DEVICE_ERROR
;
839 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
842 // Map the source data buffer for bus master access,
843 // then create a list of TDs
845 if ((EndPointAddress
& 0x80) != 0) {
846 Direction
= EfiUsbDataIn
;
848 Direction
= EfiUsbDataOut
;
851 Status
= UhciMapUserData (Uhc
, Direction
, *Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
853 if (EFI_ERROR (Status
)) {
857 Status
= EFI_OUT_OF_RESOURCES
;
858 TDs
= UhciCreateBulkOrIntTds (
867 (UINT8
) MaximumPacketLength
,
872 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
878 // Link the TDs to bulk queue head. According to the platfore
879 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
880 // to do full speed bandwidth reclamation or not.
882 BulkQh
= Uhc
->BulkQh
;
884 UhciLinkTdToQh (Uhc
, BulkQh
, TDs
);
885 Status
= UhciExecuteTransfer (Uhc
, BulkQh
, TDs
, TimeOut
, FALSE
, &QhResult
);
886 UhciUnlinkTdFromQh (BulkQh
, TDs
);
888 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
890 *TransferResult
= QhResult
.Result
;
891 *DataToggle
= QhResult
.NextToggle
;
892 *DataLength
= QhResult
.Complete
;
894 UhciDestoryTds (Uhc
, TDs
);
895 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
898 gBS
->RestoreTPL (OldTpl
);
904 Submits an asynchronous interrupt transfer to an
905 interrupt endpoint of a USB device according to UEFI 2.0 spec.
907 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
908 @param DeviceAddress Target device address.
909 @param EndPointAddress Endpoint number and direction.
910 @param DeviceSpeed Device speed.
911 @param MaximumPacketLength Maximum packet size of the target endpoint.
912 @param IsNewTransfer If TRUE, submit a new transfer, if FALSE cancel old transfer.
913 @param DataToggle On input, data toggle to use; On output, next data toggle.
914 @param PollingInterval Interrupt poll rate in milliseconds.
915 @param DataLength On input, size of the data buffer, On output,
916 actually transferred data size.
917 @param Translator A pointr to the transaction translator data.
918 @param CallBackFunction Function to call periodically.
919 @param Context User context.
921 @return EFI_SUCCESS Transfer was submitted.
922 @return EFI_INVALID_PARAMETER Some parameters are invalid.
923 @return EFI_OUT_OF_RESOURCES Failed due to a lack of resources.
924 @return EFI_DEVICE_ERROR Can't read register.
929 Uhci2AsyncInterruptTransfer (
930 IN EFI_USB2_HC_PROTOCOL
*This
,
931 IN UINT8 DeviceAddress
,
932 IN UINT8 EndPointAddress
,
933 IN UINT8 DeviceSpeed
,
934 IN UINTN MaximumPacketLength
,
935 IN BOOLEAN IsNewTransfer
,
936 IN OUT UINT8
*DataToggle
,
937 IN UINTN PollingInterval
,
939 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
940 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
945 BOOLEAN IsSlowDevice
;
955 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
962 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
964 if ((EndPointAddress
& 0x80) == 0) {
965 return EFI_INVALID_PARAMETER
;
969 // Delete Async interrupt transfer request
971 if (!IsNewTransfer
) {
972 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
973 Status
= UhciRemoveAsyncReq (Uhc
, DeviceAddress
, EndPointAddress
, DataToggle
);
975 gBS
->RestoreTPL (OldTpl
);
979 if (PollingInterval
< 1 || PollingInterval
> 255) {
980 return EFI_INVALID_PARAMETER
;
983 if (DataLength
== 0) {
984 return EFI_INVALID_PARAMETER
;
987 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
988 return EFI_INVALID_PARAMETER
;
992 // If has errors that cause host controller halt,
993 // then return EFI_DEVICE_ERROR directly.
995 UhciAckAllInterrupt (Uhc
);
997 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
998 return EFI_DEVICE_ERROR
;
1002 // Allocate and map source data buffer for bus master access.
1004 DataPtr
= UsbHcAllocateMem (Uhc
->MemPool
, DataLength
);
1006 if (DataPtr
== NULL
) {
1007 return EFI_OUT_OF_RESOURCES
;
1010 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1013 // Map the user data then create a queue head and
1014 // list of TD for it.
1016 Status
= UhciMapUserData (
1026 if (EFI_ERROR (Status
)) {
1030 Qh
= UhciCreateQh (Uhc
, PollingInterval
);
1033 Status
= EFI_OUT_OF_RESOURCES
;
1037 IntTds
= UhciCreateBulkOrIntTds (
1046 (UINT8
) MaximumPacketLength
,
1050 if (IntTds
== NULL
) {
1051 Status
= EFI_OUT_OF_RESOURCES
;
1055 UhciLinkTdToQh (Uhc
, Qh
, IntTds
);
1058 // Save QH-TD structures to async Interrupt transfer list,
1059 // for monitor interrupt transfer execution routine use.
1061 Status
= UhciCreateAsyncReq (
1076 if (EFI_ERROR (Status
)) {
1080 UhciLinkQhToFrameList (Uhc
, Qh
);
1082 gBS
->RestoreTPL (OldTpl
);
1086 UsbHcFreeMem (Uhc
->MemPool
, Qh
, sizeof (UHCI_QH_SW
));
1089 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1092 gBS
->FreePool (DataPtr
);
1093 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1095 gBS
->RestoreTPL (OldTpl
);
1100 Submits synchronous interrupt transfer to an interrupt endpoint
1101 of a USB device according to UEFI 2.0 spec.
1104 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1105 @param DeviceAddress Target device address.
1106 @param EndPointAddress Endpoint number and direction.
1107 @param DeviceSpeed Device speed.
1108 @param MaximumPacketLength Maximum packet size of the target endpoint.
1109 @param Data Array of pointers to the buffers of data.
1110 @param DataLength On input, size of the data buffer, On output,
1111 actually transferred data size.
1112 @param DataToggle On input, data toggle to use; On output, next data toggle.
1113 @param TimeOut Maximum time out, in microseconds.
1114 @param Translator A pointr to the transaction translator data.
1115 @param TransferResult Variable to receive transfer result.
1117 @return EFI_SUCCESS The transfer was completed successfully.
1118 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
1119 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1120 @return EFI_TIMEOUT Failed due to timeout.
1121 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
1126 Uhci2SyncInterruptTransfer (
1127 IN EFI_USB2_HC_PROTOCOL
*This
,
1128 IN UINT8 DeviceAddress
,
1129 IN UINT8 EndPointAddress
,
1130 IN UINT8 DeviceSpeed
,
1131 IN UINTN MaximumPacketLength
,
1133 IN OUT UINTN
*DataLength
,
1134 IN OUT UINT8
*DataToggle
,
1136 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1137 OUT UINT32
*TransferResult
1143 UHCI_QH_RESULT QhResult
;
1148 BOOLEAN IsSlowDevice
;
1150 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1155 if (DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
1156 return EFI_INVALID_PARAMETER
;
1159 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
1161 if ((DataLength
== NULL
) || (Data
== NULL
) || (TransferResult
== NULL
)) {
1162 return EFI_INVALID_PARAMETER
;
1165 if ((EndPointAddress
& 0x80) == 0) {
1166 return EFI_INVALID_PARAMETER
;
1169 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1170 return EFI_INVALID_PARAMETER
;
1173 if ((*DataLength
== 0) || (MaximumPacketLength
> 64)) {
1174 return EFI_INVALID_PARAMETER
;
1177 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
1178 return EFI_INVALID_PARAMETER
;
1181 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1182 Status
= EFI_DEVICE_ERROR
;
1185 UhciAckAllInterrupt (Uhc
);
1187 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1191 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1194 // Map the source data buffer for bus master access.
1195 // Create Tds list, then link it to the UHC's interrupt list
1197 Status
= UhciMapUserData (
1207 if (EFI_ERROR (Status
)) {
1211 TDs
= UhciCreateBulkOrIntTds (
1220 (UINT8
) MaximumPacketLength
,
1225 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1227 Status
= EFI_OUT_OF_RESOURCES
;
1232 UhciLinkTdToQh (Uhc
, Uhc
->SyncIntQh
, TDs
);
1234 Status
= UhciExecuteTransfer (Uhc
, Uhc
->SyncIntQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
1236 UhciUnlinkTdFromQh (Uhc
->SyncIntQh
, TDs
);
1237 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1239 *TransferResult
= QhResult
.Result
;
1240 *DataToggle
= QhResult
.NextToggle
;
1241 *DataLength
= QhResult
.Complete
;
1243 UhciDestoryTds (Uhc
, TDs
);
1244 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1247 gBS
->RestoreTPL (OldTpl
);
1253 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
1255 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1256 @param DeviceAddress Target device address.
1257 @param EndPointAddress Endpoint number and direction.
1258 @param DeviceSpeed Device speed.
1259 @param MaximumPacketLength Maximum packet size of the target endpoint.
1260 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1261 @param Data Array of pointers to the buffers of data.
1262 @param DataLength On input, size of the data buffer, On output,
1263 actually transferred data size.
1264 @param Translator A pointr to the transaction translator data.
1265 @param TransferResult Variable to receive transfer result.
1267 @return EFI_UNSUPPORTED
1272 Uhci2IsochronousTransfer (
1273 IN EFI_USB2_HC_PROTOCOL
*This
,
1274 IN UINT8 DeviceAddress
,
1275 IN UINT8 EndPointAddress
,
1276 IN UINT8 DeviceSpeed
,
1277 IN UINTN MaximumPacketLength
,
1278 IN UINT8 DataBuffersNumber
,
1279 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1280 IN UINTN DataLength
,
1281 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1282 OUT UINT32
*TransferResult
1285 return EFI_UNSUPPORTED
;
1290 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
1292 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1293 @param DeviceAddress Target device address.
1294 @param EndPointAddress Endpoint number and direction.
1295 @param DeviceSpeed Device speed.
1296 @param MaximumPacketLength Maximum packet size of the target endpoint.
1297 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1298 @param Data Array of pointers to the buffers of data.
1299 @param DataLength On input, size of the data buffer, On output,
1300 actually transferred data size.
1301 @param Translator A pointr to the transaction translator data.
1302 @param IsochronousCallBack Function to call when the transfer complete.
1303 @param Context Pass to the call back function as parameter.
1305 @return EFI_UNSUPPORTED
1310 Uhci2AsyncIsochronousTransfer (
1311 IN EFI_USB2_HC_PROTOCOL
*This
,
1312 IN UINT8 DeviceAddress
,
1313 IN UINT8 EndPointAddress
,
1314 IN UINT8 DeviceSpeed
,
1315 IN UINTN MaximumPacketLength
,
1316 IN UINT8 DataBuffersNumber
,
1317 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1318 IN UINTN DataLength
,
1319 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1320 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1324 return EFI_UNSUPPORTED
;
1328 Entry point for EFI drivers.
1330 @param ImageHandle EFI_HANDLE.
1331 @param SystemTable EFI_SYSTEM_TABLE.
1333 @retval EFI_SUCCESS Driver is successfully loaded.
1334 @return Others Failed.
1339 UhciDriverEntryPoint (
1340 IN EFI_HANDLE ImageHandle
,
1341 IN EFI_SYSTEM_TABLE
*SystemTable
1344 return EfiLibInstallDriverBindingComponentName2 (
1347 &gUhciDriverBinding
,
1349 &gUhciComponentName
,
1350 &gUhciComponentName2
1356 Test to see if this driver supports ControllerHandle. Any
1357 ControllerHandle that has UsbHcProtocol installed will be supported.
1359 @param This Protocol instance pointer.
1360 @param Controller Handle of device to test.
1361 @param RemainingDevicePath Not used.
1363 @return EFI_SUCCESS This driver supports this device.
1364 @return EFI_UNSUPPORTED This driver does not support this device.
1369 UhciDriverBindingSupported (
1370 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1371 IN EFI_HANDLE Controller
,
1372 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1375 EFI_STATUS OpenStatus
;
1377 EFI_PCI_IO_PROTOCOL
*PciIo
;
1378 USB_CLASSC UsbClassCReg
;
1381 // Test whether there is PCI IO Protocol attached on the controller handle.
1383 OpenStatus
= gBS
->OpenProtocol (
1385 &gEfiPciIoProtocolGuid
,
1387 This
->DriverBindingHandle
,
1389 EFI_OPEN_PROTOCOL_BY_DRIVER
1392 if (EFI_ERROR (OpenStatus
)) {
1396 Status
= PciIo
->Pci
.Read (
1399 PCI_CLASSCODE_OFFSET
,
1400 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1404 if (EFI_ERROR (Status
)) {
1405 Status
= EFI_UNSUPPORTED
;
1410 // Test whether the controller belongs to UHCI type
1412 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1413 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1414 (UsbClassCReg
.ProgInterface
!= PCI_IF_UHCI
)
1417 Status
= EFI_UNSUPPORTED
;
1421 gBS
->CloseProtocol (
1423 &gEfiPciIoProtocolGuid
,
1424 This
->DriverBindingHandle
,
1434 Allocate and initialize the empty UHCI device.
1436 @param PciIo The PCIIO to use.
1437 @param OriginalPciAttributes The original PCI attributes.
1439 @return Allocated UHCI device. If err, return NULL.
1444 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1445 IN UINT64 OriginalPciAttributes
1451 Uhc
= AllocateZeroPool (sizeof (USB_HC_DEV
));
1458 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
1459 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
1461 Uhc
->Signature
= USB_HC_DEV_SIGNATURE
;
1462 Uhc
->Usb2Hc
.GetCapability
= Uhci2GetCapability
;
1463 Uhc
->Usb2Hc
.Reset
= Uhci2Reset
;
1464 Uhc
->Usb2Hc
.GetState
= Uhci2GetState
;
1465 Uhc
->Usb2Hc
.SetState
= Uhci2SetState
;
1466 Uhc
->Usb2Hc
.ControlTransfer
= Uhci2ControlTransfer
;
1467 Uhc
->Usb2Hc
.BulkTransfer
= Uhci2BulkTransfer
;
1468 Uhc
->Usb2Hc
.AsyncInterruptTransfer
= Uhci2AsyncInterruptTransfer
;
1469 Uhc
->Usb2Hc
.SyncInterruptTransfer
= Uhci2SyncInterruptTransfer
;
1470 Uhc
->Usb2Hc
.IsochronousTransfer
= Uhci2IsochronousTransfer
;
1471 Uhc
->Usb2Hc
.AsyncIsochronousTransfer
= Uhci2AsyncIsochronousTransfer
;
1472 Uhc
->Usb2Hc
.GetRootHubPortStatus
= Uhci2GetRootHubPortStatus
;
1473 Uhc
->Usb2Hc
.SetRootHubPortFeature
= Uhci2SetRootHubPortFeature
;
1474 Uhc
->Usb2Hc
.ClearRootHubPortFeature
= Uhci2ClearRootHubPortFeature
;
1475 Uhc
->Usb2Hc
.MajorRevision
= 0x1;
1476 Uhc
->Usb2Hc
.MinorRevision
= 0x1;
1479 Uhc
->OriginalPciAttributes
= OriginalPciAttributes
;
1480 Uhc
->MemPool
= UsbHcInitMemPool (PciIo
, TRUE
, 0);
1482 if (Uhc
->MemPool
== NULL
) {
1483 Status
= EFI_OUT_OF_RESOURCES
;
1487 InitializeListHead (&Uhc
->AsyncIntList
);
1489 Status
= gBS
->CreateEvent (
1490 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1492 UhciMonitorAsyncReqList
,
1494 &Uhc
->AsyncIntMonitor
1497 if (EFI_ERROR (Status
)) {
1498 UsbHcFreeMemPool (Uhc
->MemPool
);
1511 Free the UHCI device and release its associated resources.
1513 @param Uhc The UHCI device to release.
1521 if (Uhc
->AsyncIntMonitor
!= NULL
) {
1522 gBS
->CloseEvent (Uhc
->AsyncIntMonitor
);
1525 if (Uhc
->ExitBootServiceEvent
!= NULL
) {
1526 gBS
->CloseEvent (Uhc
->ExitBootServiceEvent
);
1529 if (Uhc
->MemPool
!= NULL
) {
1530 UsbHcFreeMemPool (Uhc
->MemPool
);
1533 if (Uhc
->CtrlNameTable
!= NULL
) {
1534 FreeUnicodeStringTable (Uhc
->CtrlNameTable
);
1542 Uninstall all Uhci Interface.
1544 @param Controller Controller handle.
1545 @param This Protocol instance pointer.
1550 IN EFI_HANDLE Controller
,
1551 IN EFI_USB2_HC_PROTOCOL
*This
1557 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
1559 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1560 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1562 gBS
->UninstallProtocolInterface (
1564 &gEfiUsb2HcProtocolGuid
,
1568 UhciFreeAllAsyncReq (Uhc
);
1569 UhciDestoryFrameList (Uhc
);
1572 // Restore original PCI attributes
1574 Uhc
->PciIo
->Attributes (
1576 EfiPciIoAttributeOperationSet
,
1577 Uhc
->OriginalPciAttributes
,
1585 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1587 @param Event Pointer to this event
1588 @param Context Event hanlder private data
1593 UhcExitBootService (
1600 Uhc
= (USB_HC_DEV
*) Context
;
1603 // Stop the Host Controller
1605 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1611 Starting the Usb UHCI Driver.
1613 @param This Protocol instance pointer.
1614 @param Controller Handle of device to test.
1615 @param RemainingDevicePath Not used.
1617 @retval EFI_SUCCESS This driver supports this device.
1618 @retval EFI_UNSUPPORTED This driver does not support this device.
1619 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
1620 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
1625 UhciDriverBindingStart (
1626 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1627 IN EFI_HANDLE Controller
,
1628 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1632 EFI_PCI_IO_PROTOCOL
*PciIo
;
1635 UINT64 OriginalPciAttributes
;
1636 BOOLEAN PciAttributesSaved
;
1639 // Open PCIIO, then enable the EHC device and turn off emulation
1642 Status
= gBS
->OpenProtocol (
1644 &gEfiPciIoProtocolGuid
,
1646 This
->DriverBindingHandle
,
1648 EFI_OPEN_PROTOCOL_BY_DRIVER
1651 if (EFI_ERROR (Status
)) {
1655 PciAttributesSaved
= FALSE
;
1657 // Save original PCI attributes
1659 Status
= PciIo
->Attributes (
1661 EfiPciIoAttributeOperationGet
,
1663 &OriginalPciAttributes
1666 if (EFI_ERROR (Status
)) {
1669 PciAttributesSaved
= TRUE
;
1672 // Robustnesss improvement such as for UoL
1673 // Default is not required.
1675 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1676 UhciTurnOffUsbEmulation (PciIo
);
1679 Status
= PciIo
->Attributes (
1681 EfiPciIoAttributeOperationSupported
,
1685 if (!EFI_ERROR (Status
)) {
1686 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1687 Status
= PciIo
->Attributes (
1689 EfiPciIoAttributeOperationEnable
,
1695 if (EFI_ERROR (Status
)) {
1699 Uhc
= UhciAllocateDev (PciIo
, OriginalPciAttributes
);
1702 Status
= EFI_OUT_OF_RESOURCES
;
1707 // Allocate and Init Host Controller's Frame List Entry
1709 Status
= UhciInitFrameList (Uhc
);
1711 if (EFI_ERROR (Status
)) {
1712 Status
= EFI_OUT_OF_RESOURCES
;
1716 Status
= gBS
->SetTimer (
1717 Uhc
->AsyncIntMonitor
,
1719 UHC_ASYNC_POLL_INTERVAL
1722 if (EFI_ERROR (Status
)) {
1727 // Install USB2_HC_PROTOCOL
1729 Status
= gBS
->InstallMultipleProtocolInterfaces (
1731 &gEfiUsb2HcProtocolGuid
,
1736 if (EFI_ERROR (Status
)) {
1741 // Create event to stop the HC when exit boot service.
1743 Status
= gBS
->CreateEventEx (
1748 &gEfiEventExitBootServicesGuid
,
1749 &Uhc
->ExitBootServiceEvent
1751 if (EFI_ERROR (Status
)) {
1752 goto UNINSTALL_USBHC
;
1756 // Install the component name protocol
1758 Uhc
->CtrlNameTable
= NULL
;
1762 gUhciComponentName
.SupportedLanguages
,
1763 &Uhc
->CtrlNameTable
,
1764 L
"Usb Universal Host Controller",
1769 gUhciComponentName2
.SupportedLanguages
,
1770 &Uhc
->CtrlNameTable
,
1771 L
"Usb Universal Host Controller",
1777 // Start the UHCI hardware, also set its reclamation point to 64 bytes
1779 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_RS
| USBCMD_MAXP
);
1784 gBS
->UninstallMultipleProtocolInterfaces (
1786 &gEfiUsb2HcProtocolGuid
,
1795 if (PciAttributesSaved
) {
1797 // Restore original PCI attributes
1801 EfiPciIoAttributeOperationSet
,
1802 OriginalPciAttributes
,
1807 gBS
->CloseProtocol (
1809 &gEfiPciIoProtocolGuid
,
1810 This
->DriverBindingHandle
,
1819 Stop this driver on ControllerHandle. Support stoping any child handles
1820 created by this driver.
1822 @param This Protocol instance pointer.
1823 @param Controller Handle of device to stop driver on.
1824 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1825 @param ChildHandleBuffer List of handles for the children we need to stop.
1833 UhciDriverBindingStop (
1834 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1835 IN EFI_HANDLE Controller
,
1836 IN UINTN NumberOfChildren
,
1837 IN EFI_HANDLE
*ChildHandleBuffer
1840 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1843 Status
= gBS
->OpenProtocol (
1845 &gEfiUsb2HcProtocolGuid
,
1847 This
->DriverBindingHandle
,
1849 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1853 // Test whether the Controller handler passed in is a valid
1854 // Usb controller handle that should be supported, if not,
1855 // return the error status directly
1857 if (EFI_ERROR (Status
)) {
1861 UhciCleanDevUp (Controller
, Usb2Hc
);
1863 gBS
->CloseProtocol (
1865 &gEfiPciIoProtocolGuid
,
1866 This
->DriverBindingHandle
,