3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 GLOBAL_REMOVE_IF_UNREFERENCED UINTN gEHCDebugLevel
= EFI_D_ERROR
;
27 GLOBAL_REMOVE_IF_UNREFERENCED UINTN gEHCErrorLevel
= EFI_D_ERROR
;
31 // Ehci Driver Global Variables
33 EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding
= {
34 EhciDriverBindingSupported
,
35 EhciDriverBindingStart
,
36 EhciDriverBindingStop
,
45 EhciDriverBindingSupported (
46 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
47 IN EFI_HANDLE Controller
,
48 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
54 Test to see if this driver supports ControllerHandle. Any ControllerHandle
55 that has Usb2HcProtocol installed will be supported.
59 This - Protocol instance pointer.
60 Controlle - Handle of device to test
61 RemainingDevicePath - Not used
65 EFI_SUCCESS This driver supports this device.
66 EFI_UNSUPPORTED This driver does not support this device.
71 EFI_PCI_IO_PROTOCOL
*PciIo
;
72 USB_CLASSC UsbClassCReg
;
76 // Test whether there is PCI IO Protocol attached on the controller handle.
78 Status
= gBS
->OpenProtocol (
80 &gEfiPciIoProtocolGuid
,
82 This
->DriverBindingHandle
,
84 EFI_OPEN_PROTOCOL_BY_DRIVER
86 if (EFI_ERROR (Status
)) {
90 Status
= PciIo
->Pci
.Read (
94 sizeof (USB_CLASSC
) / sizeof (UINT8
),
97 if (EFI_ERROR (Status
)) {
100 &gEfiPciIoProtocolGuid
,
101 This
->DriverBindingHandle
,
104 Status
= EFI_UNSUPPORTED
;
109 // Test whether the controller belongs to Ehci type
111 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
112 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
113 (UsbClassCReg
.PI
!= PCI_CLASSC_PI_EHCI
)
118 &gEfiPciIoProtocolGuid
,
119 This
->DriverBindingHandle
,
123 Status
= EFI_UNSUPPORTED
;
129 &gEfiPciIoProtocolGuid
,
130 This
->DriverBindingHandle
,
140 EhciDriverBindingStart (
141 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
142 IN EFI_HANDLE Controller
,
143 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
149 Starting the Usb EHCI Driver
153 This - Protocol instance pointer.
154 Controller - Handle of device to test
155 RemainingDevicePath - Not used
159 EFI_SUCCESS supports this device.
160 EFI_UNSUPPORTED do not support this device.
161 EFI_DEVICE_ERROR cannot be started due to device Error
162 EFI_OUT_OF_RESOURCES cannot allocate resources
168 EFI_PCI_IO_PROTOCOL
*PciIo
;
171 UINT8 Is64BitCapable
;
175 // Open the PciIo Protocol
177 Status
= gBS
->OpenProtocol (
179 &gEfiPciIoProtocolGuid
,
181 This
->DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (EFI_ERROR (Status
)) {
186 Status
= EFI_OUT_OF_RESOURCES
;
191 // Enable the USB Host Controller
193 Status
= PciIo
->Attributes (
195 EfiPciIoAttributeOperationSupported
,
199 if (!EFI_ERROR (Status
)) {
200 Supports
&= EFI_PCI_DEVICE_ENABLE
;
201 Status
= PciIo
->Attributes (
203 EfiPciIoAttributeOperationEnable
,
208 if (EFI_ERROR (Status
)) {
209 Status
= EFI_OUT_OF_RESOURCES
;
210 goto close_pciio_protocol
;
214 // Allocate memory for EHC private data structure
216 HcDev
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
218 Status
= EFI_OUT_OF_RESOURCES
;
219 goto close_pciio_protocol
;
223 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
225 HcDev
->Usb2Hc
.GetCapability
= EhciGetCapability
;
226 HcDev
->Usb2Hc
.Reset
= EhciReset
;
227 HcDev
->Usb2Hc
.GetState
= EhciGetState
;
228 HcDev
->Usb2Hc
.SetState
= EhciSetState
;
229 HcDev
->Usb2Hc
.ControlTransfer
= EhciControlTransfer
;
230 HcDev
->Usb2Hc
.BulkTransfer
= EhciBulkTransfer
;
231 HcDev
->Usb2Hc
.AsyncInterruptTransfer
= EhciAsyncInterruptTransfer
;
232 HcDev
->Usb2Hc
.SyncInterruptTransfer
= EhciSyncInterruptTransfer
;
233 HcDev
->Usb2Hc
.IsochronousTransfer
= EhciIsochronousTransfer
;
234 HcDev
->Usb2Hc
.AsyncIsochronousTransfer
= EhciAsyncIsochronousTransfer
;
235 HcDev
->Usb2Hc
.GetRootHubPortStatus
= EhciGetRootHubPortStatus
;
236 HcDev
->Usb2Hc
.SetRootHubPortFeature
= EhciSetRootHubPortFeature
;
237 HcDev
->Usb2Hc
.ClearRootHubPortFeature
= EhciClearRootHubPortFeature
;
238 HcDev
->Usb2Hc
.MajorRevision
= 0x1;
239 HcDev
->Usb2Hc
.MinorRevision
= 0x1;
241 HcDev
->AsyncRequestList
= NULL
;
242 HcDev
->ControllerNameTable
= NULL
;
243 HcDev
->Signature
= USB2_HC_DEV_SIGNATURE
;
244 HcDev
->PciIo
= PciIo
;
247 // Install USB2_HC_PROTOCOL
249 Status
= gBS
->InstallProtocolInterface (
251 &gEfiUsb2HcProtocolGuid
,
252 EFI_NATIVE_INTERFACE
,
255 if (EFI_ERROR (Status
)) {
256 Status
= EFI_OUT_OF_RESOURCES
;
261 // Get Capability Register Length
263 Status
= GetCapabilityLen (HcDev
);
264 if (EFI_ERROR (Status
)) {
265 Status
= EFI_DEVICE_ERROR
;
266 goto uninstall_usb2hc_protocol
;
269 ClearLegacySupport (HcDev
);
273 DumpEHCIPortsStatus (HcDev
);
277 // Create and Init Perodic Frame List
279 Status
= EhciGetCapability (
285 if (EFI_ERROR (Status
)) {
286 Status
= EFI_OUT_OF_RESOURCES
;
287 goto uninstall_usb2hc_protocol
;
289 HcDev
->Is64BitCapable
= Is64BitCapable
;
292 // Create and Init Perodic Frame List
294 Status
= InitialPeriodicFrameList (
296 EHCI_MAX_FRAME_LIST_LENGTH
298 if (EFI_ERROR (Status
)) {
299 Status
= EFI_OUT_OF_RESOURCES
;
300 goto uninstall_usb2hc_protocol
;
304 // Init memory pool management
306 Status
= InitialMemoryManagement (HcDev
);
307 if (EFI_ERROR (Status
)) {
308 Status
= EFI_OUT_OF_RESOURCES
;
309 goto deinit_perodic_frame_list
;
312 Status
= CreateNULLQH (HcDev
);
313 if (EFI_ERROR (Status
)) {
314 Status
= EFI_OUT_OF_RESOURCES
;
315 goto deinit_perodic_frame_list
;
318 // Create AsyncRequest Polling Timer
320 Status
= CreatePollingTimer (HcDev
, (EFI_EVENT_NOTIFY
) AsyncRequestMoniter
);
321 if (EFI_ERROR (Status
)) {
322 Status
= EFI_OUT_OF_RESOURCES
;
327 // Default Maxximum Interrupt Interval is 8,
328 // it means that 8 micro frame = 1ms
332 // Start the Host Controller
334 if (IsEhcHalted (HcDev
)) {
335 Status
= StartScheduleExecution (HcDev
);
336 if (EFI_ERROR (Status
)) {
337 Status
= EFI_DEVICE_ERROR
;
343 // Set all ports routing to EHC
345 Status
= SetPortRoutingEhc (HcDev
);
346 if (EFI_ERROR (Status
)) {
347 Status
= EFI_DEVICE_ERROR
;
352 // Component name protocol
354 Status
= AddUnicodeString (
356 gEhciComponentName
.SupportedLanguages
,
357 &HcDev
->ControllerNameTable
,
358 L
"Usb Enhanced Host Controller"
360 if (EFI_ERROR (Status
)) {
361 Status
= EFI_OUT_OF_RESOURCES
;
368 // Error handle process
371 DestoryPollingTimer (HcDev
);
373 DestroyNULLQH(HcDev
);
374 DeinitialMemoryManagement (HcDev
);
375 deinit_perodic_frame_list
:
376 DeinitialPeriodicFrameList (HcDev
);
377 uninstall_usb2hc_protocol
:
378 gBS
->UninstallProtocolInterface (
380 &gEfiUsb2HcProtocolGuid
,
384 gBS
->FreePool (HcDev
);
385 close_pciio_protocol
:
388 &gEfiPciIoProtocolGuid
,
389 This
->DriverBindingHandle
,
399 EhciDriverBindingStop (
400 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
401 IN EFI_HANDLE Controller
,
402 IN UINTN NumberOfChildren
,
403 IN EFI_HANDLE
*ChildHandleBuffer
409 Stop this driver on ControllerHandle. Support stoping any child handles
410 created by this driver.
414 This - Protocol instance pointer.
415 Controller - Handle of device to stop driver on
416 NumberOfChildren - Number of Children in the ChildHandleBuffer
417 ChildHandleBuffer - List of handles for the children we need to stop.
422 EFI_DEVICE_ERROR Fail
426 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
431 // Test whether the Controller handler passed in is a valid
432 // Usb controller handle that should be supported, if not,
433 // return the error status directly
435 Status
= gBS
->OpenProtocol (
437 &gEfiUsb2HcProtocolGuid
,
439 This
->DriverBindingHandle
,
441 EFI_OPEN_PROTOCOL_GET_PROTOCOL
443 if (EFI_ERROR (Status
)) {
444 Status
= EFI_DEVICE_ERROR
;
448 HcDev
= USB2_HC_DEV_FROM_THIS (Usb2Hc
);
451 // free all the controller related memory and uninstall UHCI Protocol.
453 Status
= gBS
->UninstallProtocolInterface (
455 &gEfiUsb2HcProtocolGuid
,
458 if (EFI_ERROR (Status
)) {
459 Status
= EFI_DEVICE_ERROR
;
464 // Set Host Controller state as halt
466 Status
= Usb2Hc
->SetState (
470 if (EFI_ERROR (Status
)) {
471 Status
= EFI_DEVICE_ERROR
;
476 // Stop AsyncRequest Polling Timer
478 Status
= StopPollingTimer (HcDev
);
479 if (EFI_ERROR (Status
)) {
480 Status
= EFI_DEVICE_ERROR
;
485 // Destroy Asynchronous Request Event
487 DestoryPollingTimer (HcDev
);
490 // Destroy Perodic Frame List
492 DeinitialPeriodicFrameList (HcDev
);
497 DestroyNULLQH (HcDev
);
500 // Deinit Ehci pool memory management
502 DeinitialMemoryManagement (HcDev
);
505 // Denint Unicode String Table
507 FreeUnicodeStringTable (HcDev
->ControllerNameTable
);
510 // Disable the USB Host Controller
512 Status
= HcDev
->PciIo
->Attributes (
514 EfiPciIoAttributeOperationSupported
,
518 if (!EFI_ERROR (Status
)) {
519 Supports
&= EFI_PCI_DEVICE_ENABLE
;
520 Status
= HcDev
->PciIo
->Attributes (
522 EfiPciIoAttributeOperationDisable
,
527 if (EFI_ERROR (Status
)) {
528 Status
= EFI_DEVICE_ERROR
;
532 gBS
->FreePool (HcDev
);
536 &gEfiPciIoProtocolGuid
,
537 This
->DriverBindingHandle
,
548 IN EFI_USB2_HC_PROTOCOL
*This
,
550 OUT UINT8
*PortNumber
,
551 OUT UINT8
*Is64BitCapable
557 Retrieves the capablility of root hub ports.
561 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
562 MaxSpeed - A pointer to the number of the host controller.
563 PortNumber - A pointer to the number of the root hub ports.
564 Is64BitCapable - A pointer to the flag for whether controller supports
565 64-bit memory addressing.
569 EFI_SUCCESS host controller capability were retrieved successfully.
570 EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.
571 EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the capabilities.
577 UINT32 HcStructParamsAddr
;
578 UINT32 HcStructParamsReg
;
579 UINT32 HcCapParamsAddr
;
580 UINT32 HcCapParamsReg
;
582 if (MaxSpeed
== NULL
|| PortNumber
== NULL
|| Is64BitCapable
== NULL
) {
583 Status
= EFI_INVALID_PARAMETER
;
587 HcStructParamsAddr
= HCSPARAMS
;
588 HcCapParamsAddr
= HCCPARAMS
;
589 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
591 Status
= ReadEhcCapabiltiyReg (
596 if (EFI_ERROR (Status
)) {
597 Status
= EFI_DEVICE_ERROR
;
601 Status
= ReadEhcCapabiltiyReg (
606 if (EFI_ERROR (Status
)) {
607 Status
= EFI_DEVICE_ERROR
;
611 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
612 *PortNumber
= (UINT8
) (HcStructParamsReg
& HCSP_NPORTS
);
613 *Is64BitCapable
= (UINT8
) (HcCapParamsReg
& HCCP_64BIT
);
622 IN EFI_USB2_HC_PROTOCOL
*This
,
629 Provides software reset for the USB host controller.
633 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
634 Attributes - A bit mask of the reset operation to perform.
635 See below for a list of the supported bit mask values.
637 #define EFI_USB_HC_RESET_GLOBAL 0x0001
638 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
639 #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004
640 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
642 EFI_USB_HC_RESET_GLOBAL
643 If this bit is set, a global reset signal will be sent to the USB bus.
644 This resets all of the USB bus logic, including the USB host
645 controller hardware and all the devices attached on the USB bus.
646 EFI_USB_HC_RESET_HOST_CONTROLLER
647 If this bit is set, the USB host controller hardware will be reset.
648 No reset signal will be sent to the USB bus.
649 EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
650 If this bit is set, a global reset signal will be sent to the USB bus.
651 This resets all of the USB bus logic, including the USB host
652 controller hardware and all the devices attached on the USB bus.
653 If this is an EHCI controller and the debug port has configured, then
654 this is will still reset the host controller.
655 EFI_USB_HC_RESET_HOST_WITH_DEBUG
656 If this bit is set, the USB host controller hardware will be reset.
657 If this is an EHCI controller and the debug port has been configured,
658 then this will still reset the host controller.
663 The reset operation succeeded.
664 EFI_INVALID_PARAMETER
665 Attributes is not valid.
667 The type of reset specified by Attributes is not currently supported by
668 the host controller hardware.
670 Reset operation is rejected due to the debug port being configured and
671 active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or
672 EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
673 perform reset operation for this host controller.
675 An error was encountered while attempting to perform
683 FRAME_LIST_ENTRY
*FrameEntryPtr
;
685 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
687 switch (Attributes
) {
689 case EFI_USB_HC_RESET_GLOBAL
:
692 // Same behavior as Host Controller Reset
695 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
698 // Host Controller must be Halt when Reset it
700 if (IsEhcHalted (HcDev
)) {
701 Status
= ResetEhc (HcDev
);
702 if (EFI_ERROR (Status
)) {
703 Status
= EFI_DEVICE_ERROR
;
707 // Set to zero by Host Controller when reset process completes
709 Status
= WaitForEhcReset (HcDev
, EHCI_GENERIC_TIMEOUT
);
710 if (EFI_ERROR (Status
)) {
711 Status
= EFI_TIMEOUT
;
715 Status
= EFI_DEVICE_ERROR
;
720 // only asynchronous interrupt transfers are always alive on the bus, need to cleanup
722 CleanUpAllAsyncRequestTransfer (HcDev
);
723 Status
= ClearEhcAllStatus (HcDev
);
724 if (EFI_ERROR (Status
)) {
725 Status
= EFI_DEVICE_ERROR
;
730 // Set appropriate 4G Segment Selector
732 Status
= SetCtrlDataStructSeg (HcDev
);
733 if (EFI_ERROR (Status
)) {
734 Status
= EFI_DEVICE_ERROR
;
739 // Init Perodic List Base Addr and Frame List
741 Status
= SetFrameListBaseAddr (
743 (UINT32
)GET_0B_TO_31B (HcDev
->PeriodicFrameListBuffer
)
745 if (EFI_ERROR (Status
)) {
746 Status
= EFI_DEVICE_ERROR
;
749 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
750 for (FrameIndex
= 0; FrameIndex
< HcDev
->PeriodicFrameListLength
; FrameIndex
++) {
751 FrameEntryPtr
->LinkTerminate
= TRUE
;
756 // Start the Host Controller
758 if (IsEhcHalted (HcDev
)) {
759 Status
= StartScheduleExecution (HcDev
);
760 if (EFI_ERROR (Status
)) {
761 Status
= EFI_DEVICE_ERROR
;
767 // Set all ports routing to EHC
769 Status
= SetPortRoutingEhc (HcDev
);
770 if (EFI_ERROR (Status
)) {
771 Status
= EFI_DEVICE_ERROR
;
776 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
:
778 Status
= EFI_UNSUPPORTED
;
781 case EFI_USB_HC_RESET_HOST_WITH_DEBUG
:
783 Status
= EFI_UNSUPPORTED
;
787 Status
= EFI_INVALID_PARAMETER
;
797 IN EFI_USB2_HC_PROTOCOL
*This
,
798 OUT EFI_USB_HC_STATE
*State
804 Retrieves current state of the USB host controller.
808 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
809 State A pointer to the EFI_USB_HC_STATE data structure that
810 indicates current state of the USB host controller.
811 Type EFI_USB_HC_STATE is defined below.
815 EfiUsbHcStateOperational,
816 EfiUsbHcStateSuspend,
823 The state information of the host controller was returned in State.
824 EFI_INVALID_PARAMETER
827 An error was encountered while attempting to retrieve the
828 host controller's current state.
833 UINT32 UsbStatusAddr
;
837 Status
= EFI_INVALID_PARAMETER
;
841 UsbStatusAddr
= USBSTS
;
842 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
844 Status
= ReadEhcOperationalReg (
849 if (EFI_ERROR (Status
)) {
850 Status
= EFI_DEVICE_ERROR
;
854 if (UsbStatusReg
& USBSTS_HCH
) {
855 *State
= EfiUsbHcStateHalt
;
857 *State
= EfiUsbHcStateOperational
;
867 IN EFI_USB2_HC_PROTOCOL
*This
,
868 IN EFI_USB_HC_STATE State
874 Sets the USB host controller to a specific state.
878 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
879 State - Indicates the state of the host controller that will be set.
884 The USB host controller was successfully placed in the state
886 EFI_INVALID_PARAMETER
889 Failed to set the state specified by State due to device error.
895 UINT32 UsbCommandAddr
;
896 UINT32 UsbCommandReg
;
897 EFI_USB_HC_STATE CurrentState
;
899 UsbCommandAddr
= USBCMD
;
900 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
902 Status
= EhciGetState (This
, &CurrentState
);
903 if (EFI_ERROR (Status
)) {
904 Status
= EFI_DEVICE_ERROR
;
910 case EfiUsbHcStateHalt
:
912 if (EfiUsbHcStateHalt
== CurrentState
) {
913 Status
= EFI_SUCCESS
;
915 } else if (EfiUsbHcStateOperational
== CurrentState
) {
916 Status
= ReadEhcOperationalReg (
921 if (EFI_ERROR (Status
)) {
922 Status
= EFI_DEVICE_ERROR
;
926 UsbCommandReg
&= ~USBCMD_RS
;
927 Status
= WriteEhcOperationalReg (
932 if (EFI_ERROR (Status
)) {
933 Status
= EFI_DEVICE_ERROR
;
937 // Ensure the HC is in halt status after send the stop command
939 Status
= WaitForEhcHalt (HcDev
, EHCI_GENERIC_TIMEOUT
);
940 if (EFI_ERROR (Status
)) {
941 Status
= EFI_TIMEOUT
;
947 case EfiUsbHcStateOperational
:
949 if (IsEhcSysError (HcDev
)) {
950 Status
= EFI_DEVICE_ERROR
;
953 if (EfiUsbHcStateOperational
== CurrentState
) {
954 Status
= EFI_SUCCESS
;
956 } else if (EfiUsbHcStateHalt
== CurrentState
) {
958 // Set Host Controller Run
960 Status
= ReadEhcOperationalReg (
965 if (EFI_ERROR (Status
)) {
966 return EFI_DEVICE_ERROR
;
969 UsbCommandReg
|= USBCMD_RS
;
970 Status
= WriteEhcOperationalReg (
975 if (EFI_ERROR (Status
)) {
976 Status
= EFI_DEVICE_ERROR
;
982 case EfiUsbHcStateSuspend
:
984 Status
= EFI_UNSUPPORTED
;
989 Status
= EFI_INVALID_PARAMETER
;
998 EhciGetRootHubPortStatus (
999 IN EFI_USB2_HC_PROTOCOL
*This
,
1000 IN UINT8 PortNumber
,
1001 OUT EFI_USB_PORT_STATUS
*PortStatus
1005 Routine Description:
1007 Retrieves the current status of a USB root hub port.
1011 This - A pointer to the EFI_USB2_HC_PROTOCOL.
1012 PortNumber - Specifies the root hub port from which the status
1013 is to be retrieved. This value is zero-based. For example,
1014 if a root hub has two ports, then the first port is numbered 0,
1015 and the second port is numbered 1.
1016 PortStatus - A pointer to the current port status bits and
1017 port status change bits.
1021 EFI_SUCCESS The status of the USB root hub port specified
1022 by PortNumber was returned in PortStatus.
1023 EFI_INVALID_PARAMETER PortNumber is invalid.
1024 EFI_DEVICE_ERROR Can't read register
1030 UINT32 PortStatusControlAddr
;
1031 UINT32 PortStatusControlReg
;
1033 UINT8 TotalPortNumber
;
1034 UINT8 Is64BitCapable
;
1036 if (PortStatus
== NULL
) {
1037 Status
= EFI_INVALID_PARAMETER
;
1048 if (PortNumber
>= TotalPortNumber
) {
1049 Status
= EFI_INVALID_PARAMETER
;
1053 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
1054 PortStatusControlAddr
= (UINT32
) (PORTSC
+ (4 * PortNumber
));
1057 // Clear port status
1059 PortStatus
->PortStatus
= 0;
1060 PortStatus
->PortChangeStatus
= 0;
1062 Status
= ReadEhcOperationalReg (
1064 PortStatusControlAddr
,
1065 &PortStatusControlReg
1067 if (EFI_ERROR (Status
)) {
1068 Status
= EFI_DEVICE_ERROR
;
1073 // Fill Port Status bits
1077 // Current Connect Status
1079 if (PORTSC_CCS
& PortStatusControlReg
) {
1080 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
1083 // Port Enabled/Disabled
1085 if (PORTSC_PED
& PortStatusControlReg
) {
1086 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
1091 if (PORTSC_SUSP
& PortStatusControlReg
) {
1092 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1095 // Over-current Active
1097 if (PORTSC_OCA
& PortStatusControlReg
) {
1098 PortStatus
->PortStatus
|= USB_PORT_STAT_OVERCURRENT
;
1103 if (PORTSC_PR
& PortStatusControlReg
) {
1104 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
1109 if (PORTSC_PP
& PortStatusControlReg
) {
1110 PortStatus
->PortStatus
|= USB_PORT_STAT_POWER
;
1115 if (PORTSC_PO
& PortStatusControlReg
) {
1116 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
1119 // Identify device speed
1121 if (PORTSC_LS_KSTATE
& PortStatusControlReg
) {
1123 // Low Speed Device Attached
1125 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1128 // Not Low Speed Device Attached
1130 if ((PORTSC_CCS
& PortStatusControlReg
) && (PORTSC_CSC
& PortStatusControlReg
)) {
1131 HcDev
->DeviceSpeed
[PortNumber
] = (UINT16
) (IsHighSpeedDevice (This
, PortNumber
) ? USB_PORT_STAT_HIGH_SPEED
: 0);
1133 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| HcDev
->DeviceSpeed
[PortNumber
]);
1136 // Fill Port Status Change bits
1139 // Connect Status Change
1141 if (PORTSC_CSC
& PortStatusControlReg
) {
1142 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
1145 // Port Enabled/Disabled Change
1147 if (PORTSC_PEDC
& PortStatusControlReg
) {
1148 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
1151 // Port Over Current Change
1153 if (PORTSC_OCC
& PortStatusControlReg
) {
1154 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_OVERCURRENT
;
1163 EhciSetRootHubPortFeature (
1164 IN EFI_USB2_HC_PROTOCOL
*This
,
1165 IN UINT8 PortNumber
,
1166 IN EFI_USB_PORT_FEATURE PortFeature
1170 Routine Description:
1172 Sets a feature for the specified root hub port.
1176 This - A pointer to the EFI_USB2_HC_PROTOCOL.
1177 PortNumber - Specifies the root hub port whose feature
1178 is requested to be set.
1179 PortFeature - Indicates the feature selector associated
1180 with the feature set request.
1185 The feature specified by PortFeature was set for the
1186 USB root hub port specified by PortNumber.
1187 EFI_INVALID_PARAMETER
1188 PortNumber is invalid or PortFeature is invalid.
1196 UINT32 PortStatusControlAddr
;
1197 UINT32 PortStatusControlReg
;
1199 UINT8 TotalPortNumber
;
1200 UINT8 Is64BitCapable
;
1209 if (PortNumber
>= TotalPortNumber
) {
1210 Status
= EFI_INVALID_PARAMETER
;
1214 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
1215 PortStatusControlAddr
= (UINT32
) (PORTSC
+ (4 * PortNumber
));
1217 Status
= ReadEhcOperationalReg (
1219 PortStatusControlAddr
,
1220 &PortStatusControlReg
1222 if (EFI_ERROR (Status
)) {
1223 Status
= EFI_DEVICE_ERROR
;
1227 switch (PortFeature
) {
1229 case EfiUsbPortEnable
:
1232 // Sofeware can't set this bit, Port can only be enable by the Host Controller
1233 // as a part of the reset and enable
1235 PortStatusControlReg
&= 0xffffffd5;
1236 PortStatusControlReg
|= PORTSC_PED
;
1239 case EfiUsbPortSuspend
:
1241 PortStatusControlReg
&= 0xffffffd5;
1242 PortStatusControlReg
|= PORTSC_SUSP
;
1245 case EfiUsbPortReset
:
1248 // Make sure Host Controller not halt before reset it
1250 if (IsEhcHalted (HcDev
)) {
1251 Status
= StartScheduleExecution (HcDev
);
1252 if (EFI_ERROR (Status
)) {
1253 Status
= EFI_DEVICE_ERROR
;
1256 Status
= WaitForEhcNotHalt (HcDev
, EHCI_GENERIC_TIMEOUT
);
1257 if (EFI_ERROR (Status
)) {
1258 DEBUG ((gEHCDebugLevel
, "EHCI: WaitForEhcNotHalt TimeOut\n"));
1259 Status
= EFI_DEVICE_ERROR
;
1263 PortStatusControlReg
&= 0xffffffd5;
1264 PortStatusControlReg
|= PORTSC_PR
;
1266 // Set one to PortReset bit must also set zero to PortEnable bit
1268 PortStatusControlReg
&= ~PORTSC_PED
;
1271 case EfiUsbPortPower
:
1274 // No support, no operation
1278 case EfiUsbPortOwner
:
1280 PortStatusControlReg
&= 0xffffffd5;
1281 PortStatusControlReg
|= PORTSC_PO
;
1286 Status
= EFI_INVALID_PARAMETER
;
1290 Status
= WriteEhcOperationalReg (
1292 PortStatusControlAddr
,
1293 PortStatusControlReg
1295 if (EFI_ERROR (Status
)) {
1296 Status
= EFI_DEVICE_ERROR
;
1305 EhciClearRootHubPortFeature (
1306 IN EFI_USB2_HC_PROTOCOL
*This
,
1307 IN UINT8 PortNumber
,
1308 IN EFI_USB_PORT_FEATURE PortFeature
1312 Routine Description:
1314 Clears a feature for the specified root hub port.
1318 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
1319 PortNumber - Specifies the root hub port whose feature
1320 is requested to be cleared.
1321 PortFeature - Indicates the feature selector associated with the
1322 feature clear request.
1327 The feature specified by PortFeature was cleared for the
1328 USB root hub port specified by PortNumber.
1329 EFI_INVALID_PARAMETER
1330 PortNumber is invalid or PortFeature is invalid.
1338 UINT32 PortStatusControlAddr
;
1339 UINT32 PortStatusControlReg
;
1341 UINT8 TotalPortNumber
;
1342 UINT8 Is64BitCapable
;
1351 if (PortNumber
>= TotalPortNumber
) {
1352 Status
= EFI_INVALID_PARAMETER
;
1356 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
1357 PortStatusControlAddr
= (UINT32
) (PORTSC
+ (4 * PortNumber
));
1359 Status
= ReadEhcOperationalReg (
1361 PortStatusControlAddr
,
1362 &PortStatusControlReg
1364 if (EFI_ERROR (Status
)) {
1365 Status
= EFI_DEVICE_ERROR
;
1369 switch (PortFeature
) {
1371 case EfiUsbPortEnable
:
1374 // Clear PORT_ENABLE feature means disable port.
1376 PortStatusControlReg
&= 0xffffffd5;
1377 PortStatusControlReg
&= ~PORTSC_PED
;
1380 case EfiUsbPortSuspend
:
1383 // A write of zero to this bit is ignored by the host controller.
1384 // The host controller will unconditionally set this bit to a zero when:
1385 // 1. software sets the Forct Port Resume bit to a zero from a one.
1386 // 2. software sets the Port Reset bit to a one frome a zero.
1388 PortStatusControlReg
&= 0xffffffd5;
1389 PortStatusControlReg
&= ~PORTSC_FPR
;
1392 case EfiUsbPortReset
:
1395 // Clear PORT_RESET means clear the reset signal.
1397 PortStatusControlReg
&= 0xffffffd5;
1398 PortStatusControlReg
&= ~PORTSC_PR
;
1401 case EfiUsbPortPower
:
1404 // No support, no operation
1408 case EfiUsbPortOwner
:
1411 // Clear port owner means this port owned by EHC
1413 PortStatusControlReg
&= 0xffffffd5;
1414 PortStatusControlReg
&= ~PORTSC_PO
;
1417 case EfiUsbPortConnectChange
:
1420 // Clear connect status change
1422 PortStatusControlReg
&= 0xffffffd5;
1423 PortStatusControlReg
|= PORTSC_CSC
;
1426 case EfiUsbPortEnableChange
:
1429 // Clear enable status change
1431 PortStatusControlReg
&= 0xffffffd5;
1432 PortStatusControlReg
|= PORTSC_PEDC
;
1435 case EfiUsbPortSuspendChange
:
1438 // No related bit, no operation
1442 case EfiUsbPortOverCurrentChange
:
1445 // Clear PortOverCurrent change
1447 PortStatusControlReg
&= 0xffffffd5;
1448 PortStatusControlReg
|= PORTSC_OCC
;
1451 case EfiUsbPortResetChange
:
1454 // No related bit, no operation
1460 Status
= EFI_INVALID_PARAMETER
;
1464 Status
= WriteEhcOperationalReg (
1466 PortStatusControlAddr
,
1467 PortStatusControlReg
1469 if (EFI_ERROR (Status
)) {
1470 Status
= EFI_DEVICE_ERROR
;
1480 EhciControlTransfer (
1481 IN EFI_USB2_HC_PROTOCOL
*This
,
1482 IN UINT8 DeviceAddress
,
1483 IN UINT8 DeviceSpeed
,
1484 IN UINTN MaximumPacketLength
,
1485 IN EFI_USB_DEVICE_REQUEST
*Request
,
1486 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1488 IN OUT UINTN
*DataLength
,
1490 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1491 OUT UINT32
*TransferResult
1495 Routine Description:
1497 Submits control transfer to a target USB device.
1501 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
1502 DeviceAddress - Represents the address of the target device on the USB,
1503 which is assigned during USB enumeration.
1504 DeviceSpeed - Indicates target device speed.
1505 MaximumPacketLength - Indicates the maximum packet size that the
1506 default control transfer endpoint is capable of
1507 sending or receiving.
1508 Request - A pointer to the USB device request that will be sent
1510 TransferDirection - Specifies the data direction for the transfer.
1511 There are three values available, DataIn, DataOut
1513 Data - A pointer to the buffer of data that will be transmitted
1514 to USB device or received from USB device.
1515 DataLength - Indicates the size, in bytes, of the data buffer
1517 TimeOut - Indicates the maximum time, in microseconds,
1518 which the transfer is allowed to complete.
1519 Translator - A pointr to the transaction translator data.
1520 TransferResult - A pointer to the detailed result information generated
1521 by this control transfer.
1526 The control transfer was completed successfully.
1527 EFI_OUT_OF_RESOURCES
1528 The control transfer could not be completed due to a lack of resources.
1529 EFI_INVALID_PARAMETER
1530 Some parameters are invalid.
1532 The control transfer failed due to timeout.
1534 The control transfer failed due to host controller or device error.
1535 Caller should check TranferResult for detailed error information.
1542 EHCI_QH_ENTITY
*QhPtr
;
1543 EHCI_QTD_ENTITY
*ControlQtdsPtr
;
1546 UINT8
*RequestCursor
;
1550 ControlQtdsPtr
= NULL
;
1553 RequestCursor
= NULL
;
1555 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
1558 // Parameters Checking
1560 if (TransferDirection
!= EfiUsbDataIn
&&
1561 TransferDirection
!= EfiUsbDataOut
&&
1562 TransferDirection
!= EfiUsbNoData
1564 Status
= EFI_INVALID_PARAMETER
;
1568 if (EfiUsbNoData
== TransferDirection
) {
1569 if (NULL
!= Data
|| 0 != *DataLength
) {
1570 Status
= EFI_INVALID_PARAMETER
;
1574 if (NULL
== Data
|| 0 == *DataLength
) {
1575 Status
= EFI_INVALID_PARAMETER
;
1580 if (Request
== NULL
|| TransferResult
== NULL
) {
1581 Status
= EFI_INVALID_PARAMETER
;
1585 if (EFI_USB_SPEED_LOW
== DeviceSpeed
) {
1586 if (MaximumPacketLength
!= 8) {
1587 Status
= EFI_INVALID_PARAMETER
;
1590 } else if (MaximumPacketLength
!= 8 &&
1591 MaximumPacketLength
!= 16 &&
1592 MaximumPacketLength
!= 32 &&
1593 MaximumPacketLength
!= 64
1595 Status
= EFI_INVALID_PARAMETER
;
1600 // If errors exist that cause host controller halt,
1601 // then return EFI_DEVICE_ERROR.
1603 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
1604 ClearEhcAllStatus (HcDev
);
1605 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1606 Status
= EFI_DEVICE_ERROR
;
1611 // Map the Request for bus master access.
1612 // BusMasterRead means cpu write
1614 Status
= MapRequestBuffer (
1620 if (EFI_ERROR (Status
)) {
1621 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1622 Status
= EFI_DEVICE_ERROR
;
1627 // Map the source data buffer for bus master access.
1629 Status
= MapDataBuffer (
1638 if (EFI_ERROR (Status
)) {
1639 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1640 Status
= EFI_DEVICE_ERROR
;
1645 // Create and init control Qh
1647 Status
= CreateControlQh (
1651 MaximumPacketLength
,
1655 if (EFI_ERROR (Status
)) {
1656 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1657 Status
= EFI_OUT_OF_RESOURCES
;
1662 // Create and init control Qtds
1664 Status
= CreateControlQtds (
1673 if (EFI_ERROR (Status
)) {
1674 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1675 Status
= EFI_OUT_OF_RESOURCES
;
1682 LinkQtdToQh (QhPtr
, ControlQtdsPtr
);
1684 ClearEhcAllStatus (HcDev
);
1687 // Link Qh and Qtds to Async Schedule List
1689 Status
= LinkQhToAsyncList (HcDev
, QhPtr
);
1690 if (EFI_ERROR (Status
)) {
1691 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1692 Status
= EFI_DEVICE_ERROR
;
1697 // Poll Qh-Qtds execution and get result.
1698 // detail status is returned
1700 Status
= ExecuteTransfer (
1709 if (EFI_ERROR (Status
)) {
1714 // If has errors that cause host controller halt,
1715 // then return EFI_DEVICE_ERROR directly.
1717 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
1718 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
1721 ClearEhcAllStatus (HcDev
);
1724 UnlinkQhFromAsyncList (HcDev
, QhPtr
);
1725 DestoryQtds (HcDev
, ControlQtdsPtr
);
1727 DestoryQh (HcDev
, QhPtr
);
1729 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, DataMap
);
1731 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMap
);
1733 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
1740 IN EFI_USB2_HC_PROTOCOL
*This
,
1741 IN UINT8 DeviceAddress
,
1742 IN UINT8 EndPointAddress
,
1743 IN UINT8 DeviceSpeed
,
1744 IN UINTN MaximumPacketLength
,
1745 IN UINT8 DataBuffersNumber
,
1746 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
1747 IN OUT UINTN
*DataLength
,
1748 IN OUT UINT8
*DataToggle
,
1750 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1751 OUT UINT32
*TransferResult
1755 Routine Description:
1757 Submits bulk transfer to a bulk endpoint of a USB device.
1761 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
1762 DeviceAddress - Represents the address of the target device on the USB,
1763 which is assigned during USB enumeration.
1764 EndPointAddress - The combination of an endpoint number and an
1765 endpoint direction of the target USB device.
1766 Each endpoint address supports data transfer in
1767 one direction except the control endpoint
1768 (whose default endpoint address is 0).
1769 It is the caller's responsibility to make sure that
1770 the EndPointAddress represents a bulk endpoint.
1771 DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
1772 and EFI_USB_SPEED_HIGH.
1773 MaximumPacketLength - Indicates the maximum packet size the target endpoint
1774 is capable of sending or receiving.
1775 DataBuffersNumber - Number of data buffers prepared for the transfer.
1776 Data - Array of pointers to the buffers of data that will be transmitted
1777 to USB device or received from USB device.
1778 DataLength - When input, indicates the size, in bytes, of the data buffer
1779 specified by Data. When output, indicates the actually
1780 transferred data size.
1781 DataToggle - A pointer to the data toggle value. On input, it indicates
1782 the initial data toggle value the bulk transfer should adopt;
1783 on output, it is updated to indicate the data toggle value
1784 of the subsequent bulk transfer.
1785 Translator - A pointr to the transaction translator data.
1786 TimeOut - Indicates the maximum time, in microseconds, which the
1787 transfer is allowed to complete.
1788 TransferResult - A pointer to the detailed result information of the
1794 The bulk transfer was completed successfully.
1795 EFI_OUT_OF_RESOURCES
1796 The bulk transfer could not be submitted due to lack of resource.
1797 EFI_INVALID_PARAMETER
1798 Some parameters are invalid.
1800 The bulk transfer failed due to timeout.
1802 The bulk transfer failed due to host controller or device error.
1803 Caller should check TranferResult for detailed error information.
1810 EHCI_QH_ENTITY
*QhPtr
;
1811 EHCI_QTD_ENTITY
*BulkQtdsPtr
;
1814 EFI_USB_DATA_DIRECTION TransferDirection
;
1820 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
1823 // Parameters Checking
1825 if (NULL
== DataLength
||
1828 NULL
== TransferResult
1830 Status
= EFI_INVALID_PARAMETER
;
1834 if (*DataLength
== 0) {
1835 Status
= EFI_INVALID_PARAMETER
;
1839 if (1 != *DataToggle
&& 0 != *DataToggle
) {
1840 Status
= EFI_INVALID_PARAMETER
;
1844 if (EFI_USB_SPEED_LOW
== DeviceSpeed
) {
1845 Status
= EFI_INVALID_PARAMETER
;
1849 if (EFI_USB_SPEED_FULL
== DeviceSpeed
) {
1850 if (MaximumPacketLength
> 64) {
1851 Status
= EFI_INVALID_PARAMETER
;
1856 if (EFI_USB_SPEED_HIGH
== DeviceSpeed
) {
1857 if (MaximumPacketLength
> 512) {
1858 Status
= EFI_INVALID_PARAMETER
;
1864 // if has errors that cause host controller halt,
1865 // then return EFI_DEVICE_ERROR directly.
1867 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
1868 ClearEhcAllStatus (HcDev
);
1869 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1870 Status
= EFI_DEVICE_ERROR
;
1874 Status
= ClearEhcAllStatus (HcDev
);
1875 if (EFI_ERROR (Status
)) {
1876 Status
= EFI_DEVICE_ERROR
;
1881 // construct QH and TD data structures,
1882 // and link them together
1884 if (EndPointAddress
& 0x80) {
1885 TransferDirection
= EfiUsbDataIn
;
1887 TransferDirection
= EfiUsbDataOut
;
1890 Status
= MapDataBuffer (
1899 if (EFI_ERROR (Status
)) {
1900 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1901 Status
= EFI_DEVICE_ERROR
;
1906 // Create and init Bulk Qh
1908 Status
= CreateBulkQh (
1914 MaximumPacketLength
,
1918 if (EFI_ERROR (Status
)) {
1919 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1920 Status
= EFI_OUT_OF_RESOURCES
;
1925 // Create and init Bulk Qtds
1927 Status
= CreateBulkOrInterruptQtds (
1935 if (EFI_ERROR (Status
)) {
1936 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1937 Status
= EFI_OUT_OF_RESOURCES
;
1944 LinkQtdToQh (QhPtr
, BulkQtdsPtr
);
1946 ClearEhcAllStatus (HcDev
);
1949 // Link Qh and qtds to Async Schedule List
1951 Status
= LinkQhToAsyncList (HcDev
, QhPtr
);
1952 if (EFI_ERROR (Status
)) {
1953 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1954 Status
= EFI_DEVICE_ERROR
;
1959 // Poll QH-TDs execution and get result.
1960 // detail status is returned
1962 Status
= ExecuteTransfer (
1971 if (EFI_ERROR (Status
)) {
1976 // if has errors that cause host controller halt,
1977 // then return EFI_DEVICE_ERROR directly.
1979 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
1980 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
1983 ClearEhcAllStatus (HcDev
);
1986 UnlinkQhFromAsyncList (HcDev
, QhPtr
);
1987 DestoryQtds (HcDev
, BulkQtdsPtr
);
1989 DestoryQh (HcDev
, QhPtr
);
1991 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, DataMap
);
1993 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
1999 EhciAsyncInterruptTransfer (
2000 IN EFI_USB2_HC_PROTOCOL
* This
,
2001 IN UINT8 DeviceAddress
,
2002 IN UINT8 EndPointAddress
,
2003 IN UINT8 DeviceSpeed
,
2004 IN UINTN MaximumPacketLength
,
2005 IN BOOLEAN IsNewTransfer
,
2006 IN OUT UINT8
*DataToggle
,
2007 IN UINTN PollingInterval
,
2008 IN UINTN DataLength
,
2009 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
2010 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
2011 IN VOID
*Context OPTIONAL
2015 Routine Description:
2017 Submits an asynchronous interrupt transfer to an
2018 interrupt endpoint of a USB device.
2019 Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated
2020 in the following specification version.
2024 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2025 DeviceAddress - Represents the address of the target device on the USB,
2026 which is assigned during USB enumeration.
2027 EndPointAddress - The combination of an endpoint number and an endpoint
2028 direction of the target USB device. Each endpoint address
2029 supports data transfer in one direction except the
2030 control endpoint (whose default endpoint address is 0).
2031 It is the caller's responsibility to make sure that
2032 the EndPointAddress represents an interrupt endpoint.
2033 DeviceSpeed - Indicates device speed.
2034 MaximumPacketLength - Indicates the maximum packet size the target endpoint
2035 is capable of sending or receiving.
2036 IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between
2037 the host and the target interrupt endpoint.
2038 If FALSE, the specified asynchronous interrupt pipe
2040 DataToggle - A pointer to the data toggle value. On input, it is valid
2041 when IsNewTransfer is TRUE, and it indicates the initial
2042 data toggle value the asynchronous interrupt transfer
2044 On output, it is valid when IsNewTransfer is FALSE,
2045 and it is updated to indicate the data toggle value of
2046 the subsequent asynchronous interrupt transfer.
2047 PollingInterval - Indicates the interval, in milliseconds, that the
2048 asynchronous interrupt transfer is polled.
2049 This parameter is required when IsNewTransfer is TRUE.
2050 DataLength - Indicates the length of data to be received at the
2051 rate specified by PollingInterval from the target
2052 asynchronous interrupt endpoint. This parameter
2053 is only required when IsNewTransfer is TRUE.
2054 Translator - A pointr to the transaction translator data.
2055 CallBackFunction - The Callback function.This function is called at the
2056 rate specified by PollingInterval.This parameter is
2057 only required when IsNewTransfer is TRUE.
2058 Context - The context that is passed to the CallBackFunction.
2059 - This is an optional parameter and may be NULL.
2064 The asynchronous interrupt transfer request has been successfully
2065 submitted or canceled.
2066 EFI_INVALID_PARAMETER
2067 Some parameters are invalid.
2068 EFI_OUT_OF_RESOURCES
2069 The request could not be completed due to a lack of resources.
2078 EHCI_QH_ENTITY
*QhPtr
;
2079 EHCI_QTD_ENTITY
*InterruptQtdsPtr
;
2084 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
2088 InterruptQtdsPtr
= NULL
;
2092 AsyncRequestPtr
= NULL
;
2093 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
2096 // Parameters Checking
2098 if (!IsDataInTransfer (EndPointAddress
)) {
2099 Status
= EFI_INVALID_PARAMETER
;
2103 if (IsNewTransfer
) {
2104 if (0 == DataLength
) {
2105 Status
= EFI_INVALID_PARAMETER
;
2109 if (*DataToggle
!= 1 && *DataToggle
!= 0) {
2110 Status
= EFI_INVALID_PARAMETER
;
2114 if (PollingInterval
> 255 || PollingInterval
< 1) {
2115 Status
= EFI_INVALID_PARAMETER
;
2121 // if has errors that cause host controller halt,
2122 // then return EFI_DEVICE_ERROR directly.
2124 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
2125 ClearEhcAllStatus (HcDev
);
2126 Status
= EFI_DEVICE_ERROR
;
2130 Status
= ClearEhcAllStatus (HcDev
);
2131 if (EFI_ERROR (Status
)) {
2132 Status
= EFI_DEVICE_ERROR
;
2137 // Delete Async interrupt transfer request
2139 if (!IsNewTransfer
) {
2141 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
2143 Status
= DeleteAsyncRequestTransfer (
2150 gBS
->RestoreTPL (OldTpl
);
2155 Status
= EhciAllocatePool (
2157 (UINT8
**) &AsyncRequestPtr
,
2158 sizeof (EHCI_ASYNC_REQUEST
)
2160 if (EFI_ERROR (Status
)) {
2161 Status
= EFI_OUT_OF_RESOURCES
;
2165 Status
= EhciAllocatePool (HcDev
, &DataPtr
, DataLength
);
2166 if (EFI_ERROR (Status
)) {
2167 Status
= EFI_OUT_OF_RESOURCES
;
2171 MappedLength
= DataLength
;
2172 Status
= MapDataBuffer (
2181 if (EFI_ERROR (Status
)) {
2182 Status
= EFI_DEVICE_ERROR
;
2187 // Create and init Interrupt Qh
2189 Status
= CreateInterruptQh (
2195 MaximumPacketLength
,
2200 if (EFI_ERROR (Status
)) {
2201 Status
= EFI_OUT_OF_RESOURCES
;
2206 // Create and init Interrupt Qtds
2208 Status
= CreateBulkOrInterruptQtds (
2216 if (EFI_ERROR (Status
)) {
2217 Status
= EFI_OUT_OF_RESOURCES
;
2224 LinkQtdToQh (QhPtr
, InterruptQtdsPtr
);
2227 // Init AsyncRequest Entry
2229 AsyncRequestPtr
->Context
= Context
;
2230 AsyncRequestPtr
->CallBackFunc
= CallBackFunction
;
2231 AsyncRequestPtr
->TransferType
= ASYNC_INTERRUPT_TRANSFER
;
2232 AsyncRequestPtr
->QhPtr
= QhPtr
;
2233 AsyncRequestPtr
->Prev
= NULL
;
2234 AsyncRequestPtr
->Next
= NULL
;
2236 if (NULL
== HcDev
->AsyncRequestList
) {
2237 Status
= StartPollingTimer (HcDev
);
2238 if (EFI_ERROR (Status
)) {
2239 Status
= EFI_DEVICE_ERROR
;
2240 CleanUpAllAsyncRequestTransfer (HcDev
);
2246 // Link Entry to AsyncRequest List
2248 LinkToAsyncReqeust (HcDev
, AsyncRequestPtr
);
2250 ClearEhcAllStatus (HcDev
);
2252 Status
= DisablePeriodicSchedule (HcDev
);
2253 if (EFI_ERROR (Status
)) {
2254 Status
= EFI_DEVICE_ERROR
;
2258 Status
= WaitForPeriodicScheduleDisable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2259 if (EFI_ERROR (Status
)) {
2260 Status
= EFI_TIMEOUT
;
2265 // Link Qh and Qtds to Periodic Schedule List
2267 LinkQhToPeriodicList (HcDev
, QhPtr
);
2269 Status
= EnablePeriodicSchedule (HcDev
);
2270 if (EFI_ERROR (Status
)) {
2271 Status
= EFI_DEVICE_ERROR
;
2275 Status
= WaitForPeriodicScheduleEnable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2276 if (EFI_ERROR (Status
)) {
2277 Status
= EFI_TIMEOUT
;
2281 if (IsEhcHalted (HcDev
)) {
2282 Status
= StartScheduleExecution (HcDev
);
2283 if (EFI_ERROR (Status
)) {
2284 Status
= EFI_DEVICE_ERROR
;
2289 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2293 DestoryQh (HcDev
, QhPtr
);
2295 EhciFreePool (HcDev
, DataPtr
, DataLength
);
2299 (UINT8
*) AsyncRequestPtr
,
2300 sizeof (EHCI_ASYNC_REQUEST
)
2303 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, DataMap
);
2310 EhciSyncInterruptTransfer (
2311 IN EFI_USB2_HC_PROTOCOL
*This
,
2312 IN UINT8 DeviceAddress
,
2313 IN UINT8 EndPointAddress
,
2314 IN UINT8 DeviceSpeed
,
2315 IN UINTN MaximumPacketLength
,
2317 IN OUT UINTN
*DataLength
,
2318 IN OUT UINT8
*DataToggle
,
2320 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
2321 OUT UINT32
*TransferResult
2325 Routine Description:
2327 Submits synchronous interrupt transfer to an interrupt endpoint
2329 Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated
2330 in the following specification version.
2334 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2335 DeviceAddress - Represents the address of the target device on the USB,
2336 which is assigned during USB enumeration.
2337 EndPointAddress - The combination of an endpoint number and an endpoint
2338 direction of the target USB device. Each endpoint
2339 address supports data transfer in one direction
2340 except the control endpoint (whose default
2341 endpoint address is 0). It is the caller's responsibility
2342 to make sure that the EndPointAddress represents
2343 an interrupt endpoint.
2344 DeviceSpeed - Indicates device speed.
2345 MaximumPacketLength - Indicates the maximum packet size the target endpoint
2346 is capable of sending or receiving.
2347 Data - A pointer to the buffer of data that will be transmitted
2348 to USB device or received from USB device.
2349 DataLength - On input, the size, in bytes, of the data buffer specified
2350 by Data. On output, the number of bytes transferred.
2351 DataToggle - A pointer to the data toggle value. On input, it indicates
2352 the initial data toggle value the synchronous interrupt
2353 transfer should adopt;
2354 on output, it is updated to indicate the data toggle value
2355 of the subsequent synchronous interrupt transfer.
2356 TimeOut - Indicates the maximum time, in microseconds, which the
2357 transfer is allowed to complete.
2358 Translator - A pointr to the transaction translator data.
2359 TransferResult - A pointer to the detailed result information from
2360 the synchronous interrupt transfer.
2365 The synchronous interrupt transfer was completed successfully.
2366 EFI_OUT_OF_RESOURCES
2367 The synchronous interrupt transfer could not be submitted due
2368 to lack of resource.
2369 EFI_INVALID_PARAMETER
2370 Some parameters are invalid.
2372 The synchronous interrupt transfer failed due to timeout.
2374 The synchronous interrupt transfer failed due to host controller
2375 or device error. Caller should check TranferResult for detailed
2383 EHCI_QH_ENTITY
*QhPtr
;
2384 EHCI_QTD_ENTITY
*InterruptQtdsPtr
;
2389 InterruptQtdsPtr
= NULL
;
2392 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
2395 // Parameters Checking
2397 if (DataLength
== NULL
||
2399 TransferResult
== NULL
2401 Status
= EFI_INVALID_PARAMETER
;
2405 if (!IsDataInTransfer (EndPointAddress
)) {
2406 Status
= EFI_INVALID_PARAMETER
;
2410 if (0 == *DataLength
) {
2411 Status
= EFI_INVALID_PARAMETER
;
2415 if (*DataToggle
!= 1 && *DataToggle
!= 0) {
2416 Status
= EFI_INVALID_PARAMETER
;
2420 if (EFI_USB_SPEED_LOW
== DeviceSpeed
&& 8 != MaximumPacketLength
) {
2421 Status
= EFI_INVALID_PARAMETER
;
2425 if (EFI_USB_SPEED_FULL
== DeviceSpeed
&& MaximumPacketLength
> 64) {
2426 Status
= EFI_INVALID_PARAMETER
;
2430 if (EFI_USB_SPEED_HIGH
== DeviceSpeed
&& MaximumPacketLength
> 3072) {
2431 Status
= EFI_INVALID_PARAMETER
;
2436 // if has errors that cause host controller halt,
2437 // then return EFI_DEVICE_ERROR directly.
2439 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
2440 ClearEhcAllStatus (HcDev
);
2441 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2442 Status
= EFI_DEVICE_ERROR
;
2446 Status
= ClearEhcAllStatus (HcDev
);
2447 if (EFI_ERROR (Status
)) {
2448 Status
= EFI_DEVICE_ERROR
;
2452 Status
= MapDataBuffer (
2461 if (EFI_ERROR (Status
)) {
2462 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2463 Status
= EFI_DEVICE_ERROR
;
2468 // Create and init Interrupt Qh
2470 Status
= CreateInterruptQh (
2476 MaximumPacketLength
,
2481 if (EFI_ERROR (Status
)) {
2482 Status
= EFI_OUT_OF_RESOURCES
;
2487 // Create and init Interrupt Qtds
2489 Status
= CreateBulkOrInterruptQtds (
2497 if (EFI_ERROR (Status
)) {
2498 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2499 Status
= EFI_OUT_OF_RESOURCES
;
2506 LinkQtdToQh (QhPtr
, InterruptQtdsPtr
);
2508 ClearEhcAllStatus (HcDev
);
2510 Status
= DisablePeriodicSchedule (HcDev
);
2511 if (EFI_ERROR (Status
)) {
2512 Status
= EFI_DEVICE_ERROR
;
2516 Status
= WaitForPeriodicScheduleDisable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2517 if (EFI_ERROR (Status
)) {
2518 Status
= EFI_TIMEOUT
;
2523 // Link Qh and Qtds to Periodic Schedule List
2525 LinkQhToPeriodicList (HcDev
, QhPtr
);
2527 Status
= EnablePeriodicSchedule (HcDev
);
2528 if (EFI_ERROR (Status
)) {
2529 Status
= EFI_DEVICE_ERROR
;
2533 Status
= WaitForPeriodicScheduleEnable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2534 if (EFI_ERROR (Status
)) {
2535 Status
= EFI_TIMEOUT
;
2539 if (IsEhcHalted (HcDev
)) {
2540 Status
= StartScheduleExecution (HcDev
);
2541 if (EFI_ERROR (Status
)) {
2542 Status
= EFI_DEVICE_ERROR
;
2548 // Poll QH-TDs execution and get result.
2549 // detail status is returned
2551 Status
= ExecuteTransfer (
2560 if (EFI_ERROR (Status
)) {
2565 // if has errors that cause host controller halt,
2566 // then return EFI_DEVICE_ERROR directly.
2568 if (IsEhcHalted (HcDev
) || IsEhcSysError (HcDev
)) {
2569 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2572 ClearEhcAllStatus (HcDev
);
2575 UnlinkQhFromPeriodicList (HcDev
, QhPtr
, 0);
2576 DestoryQtds (HcDev
, InterruptQtdsPtr
);
2578 DestoryQh (HcDev
, QhPtr
);
2580 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, DataMap
);
2582 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2588 EhciIsochronousTransfer (
2589 IN EFI_USB2_HC_PROTOCOL
*This
,
2590 IN UINT8 DeviceAddress
,
2591 IN UINT8 EndPointAddress
,
2592 IN UINT8 DeviceSpeed
,
2593 IN UINTN MaximumPacketLength
,
2594 IN UINT8 DataBuffersNumber
,
2595 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
2596 IN UINTN DataLength
,
2597 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
2598 OUT UINT32
*TransferResult
2602 Routine Description:
2604 Submits isochronous transfer to a target USB device.
2608 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2609 DeviceAddress - Represents the address of the target device on the USB,
2610 which is assigned during USB enumeration.
2611 EndPointAddress - End point address
2612 DeviceSpeed - Indicates device speed.
2613 MaximumPacketLength - Indicates the maximum packet size that the
2614 default control transfer endpoint is capable of
2615 sending or receiving.
2616 DataBuffersNumber - Number of data buffers prepared for the transfer.
2617 Data - Array of pointers to the buffers of data that will be
2618 transmitted to USB device or received from USB device.
2619 DataLength - Indicates the size, in bytes, of the data buffer
2621 Translator - A pointr to the transaction translator data.
2622 TransferResult - A pointer to the detailed result information generated
2623 by this control transfer.
2631 return EFI_UNSUPPORTED
;
2636 EhciAsyncIsochronousTransfer (
2637 IN EFI_USB2_HC_PROTOCOL
*This
,
2638 IN UINT8 DeviceAddress
,
2639 IN UINT8 EndPointAddress
,
2640 IN UINT8 DeviceSpeed
,
2641 IN UINTN MaximumPacketLength
,
2642 IN UINT8 DataBuffersNumber
,
2643 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
2644 IN UINTN DataLength
,
2645 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
2646 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
2651 Routine Description:
2653 Submits Async isochronous transfer to a target USB device.
2657 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2658 DeviceAddress - Represents the address of the target device on the USB,
2659 which is assigned during USB enumeration.
2660 EndPointAddress - End point address
2661 DeviceSpeed - Indicates device speed.
2662 MaximumPacketLength - Indicates the maximum packet size that the
2663 default control transfer endpoint is capable of
2664 sending or receiving.
2665 DataBuffersNumber - Number of data buffers prepared for the transfer.
2666 Data - Array of pointers to the buffers of data that will be transmitted
2667 to USB device or received from USB device.
2668 Translator - A pointr to the transaction translator data.
2669 IsochronousCallBack - When the transfer complete, the call back function will be called
2670 Context - Pass to the call back function as parameter
2678 return EFI_UNSUPPORTED
;