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 // Driver model protocol interface
31 UHCIDriverEntryPoint (
32 IN EFI_HANDLE ImageHandle
,
33 IN EFI_SYSTEM_TABLE
*SystemTable
38 UHCIDriverBindingSupported (
39 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
40 IN EFI_HANDLE Controller
,
41 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
46 UHCIDriverBindingStart (
47 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
48 IN EFI_HANDLE Controller
,
49 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
54 UHCIDriverBindingStop (
55 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
56 IN EFI_HANDLE Controller
,
57 IN UINTN NumberOfChildren
,
58 IN EFI_HANDLE
*ChildHandleBuffer
62 // UHCI interface functions
68 IN EFI_USB_HC_PROTOCOL
*This
,
75 IN EFI_USB_HC_PROTOCOL
*This
,
76 OUT EFI_USB_HC_STATE
*State
82 IN EFI_USB_HC_PROTOCOL
*This
,
83 IN EFI_USB_HC_STATE State
89 IN EFI_USB_HC_PROTOCOL
*This
,
90 IN UINT8 DeviceAddress
,
91 IN BOOLEAN IsSlowDevice
,
92 IN UINT8 MaximumPacketLength
,
93 IN EFI_USB_DEVICE_REQUEST
*Request
,
94 IN EFI_USB_DATA_DIRECTION TransferDirection
,
95 IN OUT VOID
*Data
, OPTIONAL
96 IN OUT UINTN
*DataLength
, OPTIONAL
98 OUT UINT32
*TransferResult
104 IN EFI_USB_HC_PROTOCOL
*This
,
105 IN UINT8 DeviceAddress
,
106 IN UINT8 EndPointAddress
,
107 IN UINT8 MaximumPacketLength
,
109 IN OUT UINTN
*DataLength
,
110 IN OUT UINT8
*DataToggle
,
112 OUT UINT32
*TransferResult
117 UHCIAsyncInterruptTransfer (
118 IN EFI_USB_HC_PROTOCOL
* This
,
119 IN UINT8 DeviceAddress
,
120 IN UINT8 EndPointAddress
,
121 IN BOOLEAN IsSlowDevice
,
122 IN UINT8 MaxiumPacketLength
,
123 IN BOOLEAN IsNewTransfer
,
124 IN OUT UINT8
*DataToggle
,
125 IN UINTN PollingInterval
, OPTIONAL
126 IN UINTN DataLength
, OPTIONAL
127 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
128 IN VOID
*Context OPTIONAL
133 UHCISyncInterruptTransfer (
134 IN EFI_USB_HC_PROTOCOL
*This
,
135 IN UINT8 DeviceAddress
,
136 IN UINT8 EndPointAddress
,
137 IN BOOLEAN IsSlowDevice
,
138 IN UINT8 MaximumPacketLength
,
140 IN OUT UINTN
*DataLength
,
141 IN OUT UINT8
*DataToggle
,
143 OUT UINT32
*TransferResult
148 UHCIIsochronousTransfer (
149 IN EFI_USB_HC_PROTOCOL
*This
,
150 IN UINT8 DeviceAddress
,
151 IN UINT8 EndPointAddress
,
152 IN UINT8 MaximumPacketLength
,
155 OUT UINT32
*TransferResult
160 UHCIAsyncIsochronousTransfer (
161 IN EFI_USB_HC_PROTOCOL
* This
,
162 IN UINT8 DeviceAddress
,
163 IN UINT8 EndPointAddress
,
164 IN UINT8 MaximumPacketLength
,
167 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
168 IN VOID
*Context OPTIONAL
173 UHCIGetRootHubPortNumber (
174 IN EFI_USB_HC_PROTOCOL
*This
,
175 OUT UINT8
*PortNumber
180 UHCIGetRootHubPortStatus (
181 IN EFI_USB_HC_PROTOCOL
*This
,
183 OUT EFI_USB_PORT_STATUS
*PortStatus
188 UHCISetRootHubPortFeature (
189 IN EFI_USB_HC_PROTOCOL
*This
,
191 IN EFI_USB_PORT_FEATURE PortFeature
196 UHCIClearRootHubPortFeature (
197 IN EFI_USB_HC_PROTOCOL
*This
,
199 IN EFI_USB_PORT_FEATURE PortFeature
203 // Asynchronous interrupt transfer monitor function
207 MonitorInterruptTrans (
213 // UHCI Driver Global Variables
215 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding
= {
216 UHCIDriverBindingSupported
,
217 UHCIDriverBindingStart
,
218 UHCIDriverBindingStop
,
226 UHCIDriverBindingSupported (
227 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
228 IN EFI_HANDLE Controller
,
229 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
234 Test to see if this driver supports ControllerHandle. Any ControllerHandle
235 that has UsbHcProtocol installed will be supported.
238 This - Protocol instance pointer.
239 Controller, - Handle of device to test
240 RemainingDevicePath - Not used
243 EFI_SUCCESS - This driver supports this device.
244 EFI_UNSUPPORTED - This driver does not support this device.
248 EFI_STATUS OpenStatus
;
250 EFI_PCI_IO_PROTOCOL
*PciIo
;
251 USB_CLASSC UsbClassCReg
;
254 // Test whether there is PCI IO Protocol attached on the controller handle.
256 OpenStatus
= gBS
->OpenProtocol (
258 &gEfiPciIoProtocolGuid
,
260 This
->DriverBindingHandle
,
262 EFI_OPEN_PROTOCOL_BY_DRIVER
264 if (EFI_ERROR (OpenStatus
)) {
268 Status
= PciIo
->Pci
.Read (
272 sizeof (USB_CLASSC
) / sizeof (UINT8
),
275 if (EFI_ERROR (Status
)) {
278 &gEfiPciIoProtocolGuid
,
279 This
->DriverBindingHandle
,
282 return EFI_UNSUPPORTED
;
285 // Test whether the controller belongs to UHCI type
287 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
288 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
289 (UsbClassCReg
.PI
!= PCI_CLASSC_PI_UHCI
)) {
293 &gEfiPciIoProtocolGuid
,
294 This
->DriverBindingHandle
,
298 return EFI_UNSUPPORTED
;
302 &gEfiPciIoProtocolGuid
,
303 This
->DriverBindingHandle
,
312 UHCIDriverBindingStart (
313 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
314 IN EFI_HANDLE Controller
,
315 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
320 Starting the Usb UHCI Driver
323 This - Protocol instance pointer.
324 Controller - Handle of device to test
325 RemainingDevicePath - Not used
328 EFI_SUCCESS - This driver supports this device.
329 EFI_UNSUPPORTED - This driver does not support this device.
330 EFI_DEVICE_ERROR - This driver cannot be started due to device
338 EFI_PCI_IO_PROTOCOL
*PciIo
;
343 Status
= gBS
->OpenProtocol (
345 &gEfiPciIoProtocolGuid
,
347 This
->DriverBindingHandle
,
349 EFI_OPEN_PROTOCOL_BY_DRIVER
351 if (EFI_ERROR (Status
)) {
355 // Turn off USB emulation
357 TurnOffUSBEmulation (PciIo
);
360 // Enable the USB Host Controller
362 Status
= PciIo
->Attributes (
364 EfiPciIoAttributeOperationEnable
,
365 EFI_PCI_DEVICE_ENABLE
,
368 if (EFI_ERROR (Status
)) {
371 &gEfiPciIoProtocolGuid
,
372 This
->DriverBindingHandle
,
375 return EFI_UNSUPPORTED
;
379 // allocate memory for UHC private data structure
381 HcDev
= AllocateZeroPool (sizeof (USB_HC_DEV
));
385 &gEfiPciIoProtocolGuid
,
386 This
->DriverBindingHandle
,
389 return EFI_OUT_OF_RESOURCES
;
393 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
395 HcDev
->UsbHc
.Reset
= UHCIReset
;
396 HcDev
->UsbHc
.GetState
= UHCIGetState
;
397 HcDev
->UsbHc
.SetState
= UHCISetState
;
398 HcDev
->UsbHc
.ControlTransfer
= UHCIControlTransfer
;
399 HcDev
->UsbHc
.BulkTransfer
= UHCIBulkTransfer
;
400 HcDev
->UsbHc
.AsyncInterruptTransfer
= UHCIAsyncInterruptTransfer
;
401 HcDev
->UsbHc
.SyncInterruptTransfer
= UHCISyncInterruptTransfer
;
402 HcDev
->UsbHc
.IsochronousTransfer
= UHCIIsochronousTransfer
;
403 HcDev
->UsbHc
.AsyncIsochronousTransfer
= UHCIAsyncIsochronousTransfer
;
404 HcDev
->UsbHc
.GetRootHubPortNumber
= UHCIGetRootHubPortNumber
;
405 HcDev
->UsbHc
.GetRootHubPortStatus
= UHCIGetRootHubPortStatus
;
406 HcDev
->UsbHc
.SetRootHubPortFeature
= UHCISetRootHubPortFeature
;
407 HcDev
->UsbHc
.ClearRootHubPortFeature
= UHCIClearRootHubPortFeature
;
409 HcDev
->UsbHc
.MajorRevision
= 0x1;
410 HcDev
->UsbHc
.MinorRevision
= 0x1;
413 // Init UHCI private data structures
415 HcDev
->Signature
= USB_HC_DEV_SIGNATURE
;
416 HcDev
->PciIo
= PciIo
;
418 FlBaseAddrReg
= USBFLBASEADD
;
421 // Allocate and Init Host Controller's Frame List Entry
423 Status
= CreateFrameList (HcDev
, (UINT32
) FlBaseAddrReg
);
424 if (EFI_ERROR (Status
)) {
427 gBS
->FreePool (HcDev
);
432 &gEfiPciIoProtocolGuid
,
433 This
->DriverBindingHandle
,
436 return EFI_OUT_OF_RESOURCES
;
440 // Init interrupt list head in the HcDev structure.
442 InitializeListHead (&(HcDev
->InterruptListHead
));
445 // Create timer for interrupt transfer result polling
447 Status
= gBS
->CreateEvent (
448 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
450 MonitorInterruptTrans
,
452 &HcDev
->InterruptTransTimer
454 if (EFI_ERROR (Status
)) {
456 FreeFrameListEntry (HcDev
);
459 gBS
->FreePool (HcDev
);
464 &gEfiPciIoProtocolGuid
,
465 This
->DriverBindingHandle
,
468 return EFI_UNSUPPORTED
;
472 // Here set interrupt transfer polling timer in 50ms unit.
474 Status
= gBS
->SetTimer (
475 HcDev
->InterruptTransTimer
,
477 INTERRUPT_POLLING_TIME
479 if (EFI_ERROR (Status
)) {
480 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
482 FreeFrameListEntry (HcDev
);
485 gBS
->FreePool (HcDev
);
490 &gEfiPciIoProtocolGuid
,
491 This
->DriverBindingHandle
,
494 return EFI_UNSUPPORTED
;
498 // QH,TD structures must in common buffer that will be
499 // accessed by both cpu and usb bus master at the same time.
500 // so, there must has memory management for QH,TD structures.
502 Status
= InitializeMemoryManagement (HcDev
);
503 if (EFI_ERROR (Status
)) {
505 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
507 FreeFrameListEntry (HcDev
);
510 gBS
->FreePool (HcDev
);
515 &gEfiPciIoProtocolGuid
,
516 This
->DriverBindingHandle
,
523 // Install Host Controller Protocol
525 Status
= gBS
->InstallProtocolInterface (
527 &gEfiUsbHcProtocolGuid
,
528 EFI_NATIVE_INTERFACE
,
531 if (EFI_ERROR (Status
)) {
532 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
533 FreeFrameListEntry (HcDev
);
534 DelMemoryManagement (HcDev
);
537 gBS
->FreePool (HcDev
);
542 &gEfiPciIoProtocolGuid
,
543 This
->DriverBindingHandle
,
550 // component name protocol.
552 HcDev
->ControllerNameTable
= NULL
;
555 gUhciComponentName
.SupportedLanguages
,
556 &HcDev
->ControllerNameTable
,
557 (CHAR16
*) L
"Usb Universal Host Controller"
565 UnInstallUHCInterface (
566 IN EFI_HANDLE Controller
,
567 IN EFI_USB_HC_PROTOCOL
*This
571 UnInstall UHCInterface
573 Controller - Controller handle
574 This - Protocol instance pointer.
582 HcDev
= USB_HC_DEV_FROM_THIS (This
);
584 gBS
->UninstallProtocolInterface (
586 &gEfiUsbHcProtocolGuid
,
591 // first stop USB Host Controller
593 This
->SetState (This
, EfiUsbHcStateHalt
);
596 // Delete interrupt transfer polling timer
598 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
601 // Delete all the asynchronous interrupt transfers in the interrupt list
602 // and free associated memory
604 ReleaseInterruptList (HcDev
, &(HcDev
->InterruptListHead
));
607 // free Frame List Entry.
609 FreeFrameListEntry (HcDev
);
612 // Free common buffer allocated for QH,TD structures
614 DelMemoryManagement (HcDev
);
616 if (HcDev
->ControllerNameTable
) {
617 FreeUnicodeStringTable (HcDev
->ControllerNameTable
);
620 // Disable the USB Host Controller
622 HcDev
->PciIo
->Attributes (
624 EfiPciIoAttributeOperationDisable
,
625 EFI_PCI_DEVICE_ENABLE
,
629 gBS
->FreePool (HcDev
);
637 UHCIDriverBindingStop (
638 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
639 IN EFI_HANDLE Controller
,
640 IN UINTN NumberOfChildren
,
641 IN EFI_HANDLE
*ChildHandleBuffer
646 Stop this driver on ControllerHandle. Support stoping any child handles
647 created by this driver.
650 This - Protocol instance pointer.
651 Controller - Handle of device to stop driver on
652 NumberOfChildren - Number of Children in the ChildHandleBuffer
653 ChildHandleBuffer - List of handles for the children we need to stop.
661 EFI_USB_HC_PROTOCOL
*UsbHc
;
662 EFI_STATUS OpenStatus
;
664 OpenStatus
= gBS
->OpenProtocol (
666 &gEfiUsbHcProtocolGuid
,
668 This
->DriverBindingHandle
,
670 EFI_OPEN_PROTOCOL_GET_PROTOCOL
674 // Test whether the Controller handler passed in is a valid
675 // Usb controller handle that should be supported, if not,
676 // return the error status directly
678 if (EFI_ERROR (OpenStatus
)) {
682 // free all the controller related memory and uninstall UHCI Protocol.
684 UnInstallUHCInterface (Controller
, UsbHc
);
688 &gEfiPciIoProtocolGuid
,
689 This
->DriverBindingHandle
,
701 IN EFI_USB_HC_PROTOCOL
*This
,
707 Provides software reset for the USB host controller.
711 This A pointer to the EFI_USB_HC_PROTOCOL instance.
713 Attributes A bit mask of the reset operation to perform.
714 See below for a list of the supported bit mask values.
716 #define EFI_USB_HC_RESET_GLOBAL 0x0001
717 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
719 EFI_USB_HC_RESET_GLOBAL
720 If this bit is set, a global reset signal will be sent to the USB bus.
721 This resets all of the USB bus logic, including the USB host
722 controller hardware and all the devices attached on the USB bus.
723 EFI_USB_HC_RESET_HOST_CONTROLLER
724 If this bit is set, the USB host controller hardware will be reset.
725 No reset signal will be sent to the USB bus.
729 The reset operation succeeded.
730 EFI_INVALID_PARAMETER
731 Attributes is not valid.
733 An error was encountered while attempting to perform
739 UINT32 CommandRegAddr
;
740 UINT32 FlBaseAddrReg
;
745 HcDev
= USB_HC_DEV_FROM_THIS (This
);
747 CommandRegAddr
= (UINT32
) (USBCMD
);
748 FlBaseAddrReg
= (UINT32
) (USBFLBASEADD
);
750 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
753 // set the Global Reset bit in the command register
755 Status
= ReadUHCCommandReg (
760 if (EFI_ERROR (Status
)) {
761 return EFI_DEVICE_ERROR
;
764 Command
|= USBCMD_GRESET
;
765 Status
= WriteUHCCommandReg (
770 if (EFI_ERROR (Status
)) {
771 return EFI_DEVICE_ERROR
;
775 // Wait 50ms for root port to let reset complete
776 // See UHCI spec page122 Reset signaling
778 gBS
->Stall (ROOT_PORT_REST_TIME
);
781 // Clear the Global Reset bit to zero.
783 Command
&= ~USBCMD_GRESET
;
784 Status
= WriteUHCCommandReg (
789 if (EFI_ERROR (Status
)) {
790 return EFI_DEVICE_ERROR
;
793 // UHCI spec page120 reset recovery time
795 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
798 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
801 // set Host Controller Reset bit to 1
803 Status
= ReadUHCCommandReg (
808 if (EFI_ERROR (Status
)) {
809 return EFI_DEVICE_ERROR
;
812 Command
|= USBCMD_HCRESET
;
813 Status
= WriteUHCCommandReg (
818 if (EFI_ERROR (Status
)) {
819 return EFI_DEVICE_ERROR
;
822 // this bit will be reset by Host Controller when reset is completed.
823 // wait 10ms to let reset complete
825 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
829 return EFI_INVALID_PARAMETER
;
833 // Delete all old transactions on the USB bus
835 CleanUsbTransactions (HcDev
);
838 // Initialize Universal Host Controller's Frame List Data Structure
840 InitFrameList (HcDev
);
843 // Reset may cause Frame List Base Address Register reset to zero,
844 // so set the original value back again.
846 SetFrameListBaseAddress (
849 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
858 IN EFI_USB_HC_PROTOCOL
*This
,
859 OUT EFI_USB_HC_STATE
*State
864 Retrieves current state of the USB host controller.
868 This A pointer to the EFI_USB_HC_PROTOCOL instance.
870 State A pointer to the EFI_USB_HC_STATE data structure that
871 indicates current state of the USB host controller.
872 Type EFI_USB_HC_STATE is defined below.
876 EfiUsbHcStateOperational,
877 EfiUsbHcStateSuspend,
883 The state information of the host controller was returned in State.
884 EFI_INVALID_PARAMETER
887 An error was encountered while attempting to retrieve the
888 host controller's current state.
892 UINT32 CommandRegAddr
;
893 UINT32 StatusRegAddr
;
899 return EFI_INVALID_PARAMETER
;
902 HcDev
= USB_HC_DEV_FROM_THIS (This
);
904 CommandRegAddr
= (UINT32
) (USBCMD
);
905 StatusRegAddr
= (UINT32
) (USBSTS
);
907 Status
= ReadUHCCommandReg (
913 if (EFI_ERROR (Status
)) {
914 return EFI_DEVICE_ERROR
;
917 Status
= ReadUHCCommandReg (
922 if (EFI_ERROR (Status
)) {
923 return EFI_DEVICE_ERROR
;
926 if (UhcCommand
& USBCMD_EGSM
) {
927 *State
= EfiUsbHcStateSuspend
;
931 if ((UhcStatus
& USBSTS_HCH
) == 0) {
932 *State
= EfiUsbHcStateOperational
;
934 *State
= EfiUsbHcStateHalt
;
944 IN EFI_USB_HC_PROTOCOL
*This
,
945 IN EFI_USB_HC_STATE State
950 Sets the USB host controller to a specific state.
954 This A pointer to the EFI_USB_HC_PROTOCOL instance.
956 State Indicates the state of the host controller that will be set.
960 The USB host controller was successfully placed in the state
962 EFI_INVALID_PARAMETER
965 Failed to set the state specified by State due to device error.
969 UINT32 CommandRegAddr
;
970 UINT32 StatusRegAddr
;
972 EFI_USB_HC_STATE CurrentState
;
975 HcDev
= USB_HC_DEV_FROM_THIS (This
);
977 CommandRegAddr
= (UINT32
) (USBCMD
);
978 StatusRegAddr
= (UINT32
) (USBSTS
);
980 Status
= UHCIGetState (This
, &CurrentState
);
981 if (EFI_ERROR (Status
)) {
982 return EFI_DEVICE_ERROR
;
987 case EfiUsbHcStateHalt
:
988 if (CurrentState
== EfiUsbHcStateHalt
) {
992 Status
= ReadUHCCommandReg (
997 if (EFI_ERROR (Status
)) {
998 return EFI_DEVICE_ERROR
;
1001 Command
&= ~USBCMD_RS
;
1003 Status
= WriteUHCCommandReg (
1008 if (EFI_ERROR (Status
)) {
1009 return EFI_DEVICE_ERROR
;
1012 StatusRegAddr
= (UINT32
) (USBSTS
);
1014 // ensure the HC is in halt status after send the stop command
1016 if (WaitForUHCHalt (HcDev
->PciIo
, StatusRegAddr
, STALL_1_SECOND
) == EFI_TIMEOUT
) {
1017 return EFI_DEVICE_ERROR
;
1021 case EfiUsbHcStateOperational
:
1022 if (IsHostSysOrProcessErr (HcDev
->PciIo
, StatusRegAddr
)) {
1023 return EFI_DEVICE_ERROR
;
1026 switch (CurrentState
) {
1028 case EfiUsbHcStateOperational
:
1031 case EfiUsbHcStateHalt
:
1033 // Set Run/Stop bit to 1.
1035 Status
= ReadUHCCommandReg (
1040 if (EFI_ERROR (Status
)) {
1041 return EFI_DEVICE_ERROR
;
1044 Command
|= USBCMD_RS
| USBCMD_MAXP
;
1045 Status
= WriteUHCCommandReg (
1050 if (EFI_ERROR (Status
)) {
1051 return EFI_DEVICE_ERROR
;
1056 case EfiUsbHcStateSuspend
:
1057 Status
= ReadUHCCommandReg (
1062 if (EFI_ERROR (Status
)) {
1063 return EFI_DEVICE_ERROR
;
1067 // FGR(Force Global Resume) bit is 0
1069 if ((Command
| (~USBCMD_FGR
)) != 0xFF) {
1071 // Write FGR bit to 1
1073 Command
|= USBCMD_FGR
;
1074 WriteUHCCommandReg (
1082 // wait 20ms to let resume complete
1083 // (20ms is specified by UHCI spec)
1085 gBS
->Stall (FORCE_GLOBAL_RESUME_TIME
);
1088 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
1090 Command
&= ~USBCMD_FGR
;
1091 Command
&= ~USBCMD_EGSM
;
1092 Command
|= USBCMD_RS
;
1093 WriteUHCCommandReg (
1105 case EfiUsbHcStateSuspend
:
1106 if (CurrentState
== EfiUsbHcStateSuspend
) {
1110 Status
= UHCISetState (This
, EfiUsbHcStateHalt
);
1111 if (EFI_ERROR (Status
)) {
1112 return EFI_DEVICE_ERROR
;
1115 // Set Enter Global Suspend Mode bit to 1.
1117 Status
= ReadUHCCommandReg (
1122 if (EFI_ERROR (Status
)) {
1123 return EFI_DEVICE_ERROR
;
1126 Command
|= USBCMD_EGSM
;
1127 Status
= WriteUHCCommandReg (
1132 if (EFI_ERROR (Status
)) {
1133 return EFI_DEVICE_ERROR
;
1138 return EFI_INVALID_PARAMETER
;
1146 UHCIGetRootHubPortNumber (
1147 IN EFI_USB_HC_PROTOCOL
*This
,
1148 OUT UINT8
*PortNumber
1152 Routine Description:
1153 Retrieves the number of root hub ports.
1157 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1159 PortNumber A pointer to the number of the root hub ports.
1163 The port number was retrieved successfully.
1164 EFI_INVALID_PARAMETER
1167 An error was encountered while attempting to
1168 retrieve the port number.
1173 UINT16 RHPortControl
;
1177 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1179 if (PortNumber
== NULL
) {
1180 return EFI_INVALID_PARAMETER
;
1185 for (Index
= 0; Index
< 2; Index
++) {
1186 PSAddr
= (UINT32
) (USBPORTSC1
+ Index
* 2);
1187 Status
= ReadRootPortReg (
1192 if (EFI_ERROR (Status
)) {
1193 return EFI_DEVICE_ERROR
;
1196 // Port Register content is valid
1198 if (RHPortControl
!= 0xff) {
1208 UHCIGetRootHubPortStatus (
1209 IN EFI_USB_HC_PROTOCOL
*This
,
1210 IN UINT8 PortNumber
,
1211 OUT EFI_USB_PORT_STATUS
*PortStatus
1215 Routine Description:
1216 Retrieves the current status of a USB root hub port.
1220 This A pointer to the EFI_USB_HC_PROTOCOL.
1222 PortNumber Specifies the root hub port from which the status
1223 is to be retrieved. This value is zero-based. For example,
1224 if a root hub has two ports, then the first port is numbered 0,
1225 and the second port is numbered 1.
1227 PortStatus A pointer to the current port status bits and
1228 port status change bits.
1232 The status of the USB root hub port specified by PortNumber
1233 was returned in PortStatus.
1234 EFI_INVALID_PARAMETER
1235 PortNumber is invalid.
1236 EFI_DEVICE_ERROR - Can't read register
1241 UINT16 RHPortStatus
;
1242 UINT8 TotalPortNumber
;
1245 if (PortStatus
== NULL
) {
1246 return EFI_INVALID_PARAMETER
;
1249 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1250 if (PortNumber
>= TotalPortNumber
) {
1251 return EFI_INVALID_PARAMETER
;
1254 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1255 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1258 // Clear port status
1260 PortStatus
->PortStatus
= 0;
1261 PortStatus
->PortChangeStatus
= 0;
1263 Status
= ReadRootPortReg (
1269 if (EFI_ERROR (Status
)) {
1270 return EFI_DEVICE_ERROR
;
1273 // Fill Port Status bits
1277 // Current Connect Status
1279 if (RHPortStatus
& USBPORTSC_CCS
) {
1280 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
1283 // Port Enabled/Disabled
1285 if (RHPortStatus
& USBPORTSC_PED
) {
1286 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
1292 if (RHPortStatus
& USBPORTSC_SUSP
) {
1293 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1299 if (RHPortStatus
& USBPORTSC_PR
) {
1300 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
1304 // Low Speed Device Attached
1306 if (RHPortStatus
& USBPORTSC_LSDA
) {
1307 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1310 // Fill Port Status Change bits
1314 // Connect Status Change
1316 if (RHPortStatus
& USBPORTSC_CSC
) {
1317 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
1321 // Port Enabled/Disabled Change
1323 if (RHPortStatus
& USBPORTSC_PEDC
) {
1324 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
1332 UHCISetRootHubPortFeature (
1333 IN EFI_USB_HC_PROTOCOL
*This
,
1334 IN UINT8 PortNumber
,
1335 IN EFI_USB_PORT_FEATURE PortFeature
1339 Routine Description:
1340 Sets a feature for the specified root hub port.
1344 This A pointer to the EFI_USB_HC_PROTOCOL.
1346 PortNumber Specifies the root hub port whose feature
1347 is requested to be set.
1349 PortFeature Indicates the feature selector associated
1350 with the feature set request.
1354 The feature specified by PortFeature was set for the
1355 USB root hub port specified by PortNumber.
1356 EFI_INVALID_PARAMETER
1357 PortNumber is invalid or PortFeature is invalid.
1364 UINT32 CommandRegAddr
;
1366 // root hub port status
1368 UINT16 RHPortControl
;
1370 UINT8 TotalPortNumber
;
1373 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1374 if (PortNumber
>= TotalPortNumber
) {
1375 return EFI_INVALID_PARAMETER
;
1378 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1380 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1381 CommandRegAddr
= (UINT32
) (USBCMD
);
1383 Status
= ReadRootPortReg (
1388 if (EFI_ERROR (Status
)) {
1389 return EFI_DEVICE_ERROR
;
1392 switch (PortFeature
) {
1394 case EfiUsbPortSuspend
:
1395 Status
= ReadUHCCommandReg (
1400 if (EFI_ERROR (Status
)) {
1401 return EFI_DEVICE_ERROR
;
1404 if (!(Command
& USBCMD_EGSM
)) {
1406 // if global suspend is not active, can set port suspend
1408 RHPortControl
&= 0xfff5;
1409 RHPortControl
|= USBPORTSC_SUSP
;
1413 case EfiUsbPortReset
:
1414 RHPortControl
&= 0xfff5;
1416 // Set the reset bit
1418 RHPortControl
|= USBPORTSC_PR
;
1421 case EfiUsbPortPower
:
1424 case EfiUsbPortEnable
:
1425 RHPortControl
&= 0xfff5;
1426 RHPortControl
|= USBPORTSC_PED
;
1430 return EFI_INVALID_PARAMETER
;
1444 UHCIClearRootHubPortFeature (
1445 IN EFI_USB_HC_PROTOCOL
*This
,
1446 IN UINT8 PortNumber
,
1447 IN EFI_USB_PORT_FEATURE PortFeature
1451 Routine Description:
1452 Clears a feature for the specified root hub port.
1456 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1458 PortNumber Specifies the root hub port whose feature
1459 is requested to be cleared.
1461 PortFeature Indicates the feature selector associated with the
1462 feature clear request.
1466 The feature specified by PortFeature was cleared for the
1467 USB root hub port specified by PortNumber.
1468 EFI_INVALID_PARAMETER
1469 PortNumber is invalid or PortFeature is invalid.
1476 UINT16 RHPortControl
;
1477 UINT8 TotalPortNumber
;
1480 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1482 if (PortNumber
>= TotalPortNumber
) {
1483 return EFI_INVALID_PARAMETER
;
1486 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1487 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1489 Status
= ReadRootPortReg (
1494 if (EFI_ERROR (Status
)) {
1495 return EFI_DEVICE_ERROR
;
1498 switch (PortFeature
) {
1500 // clear PORT_ENABLE feature means disable port.
1502 case EfiUsbPortEnable
:
1503 RHPortControl
&= 0xfff5;
1504 RHPortControl
&= ~USBPORTSC_PED
;
1508 // clear PORT_SUSPEND feature means resume the port.
1509 // (cause a resume on the specified port if in suspend mode)
1511 case EfiUsbPortSuspend
:
1512 RHPortControl
&= 0xfff5;
1513 RHPortControl
&= ~USBPORTSC_SUSP
;
1519 case EfiUsbPortPower
:
1523 // clear PORT_RESET means clear the reset signal.
1525 case EfiUsbPortReset
:
1526 RHPortControl
&= 0xfff5;
1527 RHPortControl
&= ~USBPORTSC_PR
;
1531 // clear connect status change
1533 case EfiUsbPortConnectChange
:
1534 RHPortControl
&= 0xfff5;
1535 RHPortControl
|= USBPORTSC_CSC
;
1539 // clear enable/disable status change
1541 case EfiUsbPortEnableChange
:
1542 RHPortControl
&= 0xfff5;
1543 RHPortControl
|= USBPORTSC_PEDC
;
1547 // root hub does not support this request
1549 case EfiUsbPortSuspendChange
:
1553 // root hub does not support this request
1555 case EfiUsbPortOverCurrentChange
:
1559 // root hub does not support this request
1561 case EfiUsbPortResetChange
:
1565 return EFI_INVALID_PARAMETER
;
1579 UHCIControlTransfer (
1580 IN EFI_USB_HC_PROTOCOL
*This
,
1581 IN UINT8 DeviceAddress
,
1582 IN BOOLEAN IsSlowDevice
,
1583 IN UINT8 MaximumPacketLength
,
1584 IN EFI_USB_DEVICE_REQUEST
*Request
,
1585 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1586 IN OUT VOID
*Data
, OPTIONAL
1587 IN OUT UINTN
*DataLength
, OPTIONAL
1589 OUT UINT32
*TransferResult
1593 Routine Description:
1594 Submits control transfer to a target USB device.
1598 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1600 DeviceAddress Represents the address of the target device on the USB,
1601 which is assigned during USB enumeration.
1603 IsSlowDevice Indicates whether the target device is slow device
1604 or full-speed device.
1606 MaximumPacketLength Indicates the maximum packet size that the
1607 default control transfer endpoint is capable of
1608 sending or receiving.
1610 Request A pointer to the USB device request that will be sent
1613 TransferDirection Specifies the data direction for the transfer.
1614 There are three values available, DataIn, DataOut
1617 Data A pointer to the buffer of data that will be transmitted
1618 to USB device or received from USB device.
1620 DataLength Indicates the size, in bytes, of the data buffer
1623 TimeOut Indicates the maximum time, in microseconds,
1624 which the transfer is allowed to complete.
1626 TransferResult A pointer to the detailed result information generated
1627 by this control transfer.
1631 The control transfer was completed successfully.
1632 EFI_OUT_OF_RESOURCES
1633 The control transfer could not be completed due to a lack of resources.
1634 EFI_INVALID_PARAMETER
1635 Some parameters are invalid.
1637 The control transfer failed due to timeout.
1639 The control transfer failed due to host controller or device error.
1640 Caller should check TranferResult for detailed error information.
1650 TD_STRUCT
*PtrPreTD
;
1651 TD_STRUCT
*PtrSetupTD
;
1652 TD_STRUCT
*PtrStatusTD
;
1656 UINT8
*PtrDataSource
;
1659 UINT16 LoadFrameListIndex
;
1662 UINT8
*RequestMappedAddress
;
1663 VOID
*RequestMapping
;
1666 EFI_PHYSICAL_ADDRESS TempPtr
;
1669 TD_STRUCT
*PtrFirstDataTD
;
1670 TD_STRUCT
*ptrLastDataTD
;
1674 RequestMappedAddress
= NULL
;
1675 RequestMapping
= NULL
;
1677 PtrFirstDataTD
= NULL
;
1678 ptrLastDataTD
= NULL
;
1679 PktID
= INPUT_PACKET_ID
;
1681 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1682 StatusReg
= (UINT32
) (USBSTS
);
1683 FrameNumReg
= (UINT32
) (USBFRNUM
);
1688 // Parameters Checking
1690 if (Request
== NULL
|| TransferResult
== NULL
) {
1691 return EFI_INVALID_PARAMETER
;
1695 // if errors exist that cause host controller halt,
1696 // then return EFI_DEVICE_ERROR.
1698 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
1700 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
1701 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1702 return EFI_DEVICE_ERROR
;
1706 // low speed usb devices are limited to only an eight-byte
1707 // maximum data payload size
1709 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
1710 return EFI_INVALID_PARAMETER
;
1713 if (MaximumPacketLength
!= 8 &&
1714 MaximumPacketLength
!= 16 &&
1715 MaximumPacketLength
!= 32 &&
1716 MaximumPacketLength
!= 64) {
1717 return EFI_INVALID_PARAMETER
;
1720 if ((TransferDirection
!= EfiUsbNoData
) && (DataLength
== NULL
)) {
1721 return EFI_INVALID_PARAMETER
;
1724 switch (TransferDirection
) {
1727 PktID
= INPUT_PACKET_ID
;
1728 PtrDataSource
= Data
;
1729 DataLen
= *DataLength
;
1732 // map the source data buffer for bus master access.
1733 // BusMasterWrite means cpu read
1735 Status
= HcDev
->PciIo
->Map (
1737 EfiPciIoOperationBusMasterWrite
,
1743 if (EFI_ERROR (Status
)) {
1747 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
1751 PktID
= OUTPUT_PACKET_ID
;
1752 PtrDataSource
= Data
;
1753 DataLen
= *DataLength
;
1756 // map the source data buffer for bus master access.
1757 // BusMasterRead means cpu write
1759 Status
= HcDev
->PciIo
->Map (
1761 EfiPciIoOperationBusMasterRead
,
1767 if (EFI_ERROR (Status
)) {
1771 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
1778 if ((DataLength
!= NULL
) && (*DataLength
!= 0)) {
1779 return EFI_INVALID_PARAMETER
;
1782 PktID
= OUTPUT_PACKET_ID
;
1783 PtrDataSource
= NULL
;
1789 return EFI_INVALID_PARAMETER
;
1792 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
1793 if (EFI_ERROR (Status
)) {
1794 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1795 return EFI_DEVICE_ERROR
;
1798 // create QH structure and init
1800 Status
= CreateQH (HcDev
, &PtrQH
);
1801 if (EFI_ERROR (Status
)) {
1802 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1807 // map the Request for bus master access.
1808 // BusMasterRead means cpu write
1810 RequestLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
1811 Status
= HcDev
->PciIo
->Map (
1813 EfiPciIoOperationBusMasterRead
,
1820 if (EFI_ERROR (Status
)) {
1821 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1822 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1826 RequestMappedAddress
= (UINT8
*) ((UINTN
) TempPtr
);
1829 // generate Setup Stage TD
1831 Status
= GenSetupStageTD (
1836 (UINT8
*) RequestMappedAddress
,
1837 sizeof (EFI_USB_DEVICE_REQUEST
),
1841 if (EFI_ERROR (Status
)) {
1842 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1843 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1844 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
1849 // Data Stage of Control Transfer
1853 while (DataLen
> 0) {
1855 // create TD structures and link together
1859 // PktSize is the data load size that each TD carries.
1861 PktSize
= (UINT8
) DataLen
;
1862 if (DataLen
> MaximumPacketLength
) {
1863 PktSize
= MaximumPacketLength
;
1866 Status
= GenDataTD (
1878 if (EFI_ERROR (Status
)) {
1880 // free all resources occupied
1882 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1883 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1884 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
1885 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
1886 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
1891 // Link two TDs in vertical depth
1894 PtrFirstDataTD
= PtrTD
;
1895 PtrFirstDataTD
->ptrNextTD
= NULL
;
1898 LinkTDToTD (PtrPreTD
, PtrTD
);
1908 ptrLastDataTD
= PtrTD
;
1911 // Status Stage of Control Transfer
1913 if (PktID
== OUTPUT_PACKET_ID
) {
1914 PktID
= INPUT_PACKET_ID
;
1916 PktID
= OUTPUT_PACKET_ID
;
1920 // create Status Stage TD structure
1922 Status
= CreateStatusTD (
1931 if (EFI_ERROR (Status
)) {
1932 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
1933 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
1934 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
1935 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
1936 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
1942 // link setup TD structures to QH structure
1944 LinkTDToQH (PtrQH
, PtrSetupTD
);
1946 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
1949 // link QH-TDs to total 100 frame list entry to speed up the execution.
1951 for (Index
= 0; Index
< 100; Index
++) {
1953 HcDev
->FrameListEntry
,
1954 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1959 // Poll QH-TDs execution and get result.
1960 // detail status is returned
1962 Status
= ExecuteControlTransfer (
1971 // Remove Control Transfer QH-TDs structure from the frame list
1972 // and update the pointers in the Frame List
1973 // and other pointers in other related QH structures.
1975 for (Index
= 0; Index
< 100; Index
++) {
1979 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
1985 // delete setup stage TD; the QH is reserved for the next stages.
1987 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
1990 // if setup stage error, return error
1992 if (EFI_ERROR (Status
)) {
1996 // some control transfers do not have Data Stage
1998 if (PtrFirstDataTD
!= NULL
) {
2000 LinkTDToQH (PtrQH
, PtrFirstDataTD
);
2001 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2003 for (Index
= 0; Index
< 500; Index
++) {
2005 HcDev
->FrameListEntry
,
2006 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2011 Status
= ExecuteControlTransfer (
2020 for (Index
= 0; Index
< 500; Index
++) {
2024 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2030 // delete data stage TD; the QH is reserved for the next stage.
2032 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2035 // if data stage error, goto done and return error
2037 if (EFI_ERROR (Status
)) {
2041 LinkTDToQH (PtrQH
, PtrStatusTD
);
2043 // get the frame list index that the QH-TDs will be linked to.
2045 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2047 for (Index
= 0; Index
< 100; Index
++) {
2049 // put the QH-TDs directly or indirectly into the proper place
2050 // in the Frame List
2053 HcDev
->FrameListEntry
,
2054 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2059 // Poll QH-TDs execution and get result.
2060 // detail status is returned
2062 Status
= ExecuteControlTransfer (
2072 // Delete Control Transfer QH-TDs structure
2073 // and update the pointers in the Frame List
2074 // and other pointers in other related QH structures.
2076 // TRUE means must search other framelistindex
2078 for (Index
= 0; Index
< 100; Index
++) {
2082 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2088 DeleteQueuedTDs (HcDev
, PtrStatusTD
);
2092 // link setup stage TD with data stage TD
2094 PtrPreTD
= PtrSetupTD
;
2095 if (PtrFirstDataTD
!= NULL
) {
2096 LinkTDToTD (PtrSetupTD
, PtrFirstDataTD
);
2097 PtrPreTD
= ptrLastDataTD
;
2100 // link status TD with previous TD
2102 LinkTDToTD (PtrPreTD
, PtrStatusTD
);
2107 LinkTDToQH (PtrQH
, PtrSetupTD
);
2109 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2110 for (Index
= 0; Index
< 500; Index
++) {
2112 // put the QH-TDs directly or indirectly into the proper place
2113 // in the Frame List
2116 HcDev
->FrameListEntry
,
2117 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2122 // Poll QH-TDs execution and get result.
2123 // detail status is returned
2125 Status
= ExecuteControlTransfer (
2134 // Remove Control Transfer QH-TDs structure from the frame list
2135 // and update the pointers in the Frame List
2136 // and other pointers in other related QH structures.
2138 for (Index
= 0; Index
< 500; Index
++) {
2142 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2148 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2153 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2155 if (Mapping
!= NULL
) {
2156 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2159 if (RequestMapping
!= NULL
) {
2160 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2163 // if has errors that cause host controller halt,
2164 // then return EFI_DEVICE_ERROR directly.
2166 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2168 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2169 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2170 return EFI_DEVICE_ERROR
;
2173 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2174 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2181 IN EFI_USB_HC_PROTOCOL
*This
,
2182 IN UINT8 DeviceAddress
,
2183 IN UINT8 EndPointAddress
,
2184 IN UINT8 MaximumPacketLength
,
2186 IN OUT UINTN
*DataLength
,
2187 IN OUT UINT8
*DataToggle
,
2189 OUT UINT32
*TransferResult
2193 Routine Description:
2194 Submits bulk transfer to a bulk endpoint of a USB device.
2198 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2200 DeviceAddress Represents the address of the target device on the USB,
2201 which is assigned during USB enumeration.
2202 EndPointAddress The combination of an endpoint number and an
2203 endpoint direction of the target USB device.
2204 Each endpoint address supports data transfer in
2205 one direction except the control endpoint
2206 (whose default endpoint address is 0).
2207 It is the caller's responsibility to make sure that
2208 the EndPointAddress represents a bulk endpoint.
2210 MaximumPacketLength Indicates the maximum packet size the target endpoint
2211 is capable of sending or receiving.
2213 Data A pointer to the buffer of data that will be transmitted
2214 to USB device or received from USB device.
2215 DataLength When input, indicates the size, in bytes, of the data buffer
2216 specified by Data. When output, indicates the actually
2217 transferred data size.
2219 DataToggle A pointer to the data toggle value. On input, it indicates
2220 the initial data toggle value the bulk transfer should adopt;
2221 on output, it is updated to indicate the data toggle value
2222 of the subsequent bulk transfer.
2224 TimeOut Indicates the maximum time, in microseconds, which the
2225 transfer is allowed to complete.
2227 TransferResult A pointer to the detailed result information of the
2232 The bulk transfer was completed successfully.
2233 EFI_OUT_OF_RESOURCES
2234 The bulk transfer could not be submitted due to lack of resource.
2235 EFI_INVALID_PARAMETER
2236 Some parameters are invalid.
2238 The bulk transfer failed due to timeout.
2240 The bulk transfer failed due to host controller or device error.
2241 Caller should check TranferResult for detailed error information.
2250 TD_STRUCT
*PtrFirstTD
;
2252 TD_STRUCT
*PtrPreTD
;
2253 UINT16 LoadFrameListIndex
;
2254 UINT16 SavedFrameListIndex
;
2256 UINT8
*PtrDataSource
;
2263 EFI_USB_DATA_DIRECTION TransferDirection
;
2265 // Used to calculate how many entries are linked to the
2266 // specified bulk transfer QH-TDs
2270 BOOLEAN ShortPacketEnable
;
2271 EFI_PHYSICAL_ADDRESS TempPtr
;
2274 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2275 StatusReg
= (UINT32
) (USBSTS
);
2276 FrameNumReg
= (UINT32
) (USBFRNUM
);
2277 PktID
= INPUT_PACKET_ID
;
2284 ShortPacketEnable
= FALSE
;
2288 // Parameters Checking
2291 if ((DataLength
== NULL
) ||
2293 (TransferResult
== NULL
)) {
2294 return EFI_INVALID_PARAMETER
;
2298 // if has errors that cause host controller halt,
2299 // then return EFI_DEVICE_ERROR directly.
2301 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2303 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2304 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2305 return EFI_DEVICE_ERROR
;
2308 if (*DataLength
== 0) {
2309 return EFI_INVALID_PARAMETER
;
2312 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2313 return EFI_INVALID_PARAMETER
;
2316 if (MaximumPacketLength
!= 8 &&
2317 MaximumPacketLength
!= 16 &&
2318 MaximumPacketLength
!= 32 &&
2319 MaximumPacketLength
!= 64) {
2320 return EFI_INVALID_PARAMETER
;
2324 // Enable the maximum packet size (64bytes)
2325 // that can be used for full speed bandwidth reclamation
2326 // at the end of a frame.
2328 EnableMaxPacketSize (HcDev
);
2330 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2331 if (EFI_ERROR (Status
)) {
2332 return EFI_DEVICE_ERROR
;
2336 // construct QH and TD data structures,
2337 // and link them together
2339 if (EndPointAddress
& 0x80) {
2340 TransferDirection
= EfiUsbDataIn
;
2342 TransferDirection
= EfiUsbDataOut
;
2345 switch (TransferDirection
) {
2348 ShortPacketEnable
= TRUE
;
2349 PktID
= INPUT_PACKET_ID
;
2350 PtrDataSource
= Data
;
2351 DataLen
= *DataLength
;
2354 // BusMasterWrite means cpu read
2356 Status
= HcDev
->PciIo
->Map (
2358 EfiPciIoOperationBusMasterWrite
,
2364 if (EFI_ERROR (Status
)) {
2368 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2372 PktID
= OUTPUT_PACKET_ID
;
2373 PtrDataSource
= Data
;
2374 DataLen
= *DataLength
;
2377 // BusMasterRead means cpu write
2379 Status
= HcDev
->PciIo
->Map (
2381 EfiPciIoOperationBusMasterRead
,
2387 if (EFI_ERROR (Status
)) {
2391 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2395 return EFI_INVALID_PARAMETER
;
2399 // create QH structure and init
2401 Status
= CreateQH (HcDev
, &PtrQH
);
2402 if (EFI_ERROR (Status
)) {
2403 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2408 // i is used to calculate the total number of TDs.
2413 while (DataLen
> 0) {
2416 // create TD structures and link together
2419 PktSize
= (UINT8
) DataLen
;
2420 if (DataLen
> MaximumPacketLength
) {
2421 PktSize
= MaximumPacketLength
;
2424 Status
= GenDataTD (
2436 if (EFI_ERROR (Status
)) {
2437 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2438 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2439 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2444 // Enable short packet detection.
2445 // (default action is disabling short packet detection)
2447 if (ShortPacketEnable
) {
2448 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
2453 PtrFirstTD
->ptrNextTD
= NULL
;
2457 // Link two TDs in vertical depth
2459 LinkTDToTD (PtrPreTD
, PtrTD
);
2472 // link TD structures to QH structure
2474 LinkTDToQH (PtrQH
, PtrFirstTD
);
2477 // calculate how many entries are linked to the specified bulk transfer QH-TDs
2478 // the below values are referred to the USB spec revision1.1.
2480 switch (MaximumPacketLength
) {
2482 LinkTimes
= Index
/ 71 + 1;
2486 LinkTimes
= Index
/ 51 + 1;
2490 LinkTimes
= Index
/ 33 + 1;
2494 LinkTimes
= Index
/ 19 + 1;
2501 // put QH-TDs into Frame list
2503 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2504 SavedFrameListIndex
= LoadFrameListIndex
;
2506 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2509 // put the QH-TD directly or indirectly into the proper place
2510 // in the Frame List
2512 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
2514 LoadFrameListIndex
+= 1;
2515 LoadFrameListIndex
&= 0x3FF;
2518 LoadFrameListIndex
= SavedFrameListIndex
;
2521 // Execute QH-TD and get result
2524 // detail status is put into the Result field in the pIRP
2525 // the Data Toggle value is also re-updated to the value
2526 // of the last successful TD
2528 Status
= ExecBulkorSyncInterruptTransfer (
2539 // Delete Bulk transfer QH-TD structure
2540 // and maitain the pointers in the Frame List
2541 // and other pointers in related QH structure
2543 // TRUE means must search other framelistindex
2545 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2553 LoadFrameListIndex
+= 1;
2554 LoadFrameListIndex
&= 0x3FF;
2557 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2559 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2561 if (Mapping
!= NULL
) {
2562 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2566 // if has errors that cause host controller halt,
2567 // then return EFI_DEVICE_ERROR directly.
2569 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2571 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2572 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2573 return EFI_DEVICE_ERROR
;
2576 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2578 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2585 UHCIAsyncInterruptTransfer (
2586 IN EFI_USB_HC_PROTOCOL
* This
,
2587 IN UINT8 DeviceAddress
,
2588 IN UINT8 EndPointAddress
,
2589 IN BOOLEAN IsSlowDevice
,
2590 IN UINT8 MaxiumPacketLength
,
2591 IN BOOLEAN IsNewTransfer
,
2592 IN OUT UINT8
*DataToggle
,
2593 IN UINTN PollingInterval
, OPTIONAL
2594 IN UINTN DataLength
, OPTIONAL
2595 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
2596 IN VOID
*Context OPTIONAL
2600 Routine Description:
2601 Submits an asynchronous interrupt transfer to an
2602 interrupt endpoint of a USB device.
2606 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2608 DeviceAddress Represents the address of the target device on the USB,
2609 which is assigned during USB enumeration.
2611 EndPointAddress The combination of an endpoint number and an endpoint
2612 direction of the target USB device. Each endpoint address
2613 supports data transfer in one direction except the
2614 control endpoint (whose default endpoint address is 0).
2615 It is the caller's responsibility to make sure that
2616 the EndPointAddress represents an interrupt endpoint.
2618 IsSlowDevice Indicates whether the target device is slow device
2619 or full-speed device.
2621 MaxiumPacketLength Indicates the maximum packet size the target endpoint
2622 is capable of sending or receiving.
2624 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
2625 the host and the target interrupt endpoint.
2626 If FALSE, the specified asynchronous interrupt pipe
2629 DataToggle A pointer to the data toggle value. On input, it is valid
2630 when IsNewTransfer is TRUE, and it indicates the initial
2631 data toggle value the asynchronous interrupt transfer
2633 On output, it is valid when IsNewTransfer is FALSE,
2634 and it is updated to indicate the data toggle value of
2635 the subsequent asynchronous interrupt transfer.
2637 PollingInterval Indicates the interval, in milliseconds, that the
2638 asynchronous interrupt transfer is polled.
2639 This parameter is required when IsNewTransfer is TRUE.
2641 DataLength Indicates the length of data to be received at the
2642 rate specified by PollingInterval from the target
2643 asynchronous interrupt endpoint. This parameter
2644 is only required when IsNewTransfer is TRUE.
2646 CallBackFunction The Callback function.This function is called at the
2647 rate specified by PollingInterval.This parameter is
2648 only required when IsNewTransfer is TRUE.
2650 Context The context that is passed to the CallBackFunction.
2651 This is an optional parameter and may be NULL.
2655 The asynchronous interrupt transfer request has been successfully
2656 submitted or canceled.
2657 EFI_INVALID_PARAMETER
2658 Some parameters are invalid.
2659 EFI_OUT_OF_RESOURCES
2660 The request could not be completed due to a lack of resources.
2669 QH_STRUCT
*ptrFirstQH
;
2671 QH_STRUCT
*ptrPreQH
;
2672 TD_STRUCT
*PtrFirstTD
;
2674 TD_STRUCT
*PtrPreTD
;
2675 UINT16 LoadFrameListIndex
;
2683 BOOLEAN ShortPacketEnable
;
2684 UINT8 CurrentDataToggle
;
2685 EFI_PHYSICAL_ADDRESS TempPtr
;
2691 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2692 StatusReg
= (UINT32
) (USBSTS
);
2693 FrameNumReg
= (UINT32
) (USBFRNUM
);
2695 ShortPacketEnable
= FALSE
;
2697 PktID
= INPUT_PACKET_ID
;
2706 if ((EndPointAddress
& 0x80) == 0) {
2707 return EFI_INVALID_PARAMETER
;
2711 // delete Async interrupt transfer request
2713 if (!IsNewTransfer
) {
2715 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
2717 Status
= DeleteAsyncINTQHTDs (
2724 gBS
->RestoreTPL (OldTpl
);
2729 // if has errors that cause host controller halt,
2730 // then return EFI_DEVICE_ERROR directly.
2732 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2734 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2735 return EFI_DEVICE_ERROR
;
2738 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2741 // submit Async interrupt transfer request
2743 if (PollingInterval
< 1 || PollingInterval
> 255) {
2744 return EFI_INVALID_PARAMETER
;
2747 if (DataLength
== 0) {
2748 return EFI_INVALID_PARAMETER
;
2751 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2752 return EFI_INVALID_PARAMETER
;
2755 ShortPacketEnable
= TRUE
;
2756 PktID
= INPUT_PACKET_ID
;
2757 DataLen
= DataLength
;
2758 Ptr
= AllocatePool (DataLen
);
2760 return EFI_OUT_OF_RESOURCES
;
2764 // BusMasterWrite means cpu read
2766 Status
= HcDev
->PciIo
->Map (
2768 EfiPciIoOperationBusMasterWrite
,
2774 if (EFI_ERROR (Status
)) {
2775 gBS
->FreePool (Ptr
);
2779 MappedPtr
= (UINT8
*) ((UINTN
) TempPtr
);
2781 CurrentDataToggle
= *DataToggle
;
2785 while (DataLen
> 0) {
2787 // create TD structures and link together
2790 PktSize
= (UINT8
) DataLen
;
2791 if (DataLen
> MaxiumPacketLength
) {
2792 PktSize
= MaxiumPacketLength
;
2795 Status
= GenDataTD (
2806 if (EFI_ERROR (Status
)) {
2807 gBS
->FreePool (Ptr
);
2808 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2809 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2813 // Enable short packet detection.
2815 if (ShortPacketEnable
) {
2816 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
2821 PtrFirstTD
->ptrNextTD
= NULL
;
2825 // Link two TDs in vertical depth
2827 LinkTDToTD (PtrPreTD
, PtrTD
);
2832 CurrentDataToggle
^= 1;
2833 MappedPtr
+= PktSize
;
2838 // roll one value back
2840 CurrentDataToggle
^= 1;
2843 // create a list of QH structures and init,
2844 // link TDs to all the QHs, and link all the QHs together using internal
2845 // defined pointer of the QH_STRUCT.
2849 for (Index
= 0; Index
< 1024;) {
2851 Status
= CreateQH (HcDev
, &PtrQH
);
2852 if (EFI_ERROR (Status
)) {
2853 gBS
->FreePool (Ptr
);
2854 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2855 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2859 PtrQH
= TempQH
->ptrNextIntQH
;
2860 UhciFreePool (HcDev
, (UINT8
*) TempQH
, sizeof (QH_STRUCT
));
2867 // link TD structures to QH structure
2869 LinkTDToQH (PtrQH
, PtrFirstTD
);
2873 ptrFirstQH
->ptrNextIntQH
= NULL
;
2877 // link neighbor QH structures together
2879 ptrPreQH
->ptrNextIntQH
= PtrQH
;
2884 Index
= (UINT16
) (PollingInterval
+ Index
);
2887 // last QH in QH list should set its next QH pointer to NULL.
2889 PtrQH
->ptrNextIntQH
= NULL
;
2892 // Save QH-TD structures in Interrupt transfer list,
2893 // for monitor interrupt transfer execution routine use.
2895 InsertQHTDToINTList (
2911 // put QHs-TDs into Frame list
2913 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2917 for (Index
= LoadFrameListIndex
; Index
< (1024 + LoadFrameListIndex
);) {
2920 // put the QH-TD directly or indirectly into the proper place
2921 // in the Frame List
2923 LinkQHToFrameList (HcDev
->FrameListEntry
, (UINT16
) (Index
& 0x3FF), PtrQH
);
2925 Index
= (UINT16
) (PollingInterval
+ Index
);
2927 PtrQH
= PtrQH
->ptrNextIntQH
;
2930 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2937 UHCISyncInterruptTransfer (
2938 IN EFI_USB_HC_PROTOCOL
*This
,
2939 IN UINT8 DeviceAddress
,
2940 IN UINT8 EndPointAddress
,
2941 IN BOOLEAN IsSlowDevice
,
2942 IN UINT8 MaximumPacketLength
,
2944 IN OUT UINTN
*DataLength
,
2945 IN OUT UINT8
*DataToggle
,
2947 OUT UINT32
*TransferResult
2951 Routine Description:
2952 Submits synchronous interrupt transfer to an interrupt endpoint
2957 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2959 DeviceAddress Represents the address of the target device on the USB,
2960 which is assigned during USB enumeration.
2962 EndPointAddress The combination of an endpoint number and an endpoint
2963 direction of the target USB device. Each endpoint
2964 address supports data transfer in one direction
2965 except the control endpoint (whose default
2966 endpoint address is 0). It is the caller's responsibility
2967 to make sure that the EndPointAddress represents
2968 an interrupt endpoint.
2970 IsSlowDevice Indicates whether the target device is slow device
2971 or full-speed device.
2973 MaximumPacketLength Indicates the maximum packet size the target endpoint
2974 is capable of sending or receiving.
2976 Data A pointer to the buffer of data that will be transmitted
2977 to USB device or received from USB device.
2979 DataLength On input, the size, in bytes, of the data buffer specified
2980 by Data. On output, the number of bytes transferred.
2982 DataToggle A pointer to the data toggle value. On input, it indicates
2983 the initial data toggle value the synchronous interrupt
2984 transfer should adopt;
2985 on output, it is updated to indicate the data toggle value
2986 of the subsequent synchronous interrupt transfer.
2988 TimeOut Indicates the maximum time, in microseconds, which the
2989 transfer is allowed to complete.
2991 TransferResult A pointer to the detailed result information from
2992 the synchronous interrupt transfer.
2996 The synchronous interrupt transfer was completed successfully.
2997 EFI_OUT_OF_RESOURCES
2998 The synchronous interrupt transfer could not be submitted due
2999 to lack of resource.
3000 EFI_INVALID_PARAMETER
3001 Some parameters are invalid.
3003 The synchronous interrupt transfer failed due to timeout.
3005 The synchronous interrupt transfer failed due to host controller
3006 or device error. Caller should check TranferResult for detailed
3015 TD_STRUCT
*PtrFirstTD
;
3017 TD_STRUCT
*PtrPreTD
;
3018 UINT16 LoadFrameListIndex
;
3019 UINT16 SavedFrameListIndex
;
3023 UINT8
*PtrDataSource
;
3027 BOOLEAN ShortPacketEnable
;
3028 EFI_PHYSICAL_ADDRESS TempPtr
;
3032 HcDev
= USB_HC_DEV_FROM_THIS (This
);
3033 StatusReg
= (UINT32
) (USBSTS
);
3034 FrameNumReg
= (UINT32
) (USBFRNUM
);
3035 ShortPacketEnable
= FALSE
;
3037 PktID
= INPUT_PACKET_ID
;
3047 // Parameters Checking
3050 if ((DataLength
== NULL
) ||
3052 (TransferResult
== NULL
)) {
3053 return EFI_INVALID_PARAMETER
;
3057 // if has errors that cause host controller halt,
3058 // then return EFI_DEVICE_ERROR directly.
3060 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3062 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3063 *TransferResult
= EFI_USB_ERR_SYSTEM
;
3064 return EFI_DEVICE_ERROR
;
3067 if ((EndPointAddress
& 0x80) == 0) {
3068 return EFI_INVALID_PARAMETER
;
3071 if (*DataLength
== 0) {
3072 return EFI_INVALID_PARAMETER
;
3075 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
3076 return EFI_INVALID_PARAMETER
;
3079 if (MaximumPacketLength
> 64) {
3080 return EFI_INVALID_PARAMETER
;
3083 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
3084 return EFI_INVALID_PARAMETER
;
3087 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3090 // submit Sync interrupt transfer request
3092 ShortPacketEnable
= TRUE
;
3093 PktID
= INPUT_PACKET_ID
;
3094 DataLen
= *DataLength
;
3095 PtrDataSource
= Data
;
3098 // create QH structure and init
3100 Status
= CreateQH (HcDev
, &PtrQH
);
3101 if (EFI_ERROR (Status
)) {
3106 // BusMasterWrite means cpu read
3108 Status
= HcDev
->PciIo
->Map (
3110 EfiPciIoOperationBusMasterWrite
,
3116 if (EFI_ERROR (Status
)) {
3117 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3121 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
3124 while (DataLen
> 0) {
3126 // create TD structures and link together
3128 PktSize
= (UINT8
) DataLen
;
3129 if (DataLen
> MaximumPacketLength
) {
3130 PktSize
= MaximumPacketLength
;
3133 Status
= GenDataTD (
3144 if (EFI_ERROR (Status
)) {
3145 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3146 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3147 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3151 // Enable short packet detection.
3153 if (ShortPacketEnable
) {
3154 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
3159 PtrFirstTD
->ptrNextTD
= NULL
;
3163 // Link two TDs in vertical depth
3165 LinkTDToTD (PtrPreTD
, PtrTD
);
3178 // link TD structures to QH structure
3180 LinkTDToQH (PtrQH
, PtrFirstTD
);
3182 switch (MaximumPacketLength
) {
3184 LinkTimes
= Index
/ 71 + 1;
3188 LinkTimes
= Index
/ 51 + 1;
3192 LinkTimes
= Index
/ 33 + 1;
3196 LinkTimes
= Index
/ 19 + 1;
3202 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
3203 SavedFrameListIndex
= LoadFrameListIndex
;
3205 for (Index
= 0; Index
< LinkTimes
; Index
++) {
3208 // put the QH-TD directly or indirectly into the proper place
3209 // in the Frame List
3211 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
3213 LoadFrameListIndex
+= 1;
3214 LoadFrameListIndex
&= 0x3FF;
3217 LoadFrameListIndex
= SavedFrameListIndex
;
3219 // detail status is put into the Result field in the pIRP
3220 // the Data Toggle value is also re-updated to the value
3221 // of the last successful TD
3223 Status
= ExecBulkorSyncInterruptTransfer (
3233 // Delete Sync Interrupt transfer QH-TD structure
3234 // and maintain the pointers in the Frame List
3235 // and other pointers in related QH structure
3237 // TRUE means must search other framelistindex
3239 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
3247 LoadFrameListIndex
+= 1;
3248 LoadFrameListIndex
&= 0x3FF;
3251 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3253 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3255 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3258 // if has errors that cause host controller halt,
3259 // then return EFI_DEVICE_ERROR directly.
3261 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3263 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3264 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
3265 return EFI_DEVICE_ERROR
;
3268 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3270 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
3277 UHCIIsochronousTransfer (
3278 IN EFI_USB_HC_PROTOCOL
*This
,
3279 IN UINT8 DeviceAddress
,
3280 IN UINT8 EndPointAddress
,
3281 IN UINT8 MaximumPacketLength
,
3283 IN UINTN DataLength
,
3284 OUT UINT32
*TransferResult
3288 Routine Description:
3289 Submits isochronous transfer to a target USB device.
3293 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3294 DeviceAddress - Represents the address of the target device on the USB,
3295 which is assigned during USB enumeration.
3296 EndPointAddress - End point address
3297 MaximumPacketLength - Indicates the maximum packet size that the
3298 default control transfer endpoint is capable of
3299 sending or receiving.
3300 Data - A pointer to the buffer of data that will be transmitted
3301 to USB device or received from USB device.
3302 DataLength - Indicates the size, in bytes, of the data buffer
3304 TransferResult - A pointer to the detailed result information generated
3305 by this control transfer.
3311 return EFI_UNSUPPORTED
;
3317 UHCIAsyncIsochronousTransfer (
3318 IN EFI_USB_HC_PROTOCOL
* This
,
3319 IN UINT8 DeviceAddress
,
3320 IN UINT8 EndPointAddress
,
3321 IN UINT8 MaximumPacketLength
,
3323 IN UINTN DataLength
,
3324 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
3325 IN VOID
*Context OPTIONAL
3329 Routine Description:
3330 Submits Async isochronous transfer to a target USB device.
3334 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3336 DeviceAddress - Represents the address of the target device on the USB,
3337 which is assigned during USB enumeration.
3339 EndPointAddress - End point address
3341 MaximumPacketLength - Indicates the maximum packet size that the
3342 default control transfer endpoint is capable of
3343 sending or receiving.
3345 Data - A pointer to the buffer of data that will be transmitted
3346 to USB device or received from USB device.
3348 IsochronousCallBack - When the transfer complete, the call back function will be called
3350 Context - Pass to the call back function as parameter
3357 return EFI_UNSUPPORTED
;
3362 MonitorInterruptTrans (
3367 Routine Description:
3368 Interrupt transfer periodic check handler
3370 Event - Interrupt event
3371 Contex - Pointer to USB_HC_DEV
3378 INTERRUPT_LIST
*PtrList
;
3386 LIST_ENTRY
*NextLink
;
3388 HcDev
= (USB_HC_DEV
*) Context
;
3389 StatusAddr
= (UINT32
) (USBSTS
);
3392 // interrupt transfer list is empty, means that no interrupt transfer
3393 // is submitted by far.
3395 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
3399 NextLink
= HcDev
->InterruptListHead
.ForwardLink
;
3403 NextLink
= Link
->ForwardLink
;
3405 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
3408 // get TD execution results.
3409 // ErrTDPos is zero-based value indicating the first error TD's position
3410 // in the TDs' list.
3411 // This value is only valid when Result not equal NOERROR.
3413 ExecuteAsyncINTTDs (
3422 // interrupt transfer has not been executed yet.
3424 if (((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
) ||
3425 ((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
)) {
3429 // get actual data length transferred data and its data length.
3431 DataLen
= ActualLen
;
3432 DataBuffer
= AllocatePool (DataLen
);
3433 if (DataBuffer
== NULL
) {
3439 PtrList
->PtrFirstTD
->pTDBuffer
,
3444 // only if interrupt endpoint responds
3445 // and the interrupt transfer stops because of completion
3446 // or error, then we will call callback function.
3448 if (Result
== EFI_USB_NOERROR
) {
3450 // add for real platform debug
3452 if (PtrList
->InterruptCallBack
!= NULL
) {
3453 (PtrList
->InterruptCallBack
) (
3456 PtrList
->InterruptContext
,
3462 gBS
->FreePool (DataBuffer
);
3466 // update should done after data buffer got.
3468 UpdateAsyncINTQHTDs (PtrList
, Result
, (UINT32
) ErrTDPos
);
3472 DEBUG ((EFI_D_ERROR
, "interrupt transfer error code is %x\n", Result
));
3475 gBS
->FreePool (DataBuffer
);
3478 // leave error recovery to its related device driver.
3479 // A common case of the error recovery is to re-submit the interrupt
3481 // When an interrupt transfer is re-submitted, its position in the linked
3482 // list is changed. It is inserted to the head of the linked list, while
3483 // this function scans the whole list from head to tail. Thus, the
3484 // re-submitted interrupt transfer's callback function will not be called
3485 // again in this round.
3487 if (PtrList
->InterruptCallBack
!= NULL
) {
3488 (PtrList
->InterruptCallBack
) (
3491 PtrList
->InterruptContext
,
3496 } while (NextLink
!= &(HcDev
->InterruptListHead
));