3 The UHCI driver model and HC protocol routines.
5 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
6 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 if (Uhc
->DevicePath
!= NULL
) {
60 // Report Status Code to indicate reset happens
62 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
64 (EFI_IO_BUS_USB
| EFI_IOB_PC_RESET
),
69 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
72 case EFI_USB_HC_RESET_GLOBAL
:
74 // Stop schedule and set the Global Reset bit in the command register
76 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
77 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_GRESET
);
79 gBS
->Stall (UHC_ROOT_PORT_RESET_STALL
);
82 // Clear the Global Reset bit to zero.
84 UhciClearRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_GRESET
);
86 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
89 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
91 // Stop schedule and set Host Controller Reset bit to 1
93 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
94 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_HCRESET
);
96 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
100 goto ON_INVAILD_PARAMETER
;
104 // Delete all old transactions on the USB bus, then
105 // reinitialize the frame list
107 UhciFreeAllAsyncReq (Uhc
);
108 UhciDestoryFrameList (Uhc
);
109 UhciInitFrameList (Uhc
);
111 gBS
->RestoreTPL (OldTpl
);
115 ON_INVAILD_PARAMETER
:
117 gBS
->RestoreTPL (OldTpl
);
119 return EFI_INVALID_PARAMETER
;
124 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
126 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
127 @param State Variable to receive current device state.
129 @return EFI_SUCCESS The state is returned.
130 @return EFI_INVALID_PARAMETER State is not valid.
131 @return EFI_DEVICE_ERROR Other errors.
137 IN EFI_USB2_HC_PROTOCOL
*This
,
138 OUT EFI_USB_HC_STATE
*State
146 return EFI_INVALID_PARAMETER
;
149 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
151 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
152 UsbSts
= UhciReadReg (Uhc
->PciIo
, USBSTS_OFFSET
);
154 if ((UsbCmd
& USBCMD_EGSM
) !=0 ) {
155 *State
= EfiUsbHcStateSuspend
;
157 } else if ((UsbSts
& USBSTS_HCH
) != 0) {
158 *State
= EfiUsbHcStateHalt
;
161 *State
= EfiUsbHcStateOperational
;
169 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
171 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
172 @param State Indicates the state of the host controller that will
175 @return EFI_SUCCESS Host controller was successfully placed in the state.
176 @return EFI_INVALID_PARAMETER State is invalid.
177 @return EFI_DEVICE_ERROR Failed to set the state.
183 IN EFI_USB2_HC_PROTOCOL
*This
,
184 IN EFI_USB_HC_STATE State
187 EFI_USB_HC_STATE CurState
;
193 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
194 Status
= Uhci2GetState (This
, &CurState
);
196 if (EFI_ERROR (Status
)) {
197 return EFI_DEVICE_ERROR
;
200 if (CurState
== State
) {
204 Status
= EFI_SUCCESS
;
205 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
208 case EfiUsbHcStateHalt
:
209 Status
= UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
212 case EfiUsbHcStateOperational
:
213 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
215 if (CurState
== EfiUsbHcStateHalt
) {
217 // Set Run/Stop bit to 1, also set the bandwidht reclamation
220 UsbCmd
|= USBCMD_RS
| USBCMD_MAXP
;
221 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
223 } else if (CurState
== EfiUsbHcStateSuspend
) {
225 // If FGR(Force Global Resume) bit is 0, set it
227 if ((UsbCmd
& USBCMD_FGR
) == 0) {
228 UsbCmd
|= USBCMD_FGR
;
229 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
233 // wait 20ms to let resume complete (20ms is specified by UHCI spec)
235 gBS
->Stall (UHC_FORCE_GLOBAL_RESUME_STALL
);
238 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
240 UsbCmd
&= ~USBCMD_FGR
;
241 UsbCmd
&= ~USBCMD_EGSM
;
243 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
248 case EfiUsbHcStateSuspend
:
249 Status
= Uhci2SetState (This
, EfiUsbHcStateHalt
);
251 if (EFI_ERROR (Status
)) {
252 Status
= EFI_DEVICE_ERROR
;
257 // Set Enter Global Suspend Mode bit to 1.
259 UsbCmd
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
260 UsbCmd
|= USBCMD_EGSM
;
261 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, UsbCmd
);
265 Status
= EFI_INVALID_PARAMETER
;
270 gBS
->RestoreTPL (OldTpl
);
275 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
277 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
278 @param MaxSpeed A pointer to the max speed USB host controller
280 @param PortNumber A pointer to the number of root hub ports.
281 @param Is64BitCapable A pointer to an integer to show whether USB host
282 controller supports 64-bit memory addressing.
284 @return EFI_SUCCESS capabilities were retrieved successfully.
285 @return EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.
286 @return EFI_DEVICE_ERROR An error was encountered.
292 IN EFI_USB2_HC_PROTOCOL
*This
,
294 OUT UINT8
*PortNumber
,
295 OUT UINT8
*Is64BitCapable
303 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
305 if ((NULL
== MaxSpeed
) || (NULL
== PortNumber
) || (NULL
== Is64BitCapable
)) {
306 return EFI_INVALID_PARAMETER
;
309 *MaxSpeed
= EFI_USB_SPEED_FULL
;
310 *Is64BitCapable
= (UINT8
) FALSE
;
314 for (Index
= 0; Index
< USB_MAX_ROOTHUB_PORT
; Index
++) {
315 Offset
= USBPORTSC_OFFSET
+ Index
* 2;
316 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
319 // Port status's bit 7 is reserved and always returns 1 if
320 // the port number is valid. Intel's UHCI (in EHCI controller)
321 // returns 0 in this bit if port number is invalid. Also, if
322 // PciIo IoRead returns error, 0xFFFF is returned to caller.
324 if (((PortSC
& 0x80) == 0) || (PortSC
== 0xFFFF)) {
330 Uhc
->RootPorts
= *PortNumber
;
332 DEBUG ((EFI_D_INFO
, "Uhci2GetCapability: %d ports\n", (UINT32
)Uhc
->RootPorts
));
338 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
340 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
341 @param PortNumber The port to get status.
342 @param PortStatus A pointer to the current port status bits and port
345 @return EFI_SUCCESS status of the USB root hub port was returned in PortStatus.
346 @return EFI_INVALID_PARAMETER PortNumber is invalid.
347 @return EFI_DEVICE_ERROR Can't read register.
352 Uhci2GetRootHubPortStatus (
353 IN EFI_USB2_HC_PROTOCOL
*This
,
355 OUT EFI_USB_PORT_STATUS
*PortStatus
362 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
364 if (PortStatus
== NULL
) {
365 return EFI_INVALID_PARAMETER
;
368 if (PortNumber
>= Uhc
->RootPorts
) {
369 return EFI_INVALID_PARAMETER
;
372 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
373 PortStatus
->PortStatus
= 0;
374 PortStatus
->PortChangeStatus
= 0;
376 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
378 if ((PortSC
& USBPORTSC_CCS
) != 0) {
379 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
382 if ((PortSC
& USBPORTSC_PED
) != 0) {
383 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
386 if ((PortSC
& USBPORTSC_SUSP
) != 0) {
387 DEBUG ((EFI_D_INFO
, "Uhci2GetRootHubPortStatus: port %d is suspended\n", PortNumber
));
388 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
391 if ((PortSC
& USBPORTSC_PR
) != 0) {
392 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
395 if ((PortSC
& USBPORTSC_LSDA
) != 0) {
396 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
400 // CHC will always return one in port owner bit
402 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
404 if ((PortSC
& USBPORTSC_CSC
) != 0) {
405 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
408 if ((PortSC
& USBPORTSC_PEDC
) != 0) {
409 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
417 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
419 @param This A pointer to the EFI_USB2_HC_PROTOCOL.
420 @param PortNumber Specifies the root hub port whose feature is
422 @param PortFeature Indicates the feature selector associated with the
425 @return EFI_SUCCESS PortFeature was set for the root port.
426 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
427 @return EFI_DEVICE_ERROR Can't read register.
432 Uhci2SetRootHubPortFeature (
433 IN EFI_USB2_HC_PROTOCOL
*This
,
435 IN EFI_USB_PORT_FEATURE PortFeature
444 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
446 if (PortNumber
>= Uhc
->RootPorts
) {
447 return EFI_INVALID_PARAMETER
;
450 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
452 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
453 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
455 switch (PortFeature
) {
456 case EfiUsbPortSuspend
:
457 Command
= UhciReadReg (Uhc
->PciIo
, USBCMD_OFFSET
);
458 if ((Command
& USBCMD_EGSM
) == 0) {
460 // if global suspend is not active, can set port suspend
463 PortSC
|= USBPORTSC_SUSP
;
467 case EfiUsbPortReset
:
469 PortSC
|= USBPORTSC_PR
;
472 case EfiUsbPortPower
:
478 case EfiUsbPortEnable
:
480 PortSC
|= USBPORTSC_PED
;
484 gBS
->RestoreTPL (OldTpl
);
485 return EFI_INVALID_PARAMETER
;
488 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
489 gBS
->RestoreTPL (OldTpl
);
496 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
498 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
499 @param PortNumber Specifies the root hub port whose feature is
500 requested to be cleared.
501 @param PortFeature Indicates the feature selector associated with the
502 feature clear request.
504 @return EFI_SUCCESS PortFeature was cleared for the USB root hub port.
505 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
506 @return EFI_DEVICE_ERROR Can't read register.
511 Uhci2ClearRootHubPortFeature (
512 IN EFI_USB2_HC_PROTOCOL
*This
,
514 IN EFI_USB_PORT_FEATURE PortFeature
522 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
524 if (PortNumber
>= Uhc
->RootPorts
) {
525 return EFI_INVALID_PARAMETER
;
528 Offset
= USBPORTSC_OFFSET
+ PortNumber
* 2;
530 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
531 PortSC
= UhciReadReg (Uhc
->PciIo
, Offset
);
533 switch (PortFeature
) {
534 case EfiUsbPortEnable
:
536 PortSC
&= ~USBPORTSC_PED
;
539 case EfiUsbPortSuspend
:
541 // Cause a resume on the specified port if in suspend mode.
544 PortSC
&= ~USBPORTSC_SUSP
;
547 case EfiUsbPortPower
:
553 case EfiUsbPortReset
:
555 PortSC
&= ~USBPORTSC_PR
;
558 case EfiUsbPortConnectChange
:
560 PortSC
|= USBPORTSC_CSC
;
563 case EfiUsbPortEnableChange
:
565 PortSC
|= USBPORTSC_PEDC
;
568 case EfiUsbPortSuspendChange
:
570 // Root hub does not support this
574 case EfiUsbPortOverCurrentChange
:
576 // Root hub does not support this
580 case EfiUsbPortResetChange
:
582 // Root hub does not support this
587 gBS
->RestoreTPL (OldTpl
);
588 return EFI_INVALID_PARAMETER
;
591 UhciWriteReg (Uhc
->PciIo
, Offset
, PortSC
);
592 gBS
->RestoreTPL (OldTpl
);
599 Submits control transfer to a target USB device accroding to UEFI 2.0 spec.
601 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
602 @param DeviceAddress Target device address.
603 @param DeviceSpeed Device speed.
604 @param MaximumPacketLength Maximum packet size of the target endpoint.
605 @param Request USB device request to send.
606 @param TransferDirection Data direction of the Data stage in control transfer.
607 @param Data Data to transmit/receive in data stage.
608 @param DataLength Length of the data.
609 @param TimeOut Maximum time, in microseconds, for transfer to complete.
610 @param Translator Transaction translator to be used by this device.
611 @param TransferResult Variable to receive the transfer result.
613 @return EFI_SUCCESS The control transfer was completed successfully.
614 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
615 @return EFI_INVALID_PARAMETER Some parameters are invalid.
616 @return EFI_TIMEOUT Failed due to timeout.
617 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
622 Uhci2ControlTransfer (
623 IN EFI_USB2_HC_PROTOCOL
*This
,
624 IN UINT8 DeviceAddress
,
625 IN UINT8 DeviceSpeed
,
626 IN UINTN MaximumPacketLength
,
627 IN EFI_USB_DEVICE_REQUEST
*Request
,
628 IN EFI_USB_DATA_DIRECTION TransferDirection
,
630 IN OUT UINTN
*DataLength
,
632 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
633 OUT UINT32
*TransferResult
640 UHCI_QH_RESULT QhResult
;
646 BOOLEAN IsSlowDevice
;
647 UINTN TransferDataLength
;
649 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
656 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
659 // Parameters Checking
661 if (Request
== NULL
|| TransferResult
== NULL
) {
662 return EFI_INVALID_PARAMETER
;
665 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
666 return EFI_INVALID_PARAMETER
;
669 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
670 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
672 return EFI_INVALID_PARAMETER
;
675 if ((TransferDirection
!= EfiUsbNoData
) && (Data
== NULL
|| DataLength
== NULL
)) {
676 return EFI_INVALID_PARAMETER
;
679 if (TransferDirection
== EfiUsbNoData
) {
680 TransferDataLength
= 0;
682 TransferDataLength
= *DataLength
;
685 *TransferResult
= EFI_USB_ERR_SYSTEM
;
686 Status
= EFI_DEVICE_ERROR
;
689 // If errors exist that cause host controller halt,
690 // clear status then return EFI_DEVICE_ERROR.
692 UhciAckAllInterrupt (Uhc
);
694 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
695 return EFI_DEVICE_ERROR
;
698 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
701 // Map the Request and data for bus master access,
702 // then create a list of TD for this transfer
704 Status
= UhciMapUserRequest (Uhc
, Request
, &RequestPhy
, &RequestMap
);
706 if (EFI_ERROR (Status
)) {
710 Status
= UhciMapUserData (Uhc
, TransferDirection
, Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
712 if (EFI_ERROR (Status
)) {
713 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
717 TDs
= UhciCreateCtrlTds (
726 (UINT8
) MaximumPacketLength
,
731 Status
= EFI_OUT_OF_RESOURCES
;
736 // According to the speed of the end point, link
737 // the TD to corrosponding queue head, then check
738 // the execution result
740 UhciLinkTdToQh (Uhc
, Uhc
->CtrlQh
, TDs
);
741 Status
= UhciExecuteTransfer (Uhc
, Uhc
->CtrlQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
742 UhciUnlinkTdFromQh (Uhc
->CtrlQh
, TDs
);
744 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
746 *TransferResult
= QhResult
.Result
;
748 if (DataLength
!= NULL
) {
749 *DataLength
= QhResult
.Complete
;
752 UhciDestoryTds (Uhc
, TDs
);
755 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
756 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, RequestMap
);
759 gBS
->RestoreTPL (OldTpl
);
765 Submits bulk transfer to a bulk endpoint of a USB device.
767 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
768 @param DeviceAddress Target device address.
769 @param EndPointAddress Endpoint number and direction.
770 @param DeviceSpeed Device speed.
771 @param MaximumPacketLength Maximum packet size of the target endpoint.
772 @param DataBuffersNumber Number of data buffers prepared for the transfer.
773 @param Data Array of pointers to the buffers of data.
774 @param DataLength On input, size of the data buffer, On output,
775 actually transferred data size.
776 @param DataToggle On input, data toggle to use; On output, next data toggle.
777 @param TimeOut Maximum time out, in microseconds.
778 @param Translator A pointr to the transaction translator data.
779 @param TransferResult Variable to receive transfer result.
781 @return EFI_SUCCESS The bulk transfer was completed successfully.
782 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
783 @return EFI_INVALID_PARAMETER Some parameters are invalid.
784 @return EFI_TIMEOUT Failed due to timeout.
785 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
791 IN EFI_USB2_HC_PROTOCOL
*This
,
792 IN UINT8 DeviceAddress
,
793 IN UINT8 EndPointAddress
,
794 IN UINT8 DeviceSpeed
,
795 IN UINTN MaximumPacketLength
,
796 IN UINT8 DataBuffersNumber
,
797 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
798 IN OUT UINTN
*DataLength
,
799 IN OUT UINT8
*DataToggle
,
801 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
802 OUT UINT32
*TransferResult
805 EFI_USB_DATA_DIRECTION Direction
;
810 UHCI_QH_RESULT QhResult
;
816 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
820 if (DeviceSpeed
== EFI_USB_SPEED_LOW
) {
821 return EFI_INVALID_PARAMETER
;
824 if ((DataLength
== NULL
) || (*DataLength
== 0) || (Data
== NULL
) || (TransferResult
== NULL
)) {
825 return EFI_INVALID_PARAMETER
;
828 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
829 return EFI_INVALID_PARAMETER
;
832 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
833 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
834 return EFI_INVALID_PARAMETER
;
837 *TransferResult
= EFI_USB_ERR_SYSTEM
;
838 Status
= EFI_OUT_OF_RESOURCES
;
841 // If has errors that cause host controller halt,
842 // then return EFI_DEVICE_ERROR directly.
844 UhciAckAllInterrupt (Uhc
);
846 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
847 return EFI_DEVICE_ERROR
;
850 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
853 // Map the source data buffer for bus master access,
854 // then create a list of TDs
856 if ((EndPointAddress
& 0x80) != 0) {
857 Direction
= EfiUsbDataIn
;
859 Direction
= EfiUsbDataOut
;
862 Status
= UhciMapUserData (Uhc
, Direction
, *Data
, DataLength
, &PktId
, &DataPhy
, &DataMap
);
864 if (EFI_ERROR (Status
)) {
868 Status
= EFI_OUT_OF_RESOURCES
;
869 TDs
= UhciCreateBulkOrIntTds (
878 (UINT8
) MaximumPacketLength
,
883 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
889 // Link the TDs to bulk queue head. According to the platfore
890 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
891 // to do full speed bandwidth reclamation or not.
893 BulkQh
= Uhc
->BulkQh
;
895 UhciLinkTdToQh (Uhc
, BulkQh
, TDs
);
896 Status
= UhciExecuteTransfer (Uhc
, BulkQh
, TDs
, TimeOut
, FALSE
, &QhResult
);
897 UhciUnlinkTdFromQh (BulkQh
, TDs
);
899 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
901 *TransferResult
= QhResult
.Result
;
902 *DataToggle
= QhResult
.NextToggle
;
903 *DataLength
= QhResult
.Complete
;
905 UhciDestoryTds (Uhc
, TDs
);
906 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
909 gBS
->RestoreTPL (OldTpl
);
915 Submits an asynchronous interrupt transfer to an
916 interrupt endpoint of a USB device according to UEFI 2.0 spec.
918 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
919 @param DeviceAddress Target device address.
920 @param EndPointAddress Endpoint number and direction.
921 @param DeviceSpeed Device speed.
922 @param MaximumPacketLength Maximum packet size of the target endpoint.
923 @param IsNewTransfer If TRUE, submit a new transfer, if FALSE cancel old transfer.
924 @param DataToggle On input, data toggle to use; On output, next data toggle.
925 @param PollingInterval Interrupt poll rate in milliseconds.
926 @param DataLength On input, size of the data buffer, On output,
927 actually transferred data size.
928 @param Translator A pointr to the transaction translator data.
929 @param CallBackFunction Function to call periodically.
930 @param Context User context.
932 @return EFI_SUCCESS Transfer was submitted.
933 @return EFI_INVALID_PARAMETER Some parameters are invalid.
934 @return EFI_OUT_OF_RESOURCES Failed due to a lack of resources.
935 @return EFI_DEVICE_ERROR Can't read register.
940 Uhci2AsyncInterruptTransfer (
941 IN EFI_USB2_HC_PROTOCOL
*This
,
942 IN UINT8 DeviceAddress
,
943 IN UINT8 EndPointAddress
,
944 IN UINT8 DeviceSpeed
,
945 IN UINTN MaximumPacketLength
,
946 IN BOOLEAN IsNewTransfer
,
947 IN OUT UINT8
*DataToggle
,
948 IN UINTN PollingInterval
,
950 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
951 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
956 BOOLEAN IsSlowDevice
;
965 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
971 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
973 if ((EndPointAddress
& 0x80) == 0) {
974 return EFI_INVALID_PARAMETER
;
978 // Delete Async interrupt transfer request
980 if (!IsNewTransfer
) {
981 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
982 Status
= UhciRemoveAsyncReq (Uhc
, DeviceAddress
, EndPointAddress
, DataToggle
);
984 gBS
->RestoreTPL (OldTpl
);
988 if (PollingInterval
< 1 || PollingInterval
> 255) {
989 return EFI_INVALID_PARAMETER
;
992 if (DataLength
== 0) {
993 return EFI_INVALID_PARAMETER
;
996 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
997 return EFI_INVALID_PARAMETER
;
1001 // If has errors that cause host controller halt,
1002 // then return EFI_DEVICE_ERROR directly.
1004 UhciAckAllInterrupt (Uhc
);
1006 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1007 return EFI_DEVICE_ERROR
;
1010 if ((EndPointAddress
& 0x80) == 0) {
1011 PktId
= OUTPUT_PACKET_ID
;
1013 PktId
= INPUT_PACKET_ID
;
1017 // Allocate and map source data buffer for bus master access.
1019 DataPtr
= UsbHcAllocateMem (Uhc
->MemPool
, DataLength
);
1021 if (DataPtr
== NULL
) {
1022 return EFI_OUT_OF_RESOURCES
;
1025 DataPhy
= (UINT8
*) (UINTN
) UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, DataPtr
, DataLength
);
1027 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1029 Qh
= UhciCreateQh (Uhc
, PollingInterval
);
1032 Status
= EFI_OUT_OF_RESOURCES
;
1036 IntTds
= UhciCreateBulkOrIntTds (
1045 (UINT8
) MaximumPacketLength
,
1049 if (IntTds
== NULL
) {
1050 Status
= EFI_OUT_OF_RESOURCES
;
1054 UhciLinkTdToQh (Uhc
, Qh
, IntTds
);
1057 // Save QH-TD structures to async Interrupt transfer list,
1058 // for monitor interrupt transfer execution routine use.
1060 Status
= UhciCreateAsyncReq (
1074 if (EFI_ERROR (Status
)) {
1078 UhciLinkQhToFrameList (Uhc
, Qh
);
1080 gBS
->RestoreTPL (OldTpl
);
1084 UsbHcFreeMem (Uhc
->MemPool
, Qh
, sizeof (UHCI_QH_SW
));
1087 UsbHcFreeMem (Uhc
->MemPool
, DataPtr
, DataLength
);
1088 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1090 gBS
->RestoreTPL (OldTpl
);
1095 Submits synchronous interrupt transfer to an interrupt endpoint
1096 of a USB device according to UEFI 2.0 spec.
1099 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1100 @param DeviceAddress Target device address.
1101 @param EndPointAddress Endpoint number and direction.
1102 @param DeviceSpeed Device speed.
1103 @param MaximumPacketLength Maximum packet size of the target endpoint.
1104 @param Data Array of pointers to the buffers of data.
1105 @param DataLength On input, size of the data buffer, On output,
1106 actually transferred data size.
1107 @param DataToggle On input, data toggle to use; On output, next data toggle.
1108 @param TimeOut Maximum time out, in microseconds.
1109 @param Translator A pointr to the transaction translator data.
1110 @param TransferResult Variable to receive transfer result.
1112 @return EFI_SUCCESS The transfer was completed successfully.
1113 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
1114 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1115 @return EFI_TIMEOUT Failed due to timeout.
1116 @return EFI_DEVICE_ERROR Failed due to host controller or device error.
1121 Uhci2SyncInterruptTransfer (
1122 IN EFI_USB2_HC_PROTOCOL
*This
,
1123 IN UINT8 DeviceAddress
,
1124 IN UINT8 EndPointAddress
,
1125 IN UINT8 DeviceSpeed
,
1126 IN UINTN MaximumPacketLength
,
1128 IN OUT UINTN
*DataLength
,
1129 IN OUT UINT8
*DataToggle
,
1131 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1132 OUT UINT32
*TransferResult
1138 UHCI_QH_RESULT QhResult
;
1143 BOOLEAN IsSlowDevice
;
1145 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1150 if (DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
1151 return EFI_INVALID_PARAMETER
;
1154 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
1156 if ((DataLength
== NULL
) || (Data
== NULL
) || (TransferResult
== NULL
)) {
1157 return EFI_INVALID_PARAMETER
;
1160 if ((EndPointAddress
& 0x80) == 0) {
1161 return EFI_INVALID_PARAMETER
;
1164 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1165 return EFI_INVALID_PARAMETER
;
1168 if ((*DataLength
== 0) || (MaximumPacketLength
> 64)) {
1169 return EFI_INVALID_PARAMETER
;
1172 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
1173 return EFI_INVALID_PARAMETER
;
1176 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1177 Status
= EFI_DEVICE_ERROR
;
1180 UhciAckAllInterrupt (Uhc
);
1182 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1186 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1189 // Map the source data buffer for bus master access.
1190 // Create Tds list, then link it to the UHC's interrupt list
1192 Status
= UhciMapUserData (
1202 if (EFI_ERROR (Status
)) {
1206 TDs
= UhciCreateBulkOrIntTds (
1215 (UINT8
) MaximumPacketLength
,
1220 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1222 Status
= EFI_OUT_OF_RESOURCES
;
1227 UhciLinkTdToQh (Uhc
, Uhc
->SyncIntQh
, TDs
);
1229 Status
= UhciExecuteTransfer (Uhc
, Uhc
->SyncIntQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
1231 UhciUnlinkTdFromQh (Uhc
->SyncIntQh
, TDs
);
1232 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1234 *TransferResult
= QhResult
.Result
;
1235 *DataToggle
= QhResult
.NextToggle
;
1236 *DataLength
= QhResult
.Complete
;
1238 UhciDestoryTds (Uhc
, TDs
);
1239 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1242 gBS
->RestoreTPL (OldTpl
);
1248 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
1250 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1251 @param DeviceAddress Target device address.
1252 @param EndPointAddress Endpoint number and direction.
1253 @param DeviceSpeed Device speed.
1254 @param MaximumPacketLength Maximum packet size of the target endpoint.
1255 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1256 @param Data Array of pointers to the buffers of data.
1257 @param DataLength On input, size of the data buffer, On output,
1258 actually transferred data size.
1259 @param Translator A pointr to the transaction translator data.
1260 @param TransferResult Variable to receive transfer result.
1262 @return EFI_UNSUPPORTED
1267 Uhci2IsochronousTransfer (
1268 IN EFI_USB2_HC_PROTOCOL
*This
,
1269 IN UINT8 DeviceAddress
,
1270 IN UINT8 EndPointAddress
,
1271 IN UINT8 DeviceSpeed
,
1272 IN UINTN MaximumPacketLength
,
1273 IN UINT8 DataBuffersNumber
,
1274 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1275 IN UINTN DataLength
,
1276 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1277 OUT UINT32
*TransferResult
1280 return EFI_UNSUPPORTED
;
1285 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
1287 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1288 @param DeviceAddress Target device address.
1289 @param EndPointAddress Endpoint number and direction.
1290 @param DeviceSpeed Device speed.
1291 @param MaximumPacketLength Maximum packet size of the target endpoint.
1292 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1293 @param Data Array of pointers to the buffers of data.
1294 @param DataLength On input, size of the data buffer, On output,
1295 actually transferred data size.
1296 @param Translator A pointr to the transaction translator data.
1297 @param IsochronousCallBack Function to call when the transfer complete.
1298 @param Context Pass to the call back function as parameter.
1300 @return EFI_UNSUPPORTED
1305 Uhci2AsyncIsochronousTransfer (
1306 IN EFI_USB2_HC_PROTOCOL
*This
,
1307 IN UINT8 DeviceAddress
,
1308 IN UINT8 EndPointAddress
,
1309 IN UINT8 DeviceSpeed
,
1310 IN UINTN MaximumPacketLength
,
1311 IN UINT8 DataBuffersNumber
,
1312 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1313 IN UINTN DataLength
,
1314 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1315 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1319 return EFI_UNSUPPORTED
;
1323 Entry point for EFI drivers.
1325 @param ImageHandle EFI_HANDLE.
1326 @param SystemTable EFI_SYSTEM_TABLE.
1328 @retval EFI_SUCCESS Driver is successfully loaded.
1329 @return Others Failed.
1334 UhciDriverEntryPoint (
1335 IN EFI_HANDLE ImageHandle
,
1336 IN EFI_SYSTEM_TABLE
*SystemTable
1339 return EfiLibInstallDriverBindingComponentName2 (
1342 &gUhciDriverBinding
,
1344 &gUhciComponentName
,
1345 &gUhciComponentName2
1351 Test to see if this driver supports ControllerHandle. Any
1352 ControllerHandle that has UsbHcProtocol installed will be supported.
1354 @param This Protocol instance pointer.
1355 @param Controller Handle of device to test.
1356 @param RemainingDevicePath Not used.
1358 @return EFI_SUCCESS This driver supports this device.
1359 @return EFI_UNSUPPORTED This driver does not support this device.
1364 UhciDriverBindingSupported (
1365 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1366 IN EFI_HANDLE Controller
,
1367 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1370 EFI_STATUS OpenStatus
;
1372 EFI_PCI_IO_PROTOCOL
*PciIo
;
1373 USB_CLASSC UsbClassCReg
;
1376 // Test whether there is PCI IO Protocol attached on the controller handle.
1378 OpenStatus
= gBS
->OpenProtocol (
1380 &gEfiPciIoProtocolGuid
,
1382 This
->DriverBindingHandle
,
1384 EFI_OPEN_PROTOCOL_BY_DRIVER
1387 if (EFI_ERROR (OpenStatus
)) {
1391 Status
= PciIo
->Pci
.Read (
1394 PCI_CLASSCODE_OFFSET
,
1395 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1399 if (EFI_ERROR (Status
)) {
1400 Status
= EFI_UNSUPPORTED
;
1405 // Test whether the controller belongs to UHCI type
1407 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1408 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1409 (UsbClassCReg
.ProgInterface
!= PCI_IF_UHCI
)
1412 Status
= EFI_UNSUPPORTED
;
1416 gBS
->CloseProtocol (
1418 &gEfiPciIoProtocolGuid
,
1419 This
->DriverBindingHandle
,
1429 Allocate and initialize the empty UHCI device.
1431 @param PciIo The PCIIO to use.
1432 @param DevicePath The device path of host controller.
1433 @param OriginalPciAttributes The original PCI attributes.
1435 @return Allocated UHCI device. If err, return NULL.
1440 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1441 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1442 IN UINT64 OriginalPciAttributes
1448 Uhc
= AllocateZeroPool (sizeof (USB_HC_DEV
));
1455 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
1456 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
1458 Uhc
->Signature
= USB_HC_DEV_SIGNATURE
;
1459 Uhc
->Usb2Hc
.GetCapability
= Uhci2GetCapability
;
1460 Uhc
->Usb2Hc
.Reset
= Uhci2Reset
;
1461 Uhc
->Usb2Hc
.GetState
= Uhci2GetState
;
1462 Uhc
->Usb2Hc
.SetState
= Uhci2SetState
;
1463 Uhc
->Usb2Hc
.ControlTransfer
= Uhci2ControlTransfer
;
1464 Uhc
->Usb2Hc
.BulkTransfer
= Uhci2BulkTransfer
;
1465 Uhc
->Usb2Hc
.AsyncInterruptTransfer
= Uhci2AsyncInterruptTransfer
;
1466 Uhc
->Usb2Hc
.SyncInterruptTransfer
= Uhci2SyncInterruptTransfer
;
1467 Uhc
->Usb2Hc
.IsochronousTransfer
= Uhci2IsochronousTransfer
;
1468 Uhc
->Usb2Hc
.AsyncIsochronousTransfer
= Uhci2AsyncIsochronousTransfer
;
1469 Uhc
->Usb2Hc
.GetRootHubPortStatus
= Uhci2GetRootHubPortStatus
;
1470 Uhc
->Usb2Hc
.SetRootHubPortFeature
= Uhci2SetRootHubPortFeature
;
1471 Uhc
->Usb2Hc
.ClearRootHubPortFeature
= Uhci2ClearRootHubPortFeature
;
1472 Uhc
->Usb2Hc
.MajorRevision
= 0x1;
1473 Uhc
->Usb2Hc
.MinorRevision
= 0x1;
1476 Uhc
->DevicePath
= DevicePath
;
1477 Uhc
->OriginalPciAttributes
= OriginalPciAttributes
;
1478 Uhc
->MemPool
= UsbHcInitMemPool (PciIo
, TRUE
, 0);
1480 if (Uhc
->MemPool
== NULL
) {
1481 Status
= EFI_OUT_OF_RESOURCES
;
1485 InitializeListHead (&Uhc
->AsyncIntList
);
1487 Status
= gBS
->CreateEvent (
1488 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1490 UhciMonitorAsyncReqList
,
1492 &Uhc
->AsyncIntMonitor
1495 if (EFI_ERROR (Status
)) {
1496 UsbHcFreeMemPool (Uhc
->MemPool
);
1509 Free the UHCI device and release its associated resources.
1511 @param Uhc The UHCI device to release.
1519 if (Uhc
->AsyncIntMonitor
!= NULL
) {
1520 gBS
->CloseEvent (Uhc
->AsyncIntMonitor
);
1523 if (Uhc
->ExitBootServiceEvent
!= NULL
) {
1524 gBS
->CloseEvent (Uhc
->ExitBootServiceEvent
);
1527 if (Uhc
->MemPool
!= NULL
) {
1528 UsbHcFreeMemPool (Uhc
->MemPool
);
1531 if (Uhc
->CtrlNameTable
!= NULL
) {
1532 FreeUnicodeStringTable (Uhc
->CtrlNameTable
);
1540 Uninstall all Uhci Interface.
1542 @param Controller Controller handle.
1543 @param This Protocol instance pointer.
1548 IN EFI_HANDLE Controller
,
1549 IN EFI_USB2_HC_PROTOCOL
*This
1555 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
1557 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1558 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1560 gBS
->UninstallProtocolInterface (
1562 &gEfiUsb2HcProtocolGuid
,
1566 UhciFreeAllAsyncReq (Uhc
);
1567 UhciDestoryFrameList (Uhc
);
1570 // Restore original PCI attributes
1572 Uhc
->PciIo
->Attributes (
1574 EfiPciIoAttributeOperationSet
,
1575 Uhc
->OriginalPciAttributes
,
1583 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1585 @param Event Pointer to this event
1586 @param Context Event hanlder private data
1591 UhcExitBootService (
1598 Uhc
= (USB_HC_DEV
*) Context
;
1601 // Stop the Host Controller
1603 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1606 // Reset the Host Controller
1608 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_HCRESET
);
1609 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
1613 Starting the Usb UHCI Driver.
1615 @param This Protocol instance pointer.
1616 @param Controller Handle of device to test.
1617 @param RemainingDevicePath Not used.
1619 @retval EFI_SUCCESS This driver supports this device.
1620 @retval EFI_UNSUPPORTED This driver does not support this device.
1621 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
1622 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
1627 UhciDriverBindingStart (
1628 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1629 IN EFI_HANDLE Controller
,
1630 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1634 EFI_PCI_IO_PROTOCOL
*PciIo
;
1637 UINT64 OriginalPciAttributes
;
1638 BOOLEAN PciAttributesSaved
;
1639 EFI_DEVICE_PATH_PROTOCOL
*HcDevicePath
;
1642 // Open PCIIO, then enable the EHC device and turn off emulation
1645 Status
= gBS
->OpenProtocol (
1647 &gEfiPciIoProtocolGuid
,
1649 This
->DriverBindingHandle
,
1651 EFI_OPEN_PROTOCOL_BY_DRIVER
1654 if (EFI_ERROR (Status
)) {
1659 // Open Device Path Protocol for on USB host controller
1661 HcDevicePath
= NULL
;
1662 Status
= gBS
->OpenProtocol (
1664 &gEfiDevicePathProtocolGuid
,
1665 (VOID
**) &HcDevicePath
,
1666 This
->DriverBindingHandle
,
1668 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1671 PciAttributesSaved
= FALSE
;
1673 // Save original PCI attributes
1675 Status
= PciIo
->Attributes (
1677 EfiPciIoAttributeOperationGet
,
1679 &OriginalPciAttributes
1682 if (EFI_ERROR (Status
)) {
1685 PciAttributesSaved
= TRUE
;
1688 // Robustnesss improvement such as for UoL
1689 // Default is not required.
1691 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1692 UhciTurnOffUsbEmulation (PciIo
);
1695 Status
= PciIo
->Attributes (
1697 EfiPciIoAttributeOperationSupported
,
1701 if (!EFI_ERROR (Status
)) {
1702 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1703 Status
= PciIo
->Attributes (
1705 EfiPciIoAttributeOperationEnable
,
1711 if (EFI_ERROR (Status
)) {
1715 Uhc
= UhciAllocateDev (PciIo
, HcDevicePath
, OriginalPciAttributes
);
1718 Status
= EFI_OUT_OF_RESOURCES
;
1723 // Allocate and Init Host Controller's Frame List Entry
1725 Status
= UhciInitFrameList (Uhc
);
1727 if (EFI_ERROR (Status
)) {
1728 Status
= EFI_OUT_OF_RESOURCES
;
1732 Status
= gBS
->SetTimer (
1733 Uhc
->AsyncIntMonitor
,
1735 UHC_ASYNC_POLL_INTERVAL
1738 if (EFI_ERROR (Status
)) {
1743 // Install USB2_HC_PROTOCOL
1745 Status
= gBS
->InstallMultipleProtocolInterfaces (
1747 &gEfiUsb2HcProtocolGuid
,
1752 if (EFI_ERROR (Status
)) {
1757 // Create event to stop the HC when exit boot service.
1759 Status
= gBS
->CreateEventEx (
1764 &gEfiEventExitBootServicesGuid
,
1765 &Uhc
->ExitBootServiceEvent
1767 if (EFI_ERROR (Status
)) {
1768 goto UNINSTALL_USBHC
;
1772 // Install the component name protocol
1774 Uhc
->CtrlNameTable
= NULL
;
1778 gUhciComponentName
.SupportedLanguages
,
1779 &Uhc
->CtrlNameTable
,
1780 L
"Usb Universal Host Controller",
1785 gUhciComponentName2
.SupportedLanguages
,
1786 &Uhc
->CtrlNameTable
,
1787 L
"Usb Universal Host Controller",
1793 // Start the UHCI hardware, also set its reclamation point to 64 bytes
1795 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_RS
| USBCMD_MAXP
);
1800 gBS
->UninstallMultipleProtocolInterfaces (
1802 &gEfiUsb2HcProtocolGuid
,
1811 if (PciAttributesSaved
) {
1813 // Restore original PCI attributes
1817 EfiPciIoAttributeOperationSet
,
1818 OriginalPciAttributes
,
1823 gBS
->CloseProtocol (
1825 &gEfiPciIoProtocolGuid
,
1826 This
->DriverBindingHandle
,
1835 Stop this driver on ControllerHandle. Support stoping any child handles
1836 created by this driver.
1838 @param This Protocol instance pointer.
1839 @param Controller Handle of device to stop driver on.
1840 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1841 @param ChildHandleBuffer List of handles for the children we need to stop.
1849 UhciDriverBindingStop (
1850 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1851 IN EFI_HANDLE Controller
,
1852 IN UINTN NumberOfChildren
,
1853 IN EFI_HANDLE
*ChildHandleBuffer
1856 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1859 Status
= gBS
->OpenProtocol (
1861 &gEfiUsb2HcProtocolGuid
,
1863 This
->DriverBindingHandle
,
1865 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1869 // Test whether the Controller handler passed in is a valid
1870 // Usb controller handle that should be supported, if not,
1871 // return the error status directly
1873 if (EFI_ERROR (Status
)) {
1877 UhciCleanDevUp (Controller
, Usb2Hc
);
1879 gBS
->CloseProtocol (
1881 &gEfiPciIoProtocolGuid
,
1882 This
->DriverBindingHandle
,