3 The UHCI driver model and HC protocol routines.
5 Copyright (c) 2004 - 2015, 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 according 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 ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1161 return EFI_INVALID_PARAMETER
;
1164 if ((*DataLength
== 0) || (MaximumPacketLength
> 64)) {
1165 return EFI_INVALID_PARAMETER
;
1168 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
1169 return EFI_INVALID_PARAMETER
;
1172 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1173 Status
= EFI_DEVICE_ERROR
;
1176 UhciAckAllInterrupt (Uhc
);
1178 if (!UhciIsHcWorking (Uhc
->PciIo
)) {
1182 OldTpl
= gBS
->RaiseTPL (UHCI_TPL
);
1185 // Map the source data buffer for bus master access.
1186 // Create Tds list, then link it to the UHC's interrupt list
1188 Status
= UhciMapUserData (
1198 if (EFI_ERROR (Status
)) {
1202 TDs
= UhciCreateBulkOrIntTds (
1211 (UINT8
) MaximumPacketLength
,
1216 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1218 Status
= EFI_OUT_OF_RESOURCES
;
1223 UhciLinkTdToQh (Uhc
, Uhc
->SyncIntQh
, TDs
);
1225 Status
= UhciExecuteTransfer (Uhc
, Uhc
->SyncIntQh
, TDs
, TimeOut
, IsSlowDevice
, &QhResult
);
1227 UhciUnlinkTdFromQh (Uhc
->SyncIntQh
, TDs
);
1228 Uhc
->PciIo
->Flush (Uhc
->PciIo
);
1230 *TransferResult
= QhResult
.Result
;
1231 *DataToggle
= QhResult
.NextToggle
;
1232 *DataLength
= QhResult
.Complete
;
1234 UhciDestoryTds (Uhc
, TDs
);
1235 Uhc
->PciIo
->Unmap (Uhc
->PciIo
, DataMap
);
1238 gBS
->RestoreTPL (OldTpl
);
1244 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
1246 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1247 @param DeviceAddress Target device address.
1248 @param EndPointAddress Endpoint number and direction.
1249 @param DeviceSpeed Device speed.
1250 @param MaximumPacketLength Maximum packet size of the target endpoint.
1251 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1252 @param Data Array of pointers to the buffers of data.
1253 @param DataLength On input, size of the data buffer, On output,
1254 actually transferred data size.
1255 @param Translator A pointr to the transaction translator data.
1256 @param TransferResult Variable to receive transfer result.
1258 @return EFI_UNSUPPORTED
1263 Uhci2IsochronousTransfer (
1264 IN EFI_USB2_HC_PROTOCOL
*This
,
1265 IN UINT8 DeviceAddress
,
1266 IN UINT8 EndPointAddress
,
1267 IN UINT8 DeviceSpeed
,
1268 IN UINTN MaximumPacketLength
,
1269 IN UINT8 DataBuffersNumber
,
1270 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1271 IN UINTN DataLength
,
1272 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1273 OUT UINT32
*TransferResult
1276 return EFI_UNSUPPORTED
;
1281 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
1283 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
1284 @param DeviceAddress Target device address.
1285 @param EndPointAddress Endpoint number and direction.
1286 @param DeviceSpeed Device speed.
1287 @param MaximumPacketLength Maximum packet size of the target endpoint.
1288 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1289 @param Data Array of pointers to the buffers of data.
1290 @param DataLength On input, size of the data buffer, On output,
1291 actually transferred data size.
1292 @param Translator A pointr to the transaction translator data.
1293 @param IsochronousCallBack Function to call when the transfer complete.
1294 @param Context Pass to the call back function as parameter.
1296 @return EFI_UNSUPPORTED
1301 Uhci2AsyncIsochronousTransfer (
1302 IN EFI_USB2_HC_PROTOCOL
*This
,
1303 IN UINT8 DeviceAddress
,
1304 IN UINT8 EndPointAddress
,
1305 IN UINT8 DeviceSpeed
,
1306 IN UINTN MaximumPacketLength
,
1307 IN UINT8 DataBuffersNumber
,
1308 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1309 IN UINTN DataLength
,
1310 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1311 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1315 return EFI_UNSUPPORTED
;
1319 Entry point for EFI drivers.
1321 @param ImageHandle EFI_HANDLE.
1322 @param SystemTable EFI_SYSTEM_TABLE.
1324 @retval EFI_SUCCESS Driver is successfully loaded.
1325 @return Others Failed.
1330 UhciDriverEntryPoint (
1331 IN EFI_HANDLE ImageHandle
,
1332 IN EFI_SYSTEM_TABLE
*SystemTable
1335 return EfiLibInstallDriverBindingComponentName2 (
1338 &gUhciDriverBinding
,
1340 &gUhciComponentName
,
1341 &gUhciComponentName2
1347 Test to see if this driver supports ControllerHandle. Any
1348 ControllerHandle that has UsbHcProtocol installed will be supported.
1350 @param This Protocol instance pointer.
1351 @param Controller Handle of device to test.
1352 @param RemainingDevicePath Not used.
1354 @return EFI_SUCCESS This driver supports this device.
1355 @return EFI_UNSUPPORTED This driver does not support this device.
1360 UhciDriverBindingSupported (
1361 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1362 IN EFI_HANDLE Controller
,
1363 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1366 EFI_STATUS OpenStatus
;
1368 EFI_PCI_IO_PROTOCOL
*PciIo
;
1369 USB_CLASSC UsbClassCReg
;
1372 // Test whether there is PCI IO Protocol attached on the controller handle.
1374 OpenStatus
= gBS
->OpenProtocol (
1376 &gEfiPciIoProtocolGuid
,
1378 This
->DriverBindingHandle
,
1380 EFI_OPEN_PROTOCOL_BY_DRIVER
1383 if (EFI_ERROR (OpenStatus
)) {
1387 Status
= PciIo
->Pci
.Read (
1390 PCI_CLASSCODE_OFFSET
,
1391 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1395 if (EFI_ERROR (Status
)) {
1396 Status
= EFI_UNSUPPORTED
;
1401 // Test whether the controller belongs to UHCI type
1403 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1404 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1405 (UsbClassCReg
.ProgInterface
!= PCI_IF_UHCI
)
1408 Status
= EFI_UNSUPPORTED
;
1412 gBS
->CloseProtocol (
1414 &gEfiPciIoProtocolGuid
,
1415 This
->DriverBindingHandle
,
1425 Allocate and initialize the empty UHCI device.
1427 @param PciIo The PCIIO to use.
1428 @param DevicePath The device path of host controller.
1429 @param OriginalPciAttributes The original PCI attributes.
1431 @return Allocated UHCI device. If err, return NULL.
1436 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1437 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1438 IN UINT64 OriginalPciAttributes
1444 Uhc
= AllocateZeroPool (sizeof (USB_HC_DEV
));
1451 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
1452 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
1454 Uhc
->Signature
= USB_HC_DEV_SIGNATURE
;
1455 Uhc
->Usb2Hc
.GetCapability
= Uhci2GetCapability
;
1456 Uhc
->Usb2Hc
.Reset
= Uhci2Reset
;
1457 Uhc
->Usb2Hc
.GetState
= Uhci2GetState
;
1458 Uhc
->Usb2Hc
.SetState
= Uhci2SetState
;
1459 Uhc
->Usb2Hc
.ControlTransfer
= Uhci2ControlTransfer
;
1460 Uhc
->Usb2Hc
.BulkTransfer
= Uhci2BulkTransfer
;
1461 Uhc
->Usb2Hc
.AsyncInterruptTransfer
= Uhci2AsyncInterruptTransfer
;
1462 Uhc
->Usb2Hc
.SyncInterruptTransfer
= Uhci2SyncInterruptTransfer
;
1463 Uhc
->Usb2Hc
.IsochronousTransfer
= Uhci2IsochronousTransfer
;
1464 Uhc
->Usb2Hc
.AsyncIsochronousTransfer
= Uhci2AsyncIsochronousTransfer
;
1465 Uhc
->Usb2Hc
.GetRootHubPortStatus
= Uhci2GetRootHubPortStatus
;
1466 Uhc
->Usb2Hc
.SetRootHubPortFeature
= Uhci2SetRootHubPortFeature
;
1467 Uhc
->Usb2Hc
.ClearRootHubPortFeature
= Uhci2ClearRootHubPortFeature
;
1468 Uhc
->Usb2Hc
.MajorRevision
= 0x1;
1469 Uhc
->Usb2Hc
.MinorRevision
= 0x1;
1472 Uhc
->DevicePath
= DevicePath
;
1473 Uhc
->OriginalPciAttributes
= OriginalPciAttributes
;
1474 Uhc
->MemPool
= UsbHcInitMemPool (PciIo
, TRUE
, 0);
1476 if (Uhc
->MemPool
== NULL
) {
1477 Status
= EFI_OUT_OF_RESOURCES
;
1481 InitializeListHead (&Uhc
->AsyncIntList
);
1483 Status
= gBS
->CreateEvent (
1484 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1486 UhciMonitorAsyncReqList
,
1488 &Uhc
->AsyncIntMonitor
1491 if (EFI_ERROR (Status
)) {
1492 UsbHcFreeMemPool (Uhc
->MemPool
);
1505 Free the UHCI device and release its associated resources.
1507 @param Uhc The UHCI device to release.
1515 if (Uhc
->AsyncIntMonitor
!= NULL
) {
1516 gBS
->CloseEvent (Uhc
->AsyncIntMonitor
);
1519 if (Uhc
->ExitBootServiceEvent
!= NULL
) {
1520 gBS
->CloseEvent (Uhc
->ExitBootServiceEvent
);
1523 if (Uhc
->MemPool
!= NULL
) {
1524 UsbHcFreeMemPool (Uhc
->MemPool
);
1527 if (Uhc
->CtrlNameTable
!= NULL
) {
1528 FreeUnicodeStringTable (Uhc
->CtrlNameTable
);
1536 Uninstall all Uhci Interface.
1538 @param Controller Controller handle.
1539 @param This Protocol instance pointer.
1544 IN EFI_HANDLE Controller
,
1545 IN EFI_USB2_HC_PROTOCOL
*This
1552 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
1554 Uhc
= UHC_FROM_USB2_HC_PROTO (This
);
1557 Status
= gBS
->UninstallProtocolInterface (
1559 &gEfiUsb2HcProtocolGuid
,
1562 if (EFI_ERROR (Status
)) {
1566 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1567 UhciFreeAllAsyncReq (Uhc
);
1568 UhciDestoryFrameList (Uhc
);
1571 // Restore original PCI attributes
1573 Uhc
->PciIo
->Attributes (
1575 EfiPciIoAttributeOperationSet
,
1576 Uhc
->OriginalPciAttributes
,
1584 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1586 @param Event Pointer to this event
1587 @param Context Event handler private data
1592 UhcExitBootService (
1599 Uhc
= (USB_HC_DEV
*) Context
;
1602 // Stop the Host Controller
1604 UhciStopHc (Uhc
, UHC_GENERIC_TIMEOUT
);
1607 // Reset the Host Controller
1609 UhciSetRegBit (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_HCRESET
);
1610 gBS
->Stall (UHC_ROOT_PORT_RECOVERY_STALL
);
1614 Starting the Usb UHCI Driver.
1616 @param This Protocol instance pointer.
1617 @param Controller Handle of device to test.
1618 @param RemainingDevicePath Not used.
1620 @retval EFI_SUCCESS This driver supports this device.
1621 @retval EFI_UNSUPPORTED This driver does not support this device.
1622 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
1623 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
1628 UhciDriverBindingStart (
1629 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1630 IN EFI_HANDLE Controller
,
1631 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1635 EFI_PCI_IO_PROTOCOL
*PciIo
;
1638 UINT64 OriginalPciAttributes
;
1639 BOOLEAN PciAttributesSaved
;
1640 EFI_DEVICE_PATH_PROTOCOL
*HcDevicePath
;
1643 // Open PCIIO, then enable the EHC device and turn off emulation
1646 Status
= gBS
->OpenProtocol (
1648 &gEfiPciIoProtocolGuid
,
1650 This
->DriverBindingHandle
,
1652 EFI_OPEN_PROTOCOL_BY_DRIVER
1655 if (EFI_ERROR (Status
)) {
1660 // Open Device Path Protocol for on USB host controller
1662 HcDevicePath
= NULL
;
1663 Status
= gBS
->OpenProtocol (
1665 &gEfiDevicePathProtocolGuid
,
1666 (VOID
**) &HcDevicePath
,
1667 This
->DriverBindingHandle
,
1669 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1672 PciAttributesSaved
= FALSE
;
1674 // Save original PCI attributes
1676 Status
= PciIo
->Attributes (
1678 EfiPciIoAttributeOperationGet
,
1680 &OriginalPciAttributes
1683 if (EFI_ERROR (Status
)) {
1686 PciAttributesSaved
= TRUE
;
1689 // Robustnesss improvement such as for UoL
1690 // Default is not required.
1692 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1693 UhciTurnOffUsbEmulation (PciIo
);
1696 Status
= PciIo
->Attributes (
1698 EfiPciIoAttributeOperationSupported
,
1702 if (!EFI_ERROR (Status
)) {
1703 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
1704 Status
= PciIo
->Attributes (
1706 EfiPciIoAttributeOperationEnable
,
1712 if (EFI_ERROR (Status
)) {
1716 Uhc
= UhciAllocateDev (PciIo
, HcDevicePath
, OriginalPciAttributes
);
1719 Status
= EFI_OUT_OF_RESOURCES
;
1724 // Allocate and Init Host Controller's Frame List Entry
1726 Status
= UhciInitFrameList (Uhc
);
1728 if (EFI_ERROR (Status
)) {
1729 Status
= EFI_OUT_OF_RESOURCES
;
1733 Status
= gBS
->SetTimer (
1734 Uhc
->AsyncIntMonitor
,
1736 UHC_ASYNC_POLL_INTERVAL
1739 if (EFI_ERROR (Status
)) {
1744 // Install USB2_HC_PROTOCOL
1746 Status
= gBS
->InstallMultipleProtocolInterfaces (
1748 &gEfiUsb2HcProtocolGuid
,
1753 if (EFI_ERROR (Status
)) {
1758 // Create event to stop the HC when exit boot service.
1760 Status
= gBS
->CreateEventEx (
1765 &gEfiEventExitBootServicesGuid
,
1766 &Uhc
->ExitBootServiceEvent
1768 if (EFI_ERROR (Status
)) {
1769 goto UNINSTALL_USBHC
;
1773 // Install the component name protocol
1775 Uhc
->CtrlNameTable
= NULL
;
1779 gUhciComponentName
.SupportedLanguages
,
1780 &Uhc
->CtrlNameTable
,
1781 L
"Usb Universal Host Controller",
1786 gUhciComponentName2
.SupportedLanguages
,
1787 &Uhc
->CtrlNameTable
,
1788 L
"Usb Universal Host Controller",
1794 // Start the UHCI hardware, also set its reclamation point to 64 bytes
1796 UhciWriteReg (Uhc
->PciIo
, USBCMD_OFFSET
, USBCMD_RS
| USBCMD_MAXP
);
1801 gBS
->UninstallMultipleProtocolInterfaces (
1803 &gEfiUsb2HcProtocolGuid
,
1812 if (PciAttributesSaved
) {
1814 // Restore original PCI attributes
1818 EfiPciIoAttributeOperationSet
,
1819 OriginalPciAttributes
,
1824 gBS
->CloseProtocol (
1826 &gEfiPciIoProtocolGuid
,
1827 This
->DriverBindingHandle
,
1836 Stop this driver on ControllerHandle. Support stopping any child handles
1837 created by this driver.
1839 @param This Protocol instance pointer.
1840 @param Controller Handle of device to stop driver on.
1841 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1842 @param ChildHandleBuffer List of handles for the children we need to stop.
1850 UhciDriverBindingStop (
1851 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1852 IN EFI_HANDLE Controller
,
1853 IN UINTN NumberOfChildren
,
1854 IN EFI_HANDLE
*ChildHandleBuffer
1857 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1860 Status
= gBS
->OpenProtocol (
1862 &gEfiUsb2HcProtocolGuid
,
1864 This
->DriverBindingHandle
,
1866 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1870 // Test whether the Controller handler passed in is a valid
1871 // Usb controller handle that should be supported, if not,
1872 // return the error status directly
1874 if (EFI_ERROR (Status
)) {
1878 UhciCleanDevUp (Controller
, Usb2Hc
);
1880 gBS
->CloseProtocol (
1882 &gEfiPciIoProtocolGuid
,
1883 This
->DriverBindingHandle
,