3 The UHCI driver model and HC protocol routines.
5 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding
= {
13 UhciDriverBindingSupported
,
14 UhciDriverBindingStart
,
15 UhciDriverBindingStop
,
22 Provides software reset for the USB host controller according to UEFI 2.0 spec.
24 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
25 @param Attributes A bit mask of the reset operation to perform. See
26 below for a list of the supported bit mask values.
28 @return EFI_SUCCESS The reset operation succeeded.
29 @return EFI_INVALID_PARAMETER Attributes is not valid.
30 @return EFI_UNSUPPORTED This type of reset is not currently supported.
31 @return EFI_DEVICE_ERROR Other errors.
37 IN EFI_USB2_HC_PROTOCOL
*This
,
44 if ((Attributes
== EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
) ||
45 (Attributes
== EFI_USB_HC_RESET_HOST_WITH_DEBUG
))
47 return EFI_UNSUPPORTED
;
50 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
52 if (Uhc
->DevicePath
!= NULL
) {
54 // Report Status Code to indicate reset happens
56 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
58 (EFI_IO_BUS_USB
| EFI_IOB_PC_RESET
),
63 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
66 case EFI_USB_HC_RESET_GLOBAL
:
68 // Stop schedule and set the Global Reset bit in the command register
70 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
71 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_GRESET
);
73 gBS
->Stall (UHC_ROOT_PORT_RESET_STALL
);
76 // Clear the Global Reset bit to zero.
78 UhciClearRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_GRESET
);
80 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
83 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
85 // Stop schedule and set Host Controller Reset bit to 1
87 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
88 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_HCRESET
);
90 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
94 goto ON_INVAILD_PARAMETER
;
98 // Delete all old transactions on the USB bus, then
99 // reinitialize the frame list
101 UhciFreeAllAsyncReq (Uhc
);
102 UhciDestoryFrameList (Uhc
);
103 UhciInitFrameList (Uhc
);
105 gBS
->RestoreTPL (OldTpl
);
109 ON_INVAILD_PARAMETER
:
111 gBS
->RestoreTPL (OldTpl
);
113 return EFI_INVALID_PARAMETER
;
117 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
119 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
120 @param State Variable to receive current device state.
122 @return EFI_SUCCESS The state is returned.
123 @return EFI_INVALID_PARAMETER State is not valid.
124 @return EFI_DEVICE_ERROR Other errors.
130 IN EFI_USB2_HC_PROTOCOL
*This
,
131 OUT EFI_USB_HC_STATE
*State
139 return EFI_INVALID_PARAMETER
;
142 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
144 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
145 UsbSts
= UhciReadReg (Uhc
->PciIo
, USBSTS_OFFSET
);
147 if ((UsbCmd
& USBCMD_EGSM
) != 0 ) {
148 *State
= EfiUsbHcStateSuspend
;
149 } else if ((UsbSts
& USBSTS_HCH
) != 0) {
150 *State
= EfiUsbHcStateHalt
;
152 *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.
173 IN EFI_USB2_HC_PROTOCOL
*This
,
174 IN EFI_USB_HC_STATE State
177 EFI_USB_HC_STATE CurState
;
183 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
184 Status
= Uhci2GetState (This
, &CurState
);
186 if (EFI_ERROR (Status
)) {
187 return EFI_DEVICE_ERROR
;
190 if (CurState
== State
) {
194 Status
= EFI_SUCCESS
;
195 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
198 case EfiUsbHcStateHalt
:
199 Status
= UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
202 case EfiUsbHcStateOperational
:
203 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
205 if (CurState
== EfiUsbHcStateHalt
) {
207 // Set Run/Stop bit to 1, also set the bandwidht reclamation
210 UsbCmd
|= USBCMD_RS
| USBCMD_MAXP
;
211 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)) {
320 Uhc
->RootPorts
= *PortNumber
;
322 DEBUG ((DEBUG_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 EFI_USB2_HC_PROTOCOL
*This
,
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 ((DEBUG_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
;
405 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
407 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
408 @param PortNumber Specifies the root hub port whose feature is
410 @param PortFeature Indicates the feature selector associated with the
413 @return EFI_SUCCESS PortFeature was set for the root port.
414 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
415 @return EFI_DEVICE_ERROR Can't read register.
420 Uhci2SetRootHubPortFeature (
421 IN EFI_USB2_HC_PROTOCOL
*This
,
423 IN EFI_USB_PORT_FEATURE PortFeature
432 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
434 if (PortNumber
>= Uhc
->RootPorts
) {
435 return EFI_INVALID_PARAMETER
;
438 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
440 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
441 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
443 switch (PortFeature
) {
444 case EfiUsbPortSuspend
:
445 Command
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
446 if ((Command
& USBCMD_EGSM
) == 0) {
448 // if global suspend is not active, can set port suspend
451 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
);
484 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
486 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
487 @param PortNumber Specifies the root hub port whose feature is
488 requested to be cleared.
489 @param PortFeature Indicates the feature selector associated with the
490 feature clear request.
492 @return EFI_SUCCESS PortFeature was cleared for the USB root hub port.
493 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
494 @return EFI_DEVICE_ERROR Can't read register.
499 Uhci2ClearRootHubPortFeature (
500 IN EFI_USB2_HC_PROTOCOL
*This
,
502 IN EFI_USB_PORT_FEATURE PortFeature
510 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
512 if (PortNumber
>= Uhc
->RootPorts
) {
513 return EFI_INVALID_PARAMETER
;
516 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
518 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
519 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
521 switch (PortFeature
) {
522 case EfiUsbPortEnable
:
524 PortSC
&= ~USBPORTSC_PED
;
527 case EfiUsbPortSuspend
:
529 // Cause a resume on the specified port if in suspend mode.
532 PortSC
&= ~USBPORTSC_SUSP
;
535 case EfiUsbPortPower
:
541 case EfiUsbPortReset
:
543 PortSC
&= ~USBPORTSC_PR
;
546 case EfiUsbPortConnectChange
:
548 PortSC
|= USBPORTSC_CSC
;
551 case EfiUsbPortEnableChange
:
553 PortSC
|= USBPORTSC_PEDC
;
556 case EfiUsbPortSuspendChange
:
558 // Root hub does not support this
562 case EfiUsbPortOverCurrentChange
:
564 // Root hub does not support this
568 case EfiUsbPortResetChange
:
570 // Root hub does not support this
575 gBS
->RestoreTPL (OldTpl
);
576 return EFI_INVALID_PARAMETER
;
579 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
580 gBS
->RestoreTPL (OldTpl
);
586 Submits control transfer to a target USB device according to UEFI 2.0 spec.
588 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
589 @param DeviceAddress Target device address.
590 @param DeviceSpeed Device speed.
591 @param MaximumPacketLength Maximum packet size of the target endpoint.
592 @param Request USB device request to send.
593 @param TransferDirection Data direction of the Data stage in control transfer.
594 @param Data Data to transmit/receive in data stage.
595 @param DataLength Length of the data.
596 @param TimeOut Maximum time, in microseconds, for transfer to complete.
597 @param Translator Transaction translator to be used by this device.
598 @param TransferResult Variable to receive the transfer result.
600 @return EFI_SUCCESS The control transfer was completed successfully.
601 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
602 @return EFI_INVALID_PARAMETER Some parameters are invalid.
603 @return EFI_TIMEOUT Failed due to timeout.
604 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
609 Uhci2ControlTransfer (
610 IN EFI_USB2_HC_PROTOCOL
*This
,
611 IN UINT8 DeviceAddress
,
612 IN UINT8 DeviceSpeed
,
613 IN UINTN MaximumPacketLength
,
614 IN EFI_USB_DEVICE_REQUEST
*Request
,
615 IN EFI_USB_DATA_DIRECTION TransferDirection
,
617 IN OUT UINTN
*DataLength
,
619 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
620 OUT UINT32
*TransferResult
627 UHCI_QH_RESULT QhResult
;
633 BOOLEAN IsSlowDevice
;
634 UINTN TransferDataLength
;
636 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
643 IsSlowDevice
= (BOOLEAN
)((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
646 // Parameters Checking
648 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
649 return EFI_INVALID_PARAMETER
;
652 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
653 return EFI_INVALID_PARAMETER
;
656 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
657 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64))
659 return EFI_INVALID_PARAMETER
;
662 if ((TransferDirection
!= EfiUsbNoData
) && ((Data
== NULL
) || (DataLength
== NULL
))) {
663 return EFI_INVALID_PARAMETER
;
666 if (TransferDirection
== EfiUsbNoData
) {
667 TransferDataLength
= 0;
669 TransferDataLength
= *DataLength
;
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 (
713 (UINT8
)MaximumPacketLength
,
718 Status
= EFI_OUT_OF_RESOURCES
;
723 // According to the speed of the end point, link
724 // the TD to corrosponding queue head, then check
725 // the execution result
727 UhciLinkTdToQh (Uhc
, Uhc
->CtrlQh
, TDs
);
728 Status
= UhciExecuteTransfer (Uhc
, Uhc
->CtrlQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
729 UhciUnlinkTdFromQh (Uhc
->CtrlQh
, TDs
);
731 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
733 *TransferResult
= QhResult
.Result
;
735 if (DataLength
!= NULL
) {
736 *DataLength
= QhResult
.Complete
;
739 UhciDestoryTds (Uhc
, TDs
);
742 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
743 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
746 gBS
->RestoreTPL (OldTpl
);
751 Submits bulk transfer to a bulk endpoint of a USB device.
753 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
754 @param DeviceAddress Target device address.
755 @param EndPointAddress Endpoint number and direction.
756 @param DeviceSpeed Device speed.
757 @param MaximumPacketLength Maximum packet size of the target endpoint.
758 @param DataBuffersNumber Number of data buffers prepared for the transfer.
759 @param Data Array of pointers to the buffers of data.
760 @param DataLength On input, size of the data buffer, On output,
761 actually transferred data size.
762 @param DataToggle On input, data toggle to use; On output, next data toggle.
763 @param TimeOut Maximum time out, in microseconds.
764 @param Translator A pointr to the transaction translator data.
765 @param 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.
777 IN EFI_USB2_HC_PROTOCOL
*This
,
778 IN UINT8 DeviceAddress
,
779 IN UINT8 EndPointAddress
,
780 IN UINT8 DeviceSpeed
,
781 IN UINTN MaximumPacketLength
,
782 IN UINT8 DataBuffersNumber
,
783 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
784 IN OUT UINTN
*DataLength
,
785 IN OUT UINT8
*DataToggle
,
787 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
788 OUT UINT32
*TransferResult
791 EFI_USB_DATA_DIRECTION Direction
;
796 UHCI_QH_RESULT QhResult
;
802 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
806 if (DeviceSpeed
== EFI_USB_SPEED_LOW
) {
807 return EFI_INVALID_PARAMETER
;
810 if ((DataLength
== NULL
) || (*DataLength
== 0) || (Data
== NULL
) || (TransferResult
== NULL
)) {
811 return EFI_INVALID_PARAMETER
;
814 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
815 return EFI_INVALID_PARAMETER
;
818 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
819 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64))
821 return EFI_INVALID_PARAMETER
;
824 *TransferResult
= EFI_USB_ERR_SYSTEM
;
825 Status
= EFI_OUT_OF_RESOURCES
;
828 // If has errors that cause host controller halt,
829 // then return EFI_DEVICE_ERROR directly.
831 UhciAckAllInterrupt (Uhc
);
833 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
834 return EFI_DEVICE_ERROR
;
837 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
840 // Map the source data buffer for bus master access,
841 // then create a list of TDs
843 if ((EndPointAddress
& 0x80) != 0) {
844 Direction
= EfiUsbDataIn
;
846 Direction
= EfiUsbDataOut
;
849 Status
= UhciMapUserData (Uhc
, Direction
, *Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
851 if (EFI_ERROR (Status
)) {
855 Status
= EFI_OUT_OF_RESOURCES
;
856 TDs
= UhciCreateBulkOrIntTds (
865 (UINT8
)MaximumPacketLength
,
870 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
875 // Link the TDs to bulk queue head. According to the platfore
876 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
877 // to do full speed bandwidth reclamation or not.
879 BulkQh
= Uhc
->BulkQh
;
881 UhciLinkTdToQh (Uhc
, BulkQh
, TDs
);
882 Status
= UhciExecuteTransfer (Uhc
, BulkQh
, TDs
, TimeOut
, FALSE
, &QhResult
);
883 UhciUnlinkTdFromQh (BulkQh
, TDs
);
885 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
887 *TransferResult
= QhResult
.Result
;
888 *DataToggle
= QhResult
.NextToggle
;
889 *DataLength
= QhResult
.Complete
;
891 UhciDestoryTds (Uhc
, TDs
);
892 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
895 gBS
->RestoreTPL (OldTpl
);
900 Submits an asynchronous interrupt transfer to an
901 interrupt endpoint of a USB device according to UEFI 2.0 spec.
903 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
904 @param DeviceAddress Target device address.
905 @param EndPointAddress Endpoint number and direction.
906 @param DeviceSpeed Device speed.
907 @param MaximumPacketLength Maximum packet size of the target endpoint.
908 @param IsNewTransfer If TRUE, submit a new transfer, if FALSE cancel old transfer.
909 @param DataToggle On input, data toggle to use; On output, next data toggle.
910 @param PollingInterval Interrupt poll rate in milliseconds.
911 @param DataLength On input, size of the data buffer, On output,
912 actually transferred data size.
913 @param Translator A pointr to the transaction translator data.
914 @param CallBackFunction Function to call periodically.
915 @param Context User context.
917 @return EFI_SUCCESS Transfer was submitted.
918 @return EFI_INVALID_PARAMETER Some parameters are invalid.
919 @return EFI_OUT_OF_RESOURCES Failed due to a lack of resources.
920 @return EFI_DEVICE_ERROR Can't read register.
925 Uhci2AsyncInterruptTransfer (
926 IN EFI_USB2_HC_PROTOCOL
*This
,
927 IN UINT8 DeviceAddress
,
928 IN UINT8 EndPointAddress
,
929 IN UINT8 DeviceSpeed
,
930 IN UINTN MaximumPacketLength
,
931 IN BOOLEAN IsNewTransfer
,
932 IN OUT UINT8
*DataToggle
,
933 IN UINTN PollingInterval
,
935 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
936 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
941 BOOLEAN IsSlowDevice
;
950 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
956 IsSlowDevice
= (BOOLEAN
)((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
958 if ((EndPointAddress
& 0x80) == 0) {
959 return EFI_INVALID_PARAMETER
;
963 // Delete Async interrupt transfer request
965 if (!IsNewTransfer
) {
966 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
967 Status
= UhciRemoveAsyncReq (Uhc
, DeviceAddress
, EndPointAddress
, DataToggle
);
969 gBS
->RestoreTPL (OldTpl
);
973 if ((PollingInterval
< 1) || (PollingInterval
> 255)) {
974 return EFI_INVALID_PARAMETER
;
977 if (DataLength
== 0) {
978 return EFI_INVALID_PARAMETER
;
981 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
982 return EFI_INVALID_PARAMETER
;
986 // If has errors that cause host controller halt,
987 // then return EFI_DEVICE_ERROR directly.
989 UhciAckAllInterrupt (Uhc
);
991 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
992 return EFI_DEVICE_ERROR
;
995 if ((EndPointAddress
& 0x80) == 0) {
996 PktId
= OUTPUT_PACKET_ID
;
998 PktId
= INPUT_PACKET_ID
;
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 DataPhy
= (UINT8
*)(UINTN
)UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, DataPtr
, DataLength
);
1012 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1014 Qh
= UhciCreateQh (Uhc
, PollingInterval
);
1017 Status
= EFI_OUT_OF_RESOURCES
;
1021 IntTds
= UhciCreateBulkOrIntTds (
1030 (UINT8
)MaximumPacketLength
,
1034 if (IntTds
== NULL
) {
1035 Status
= EFI_OUT_OF_RESOURCES
;
1039 UhciLinkTdToQh (Uhc
, Qh
, IntTds
);
1042 // Save QH-TD structures to async Interrupt transfer list,
1043 // for monitor interrupt transfer execution routine use.
1045 Status
= UhciCreateAsyncReq (
1059 if (EFI_ERROR (Status
)) {
1063 UhciLinkQhToFrameList (Uhc
, Qh
);
1065 gBS
->RestoreTPL (OldTpl
);
1069 UsbHcFreeMem (Uhc
->MemPool
, Qh
, sizeof (UHCI_QH_SW
));
1072 UsbHcFreeMem (Uhc
->MemPool
, DataPtr
, DataLength
);
1073 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1075 gBS
->RestoreTPL (OldTpl
);
1080 Submits synchronous interrupt transfer to an interrupt endpoint
1081 of a USB device according to UEFI 2.0 spec.
1084 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1085 @param DeviceAddress Target device address.
1086 @param EndPointAddress Endpoint number and direction.
1087 @param DeviceSpeed Device speed.
1088 @param MaximumPacketLength Maximum packet size of the target endpoint.
1089 @param Data Array of pointers to the buffers of data.
1090 @param DataLength On input, size of the data buffer, On output,
1091 actually transferred data size.
1092 @param DataToggle On input, data toggle to use; On output, next data toggle.
1093 @param TimeOut Maximum time out, in microseconds.
1094 @param Translator A pointr to the transaction translator data.
1095 @param TransferResult Variable to receive transfer result.
1097 @return EFI_SUCCESS The transfer was completed successfully.
1098 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
1099 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1100 @return EFI_TIMEOUT Failed due to timeout.
1101 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
1106 Uhci2SyncInterruptTransfer (
1107 IN EFI_USB2_HC_PROTOCOL
*This
,
1108 IN UINT8 DeviceAddress
,
1109 IN UINT8 EndPointAddress
,
1110 IN UINT8 DeviceSpeed
,
1111 IN UINTN MaximumPacketLength
,
1113 IN OUT UINTN
*DataLength
,
1114 IN OUT UINT8
*DataToggle
,
1116 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1117 OUT UINT32
*TransferResult
1123 UHCI_QH_RESULT QhResult
;
1128 BOOLEAN IsSlowDevice
;
1130 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1135 if (DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
1136 return EFI_INVALID_PARAMETER
;
1139 IsSlowDevice
= (BOOLEAN
)((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
1141 if ((DataLength
== NULL
) || (Data
== NULL
) || (TransferResult
== NULL
)) {
1142 return EFI_INVALID_PARAMETER
;
1145 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1146 return EFI_INVALID_PARAMETER
;
1149 if ((*DataLength
== 0) || (MaximumPacketLength
> 64)) {
1150 return EFI_INVALID_PARAMETER
;
1153 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
1154 return EFI_INVALID_PARAMETER
;
1157 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1158 Status
= EFI_DEVICE_ERROR
;
1160 UhciAckAllInterrupt (Uhc
);
1162 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1166 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1169 // Map the source data buffer for bus master access.
1170 // Create Tds list, then link it to the UHC's interrupt list
1172 Status
= UhciMapUserData (
1182 if (EFI_ERROR (Status
)) {
1186 TDs
= UhciCreateBulkOrIntTds (
1195 (UINT8
)MaximumPacketLength
,
1200 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1202 Status
= EFI_OUT_OF_RESOURCES
;
1206 UhciLinkTdToQh (Uhc
, Uhc
->SyncIntQh
, TDs
);
1208 Status
= UhciExecuteTransfer (Uhc
, Uhc
->SyncIntQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
1210 UhciUnlinkTdFromQh (Uhc
->SyncIntQh
, TDs
);
1211 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1213 *TransferResult
= QhResult
.Result
;
1214 *DataToggle
= QhResult
.NextToggle
;
1215 *DataLength
= QhResult
.Complete
;
1217 UhciDestoryTds (Uhc
, TDs
);
1218 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1221 gBS
->RestoreTPL (OldTpl
);
1226 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
1228 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1229 @param DeviceAddress Target device address.
1230 @param EndPointAddress Endpoint number and direction.
1231 @param DeviceSpeed Device speed.
1232 @param MaximumPacketLength Maximum packet size of the target endpoint.
1233 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1234 @param Data Array of pointers to the buffers of data.
1235 @param DataLength On input, size of the data buffer, On output,
1236 actually transferred data size.
1237 @param Translator A pointr to the transaction translator data.
1238 @param TransferResult Variable to receive transfer result.
1240 @return EFI_UNSUPPORTED
1245 Uhci2IsochronousTransfer (
1246 IN EFI_USB2_HC_PROTOCOL
*This
,
1247 IN UINT8 DeviceAddress
,
1248 IN UINT8 EndPointAddress
,
1249 IN UINT8 DeviceSpeed
,
1250 IN UINTN MaximumPacketLength
,
1251 IN UINT8 DataBuffersNumber
,
1252 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1253 IN UINTN DataLength
,
1254 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1255 OUT UINT32
*TransferResult
1258 return EFI_UNSUPPORTED
;
1262 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
1264 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1265 @param DeviceAddress Target device address.
1266 @param EndPointAddress Endpoint number and direction.
1267 @param DeviceSpeed Device speed.
1268 @param MaximumPacketLength Maximum packet size of the target endpoint.
1269 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1270 @param Data Array of pointers to the buffers of data.
1271 @param DataLength On input, size of the data buffer, On output,
1272 actually transferred data size.
1273 @param Translator A pointr to the transaction translator data.
1274 @param IsochronousCallBack Function to call when the transfer complete.
1275 @param Context Pass to the call back function as parameter.
1277 @return EFI_UNSUPPORTED
1282 Uhci2AsyncIsochronousTransfer (
1283 IN EFI_USB2_HC_PROTOCOL
*This
,
1284 IN UINT8 DeviceAddress
,
1285 IN UINT8 EndPointAddress
,
1286 IN UINT8 DeviceSpeed
,
1287 IN UINTN MaximumPacketLength
,
1288 IN UINT8 DataBuffersNumber
,
1289 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1290 IN UINTN DataLength
,
1291 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1292 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1296 return EFI_UNSUPPORTED
;
1300 Entry point for EFI drivers.
1302 @param ImageHandle EFI_HANDLE.
1303 @param SystemTable EFI_SYSTEM_TABLE.
1305 @retval EFI_SUCCESS Driver is successfully loaded.
1306 @return Others Failed.
1311 UhciDriverEntryPoint (
1312 IN EFI_HANDLE ImageHandle
,
1313 IN EFI_SYSTEM_TABLE
*SystemTable
1316 return EfiLibInstallDriverBindingComponentName2 (
1319 &gUhciDriverBinding
,
1321 &gUhciComponentName
,
1322 &gUhciComponentName2
1327 Test to see if this driver supports ControllerHandle. Any
1328 ControllerHandle that has UsbHcProtocol installed will be supported.
1330 @param This Protocol instance pointer.
1331 @param Controller Handle of device to test.
1332 @param RemainingDevicePath Not used.
1334 @return EFI_SUCCESS This driver supports this device.
1335 @return EFI_UNSUPPORTED This driver does not support this device.
1340 UhciDriverBindingSupported (
1341 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1342 IN EFI_HANDLE Controller
,
1343 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1346 EFI_STATUS OpenStatus
;
1348 EFI_PCI_IO_PROTOCOL
*PciIo
;
1349 USB_CLASSC UsbClassCReg
;
1352 // Test whether there is PCI IO Protocol attached on the controller handle.
1354 OpenStatus
= gBS
->OpenProtocol (
1356 &gEfiPciIoProtocolGuid
,
1358 This
->DriverBindingHandle
,
1360 EFI_OPEN_PROTOCOL_BY_DRIVER
1363 if (EFI_ERROR (OpenStatus
)) {
1367 Status
= PciIo
->Pci
.Read (
1370 PCI_CLASSCODE_OFFSET
,
1371 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1375 if (EFI_ERROR (Status
)) {
1376 Status
= EFI_UNSUPPORTED
;
1381 // Test whether the controller belongs to UHCI type
1383 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1384 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1385 (UsbClassCReg
.ProgInterface
!= PCI_IF_UHCI
)
1388 Status
= EFI_UNSUPPORTED
;
1392 gBS
->CloseProtocol (
1394 &gEfiPciIoProtocolGuid
,
1395 This
->DriverBindingHandle
,
1403 Allocate and initialize the empty UHCI device.
1405 @param PciIo The PCIIO to use.
1406 @param DevicePath The device path of host controller.
1407 @param OriginalPciAttributes The original PCI attributes.
1409 @return Allocated UHCI device. If err, return NULL.
1414 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1415 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1416 IN UINT64 OriginalPciAttributes
1422 Uhc
= AllocateZeroPool (sizeof (USB_HC_DEV
));
1429 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
1430 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
1432 Uhc
->Signature
= USB_HC_DEV_SIGNATURE
;
1433 Uhc
->Usb2Hc
.GetCapability
= Uhci2GetCapability
;
1434 Uhc
->Usb2Hc
.Reset
= Uhci2Reset
;
1435 Uhc
->Usb2Hc
.GetState
= Uhci2GetState
;
1436 Uhc
->Usb2Hc
.SetState
= Uhci2SetState
;
1437 Uhc
->Usb2Hc
.ControlTransfer
= Uhci2ControlTransfer
;
1438 Uhc
->Usb2Hc
.BulkTransfer
= Uhci2BulkTransfer
;
1439 Uhc
->Usb2Hc
.AsyncInterruptTransfer
= Uhci2AsyncInterruptTransfer
;
1440 Uhc
->Usb2Hc
.SyncInterruptTransfer
= Uhci2SyncInterruptTransfer
;
1441 Uhc
->Usb2Hc
.IsochronousTransfer
= Uhci2IsochronousTransfer
;
1442 Uhc
->Usb2Hc
.AsyncIsochronousTransfer
= Uhci2AsyncIsochronousTransfer
;
1443 Uhc
->Usb2Hc
.GetRootHubPortStatus
= Uhci2GetRootHubPortStatus
;
1444 Uhc
->Usb2Hc
.SetRootHubPortFeature
= Uhci2SetRootHubPortFeature
;
1445 Uhc
->Usb2Hc
.ClearRootHubPortFeature
= Uhci2ClearRootHubPortFeature
;
1446 Uhc
->Usb2Hc
.MajorRevision
= 0x1;
1447 Uhc
->Usb2Hc
.MinorRevision
= 0x1;
1450 Uhc
->DevicePath
= DevicePath
;
1451 Uhc
->OriginalPciAttributes
= OriginalPciAttributes
;
1452 Uhc
->MemPool
= UsbHcInitMemPool (PciIo
, TRUE
, 0);
1454 if (Uhc
->MemPool
== NULL
) {
1455 Status
= EFI_OUT_OF_RESOURCES
;
1459 InitializeListHead (&Uhc
->AsyncIntList
);
1461 Status
= gBS
->CreateEvent (
1462 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1464 UhciMonitorAsyncReqList
,
1466 &Uhc
->AsyncIntMonitor
1469 if (EFI_ERROR (Status
)) {
1470 UsbHcFreeMemPool (Uhc
->MemPool
);
1482 Free the UHCI device and release its associated resources.
1484 @param Uhc The UHCI device to release.
1492 if (Uhc
->AsyncIntMonitor
!= NULL
) {
1493 gBS
->CloseEvent (Uhc
->AsyncIntMonitor
);
1496 if (Uhc
->ExitBootServiceEvent
!= NULL
) {
1497 gBS
->CloseEvent (Uhc
->ExitBootServiceEvent
);
1500 if (Uhc
->MemPool
!= NULL
) {
1501 UsbHcFreeMemPool (Uhc
->MemPool
);
1504 if (Uhc
->CtrlNameTable
!= NULL
) {
1505 FreeUnicodeStringTable (Uhc
->CtrlNameTable
);
1512 Uninstall all Uhci Interface.
1514 @param Controller Controller handle.
1515 @param This Protocol instance pointer.
1520 IN EFI_HANDLE Controller
,
1521 IN EFI_USB2_HC_PROTOCOL
*This
1528 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
1530 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1532 Status
= gBS
->UninstallProtocolInterface (
1534 &gEfiUsb2HcProtocolGuid
,
1537 if (EFI_ERROR (Status
)) {
1541 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1542 UhciFreeAllAsyncReq (Uhc
);
1543 UhciDestoryFrameList (Uhc
);
1546 // Restore original PCI attributes
1548 Uhc
->PciIo
->Attributes (
1550 EfiPciIoAttributeOperationSet
,
1551 Uhc
->OriginalPciAttributes
,
1559 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1561 @param Event Pointer to this event
1562 @param Context Event handler private data
1567 UhcExitBootService (
1574 Uhc
= (USB_HC_DEV
*)Context
;
1577 // Stop the Host Controller
1579 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1582 // Reset the Host Controller
1584 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_HCRESET
);
1585 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
1589 Starting the Usb UHCI Driver.
1591 @param This Protocol instance pointer.
1592 @param Controller Handle of device to test.
1593 @param RemainingDevicePath Not used.
1595 @retval EFI_SUCCESS This driver supports this device.
1596 @retval EFI_UNSUPPORTED This driver does not support this device.
1597 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
1598 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
1603 UhciDriverBindingStart (
1604 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1605 IN EFI_HANDLE Controller
,
1606 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1610 EFI_PCI_IO_PROTOCOL
*PciIo
;
1613 UINT64 OriginalPciAttributes
;
1614 BOOLEAN PciAttributesSaved
;
1615 EFI_DEVICE_PATH_PROTOCOL
*HcDevicePath
;
1618 // Open PCIIO, then enable the EHC device and turn off emulation
1621 Status
= gBS
->OpenProtocol (
1623 &gEfiPciIoProtocolGuid
,
1625 This
->DriverBindingHandle
,
1627 EFI_OPEN_PROTOCOL_BY_DRIVER
1630 if (EFI_ERROR (Status
)) {
1635 // Open Device Path Protocol for on USB host controller
1637 HcDevicePath
= NULL
;
1638 Status
= gBS
->OpenProtocol (
1640 &gEfiDevicePathProtocolGuid
,
1641 (VOID
**)&HcDevicePath
,
1642 This
->DriverBindingHandle
,
1644 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1647 PciAttributesSaved
= FALSE
;
1649 // Save original PCI attributes
1651 Status
= PciIo
->Attributes (
1653 EfiPciIoAttributeOperationGet
,
1655 &OriginalPciAttributes
1658 if (EFI_ERROR (Status
)) {
1662 PciAttributesSaved
= TRUE
;
1665 // Robustnesss improvement such as for UoL
1666 // Default is not required.
1668 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1669 UhciTurnOffUsbEmulation (PciIo
);
1672 Status
= PciIo
->Attributes (
1674 EfiPciIoAttributeOperationSupported
,
1678 if (!EFI_ERROR (Status
)) {
1679 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
1680 Status
= PciIo
->Attributes (
1682 EfiPciIoAttributeOperationEnable
,
1688 if (EFI_ERROR (Status
)) {
1692 Uhc
= UhciAllocateDev (PciIo
, HcDevicePath
, OriginalPciAttributes
);
1695 Status
= EFI_OUT_OF_RESOURCES
;
1700 // Allocate and Init Host Controller's Frame List Entry
1702 Status
= UhciInitFrameList (Uhc
);
1704 if (EFI_ERROR (Status
)) {
1705 Status
= EFI_OUT_OF_RESOURCES
;
1709 Status
= gBS
->SetTimer (
1710 Uhc
->AsyncIntMonitor
,
1712 UHC_ASYNC_POLL_INTERVAL
1715 if (EFI_ERROR (Status
)) {
1720 // Install USB2_HC_PROTOCOL
1722 Status
= gBS
->InstallMultipleProtocolInterfaces (
1724 &gEfiUsb2HcProtocolGuid
,
1729 if (EFI_ERROR (Status
)) {
1734 // Create event to stop the HC when exit boot service.
1736 Status
= gBS
->CreateEventEx (
1741 &gEfiEventExitBootServicesGuid
,
1742 &Uhc
->ExitBootServiceEvent
1744 if (EFI_ERROR (Status
)) {
1745 goto UNINSTALL_USBHC
;
1749 // Install the component name protocol
1751 Uhc
->CtrlNameTable
= NULL
;
1755 gUhciComponentName
.SupportedLanguages
,
1756 &Uhc
->CtrlNameTable
,
1757 L
"Usb Universal Host Controller",
1762 gUhciComponentName2
.SupportedLanguages
,
1763 &Uhc
->CtrlNameTable
,
1764 L
"Usb Universal Host Controller",
1769 // Start the UHCI hardware, also set its reclamation point to 64 bytes
1771 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_RS
| USBCMD_MAXP
);
1776 gBS
->UninstallMultipleProtocolInterfaces (
1778 &gEfiUsb2HcProtocolGuid
,
1787 if (PciAttributesSaved
) {
1789 // Restore original PCI attributes
1793 EfiPciIoAttributeOperationSet
,
1794 OriginalPciAttributes
,
1799 gBS
->CloseProtocol (
1801 &gEfiPciIoProtocolGuid
,
1802 This
->DriverBindingHandle
,
1810 Stop this driver on ControllerHandle. Support stopping any child handles
1811 created by this driver.
1813 @param This Protocol instance pointer.
1814 @param Controller Handle of device to stop driver on.
1815 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1816 @param ChildHandleBuffer List of handles for the children we need to stop.
1824 UhciDriverBindingStop (
1825 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1826 IN EFI_HANDLE Controller
,
1827 IN UINTN NumberOfChildren
,
1828 IN EFI_HANDLE
*ChildHandleBuffer
1831 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1834 Status
= gBS
->OpenProtocol (
1836 &gEfiUsb2HcProtocolGuid
,
1838 This
->DriverBindingHandle
,
1840 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1844 // Test whether the Controller handler passed in is a valid
1845 // Usb controller handle that should be supported, if not,
1846 // return the error status directly
1848 if (EFI_ERROR (Status
)) {
1852 UhciCleanDevUp (Controller
, Usb2Hc
);
1854 gBS
->CloseProtocol (
1856 &gEfiPciIoProtocolGuid
,
1857 This
->DriverBindingHandle
,