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.
25 // UHCI Driver Global Variables
27 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding
= {
28 UHCIDriverBindingSupported
,
29 UHCIDriverBindingStart
,
30 UHCIDriverBindingStop
,
38 UHCIDriverBindingSupported (
39 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
40 IN EFI_HANDLE Controller
,
41 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
46 Test to see if this driver supports ControllerHandle. Any ControllerHandle
47 that has UsbHcProtocol installed will be supported.
50 This - Protocol instance pointer.
51 Controller - Handle of device to test
52 RemainingDevicePath - Not used
55 EFI_SUCCESS - This driver supports this device.
56 EFI_UNSUPPORTED - This driver does not support this device.
60 EFI_STATUS OpenStatus
;
62 EFI_PCI_IO_PROTOCOL
*PciIo
;
63 USB_CLASSC UsbClassCReg
;
66 // Test whether there is PCI IO Protocol attached on the controller handle.
68 OpenStatus
= gBS
->OpenProtocol (
70 &gEfiPciIoProtocolGuid
,
72 This
->DriverBindingHandle
,
74 EFI_OPEN_PROTOCOL_BY_DRIVER
76 if (EFI_ERROR (OpenStatus
)) {
80 Status
= PciIo
->Pci
.Read (
84 sizeof (USB_CLASSC
) / sizeof (UINT8
),
87 if (EFI_ERROR (Status
)) {
90 &gEfiPciIoProtocolGuid
,
91 This
->DriverBindingHandle
,
94 return EFI_UNSUPPORTED
;
97 // Test whether the controller belongs to UHCI type
99 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
100 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
101 (UsbClassCReg
.PI
!= PCI_CLASSC_PI_UHCI
)) {
105 &gEfiPciIoProtocolGuid
,
106 This
->DriverBindingHandle
,
110 return EFI_UNSUPPORTED
;
114 &gEfiPciIoProtocolGuid
,
115 This
->DriverBindingHandle
,
124 UHCIDriverBindingStart (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE Controller
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
132 Starting the Usb UHCI Driver
135 This - Protocol instance pointer.
136 Controller - Handle of device to test
137 RemainingDevicePath - Not used
140 EFI_SUCCESS - This driver supports this device.
141 EFI_UNSUPPORTED - This driver does not support this device.
142 EFI_DEVICE_ERROR - This driver cannot be started due to device
150 EFI_PCI_IO_PROTOCOL
*PciIo
;
156 Status
= gBS
->OpenProtocol (
158 &gEfiPciIoProtocolGuid
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
164 if (EFI_ERROR (Status
)) {
169 // Turn off USB emulation
171 TurnOffUSBEmulation (PciIo
);
174 // Enable the USB Host Controller
176 Status
= PciIo
->Attributes (
178 EfiPciIoAttributeOperationSupported
,
182 if (!EFI_ERROR (Status
)) {
183 Supports
&= EFI_PCI_DEVICE_ENABLE
;
184 Status
= PciIo
->Attributes (
186 EfiPciIoAttributeOperationEnable
,
191 if (EFI_ERROR (Status
)) {
194 &gEfiPciIoProtocolGuid
,
195 This
->DriverBindingHandle
,
198 return EFI_UNSUPPORTED
;
202 // allocate memory for UHC private data structure
204 HcDev
= AllocateZeroPool (sizeof (USB_HC_DEV
));
208 &gEfiPciIoProtocolGuid
,
209 This
->DriverBindingHandle
,
212 return EFI_OUT_OF_RESOURCES
;
216 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
218 HcDev
->UsbHc
.Reset
= UHCIReset
;
219 HcDev
->UsbHc
.GetState
= UHCIGetState
;
220 HcDev
->UsbHc
.SetState
= UHCISetState
;
221 HcDev
->UsbHc
.ControlTransfer
= UHCIControlTransfer
;
222 HcDev
->UsbHc
.BulkTransfer
= UHCIBulkTransfer
;
223 HcDev
->UsbHc
.AsyncInterruptTransfer
= UHCIAsyncInterruptTransfer
;
224 HcDev
->UsbHc
.SyncInterruptTransfer
= UHCISyncInterruptTransfer
;
225 HcDev
->UsbHc
.IsochronousTransfer
= UHCIIsochronousTransfer
;
226 HcDev
->UsbHc
.AsyncIsochronousTransfer
= UHCIAsyncIsochronousTransfer
;
227 HcDev
->UsbHc
.GetRootHubPortNumber
= UHCIGetRootHubPortNumber
;
228 HcDev
->UsbHc
.GetRootHubPortStatus
= UHCIGetRootHubPortStatus
;
229 HcDev
->UsbHc
.SetRootHubPortFeature
= UHCISetRootHubPortFeature
;
230 HcDev
->UsbHc
.ClearRootHubPortFeature
= UHCIClearRootHubPortFeature
;
232 HcDev
->UsbHc
.MajorRevision
= 0x1;
233 HcDev
->UsbHc
.MinorRevision
= 0x1;
237 // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol
239 HcDev
->Usb2Hc
.GetCapability
= UHCI2GetCapability
;
240 HcDev
->Usb2Hc
.Reset
= UHCI2Reset
;
241 HcDev
->Usb2Hc
.GetState
= UHCI2GetState
;
242 HcDev
->Usb2Hc
.SetState
= UHCI2SetState
;
243 HcDev
->Usb2Hc
.ControlTransfer
= UHCI2ControlTransfer
;
244 HcDev
->Usb2Hc
.BulkTransfer
= UHCI2BulkTransfer
;
245 HcDev
->Usb2Hc
.AsyncInterruptTransfer
= UHCI2AsyncInterruptTransfer
;
246 HcDev
->Usb2Hc
.SyncInterruptTransfer
= UHCI2SyncInterruptTransfer
;
247 HcDev
->Usb2Hc
.IsochronousTransfer
= UHCI2IsochronousTransfer
;
248 HcDev
->Usb2Hc
.AsyncIsochronousTransfer
= UHCI2AsyncIsochronousTransfer
;
249 HcDev
->Usb2Hc
.GetRootHubPortStatus
= UHCI2GetRootHubPortStatus
;
250 HcDev
->Usb2Hc
.SetRootHubPortFeature
= UHCI2SetRootHubPortFeature
;
251 HcDev
->Usb2Hc
.ClearRootHubPortFeature
= UHCI2ClearRootHubPortFeature
;
253 HcDev
->Usb2Hc
.MajorRevision
= 0x1;
254 HcDev
->Usb2Hc
.MinorRevision
= 0x1;
257 // Init UHCI private data structures
259 HcDev
->Signature
= USB_HC_DEV_SIGNATURE
;
260 HcDev
->PciIo
= PciIo
;
262 FlBaseAddrReg
= USBFLBASEADD
;
265 // Allocate and Init Host Controller's Frame List Entry
267 Status
= CreateFrameList (HcDev
, (UINT32
) FlBaseAddrReg
);
268 if (EFI_ERROR (Status
)) {
271 gBS
->FreePool (HcDev
);
276 &gEfiPciIoProtocolGuid
,
277 This
->DriverBindingHandle
,
280 return EFI_OUT_OF_RESOURCES
;
284 // Init interrupt list head in the HcDev structure.
286 InitializeListHead (&(HcDev
->InterruptListHead
));
289 // Create timer for interrupt transfer result polling
291 Status
= gBS
->CreateEvent (
292 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
294 MonitorInterruptTrans
,
296 &HcDev
->InterruptTransTimer
298 if (EFI_ERROR (Status
)) {
300 FreeFrameListEntry (HcDev
);
303 gBS
->FreePool (HcDev
);
308 &gEfiPciIoProtocolGuid
,
309 This
->DriverBindingHandle
,
312 return EFI_UNSUPPORTED
;
316 // Here set interrupt transfer polling timer in 50ms unit.
318 Status
= gBS
->SetTimer (
319 HcDev
->InterruptTransTimer
,
321 INTERRUPT_POLLING_TIME
323 if (EFI_ERROR (Status
)) {
324 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
326 FreeFrameListEntry (HcDev
);
329 gBS
->FreePool (HcDev
);
334 &gEfiPciIoProtocolGuid
,
335 This
->DriverBindingHandle
,
338 return EFI_UNSUPPORTED
;
342 // QH,TD structures must in common buffer that will be
343 // accessed by both cpu and usb bus master at the same time.
344 // so, there must has memory management for QH,TD structures.
346 Status
= InitializeMemoryManagement (HcDev
);
347 if (EFI_ERROR (Status
)) {
349 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
351 FreeFrameListEntry (HcDev
);
354 gBS
->FreePool (HcDev
);
359 &gEfiPciIoProtocolGuid
,
360 This
->DriverBindingHandle
,
367 // Install Host Controller Protocol
369 Status
= gBS
->InstallProtocolInterface (
371 &gEfiUsbHcProtocolGuid
,
372 EFI_NATIVE_INTERFACE
,
375 if (EFI_ERROR (Status
)) {
376 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
377 FreeFrameListEntry (HcDev
);
378 DelMemoryManagement (HcDev
);
381 gBS
->FreePool (HcDev
);
386 &gEfiPciIoProtocolGuid
,
387 This
->DriverBindingHandle
,
394 // Install USB2.0 Host Controller Protocol
396 Status
= gBS
->InstallProtocolInterface (
398 &gEfiUsb2HcProtocolGuid
,
399 EFI_NATIVE_INTERFACE
,
402 if (EFI_ERROR (Status
)) {
403 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
404 FreeFrameListEntry (HcDev
);
405 DelMemoryManagement (HcDev
);
408 gBS
->FreePool (HcDev
);
413 &gEfiPciIoProtocolGuid
,
414 This
->DriverBindingHandle
,
422 // component name protocol.
425 HcDev
->ControllerNameTable
= NULL
;
428 gUhciComponentName
.SupportedLanguages
,
429 &HcDev
->ControllerNameTable
,
430 (CHAR16
*) L
"Usb Universal Host Controller"
438 UnInstallUHCInterface (
439 IN EFI_HANDLE Controller
,
440 IN EFI_USB_HC_PROTOCOL
*This
444 UnInstall UHCInterface
446 Controller - Controller handle
447 This - Protocol instance pointer.
457 HcDev
= USB_HC_DEV_FROM_THIS (This
);
459 gBS
->UninstallProtocolInterface (
461 &gEfiUsbHcProtocolGuid
,
465 gBS
->UninstallProtocolInterface (
467 &gEfiUsb2HcProtocolGuid
,
471 // first stop USB Host Controller
473 This
->SetState (This
, EfiUsbHcStateHalt
);
476 // Delete interrupt transfer polling timer
478 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
481 // Delete all the asynchronous interrupt transfers in the interrupt list
482 // and free associated memory
484 ReleaseInterruptList (HcDev
, &(HcDev
->InterruptListHead
));
487 // free Frame List Entry.
489 FreeFrameListEntry (HcDev
);
492 // Free common buffer allocated for QH,TD structures
494 DelMemoryManagement (HcDev
);
496 if (HcDev
->ControllerNameTable
) {
497 FreeUnicodeStringTable (HcDev
->ControllerNameTable
);
500 // Disable the USB Host Controller
502 Status
= HcDev
->PciIo
->Attributes (
504 EfiPciIoAttributeOperationSupported
,
508 if (!EFI_ERROR (Status
)) {
509 Supports
&= EFI_PCI_DEVICE_ENABLE
;
510 Status
= HcDev
->PciIo
->Attributes (
512 EfiPciIoAttributeOperationDisable
,
518 gBS
->FreePool (HcDev
);
526 UHCIDriverBindingStop (
527 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
528 IN EFI_HANDLE Controller
,
529 IN UINTN NumberOfChildren
,
530 IN EFI_HANDLE
*ChildHandleBuffer
535 Stop this driver on ControllerHandle. Support stoping any child handles
536 created by this driver.
539 This - Protocol instance pointer.
540 Controller - Handle of device to stop driver on
541 NumberOfChildren - Number of Children in the ChildHandleBuffer
542 ChildHandleBuffer - List of handles for the children we need to stop.
550 EFI_USB_HC_PROTOCOL
*UsbHc
;
551 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
552 EFI_STATUS OpenStatus
;
554 OpenStatus
= gBS
->OpenProtocol (
556 &gEfiUsbHcProtocolGuid
,
558 This
->DriverBindingHandle
,
560 EFI_OPEN_PROTOCOL_GET_PROTOCOL
564 // Test whether the Controller handler passed in is a valid
565 // Usb controller handle that should be supported, if not,
566 // return the error status directly
568 if (EFI_ERROR (OpenStatus
)) {
572 OpenStatus
= gBS
->OpenProtocol (
574 &gEfiUsb2HcProtocolGuid
,
576 This
->DriverBindingHandle
,
578 EFI_OPEN_PROTOCOL_GET_PROTOCOL
582 // Test whether the Controller handler passed in is a valid
583 // Usb controller handle that should be supported, if not,
584 // return the error status directly
586 if (EFI_ERROR (OpenStatus
)) {
590 // free all the controller related memory and uninstall UHCI Protocol.
592 UnInstallUHCInterface (Controller
, UsbHc
);
596 &gEfiPciIoProtocolGuid
,
597 This
->DriverBindingHandle
,
609 IN EFI_USB_HC_PROTOCOL
*This
,
615 Provides software reset for the USB host controller.
619 This A pointer to the EFI_USB_HC_PROTOCOL instance.
621 Attributes A bit mask of the reset operation to perform.
622 See below for a list of the supported bit mask values.
624 #define EFI_USB_HC_RESET_GLOBAL 0x0001
625 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
627 EFI_USB_HC_RESET_GLOBAL
628 If this bit is set, a global reset signal will be sent to the USB bus.
629 This resets all of the USB bus logic, including the USB host
630 controller hardware and all the devices attached on the USB bus.
631 EFI_USB_HC_RESET_HOST_CONTROLLER
632 If this bit is set, the USB host controller hardware will be reset.
633 No reset signal will be sent to the USB bus.
637 The reset operation succeeded.
638 EFI_INVALID_PARAMETER
639 Attributes is not valid.
641 An error was encountered while attempting to perform
647 UINT32 CommandRegAddr
;
648 UINT32 FlBaseAddrReg
;
653 HcDev
= USB_HC_DEV_FROM_THIS (This
);
655 CommandRegAddr
= (UINT32
) (USBCMD
);
656 FlBaseAddrReg
= (UINT32
) (USBFLBASEADD
);
658 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
661 // set the Global Reset bit in the command register
663 Status
= ReadUHCCommandReg (
668 if (EFI_ERROR (Status
)) {
669 return EFI_DEVICE_ERROR
;
672 Command
|= USBCMD_GRESET
;
673 Status
= WriteUHCCommandReg (
678 if (EFI_ERROR (Status
)) {
679 return EFI_DEVICE_ERROR
;
683 // Wait 50ms for root port to let reset complete
684 // See UHCI spec page122 Reset signaling
686 gBS
->Stall (ROOT_PORT_REST_TIME
);
689 // Clear the Global Reset bit to zero.
691 Command
&= ~USBCMD_GRESET
;
692 Status
= WriteUHCCommandReg (
697 if (EFI_ERROR (Status
)) {
698 return EFI_DEVICE_ERROR
;
701 // UHCI spec page120 reset recovery time
703 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
706 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
709 // set Host Controller Reset bit to 1
711 Status
= ReadUHCCommandReg (
716 if (EFI_ERROR (Status
)) {
717 return EFI_DEVICE_ERROR
;
720 Command
|= USBCMD_HCRESET
;
721 Status
= WriteUHCCommandReg (
726 if (EFI_ERROR (Status
)) {
727 return EFI_DEVICE_ERROR
;
730 // this bit will be reset by Host Controller when reset is completed.
731 // wait 10ms to let reset complete
733 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
737 return EFI_INVALID_PARAMETER
;
741 // Delete all old transactions on the USB bus
743 CleanUsbTransactions (HcDev
);
746 // Initialize Universal Host Controller's Frame List Data Structure
748 InitFrameList (HcDev
);
751 // Reset may cause Frame List Base Address Register reset to zero,
752 // so set the original value back again.
754 SetFrameListBaseAddress (
757 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
766 IN EFI_USB_HC_PROTOCOL
*This
,
767 OUT EFI_USB_HC_STATE
*State
772 Retrieves current state of the USB host controller.
776 This A pointer to the EFI_USB_HC_PROTOCOL instance.
778 State A pointer to the EFI_USB_HC_STATE data structure that
779 indicates current state of the USB host controller.
780 Type EFI_USB_HC_STATE is defined below.
784 EfiUsbHcStateOperational,
785 EfiUsbHcStateSuspend,
791 The state information of the host controller was returned in State.
792 EFI_INVALID_PARAMETER
795 An error was encountered while attempting to retrieve the
796 host controller's current state.
800 UINT32 CommandRegAddr
;
801 UINT32 StatusRegAddr
;
807 return EFI_INVALID_PARAMETER
;
810 HcDev
= USB_HC_DEV_FROM_THIS (This
);
812 CommandRegAddr
= (UINT32
) (USBCMD
);
813 StatusRegAddr
= (UINT32
) (USBSTS
);
815 Status
= ReadUHCCommandReg (
821 if (EFI_ERROR (Status
)) {
822 return EFI_DEVICE_ERROR
;
825 Status
= ReadUHCCommandReg (
830 if (EFI_ERROR (Status
)) {
831 return EFI_DEVICE_ERROR
;
834 if (UhcCommand
& USBCMD_EGSM
) {
835 *State
= EfiUsbHcStateSuspend
;
839 if ((UhcStatus
& USBSTS_HCH
) == 0) {
840 *State
= EfiUsbHcStateOperational
;
842 *State
= EfiUsbHcStateHalt
;
852 IN EFI_USB_HC_PROTOCOL
*This
,
853 IN EFI_USB_HC_STATE State
858 Sets the USB host controller to a specific state.
862 This A pointer to the EFI_USB_HC_PROTOCOL instance.
864 State Indicates the state of the host controller that will be set.
868 The USB host controller was successfully placed in the state
870 EFI_INVALID_PARAMETER
873 Failed to set the state specified by State due to device error.
877 UINT32 CommandRegAddr
;
878 UINT32 StatusRegAddr
;
880 EFI_USB_HC_STATE CurrentState
;
883 HcDev
= USB_HC_DEV_FROM_THIS (This
);
885 CommandRegAddr
= (UINT32
) (USBCMD
);
886 StatusRegAddr
= (UINT32
) (USBSTS
);
888 Status
= UHCIGetState (This
, &CurrentState
);
889 if (EFI_ERROR (Status
)) {
890 return EFI_DEVICE_ERROR
;
895 case EfiUsbHcStateHalt
:
896 if (CurrentState
== EfiUsbHcStateHalt
) {
900 Status
= ReadUHCCommandReg (
905 if (EFI_ERROR (Status
)) {
906 return EFI_DEVICE_ERROR
;
909 Command
&= ~USBCMD_RS
;
911 Status
= WriteUHCCommandReg (
916 if (EFI_ERROR (Status
)) {
917 return EFI_DEVICE_ERROR
;
920 StatusRegAddr
= (UINT32
) (USBSTS
);
922 // ensure the HC is in halt status after send the stop command
924 if (WaitForUHCHalt (HcDev
->PciIo
, StatusRegAddr
, STALL_1_SECOND
) == EFI_TIMEOUT
) {
925 return EFI_DEVICE_ERROR
;
929 case EfiUsbHcStateOperational
:
930 if (IsHostSysOrProcessErr (HcDev
->PciIo
, StatusRegAddr
)) {
931 return EFI_DEVICE_ERROR
;
934 switch (CurrentState
) {
936 case EfiUsbHcStateOperational
:
939 case EfiUsbHcStateHalt
:
941 // Set Run/Stop bit to 1.
943 Status
= ReadUHCCommandReg (
948 if (EFI_ERROR (Status
)) {
949 return EFI_DEVICE_ERROR
;
952 Command
|= USBCMD_RS
| USBCMD_MAXP
;
953 Status
= WriteUHCCommandReg (
958 if (EFI_ERROR (Status
)) {
959 return EFI_DEVICE_ERROR
;
964 case EfiUsbHcStateSuspend
:
965 Status
= ReadUHCCommandReg (
970 if (EFI_ERROR (Status
)) {
971 return EFI_DEVICE_ERROR
;
975 // FGR(Force Global Resume) bit is 0
977 if ((Command
| (~USBCMD_FGR
)) != 0xFF) {
979 // Write FGR bit to 1
981 Command
|= USBCMD_FGR
;
990 // wait 20ms to let resume complete
991 // (20ms is specified by UHCI spec)
993 gBS
->Stall (FORCE_GLOBAL_RESUME_TIME
);
996 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
998 Command
&= ~USBCMD_FGR
;
999 Command
&= ~USBCMD_EGSM
;
1000 Command
|= USBCMD_RS
;
1001 WriteUHCCommandReg (
1013 case EfiUsbHcStateSuspend
:
1014 if (CurrentState
== EfiUsbHcStateSuspend
) {
1018 Status
= UHCISetState (This
, EfiUsbHcStateHalt
);
1019 if (EFI_ERROR (Status
)) {
1020 return EFI_DEVICE_ERROR
;
1023 // Set Enter Global Suspend Mode bit to 1.
1025 Status
= ReadUHCCommandReg (
1030 if (EFI_ERROR (Status
)) {
1031 return EFI_DEVICE_ERROR
;
1034 Command
|= USBCMD_EGSM
;
1035 Status
= WriteUHCCommandReg (
1040 if (EFI_ERROR (Status
)) {
1041 return EFI_DEVICE_ERROR
;
1046 return EFI_INVALID_PARAMETER
;
1054 UHCIGetRootHubPortNumber (
1055 IN EFI_USB_HC_PROTOCOL
*This
,
1056 OUT UINT8
*PortNumber
1060 Routine Description:
1061 Retrieves the number of root hub ports.
1065 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1067 PortNumber A pointer to the number of the root hub ports.
1071 The port number was retrieved successfully.
1072 EFI_INVALID_PARAMETER
1075 An error was encountered while attempting to
1076 retrieve the port number.
1081 UINT16 RHPortControl
;
1085 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1087 if (PortNumber
== NULL
) {
1088 return EFI_INVALID_PARAMETER
;
1093 for (Index
= 0; Index
< 2; Index
++) {
1094 PSAddr
= (UINT32
) (USBPORTSC1
+ Index
* 2);
1095 Status
= ReadRootPortReg (
1100 if (EFI_ERROR (Status
)) {
1101 return EFI_DEVICE_ERROR
;
1104 // Port Register content is valid
1106 if (RHPortControl
!= 0xff) {
1116 UHCIGetRootHubPortStatus (
1117 IN EFI_USB_HC_PROTOCOL
*This
,
1118 IN UINT8 PortNumber
,
1119 OUT EFI_USB_PORT_STATUS
*PortStatus
1123 Routine Description:
1124 Retrieves the current status of a USB root hub port.
1128 This A pointer to the EFI_USB_HC_PROTOCOL.
1130 PortNumber Specifies the root hub port from which the status
1131 is to be retrieved. This value is zero-based. For example,
1132 if a root hub has two ports, then the first port is numbered 0,
1133 and the second port is numbered 1.
1135 PortStatus A pointer to the current port status bits and
1136 port status change bits.
1140 The status of the USB root hub port specified by PortNumber
1141 was returned in PortStatus.
1142 EFI_INVALID_PARAMETER
1143 PortNumber is invalid.
1144 EFI_DEVICE_ERROR - Can't read register
1149 UINT16 RHPortStatus
;
1150 UINT8 TotalPortNumber
;
1153 if (PortStatus
== NULL
) {
1154 return EFI_INVALID_PARAMETER
;
1157 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1158 if (PortNumber
>= TotalPortNumber
) {
1159 return EFI_INVALID_PARAMETER
;
1162 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1163 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1166 // Clear port status
1168 PortStatus
->PortStatus
= 0;
1169 PortStatus
->PortChangeStatus
= 0;
1171 Status
= ReadRootPortReg (
1177 if (EFI_ERROR (Status
)) {
1178 return EFI_DEVICE_ERROR
;
1181 // Fill Port Status bits
1185 // Current Connect Status
1187 if (RHPortStatus
& USBPORTSC_CCS
) {
1188 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
1191 // Port Enabled/Disabled
1193 if (RHPortStatus
& USBPORTSC_PED
) {
1194 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
1200 if (RHPortStatus
& USBPORTSC_SUSP
) {
1201 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1207 if (RHPortStatus
& USBPORTSC_PR
) {
1208 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
1212 // Low Speed Device Attached
1214 if (RHPortStatus
& USBPORTSC_LSDA
) {
1215 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1218 // CHC will always return one in this bit
1220 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
1222 // Fill Port Status Change bits
1226 // Connect Status Change
1228 if (RHPortStatus
& USBPORTSC_CSC
) {
1229 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
1233 // Port Enabled/Disabled Change
1235 if (RHPortStatus
& USBPORTSC_PEDC
) {
1236 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
1244 UHCISetRootHubPortFeature (
1245 IN EFI_USB_HC_PROTOCOL
*This
,
1246 IN UINT8 PortNumber
,
1247 IN EFI_USB_PORT_FEATURE PortFeature
1251 Routine Description:
1252 Sets a feature for the specified root hub port.
1256 This A pointer to the EFI_USB_HC_PROTOCOL.
1258 PortNumber Specifies the root hub port whose feature
1259 is requested to be set.
1261 PortFeature Indicates the feature selector associated
1262 with the feature set request.
1266 The feature specified by PortFeature was set for the
1267 USB root hub port specified by PortNumber.
1268 EFI_INVALID_PARAMETER
1269 PortNumber is invalid or PortFeature is invalid.
1276 UINT32 CommandRegAddr
;
1278 // root hub port status
1280 UINT16 RHPortControl
;
1282 UINT8 TotalPortNumber
;
1285 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1286 if (PortNumber
>= TotalPortNumber
) {
1287 return EFI_INVALID_PARAMETER
;
1290 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1292 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1293 CommandRegAddr
= (UINT32
) (USBCMD
);
1295 Status
= ReadRootPortReg (
1300 if (EFI_ERROR (Status
)) {
1301 return EFI_DEVICE_ERROR
;
1304 switch (PortFeature
) {
1306 case EfiUsbPortSuspend
:
1307 Status
= ReadUHCCommandReg (
1312 if (EFI_ERROR (Status
)) {
1313 return EFI_DEVICE_ERROR
;
1316 if (!(Command
& USBCMD_EGSM
)) {
1318 // if global suspend is not active, can set port suspend
1320 RHPortControl
&= 0xfff5;
1321 RHPortControl
|= USBPORTSC_SUSP
;
1325 case EfiUsbPortReset
:
1326 RHPortControl
&= 0xfff5;
1328 // Set the reset bit
1330 RHPortControl
|= USBPORTSC_PR
;
1333 case EfiUsbPortPower
:
1336 case EfiUsbPortEnable
:
1337 RHPortControl
&= 0xfff5;
1338 RHPortControl
|= USBPORTSC_PED
;
1342 return EFI_INVALID_PARAMETER
;
1356 UHCIClearRootHubPortFeature (
1357 IN EFI_USB_HC_PROTOCOL
*This
,
1358 IN UINT8 PortNumber
,
1359 IN EFI_USB_PORT_FEATURE PortFeature
1363 Routine Description:
1364 Clears a feature for the specified root hub port.
1368 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1370 PortNumber Specifies the root hub port whose feature
1371 is requested to be cleared.
1373 PortFeature Indicates the feature selector associated with the
1374 feature clear request.
1378 The feature specified by PortFeature was cleared for the
1379 USB root hub port specified by PortNumber.
1380 EFI_INVALID_PARAMETER
1381 PortNumber is invalid or PortFeature is invalid.
1388 UINT16 RHPortControl
;
1389 UINT8 TotalPortNumber
;
1392 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1394 if (PortNumber
>= TotalPortNumber
) {
1395 return EFI_INVALID_PARAMETER
;
1398 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1399 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1401 Status
= ReadRootPortReg (
1406 if (EFI_ERROR (Status
)) {
1407 return EFI_DEVICE_ERROR
;
1410 switch (PortFeature
) {
1412 // clear PORT_ENABLE feature means disable port.
1414 case EfiUsbPortEnable
:
1415 RHPortControl
&= 0xfff5;
1416 RHPortControl
&= ~USBPORTSC_PED
;
1420 // clear PORT_SUSPEND feature means resume the port.
1421 // (cause a resume on the specified port if in suspend mode)
1423 case EfiUsbPortSuspend
:
1424 RHPortControl
&= 0xfff5;
1425 RHPortControl
&= ~USBPORTSC_SUSP
;
1431 case EfiUsbPortPower
:
1435 // clear PORT_RESET means clear the reset signal.
1437 case EfiUsbPortReset
:
1438 RHPortControl
&= 0xfff5;
1439 RHPortControl
&= ~USBPORTSC_PR
;
1443 // clear connect status change
1445 case EfiUsbPortConnectChange
:
1446 RHPortControl
&= 0xfff5;
1447 RHPortControl
|= USBPORTSC_CSC
;
1451 // clear enable/disable status change
1453 case EfiUsbPortEnableChange
:
1454 RHPortControl
&= 0xfff5;
1455 RHPortControl
|= USBPORTSC_PEDC
;
1459 // root hub does not support this request
1461 case EfiUsbPortSuspendChange
:
1465 // root hub does not support this request
1467 case EfiUsbPortOverCurrentChange
:
1471 // root hub does not support this request
1473 case EfiUsbPortResetChange
:
1477 return EFI_INVALID_PARAMETER
;
1491 UHCIControlTransfer (
1492 IN EFI_USB_HC_PROTOCOL
*This
,
1493 IN UINT8 DeviceAddress
,
1494 IN BOOLEAN IsSlowDevice
,
1495 IN UINT8 MaximumPacketLength
,
1496 IN EFI_USB_DEVICE_REQUEST
*Request
,
1497 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1498 IN OUT VOID
*Data
, OPTIONAL
1499 IN OUT UINTN
*DataLength
, OPTIONAL
1501 OUT UINT32
*TransferResult
1505 Routine Description:
1506 Submits control transfer to a target USB device.
1510 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1512 DeviceAddress Represents the address of the target device on the USB,
1513 which is assigned during USB enumeration.
1515 IsSlowDevice Indicates whether the target device is slow device
1516 or full-speed device.
1518 MaximumPacketLength Indicates the maximum packet size that the
1519 default control transfer endpoint is capable of
1520 sending or receiving.
1522 Request A pointer to the USB device request that will be sent
1525 TransferDirection Specifies the data direction for the transfer.
1526 There are three values available, DataIn, DataOut
1529 Data A pointer to the buffer of data that will be transmitted
1530 to USB device or received from USB device.
1532 DataLength Indicates the size, in bytes, of the data buffer
1535 TimeOut Indicates the maximum time, in microseconds,
1536 which the transfer is allowed to complete.
1538 TransferResult A pointer to the detailed result information generated
1539 by this control transfer.
1543 The control transfer was completed successfully.
1544 EFI_OUT_OF_RESOURCES
1545 The control transfer could not be completed due to a lack of resources.
1546 EFI_INVALID_PARAMETER
1547 Some parameters are invalid.
1549 The control transfer failed due to timeout.
1551 The control transfer failed due to host controller or device error.
1552 Caller should check TranferResult for detailed error information.
1562 TD_STRUCT
*PtrPreTD
;
1563 TD_STRUCT
*PtrSetupTD
;
1564 TD_STRUCT
*PtrStatusTD
;
1568 UINT8
*PtrDataSource
;
1571 UINT16 LoadFrameListIndex
;
1574 UINT8
*RequestMappedAddress
;
1575 VOID
*RequestMapping
;
1578 EFI_PHYSICAL_ADDRESS TempPtr
;
1581 TD_STRUCT
*PtrFirstDataTD
;
1582 TD_STRUCT
*ptrLastDataTD
;
1586 RequestMappedAddress
= NULL
;
1587 RequestMapping
= NULL
;
1589 PtrFirstDataTD
= NULL
;
1590 ptrLastDataTD
= NULL
;
1591 PktID
= INPUT_PACKET_ID
;
1593 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1594 StatusReg
= (UINT32
) (USBSTS
);
1595 FrameNumReg
= (UINT32
) (USBFRNUM
);
1600 // Parameters Checking
1602 if (Request
== NULL
|| TransferResult
== NULL
) {
1603 return EFI_INVALID_PARAMETER
;
1607 // if errors exist that cause host controller halt,
1608 // then return EFI_DEVICE_ERROR.
1610 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
1612 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
1613 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1614 return EFI_DEVICE_ERROR
;
1618 // low speed usb devices are limited to only an eight-byte
1619 // maximum data payload size
1621 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
1622 return EFI_INVALID_PARAMETER
;
1625 if (MaximumPacketLength
!= 8 &&
1626 MaximumPacketLength
!= 16 &&
1627 MaximumPacketLength
!= 32 &&
1628 MaximumPacketLength
!= 64) {
1629 return EFI_INVALID_PARAMETER
;
1632 if ((TransferDirection
!= EfiUsbNoData
) && (DataLength
== NULL
)) {
1633 return EFI_INVALID_PARAMETER
;
1636 switch (TransferDirection
) {
1639 PktID
= INPUT_PACKET_ID
;
1640 PtrDataSource
= Data
;
1641 DataLen
= *DataLength
;
1644 // map the source data buffer for bus master access.
1645 // BusMasterWrite means cpu read
1647 Status
= HcDev
->PciIo
->Map (
1649 EfiPciIoOperationBusMasterWrite
,
1655 if (EFI_ERROR (Status
)) {
1659 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
1663 PktID
= OUTPUT_PACKET_ID
;
1664 PtrDataSource
= Data
;
1665 DataLen
= *DataLength
;
1668 // map the source data buffer for bus master access.
1669 // BusMasterRead means cpu write
1671 Status
= HcDev
->PciIo
->Map (
1673 EfiPciIoOperationBusMasterRead
,
1679 if (EFI_ERROR (Status
)) {
1683 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
1690 if ((DataLength
!= NULL
) && (*DataLength
!= 0)) {
1691 return EFI_INVALID_PARAMETER
;
1694 PktID
= OUTPUT_PACKET_ID
;
1695 PtrDataSource
= NULL
;
1701 return EFI_INVALID_PARAMETER
;
1704 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
1705 if (EFI_ERROR (Status
)) {
1706 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1707 return EFI_DEVICE_ERROR
;
1710 // create QH structure and init
1712 Status
= CreateQH (HcDev
, &PtrQH
);
1713 if (EFI_ERROR (Status
)) {
1714 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1719 // map the Request for bus master access.
1720 // BusMasterRead means cpu write
1722 RequestLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
1723 Status
= HcDev
->PciIo
->Map (
1725 EfiPciIoOperationBusMasterRead
,
1732 if (EFI_ERROR (Status
)) {
1733 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1734 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1738 RequestMappedAddress
= (UINT8
*) ((UINTN
) TempPtr
);
1741 // generate Setup Stage TD
1743 Status
= GenSetupStageTD (
1748 (UINT8
*) RequestMappedAddress
,
1749 sizeof (EFI_USB_DEVICE_REQUEST
),
1753 if (EFI_ERROR (Status
)) {
1754 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1755 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1756 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
1761 // Data Stage of Control Transfer
1765 while (DataLen
> 0) {
1767 // create TD structures and link together
1771 // PktSize is the data load size that each TD carries.
1773 PktSize
= (UINT8
) DataLen
;
1774 if (DataLen
> MaximumPacketLength
) {
1775 PktSize
= MaximumPacketLength
;
1778 Status
= GenDataTD (
1790 if (EFI_ERROR (Status
)) {
1792 // free all resources occupied
1794 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1795 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1796 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
1797 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
1798 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
1803 // Link two TDs in vertical depth
1806 PtrFirstDataTD
= PtrTD
;
1807 PtrFirstDataTD
->ptrNextTD
= NULL
;
1810 LinkTDToTD (PtrPreTD
, PtrTD
);
1820 ptrLastDataTD
= PtrTD
;
1823 // Status Stage of Control Transfer
1825 if (PktID
== OUTPUT_PACKET_ID
) {
1826 PktID
= INPUT_PACKET_ID
;
1828 PktID
= OUTPUT_PACKET_ID
;
1832 // create Status Stage TD structure
1834 Status
= CreateStatusTD (
1843 if (EFI_ERROR (Status
)) {
1844 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1845 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1846 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
1847 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
1848 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
1854 // link setup TD structures to QH structure
1856 LinkTDToQH (PtrQH
, PtrSetupTD
);
1858 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
1861 // link QH-TDs to total 100 frame list entry to speed up the execution.
1863 for (Index
= 0; Index
< 100; Index
++) {
1865 HcDev
->FrameListEntry
,
1866 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1871 // Poll QH-TDs execution and get result.
1872 // detail status is returned
1874 Status
= ExecuteControlTransfer (
1883 // Remove Control Transfer QH-TDs structure from the frame list
1884 // and update the pointers in the Frame List
1885 // and other pointers in other related QH structures.
1887 for (Index
= 0; Index
< 100; Index
++) {
1891 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1897 // delete setup stage TD; the QH is reserved for the next stages.
1899 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
1902 // if setup stage error, return error
1904 if (EFI_ERROR (Status
)) {
1908 // some control transfers do not have Data Stage
1910 if (PtrFirstDataTD
!= NULL
) {
1912 LinkTDToQH (PtrQH
, PtrFirstDataTD
);
1913 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
1915 for (Index
= 0; Index
< 500; Index
++) {
1917 HcDev
->FrameListEntry
,
1918 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1923 Status
= ExecuteControlTransfer (
1932 for (Index
= 0; Index
< 500; Index
++) {
1936 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1942 // delete data stage TD; the QH is reserved for the next stage.
1944 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
1947 // if data stage error, goto done and return error
1949 if (EFI_ERROR (Status
)) {
1953 LinkTDToQH (PtrQH
, PtrStatusTD
);
1955 // get the frame list index that the QH-TDs will be linked to.
1957 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
1959 for (Index
= 0; Index
< 100; Index
++) {
1961 // put the QH-TDs directly or indirectly into the proper place
1962 // in the Frame List
1965 HcDev
->FrameListEntry
,
1966 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1971 // Poll QH-TDs execution and get result.
1972 // detail status is returned
1974 Status
= ExecuteControlTransfer (
1984 // Delete Control Transfer QH-TDs structure
1985 // and update the pointers in the Frame List
1986 // and other pointers in other related QH structures.
1988 // TRUE means must search other framelistindex
1990 for (Index
= 0; Index
< 100; Index
++) {
1994 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2000 DeleteQueuedTDs (HcDev
, PtrStatusTD
);
2004 // link setup stage TD with data stage TD
2006 PtrPreTD
= PtrSetupTD
;
2007 if (PtrFirstDataTD
!= NULL
) {
2008 LinkTDToTD (PtrSetupTD
, PtrFirstDataTD
);
2009 PtrPreTD
= ptrLastDataTD
;
2012 // link status TD with previous TD
2014 LinkTDToTD (PtrPreTD
, PtrStatusTD
);
2019 LinkTDToQH (PtrQH
, PtrSetupTD
);
2021 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2022 for (Index
= 0; Index
< 500; Index
++) {
2024 // put the QH-TDs directly or indirectly into the proper place
2025 // in the Frame List
2028 HcDev
->FrameListEntry
,
2029 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2034 // Poll QH-TDs execution and get result.
2035 // detail status is returned
2037 Status
= ExecuteControlTransfer (
2046 // Remove Control Transfer QH-TDs structure from the frame list
2047 // and update the pointers in the Frame List
2048 // and other pointers in other related QH structures.
2050 for (Index
= 0; Index
< 500; Index
++) {
2054 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2060 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2065 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2067 if (Mapping
!= NULL
) {
2068 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2071 if (RequestMapping
!= NULL
) {
2072 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2075 // if has errors that cause host controller halt,
2076 // then return EFI_DEVICE_ERROR directly.
2078 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2080 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2081 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2082 return EFI_DEVICE_ERROR
;
2085 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2086 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2093 IN EFI_USB_HC_PROTOCOL
*This
,
2094 IN UINT8 DeviceAddress
,
2095 IN UINT8 EndPointAddress
,
2096 IN UINT8 MaximumPacketLength
,
2098 IN OUT UINTN
*DataLength
,
2099 IN OUT UINT8
*DataToggle
,
2101 OUT UINT32
*TransferResult
2105 Routine Description:
2106 Submits bulk transfer to a bulk endpoint of a USB device.
2110 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2112 DeviceAddress Represents the address of the target device on the USB,
2113 which is assigned during USB enumeration.
2114 EndPointAddress The combination of an endpoint number and an
2115 endpoint direction of the target USB device.
2116 Each endpoint address supports data transfer in
2117 one direction except the control endpoint
2118 (whose default endpoint address is 0).
2119 It is the caller's responsibility to make sure that
2120 the EndPointAddress represents a bulk endpoint.
2122 MaximumPacketLength Indicates the maximum packet size the target endpoint
2123 is capable of sending or receiving.
2125 Data A pointer to the buffer of data that will be transmitted
2126 to USB device or received from USB device.
2127 DataLength When input, indicates the size, in bytes, of the data buffer
2128 specified by Data. When output, indicates the actually
2129 transferred data size.
2131 DataToggle A pointer to the data toggle value. On input, it indicates
2132 the initial data toggle value the bulk transfer should adopt;
2133 on output, it is updated to indicate the data toggle value
2134 of the subsequent bulk transfer.
2136 TimeOut Indicates the maximum time, in microseconds, which the
2137 transfer is allowed to complete.
2139 TransferResult A pointer to the detailed result information of the
2144 The bulk transfer was completed successfully.
2145 EFI_OUT_OF_RESOURCES
2146 The bulk transfer could not be submitted due to lack of resource.
2147 EFI_INVALID_PARAMETER
2148 Some parameters are invalid.
2150 The bulk transfer failed due to timeout.
2152 The bulk transfer failed due to host controller or device error.
2153 Caller should check TranferResult for detailed error information.
2162 TD_STRUCT
*PtrFirstTD
;
2164 TD_STRUCT
*PtrPreTD
;
2165 UINT16 LoadFrameListIndex
;
2166 UINT16 SavedFrameListIndex
;
2168 UINT8
*PtrDataSource
;
2175 EFI_USB_DATA_DIRECTION TransferDirection
;
2177 // Used to calculate how many entries are linked to the
2178 // specified bulk transfer QH-TDs
2182 BOOLEAN ShortPacketEnable
;
2183 EFI_PHYSICAL_ADDRESS TempPtr
;
2186 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2187 StatusReg
= (UINT32
) (USBSTS
);
2188 FrameNumReg
= (UINT32
) (USBFRNUM
);
2189 PktID
= INPUT_PACKET_ID
;
2196 ShortPacketEnable
= FALSE
;
2200 // Parameters Checking
2203 if ((DataLength
== NULL
) ||
2205 (TransferResult
== NULL
)) {
2206 return EFI_INVALID_PARAMETER
;
2210 // if has errors that cause host controller halt,
2211 // then return EFI_DEVICE_ERROR directly.
2213 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2215 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2216 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2217 return EFI_DEVICE_ERROR
;
2220 if (*DataLength
== 0) {
2221 return EFI_INVALID_PARAMETER
;
2224 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2225 return EFI_INVALID_PARAMETER
;
2228 if (MaximumPacketLength
!= 8 &&
2229 MaximumPacketLength
!= 16 &&
2230 MaximumPacketLength
!= 32 &&
2231 MaximumPacketLength
!= 64) {
2232 return EFI_INVALID_PARAMETER
;
2236 // Enable the maximum packet size (64bytes)
2237 // that can be used for full speed bandwidth reclamation
2238 // at the end of a frame.
2240 EnableMaxPacketSize (HcDev
);
2242 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2243 if (EFI_ERROR (Status
)) {
2244 return EFI_DEVICE_ERROR
;
2248 // construct QH and TD data structures,
2249 // and link them together
2251 if (EndPointAddress
& 0x80) {
2252 TransferDirection
= EfiUsbDataIn
;
2254 TransferDirection
= EfiUsbDataOut
;
2257 switch (TransferDirection
) {
2260 ShortPacketEnable
= TRUE
;
2261 PktID
= INPUT_PACKET_ID
;
2262 PtrDataSource
= Data
;
2263 DataLen
= *DataLength
;
2266 // BusMasterWrite means cpu read
2268 Status
= HcDev
->PciIo
->Map (
2270 EfiPciIoOperationBusMasterWrite
,
2276 if (EFI_ERROR (Status
)) {
2280 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2284 PktID
= OUTPUT_PACKET_ID
;
2285 PtrDataSource
= Data
;
2286 DataLen
= *DataLength
;
2289 // BusMasterRead means cpu write
2291 Status
= HcDev
->PciIo
->Map (
2293 EfiPciIoOperationBusMasterRead
,
2299 if (EFI_ERROR (Status
)) {
2303 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2307 return EFI_INVALID_PARAMETER
;
2311 // create QH structure and init
2313 Status
= CreateQH (HcDev
, &PtrQH
);
2314 if (EFI_ERROR (Status
)) {
2315 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2320 // i is used to calculate the total number of TDs.
2325 while (DataLen
> 0) {
2328 // create TD structures and link together
2331 PktSize
= (UINT8
) DataLen
;
2332 if (DataLen
> MaximumPacketLength
) {
2333 PktSize
= MaximumPacketLength
;
2336 Status
= GenDataTD (
2348 if (EFI_ERROR (Status
)) {
2349 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2350 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2351 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2356 // Enable short packet detection.
2357 // (default action is disabling short packet detection)
2359 if (ShortPacketEnable
) {
2360 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
2365 PtrFirstTD
->ptrNextTD
= NULL
;
2369 // Link two TDs in vertical depth
2371 LinkTDToTD (PtrPreTD
, PtrTD
);
2384 // link TD structures to QH structure
2386 LinkTDToQH (PtrQH
, PtrFirstTD
);
2389 // calculate how many entries are linked to the specified bulk transfer QH-TDs
2390 // the below values are referred to the USB spec revision1.1.
2392 switch (MaximumPacketLength
) {
2394 LinkTimes
= Index
/ 71 + 1;
2398 LinkTimes
= Index
/ 51 + 1;
2402 LinkTimes
= Index
/ 33 + 1;
2406 LinkTimes
= Index
/ 19 + 1;
2413 // put QH-TDs into Frame list
2415 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2416 SavedFrameListIndex
= LoadFrameListIndex
;
2418 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2421 // put the QH-TD directly or indirectly into the proper place
2422 // in the Frame List
2424 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
2426 LoadFrameListIndex
+= 1;
2427 LoadFrameListIndex
&= 0x3FF;
2430 LoadFrameListIndex
= SavedFrameListIndex
;
2433 // Execute QH-TD and get result
2436 // detail status is put into the Result field in the pIRP
2437 // the Data Toggle value is also re-updated to the value
2438 // of the last successful TD
2440 Status
= ExecBulkorSyncInterruptTransfer (
2451 // Delete Bulk transfer QH-TD structure
2452 // and maitain the pointers in the Frame List
2453 // and other pointers in related QH structure
2455 // TRUE means must search other framelistindex
2457 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2465 LoadFrameListIndex
+= 1;
2466 LoadFrameListIndex
&= 0x3FF;
2469 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2471 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2473 if (Mapping
!= NULL
) {
2474 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2478 // if has errors that cause host controller halt,
2479 // then return EFI_DEVICE_ERROR directly.
2481 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2483 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2484 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2485 return EFI_DEVICE_ERROR
;
2488 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2490 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2497 UHCIAsyncInterruptTransfer (
2498 IN EFI_USB_HC_PROTOCOL
* This
,
2499 IN UINT8 DeviceAddress
,
2500 IN UINT8 EndPointAddress
,
2501 IN BOOLEAN IsSlowDevice
,
2502 IN UINT8 MaximumPacketLength
,
2503 IN BOOLEAN IsNewTransfer
,
2504 IN OUT UINT8
*DataToggle
,
2505 IN UINTN PollingInterval
, OPTIONAL
2506 IN UINTN DataLength
, OPTIONAL
2507 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
2508 IN VOID
*Context OPTIONAL
2512 Routine Description:
2513 Submits an asynchronous interrupt transfer to an
2514 interrupt endpoint of a USB device.
2518 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2520 DeviceAddress Represents the address of the target device on the USB,
2521 which is assigned during USB enumeration.
2523 EndPointAddress The combination of an endpoint number and an endpoint
2524 direction of the target USB device. Each endpoint address
2525 supports data transfer in one direction except the
2526 control endpoint (whose default endpoint address is 0).
2527 It is the caller's responsibility to make sure that
2528 the EndPointAddress represents an interrupt endpoint.
2530 IsSlowDevice Indicates whether the target device is slow device
2531 or full-speed device.
2533 MaximumPacketLength Indicates the maximum packet size the target endpoint
2534 is capable of sending or receiving.
2536 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
2537 the host and the target interrupt endpoint.
2538 If FALSE, the specified asynchronous interrupt pipe
2541 DataToggle A pointer to the data toggle value. On input, it is valid
2542 when IsNewTransfer is TRUE, and it indicates the initial
2543 data toggle value the asynchronous interrupt transfer
2545 On output, it is valid when IsNewTransfer is FALSE,
2546 and it is updated to indicate the data toggle value of
2547 the subsequent asynchronous interrupt transfer.
2549 PollingInterval Indicates the interval, in milliseconds, that the
2550 asynchronous interrupt transfer is polled.
2551 This parameter is required when IsNewTransfer is TRUE.
2553 DataLength Indicates the length of data to be received at the
2554 rate specified by PollingInterval from the target
2555 asynchronous interrupt endpoint. This parameter
2556 is only required when IsNewTransfer is TRUE.
2558 CallBackFunction The Callback function.This function is called at the
2559 rate specified by PollingInterval.This parameter is
2560 only required when IsNewTransfer is TRUE.
2562 Context The context that is passed to the CallBackFunction.
2563 This is an optional parameter and may be NULL.
2567 The asynchronous interrupt transfer request has been successfully
2568 submitted or canceled.
2569 EFI_INVALID_PARAMETER
2570 Some parameters are invalid.
2571 EFI_OUT_OF_RESOURCES
2572 The request could not be completed due to a lack of resources.
2581 QH_STRUCT
*ptrFirstQH
;
2583 QH_STRUCT
*ptrPreQH
;
2584 TD_STRUCT
*PtrFirstTD
;
2586 TD_STRUCT
*PtrPreTD
;
2587 UINT16 LoadFrameListIndex
;
2595 BOOLEAN ShortPacketEnable
;
2596 UINT8 CurrentDataToggle
;
2597 EFI_PHYSICAL_ADDRESS TempPtr
;
2603 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2604 StatusReg
= (UINT32
) (USBSTS
);
2605 FrameNumReg
= (UINT32
) (USBFRNUM
);
2607 ShortPacketEnable
= FALSE
;
2609 PktID
= INPUT_PACKET_ID
;
2618 if ((EndPointAddress
& 0x80) == 0) {
2619 return EFI_INVALID_PARAMETER
;
2623 // delete Async interrupt transfer request
2625 if (!IsNewTransfer
) {
2627 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
2629 Status
= DeleteAsyncINTQHTDs (
2636 gBS
->RestoreTPL (OldTpl
);
2641 // if has errors that cause host controller halt,
2642 // then return EFI_DEVICE_ERROR directly.
2644 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2646 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2647 return EFI_DEVICE_ERROR
;
2650 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2653 // submit Async interrupt transfer request
2655 if (PollingInterval
< 1 || PollingInterval
> 255) {
2656 return EFI_INVALID_PARAMETER
;
2659 if (DataLength
== 0) {
2660 return EFI_INVALID_PARAMETER
;
2663 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2664 return EFI_INVALID_PARAMETER
;
2667 ShortPacketEnable
= TRUE
;
2668 PktID
= INPUT_PACKET_ID
;
2669 DataLen
= DataLength
;
2670 Ptr
= AllocatePool (DataLen
);
2672 return EFI_OUT_OF_RESOURCES
;
2676 // BusMasterWrite means cpu read
2678 Status
= HcDev
->PciIo
->Map (
2680 EfiPciIoOperationBusMasterWrite
,
2686 if (EFI_ERROR (Status
)) {
2687 gBS
->FreePool (Ptr
);
2691 MappedPtr
= (UINT8
*) ((UINTN
) TempPtr
);
2693 CurrentDataToggle
= *DataToggle
;
2697 while (DataLen
> 0) {
2699 // create TD structures and link together
2702 PktSize
= (UINT8
) DataLen
;
2703 if (DataLen
> MaximumPacketLength
) {
2704 PktSize
= MaximumPacketLength
;
2707 Status
= GenDataTD (
2718 if (EFI_ERROR (Status
)) {
2719 gBS
->FreePool (Ptr
);
2720 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2721 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2725 // Enable short packet detection.
2727 if (ShortPacketEnable
) {
2728 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
2733 PtrFirstTD
->ptrNextTD
= NULL
;
2737 // Link two TDs in vertical depth
2739 LinkTDToTD (PtrPreTD
, PtrTD
);
2744 CurrentDataToggle
^= 1;
2745 MappedPtr
+= PktSize
;
2750 // roll one value back
2752 CurrentDataToggle
^= 1;
2755 // create a list of QH structures and init,
2756 // link TDs to all the QHs, and link all the QHs together using internal
2757 // defined pointer of the QH_STRUCT.
2761 for (Index
= 0; Index
< 1024;) {
2763 Status
= CreateQH (HcDev
, &PtrQH
);
2764 if (EFI_ERROR (Status
)) {
2765 gBS
->FreePool (Ptr
);
2766 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2767 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2771 PtrQH
= TempQH
->ptrNextIntQH
;
2772 UhciFreePool (HcDev
, (UINT8
*) TempQH
, sizeof (QH_STRUCT
));
2779 // link TD structures to QH structure
2781 LinkTDToQH (PtrQH
, PtrFirstTD
);
2785 ptrFirstQH
->ptrNextIntQH
= NULL
;
2789 // link neighbor QH structures together
2791 ptrPreQH
->ptrNextIntQH
= PtrQH
;
2796 Index
= (UINT16
) (PollingInterval
+ Index
);
2799 // last QH in QH list should set its next QH pointer to NULL.
2801 PtrQH
->ptrNextIntQH
= NULL
;
2804 // Save QH-TD structures in Interrupt transfer list,
2805 // for monitor interrupt transfer execution routine use.
2807 InsertQHTDToINTList (
2823 // put QHs-TDs into Frame list
2825 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2829 for (Index
= LoadFrameListIndex
; Index
< (1024 + LoadFrameListIndex
);) {
2832 // put the QH-TD directly or indirectly into the proper place
2833 // in the Frame List
2835 LinkQHToFrameList (HcDev
->FrameListEntry
, (UINT16
) (Index
& 0x3FF), PtrQH
);
2837 Index
= (UINT16
) (PollingInterval
+ Index
);
2839 PtrQH
= PtrQH
->ptrNextIntQH
;
2842 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2849 UHCISyncInterruptTransfer (
2850 IN EFI_USB_HC_PROTOCOL
*This
,
2851 IN UINT8 DeviceAddress
,
2852 IN UINT8 EndPointAddress
,
2853 IN BOOLEAN IsSlowDevice
,
2854 IN UINT8 MaximumPacketLength
,
2856 IN OUT UINTN
*DataLength
,
2857 IN OUT UINT8
*DataToggle
,
2859 OUT UINT32
*TransferResult
2863 Routine Description:
2864 Submits synchronous interrupt transfer to an interrupt endpoint
2869 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2871 DeviceAddress Represents the address of the target device on the USB,
2872 which is assigned during USB enumeration.
2874 EndPointAddress The combination of an endpoint number and an endpoint
2875 direction of the target USB device. Each endpoint
2876 address supports data transfer in one direction
2877 except the control endpoint (whose default
2878 endpoint address is 0). It is the caller's responsibility
2879 to make sure that the EndPointAddress represents
2880 an interrupt endpoint.
2882 IsSlowDevice Indicates whether the target device is slow device
2883 or full-speed device.
2885 MaximumPacketLength Indicates the maximum packet size the target endpoint
2886 is capable of sending or receiving.
2888 Data A pointer to the buffer of data that will be transmitted
2889 to USB device or received from USB device.
2891 DataLength On input, the size, in bytes, of the data buffer specified
2892 by Data. On output, the number of bytes transferred.
2894 DataToggle A pointer to the data toggle value. On input, it indicates
2895 the initial data toggle value the synchronous interrupt
2896 transfer should adopt;
2897 on output, it is updated to indicate the data toggle value
2898 of the subsequent synchronous interrupt transfer.
2900 TimeOut Indicates the maximum time, in microseconds, which the
2901 transfer is allowed to complete.
2903 TransferResult A pointer to the detailed result information from
2904 the synchronous interrupt transfer.
2908 The synchronous interrupt transfer was completed successfully.
2909 EFI_OUT_OF_RESOURCES
2910 The synchronous interrupt transfer could not be submitted due
2911 to lack of resource.
2912 EFI_INVALID_PARAMETER
2913 Some parameters are invalid.
2915 The synchronous interrupt transfer failed due to timeout.
2917 The synchronous interrupt transfer failed due to host controller
2918 or device error. Caller should check TranferResult for detailed
2927 TD_STRUCT
*PtrFirstTD
;
2929 TD_STRUCT
*PtrPreTD
;
2930 UINT16 LoadFrameListIndex
;
2931 UINT16 SavedFrameListIndex
;
2935 UINT8
*PtrDataSource
;
2939 BOOLEAN ShortPacketEnable
;
2940 EFI_PHYSICAL_ADDRESS TempPtr
;
2944 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2945 StatusReg
= (UINT32
) (USBSTS
);
2946 FrameNumReg
= (UINT32
) (USBFRNUM
);
2947 ShortPacketEnable
= FALSE
;
2949 PktID
= INPUT_PACKET_ID
;
2959 // Parameters Checking
2962 if ((DataLength
== NULL
) ||
2964 (TransferResult
== NULL
)) {
2965 return EFI_INVALID_PARAMETER
;
2969 // if has errors that cause host controller halt,
2970 // then return EFI_DEVICE_ERROR directly.
2972 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2974 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2975 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2976 return EFI_DEVICE_ERROR
;
2979 if ((EndPointAddress
& 0x80) == 0) {
2980 return EFI_INVALID_PARAMETER
;
2983 if (*DataLength
== 0) {
2984 return EFI_INVALID_PARAMETER
;
2987 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2988 return EFI_INVALID_PARAMETER
;
2991 if (MaximumPacketLength
> 64) {
2992 return EFI_INVALID_PARAMETER
;
2995 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
2996 return EFI_INVALID_PARAMETER
;
2999 if (TransferResult
== NULL
) {
3000 return EFI_INVALID_PARAMETER
;
3003 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3006 // submit Sync interrupt transfer request
3008 ShortPacketEnable
= TRUE
;
3009 PktID
= INPUT_PACKET_ID
;
3010 DataLen
= *DataLength
;
3011 PtrDataSource
= Data
;
3014 // create QH structure and init
3016 Status
= CreateQH (HcDev
, &PtrQH
);
3017 if (EFI_ERROR (Status
)) {
3022 // BusMasterWrite means cpu read
3024 Status
= HcDev
->PciIo
->Map (
3026 EfiPciIoOperationBusMasterWrite
,
3032 if (EFI_ERROR (Status
)) {
3033 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3037 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
3040 while (DataLen
> 0) {
3042 // create TD structures and link together
3044 PktSize
= (UINT8
) DataLen
;
3045 if (DataLen
> MaximumPacketLength
) {
3046 PktSize
= MaximumPacketLength
;
3049 Status
= GenDataTD (
3060 if (EFI_ERROR (Status
)) {
3061 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3062 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3063 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3067 // Enable short packet detection.
3069 if (ShortPacketEnable
) {
3070 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
3075 PtrFirstTD
->ptrNextTD
= NULL
;
3079 // Link two TDs in vertical depth
3081 LinkTDToTD (PtrPreTD
, PtrTD
);
3094 // link TD structures to QH structure
3096 LinkTDToQH (PtrQH
, PtrFirstTD
);
3098 switch (MaximumPacketLength
) {
3100 LinkTimes
= Index
/ 71 + 1;
3104 LinkTimes
= Index
/ 51 + 1;
3108 LinkTimes
= Index
/ 33 + 1;
3112 LinkTimes
= Index
/ 19 + 1;
3118 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
3119 SavedFrameListIndex
= LoadFrameListIndex
;
3121 for (Index
= 0; Index
< LinkTimes
; Index
++) {
3124 // put the QH-TD directly or indirectly into the proper place
3125 // in the Frame List
3127 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
3129 LoadFrameListIndex
+= 1;
3130 LoadFrameListIndex
&= 0x3FF;
3133 LoadFrameListIndex
= SavedFrameListIndex
;
3135 // detail status is put into the Result field in the pIRP
3136 // the Data Toggle value is also re-updated to the value
3137 // of the last successful TD
3139 Status
= ExecBulkorSyncInterruptTransfer (
3149 // Delete Sync Interrupt transfer QH-TD structure
3150 // and maintain the pointers in the Frame List
3151 // and other pointers in related QH structure
3153 // TRUE means must search other framelistindex
3155 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
3163 LoadFrameListIndex
+= 1;
3164 LoadFrameListIndex
&= 0x3FF;
3167 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3169 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3171 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3174 // if has errors that cause host controller halt,
3175 // then return EFI_DEVICE_ERROR directly.
3177 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3179 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3180 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
3181 return EFI_DEVICE_ERROR
;
3184 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3186 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
3193 UHCIIsochronousTransfer (
3194 IN EFI_USB_HC_PROTOCOL
*This
,
3195 IN UINT8 DeviceAddress
,
3196 IN UINT8 EndPointAddress
,
3197 IN UINT8 MaximumPacketLength
,
3199 IN UINTN DataLength
,
3200 OUT UINT32
*TransferResult
3204 Routine Description:
3205 Submits isochronous transfer to a target USB device.
3209 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3210 DeviceAddress - Represents the address of the target device on the USB,
3211 which is assigned during USB enumeration.
3212 EndPointAddress - End point address
3213 MaximumPacketLength - Indicates the maximum packet size that the
3214 default control transfer endpoint is capable of
3215 sending or receiving.
3216 Data - A pointer to the buffer of data that will be transmitted
3217 to USB device or received from USB device.
3218 DataLength - Indicates the size, in bytes, of the data buffer
3220 TransferResult - A pointer to the detailed result information generated
3221 by this control transfer.
3227 return EFI_UNSUPPORTED
;
3233 UHCIAsyncIsochronousTransfer (
3234 IN EFI_USB_HC_PROTOCOL
* This
,
3235 IN UINT8 DeviceAddress
,
3236 IN UINT8 EndPointAddress
,
3237 IN UINT8 MaximumPacketLength
,
3239 IN UINTN DataLength
,
3240 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
3241 IN VOID
*Context OPTIONAL
3245 Routine Description:
3246 Submits Async isochronous transfer to a target USB device.
3250 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3252 DeviceAddress - Represents the address of the target device on the USB,
3253 which is assigned during USB enumeration.
3255 EndPointAddress - End point address
3257 MaximumPacketLength - Indicates the maximum packet size that the
3258 default control transfer endpoint is capable of
3259 sending or receiving.
3261 Data - A pointer to the buffer of data that will be transmitted
3262 to USB device or received from USB device.
3264 IsochronousCallBack - When the transfer complete, the call back function will be called
3266 Context - Pass to the call back function as parameter
3273 return EFI_UNSUPPORTED
;
3277 // UEFI 2.0 Protocol
3282 IN EFI_USB2_HC_PROTOCOL
* This
,
3283 OUT UINT8
*MaxSpeed
,
3284 OUT UINT8
*PortNumber
,
3285 OUT UINT8
*Is64BitCapable
3289 Routine Description:
3290 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
3293 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3295 MaxSpeed - A pointer to the max speed USB host controller supports.
3297 PortNumber - A pointer to the number of root hub ports.
3299 Is64BitCapable - A pointer to an integer to show whether USB host controller
3300 supports 64-bit memory addressing.
3303 The host controller capabilities were retrieved successfully.
3304 EFI_INVALID_PARAMETER
3305 MaxSpeed or PortNumber or Is64BitCapable is NULL.
3307 An error was encountered while attempting to retrieve the capabilities.
3313 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3315 if ((NULL
== MaxSpeed
)
3316 ||(NULL
== PortNumber
)
3317 || (NULL
== Is64BitCapable
))
3319 return EFI_INVALID_PARAMETER
;
3322 *MaxSpeed
= EFI_USB_SPEED_FULL
;
3323 *Is64BitCapable
= (UINT8
)FALSE
;
3324 return UHCIGetRootHubPortNumber(&HcDev
->UsbHc
, PortNumber
);
3330 IN EFI_USB2_HC_PROTOCOL
* This
,
3331 IN UINT16 Attributes
3335 Routine Description:
3336 Provides software reset for the USB host controller according to UEFI 2.0 spec.
3339 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3341 Attributes - A bit mask of the reset operation to perform.
3342 See below for a list of the supported bit mask values.
3344 #define EFI_USB_HC_RESET_GLOBAL 0x0001
3345 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
3346 #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004
3347 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
3349 EFI_USB_HC_RESET_GLOBAL
3350 If this bit is set, a global reset signal will be sent to the USB bus.
3351 This resets all of the USB bus logic, including the USB host
3352 controller hardware and all the devices attached on the USB bus.
3353 EFI_USB_HC_RESET_HOST_CONTROLLER
3354 If this bit is set, the USB host controller hardware will be reset.
3355 No reset signal will be sent to the USB bus.
3359 The reset operation succeeded.
3360 EFI_INVALID_PARAMETER
3361 Attributes is not valid.
3363 The type of reset specified by Attributes is not currently supported by the host controller hardware.
3365 Reset operation is rejected due to the debug port being configured and active.
3367 An error was encountered while attempting to perform
3368 the reset operation.
3373 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3375 if (Attributes
==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
|| Attributes
==EFI_USB_HC_RESET_HOST_WITH_DEBUG
)
3376 return EFI_UNSUPPORTED
;
3387 IN EFI_USB2_HC_PROTOCOL
* This
,
3388 OUT EFI_USB_HC_STATE
* State
3392 Routine Description:
3393 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
3397 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3399 State - A pointer to the EFI_USB_HC_STATE data structure that
3400 indicates current state of the USB host controller.
3401 Type EFI_USB_HC_STATE is defined below.
3405 EfiUsbHcStateOperational,
3406 EfiUsbHcStateSuspend,
3407 EfiUsbHcStateMaximum
3412 The state information of the host controller was returned in State.
3413 EFI_INVALID_PARAMETER
3416 An error was encountered while attempting to retrieve the
3417 host controller's current state.
3422 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3423 return UHCIGetState(
3432 IN EFI_USB2_HC_PROTOCOL
* This
,
3433 IN EFI_USB_HC_STATE State
3437 Routine Description:
3438 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
3442 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3444 State - Indicates the state of the host controller that will be set.
3448 The USB host controller was successfully placed in the state
3450 EFI_INVALID_PARAMETER
3453 Failed to set the state specified by State due to device error.
3458 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3459 return UHCISetState(
3467 UHCI2ControlTransfer (
3468 IN EFI_USB2_HC_PROTOCOL
* This
,
3469 IN UINT8 DeviceAddress
,
3470 IN UINT8 DeviceSpeed
,
3471 IN UINTN MaximumPacketLength
,
3472 IN EFI_USB_DEVICE_REQUEST
* Request
,
3473 IN EFI_USB_DATA_DIRECTION TransferDirection
,
3475 IN OUT UINTN
*DataLength
,
3477 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3478 OUT UINT32
*TransferResult
3482 Routine Description:
3483 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..
3487 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3489 DeviceAddress -Represents the address of the target device on the USB,
3490 which is assigned during USB enumeration.
3492 DeviceSpeed - Indicates transfer speed of device.
3494 MaximumPacketLength - Indicates the maximum packet size that the
3495 default control transfer endpoint is capable of
3496 sending or receiving.
3498 Request - A pointer to the USB device request that will be sent
3501 TransferDirection - Specifies the data direction for the transfer.
3502 There are three values available, DataIn, DataOut
3505 Data -A pointer to the buffer of data that will be transmitted
3506 to USB device or received from USB device.
3508 DataLength - Indicates the size, in bytes, of the data buffer
3511 TimeOut - Indicates the maximum time, in microseconds,
3512 which the transfer is allowed to complete.
3514 TransferResult - A pointer to the detailed result information generated
3515 by this control transfer.
3519 The control transfer was completed successfully.
3520 EFI_OUT_OF_RESOURCES
3521 The control transfer could not be completed due to a lack of resources.
3522 EFI_INVALID_PARAMETER
3523 Some parameters are invalid.
3525 The control transfer failed due to timeout.
3527 The control transfer failed due to host controller or device error.
3528 Caller should check TranferResult for detailed error information.
3533 BOOLEAN IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
3535 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3537 return UHCIControlTransfer(
3541 (UINT8
) MaximumPacketLength
,
3554 IN EFI_USB2_HC_PROTOCOL
* This
,
3555 IN UINT8 DeviceAddress
,
3556 IN UINT8 EndPointAddress
,
3557 IN UINT8 DeviceSpeed
,
3558 IN UINTN MaximumPacketLength
,
3559 IN UINT8 DataBuffersNumber
,
3560 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
3561 IN OUT UINTN
*DataLength
,
3562 IN OUT UINT8
*DataToggle
,
3564 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3565 OUT UINT32
*TransferResult
3569 Routine Description:
3570 Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.
3574 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3576 DeviceAddress Represents the address of the target device on the USB,
3577 which is assigned during USB enumeration.
3579 EndPointAddress The combination of an endpoint number and an
3580 endpoint direction of the target USB device.
3581 Each endpoint address supports data transfer in
3582 one direction except the control endpoint
3583 (whose default endpoint address is 0).
3584 It is the caller's responsibility to make sure that
3585 the EndPointAddress represents a bulk endpoint.
3587 DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL
3588 and EFI_USB_SPEED_HIGH.
3590 MaximumPacketLength Indicates the maximum packet size the target endpoint
3591 is capable of sending or receiving.
3593 DataBuffersNumber Number of data buffers prepared for the transfer.
3595 Data Array of pointers to the buffers of data that will be transmitted
3596 to USB device or received from USB device.
3598 DataLength When input, indicates the size, in bytes, of the data buffer
3599 specified by Data. When output, indicates the actually
3600 transferred data size.
3602 DataToggle A pointer to the data toggle value. On input, it indicates
3603 the initial data toggle value the bulk transfer should adopt;
3604 on output, it is updated to indicate the data toggle value
3605 of the subsequent bulk transfer.
3607 Translator A pointr to the transaction translator data.
3609 TimeOut Indicates the maximum time, in microseconds, which the
3610 transfer is allowed to complete.
3612 TransferResult A pointer to the detailed result information of the
3617 The bulk transfer was completed successfully.
3619 EFI_OUT_OF_RESOURCES
3620 The bulk transfer could not be submitted due to lack of resource.
3622 EFI_INVALID_PARAMETER
3623 Some parameters are invalid.
3626 The bulk transfer failed due to timeout.
3629 The bulk transfer failed due to host controller or device error.
3630 Caller should check TranferResult for detailed error information.
3636 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3638 if( Data
== NULL
|| DeviceSpeed
==EFI_USB_SPEED_LOW
)
3639 return EFI_INVALID_PARAMETER
;
3640 /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */
3642 return UHCIBulkTransfer (
3646 (UINT8
) MaximumPacketLength
,
3657 UHCI2AsyncInterruptTransfer (
3658 IN EFI_USB2_HC_PROTOCOL
* This
,
3659 IN UINT8 DeviceAddress
,
3660 IN UINT8 EndPointAddress
,
3661 IN UINT8 DeviceSpeed
,
3662 IN UINTN MaximumPacketLength
,
3663 IN BOOLEAN IsNewTransfer
,
3664 IN OUT UINT8
*DataToggle
,
3665 IN UINTN PollingInterval
,
3666 IN UINTN DataLength
,
3667 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3668 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
3673 Routine Description:
3674 Submits an asynchronous interrupt transfer to an
3675 interrupt endpoint of a USB device according to UEFI 2.0 spec.
3679 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3681 DeviceAddress Represents the address of the target device on the USB,
3682 which is assigned during USB enumeration.
3684 EndPointAddress The combination of an endpoint number and an endpoint
3685 direction of the target USB device. Each endpoint address
3686 supports data transfer in one direction except the
3687 control endpoint (whose default endpoint address is 0).
3688 It is the caller's responsibility to make sure that
3689 the EndPointAddress represents an interrupt endpoint.
3691 DeviceSpeed Indicates device speed.
3693 MaximumPacketLength Indicates the maximum packet size the target endpoint
3694 is capable of sending or receiving.
3696 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
3697 the host and the target interrupt endpoint.
3698 If FALSE, the specified asynchronous interrupt pipe
3701 DataToggle A pointer to the data toggle value. On input, it is valid
3702 when IsNewTransfer is TRUE, and it indicates the initial
3703 data toggle value the asynchronous interrupt transfer
3705 On output, it is valid when IsNewTransfer is FALSE,
3706 and it is updated to indicate the data toggle value of
3707 the subsequent asynchronous interrupt transfer.
3709 PollingInterval Indicates the interval, in milliseconds, that the
3710 asynchronous interrupt transfer is polled.
3711 This parameter is required when IsNewTransfer is TRUE.
3713 DataLength Indicates the length of data to be received at the
3714 rate specified by PollingInterval from the target
3715 asynchronous interrupt endpoint. This parameter
3716 is only required when IsNewTransfer is TRUE.
3718 Translator A pointr to the transaction translator data.
3720 CallBackFunction The Callback function.This function is called at the
3721 rate specified by PollingInterval.This parameter is
3722 only required when IsNewTransfer is TRUE.
3724 Context The context that is passed to the CallBackFunction.
3725 This is an optional parameter and may be NULL.
3730 The asynchronous interrupt transfer request has been successfully
3731 submitted or canceled.
3733 EFI_INVALID_PARAMETER
3734 Some parameters are invalid.
3736 EFI_OUT_OF_RESOURCES
3737 The request could not be completed due to a lack of resources.
3744 BOOLEAN IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
3746 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3747 return UHCIAsyncInterruptTransfer(
3752 (UINT8
) MaximumPacketLength
,
3764 UHCI2SyncInterruptTransfer (
3765 IN EFI_USB2_HC_PROTOCOL
* This
,
3766 IN UINT8 DeviceAddress
,
3767 IN UINT8 EndPointAddress
,
3768 IN UINT8 DeviceSpeed
,
3769 IN UINTN MaximumPacketLength
,
3771 IN OUT UINTN
*DataLength
,
3772 IN OUT UINT8
*DataToggle
,
3774 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3775 OUT UINT32
*TransferResult
3779 Routine Description:
3780 Submits synchronous interrupt transfer to an interrupt endpoint
3781 of a USB device according to UEFI 2.0 spec.
3785 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3787 DeviceAddress Represents the address of the target device on the USB,
3788 which is assigned during USB enumeration.
3790 EndPointAddress The combination of an endpoint number and an endpoint
3791 direction of the target USB device. Each endpoint
3792 address supports data transfer in one direction
3793 except the control endpoint (whose default
3794 endpoint address is 0). It is the caller's responsibility
3795 to make sure that the EndPointAddress represents
3796 an interrupt endpoint.
3798 DeviceSpeed Indicates device speed.
3800 MaximumPacketLength Indicates the maximum packet size the target endpoint
3801 is capable of sending or receiving.
3803 Data A pointer to the buffer of data that will be transmitted
3804 to USB device or received from USB device.
3806 DataLength On input, the size, in bytes, of the data buffer specified
3807 by Data. On output, the number of bytes transferred.
3809 DataToggle A pointer to the data toggle value. On input, it indicates
3810 the initial data toggle value the synchronous interrupt
3811 transfer should adopt;
3812 on output, it is updated to indicate the data toggle value
3813 of the subsequent synchronous interrupt transfer.
3815 TimeOut Indicates the maximum time, in microseconds, which the
3816 transfer is allowed to complete.
3817 Translator A pointr to the transaction translator data.
3818 TransferResult A pointer to the detailed result information from
3819 the synchronous interrupt transfer.
3823 The synchronous interrupt transfer was completed successfully.
3824 EFI_OUT_OF_RESOURCES
3825 The synchronous interrupt transfer could not be submitted due
3826 to lack of resource.
3827 EFI_INVALID_PARAMETER
3828 Some parameters are invalid.
3830 The synchronous interrupt transfer failed due to timeout.
3832 The synchronous interrupt transfer failed due to host controller
3833 or device error. Caller should check TranferResult for detailed
3838 BOOLEAN IsSlowDevice
;
3840 if(DeviceSpeed
==EFI_USB_SPEED_HIGH
)
3841 return EFI_INVALID_PARAMETER
;
3843 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
3844 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3846 return UHCISyncInterruptTransfer(
3851 (UINT8
) MaximumPacketLength
,
3862 UHCI2IsochronousTransfer (
3863 IN EFI_USB2_HC_PROTOCOL
* This
,
3864 IN UINT8 DeviceAddress
,
3865 IN UINT8 EndPointAddress
,
3866 IN UINT8 DeviceSpeed
,
3867 IN UINTN MaximumPacketLength
,
3868 IN UINT8 DataBuffersNumber
,
3869 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
3870 IN UINTN DataLength
,
3871 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3872 OUT UINT32
*TransferResult
3876 Routine Description:
3878 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
3882 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3884 DeviceAddress Represents the address of the target device on the USB,
3885 which is assigned during USB enumeration.
3887 EndPointAddress End point address
3889 DeviceSpeed Indicates device speed.
3891 MaximumPacketLength Indicates the maximum packet size that the
3892 default control transfer endpoint is capable of
3893 sending or receiving.
3895 DataBuffersNumber Number of data buffers prepared for the transfer.
3897 Data Array of pointers to the buffers of data that will be
3898 transmitted to USB device or received from USB device.
3900 DataLength Indicates the size, in bytes, of the data buffer
3903 Translator A pointr to the transaction translator data.
3905 TransferResult A pointer to the detailed result information generated
3906 by this control transfer.
3913 return EFI_UNSUPPORTED
;
3918 UHCI2AsyncIsochronousTransfer (
3919 IN EFI_USB2_HC_PROTOCOL
* This
,
3920 IN UINT8 DeviceAddress
,
3921 IN UINT8 EndPointAddress
,
3922 IN UINT8 DeviceSpeed
,
3923 IN UINTN MaximumPacketLength
,
3924 IN UINT8 DataBuffersNumber
,
3925 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
3926 IN UINTN DataLength
,
3927 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3928 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
3933 Routine Description:
3935 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
3939 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3941 DeviceAddress Represents the address of the target device on the USB,
3942 which is assigned during USB enumeration.
3944 EndPointAddress End point address
3946 DeviceSpeed Indicates device speed.
3948 MaximumPacketLength Indicates the maximum packet size that the
3949 default control transfer endpoint is capable of
3950 sending or receiving.
3952 DataBuffersNumber Number of data buffers prepared for the transfer.
3954 Data Array of pointers to the buffers of data that will be transmitted
3955 to USB device or received from USB device.
3957 Translator A pointr to the transaction translator data.
3959 IsochronousCallBack When the transfer complete, the call back function will be called
3961 Context Pass to the call back function as parameter
3969 return EFI_UNSUPPORTED
;
3974 UHCI2GetRootHubPortStatus (
3975 IN EFI_USB2_HC_PROTOCOL
* This
,
3976 IN UINT8 PortNumber
,
3977 OUT EFI_USB_PORT_STATUS
* PortStatus
3981 Routine Description:
3982 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
3986 This A pointer to the EFI_USB2_HC_PROTOCOL.
3988 PortNumber Specifies the root hub port from which the status
3989 is to be retrieved. This value is zero-based. For example,
3990 if a root hub has two ports, then the first port is numbered 0,
3991 and the second port is numbered 1.
3993 PortStatus A pointer to the current port status bits and
3994 port status change bits.
3998 The status of the USB root hub port specified by PortNumber
3999 was returned in PortStatus.
4000 EFI_INVALID_PARAMETER
4001 PortNumber is invalid.
4002 EFI_DEVICE_ERROR - Can't read register
4007 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4009 return UHCIGetRootHubPortStatus(
4018 UHCI2SetRootHubPortFeature (
4019 IN EFI_USB2_HC_PROTOCOL
* This
,
4020 IN UINT8 PortNumber
,
4021 IN EFI_USB_PORT_FEATURE PortFeature
4025 Routine Description:
4026 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
4030 This A pointer to the EFI_USB2_HC_PROTOCOL.
4032 PortNumber Specifies the root hub port whose feature
4033 is requested to be set.
4035 PortFeature Indicates the feature selector associated
4036 with the feature set request.
4040 The feature specified by PortFeature was set for the
4041 USB root hub port specified by PortNumber.
4042 EFI_INVALID_PARAMETER
4043 PortNumber is invalid or PortFeature is invalid.
4050 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4051 return UHCISetRootHubPortFeature(
4060 UHCI2ClearRootHubPortFeature (
4061 IN EFI_USB2_HC_PROTOCOL
* This
,
4062 IN UINT8 PortNumber
,
4063 IN EFI_USB_PORT_FEATURE PortFeature
4067 Routine Description:
4068 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
4072 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4074 PortNumber Specifies the root hub port whose feature
4075 is requested to be cleared.
4077 PortFeature Indicates the feature selector associated with the
4078 feature clear request.
4082 The feature specified by PortFeature was cleared for the
4083 USB root hub port specified by PortNumber.
4084 EFI_INVALID_PARAMETER
4085 PortNumber is invalid or PortFeature is invalid.
4092 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4093 return UHCIClearRootHubPortFeature(
4102 MonitorInterruptTrans (
4107 Routine Description:
4108 Interrupt transfer periodic check handler
4110 Event - Interrupt event
4111 Contex - Pointer to USB_HC_DEV
4118 INTERRUPT_LIST
*PtrList
;
4125 LIST_ENTRY
*NextLink
;
4127 HcDev
= (USB_HC_DEV
*) Context
;
4130 // interrupt transfer list is empty, means that no interrupt transfer
4131 // is submitted by far.
4133 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
4137 NextLink
= HcDev
->InterruptListHead
.ForwardLink
;
4141 NextLink
= Link
->ForwardLink
;
4143 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
4146 // get TD execution results.
4147 // ErrTDPos is zero-based value indicating the first error TD's position
4148 // in the TDs' list.
4149 // This value is only valid when Result not equal NOERROR.
4151 ExecuteAsyncINTTDs (
4160 // interrupt transfer has not been executed yet.
4162 if (((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
) ||
4163 ((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
)) {
4167 // get actual data length transferred data and its data length.
4169 DataLen
= ActualLen
;
4170 DataBuffer
= AllocatePool (DataLen
);
4171 if (DataBuffer
== NULL
) {
4177 PtrList
->PtrFirstTD
->pTDBuffer
,
4182 // only if interrupt endpoint responds
4183 // and the interrupt transfer stops because of completion
4184 // or error, then we will call callback function.
4186 if (Result
== EFI_USB_NOERROR
) {
4188 // add for real platform debug
4190 if (PtrList
->InterruptCallBack
!= NULL
) {
4191 (PtrList
->InterruptCallBack
) (
4194 PtrList
->InterruptContext
,
4200 gBS
->FreePool (DataBuffer
);
4204 // update should done after data buffer got.
4206 UpdateAsyncINTQHTDs (PtrList
, Result
, (UINT32
) ErrTDPos
);
4210 DEBUG ((EFI_D_ERROR
, "interrupt transfer error code is %x\n", Result
));
4213 gBS
->FreePool (DataBuffer
);
4216 // leave error recovery to its related device driver.
4217 // A common case of the error recovery is to re-submit the interrupt
4219 // When an interrupt transfer is re-submitted, its position in the linked
4220 // list is changed. It is inserted to the head of the linked list, while
4221 // this function scans the whole list from head to tail. Thus, the
4222 // re-submitted interrupt transfer's callback function will not be called
4223 // again in this round.
4225 if (PtrList
->InterruptCallBack
!= NULL
) {
4226 (PtrList
->InterruptCallBack
) (
4229 PtrList
->InterruptContext
,
4234 } while (NextLink
!= &(HcDev
->InterruptListHead
));