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 UHCIDriverBindingSupported (
32 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
33 IN EFI_HANDLE Controller
,
34 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
39 UHCIDriverBindingStart (
40 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
41 IN EFI_HANDLE Controller
,
42 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
47 UHCIDriverBindingStop (
48 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
49 IN EFI_HANDLE Controller
,
50 IN UINTN NumberOfChildren
,
51 IN EFI_HANDLE
*ChildHandleBuffer
55 // UHCI interface functions
61 IN EFI_USB_HC_PROTOCOL
*This
,
68 IN EFI_USB_HC_PROTOCOL
*This
,
69 OUT EFI_USB_HC_STATE
*State
75 IN EFI_USB_HC_PROTOCOL
*This
,
76 IN EFI_USB_HC_STATE State
82 IN EFI_USB_HC_PROTOCOL
*This
,
83 IN UINT8 DeviceAddress
,
84 IN BOOLEAN IsSlowDevice
,
85 IN UINT8 MaximumPacketLength
,
86 IN EFI_USB_DEVICE_REQUEST
*Request
,
87 IN EFI_USB_DATA_DIRECTION TransferDirection
,
88 IN OUT VOID
*Data
, OPTIONAL
89 IN OUT UINTN
*DataLength
, OPTIONAL
91 OUT UINT32
*TransferResult
97 IN EFI_USB_HC_PROTOCOL
*This
,
98 IN UINT8 DeviceAddress
,
99 IN UINT8 EndPointAddress
,
100 IN UINT8 MaximumPacketLength
,
102 IN OUT UINTN
*DataLength
,
103 IN OUT UINT8
*DataToggle
,
105 OUT UINT32
*TransferResult
110 UHCIAsyncInterruptTransfer (
111 IN EFI_USB_HC_PROTOCOL
* This
,
112 IN UINT8 DeviceAddress
,
113 IN UINT8 EndPointAddress
,
114 IN BOOLEAN IsSlowDevice
,
115 IN UINT8 MaximumPacketLength
,
116 IN BOOLEAN IsNewTransfer
,
117 IN OUT UINT8
*DataToggle
,
118 IN UINTN PollingInterval
, OPTIONAL
119 IN UINTN DataLength
, OPTIONAL
120 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
121 IN VOID
*Context OPTIONAL
126 UHCISyncInterruptTransfer (
127 IN EFI_USB_HC_PROTOCOL
*This
,
128 IN UINT8 DeviceAddress
,
129 IN UINT8 EndPointAddress
,
130 IN BOOLEAN IsSlowDevice
,
131 IN UINT8 MaximumPacketLength
,
133 IN OUT UINTN
*DataLength
,
134 IN OUT UINT8
*DataToggle
,
136 OUT UINT32
*TransferResult
141 UHCIIsochronousTransfer (
142 IN EFI_USB_HC_PROTOCOL
*This
,
143 IN UINT8 DeviceAddress
,
144 IN UINT8 EndPointAddress
,
145 IN UINT8 MaximumPacketLength
,
148 OUT UINT32
*TransferResult
153 UHCIAsyncIsochronousTransfer (
154 IN EFI_USB_HC_PROTOCOL
* This
,
155 IN UINT8 DeviceAddress
,
156 IN UINT8 EndPointAddress
,
157 IN UINT8 MaximumPacketLength
,
160 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
161 IN VOID
*Context OPTIONAL
166 UHCIGetRootHubPortNumber (
167 IN EFI_USB_HC_PROTOCOL
*This
,
168 OUT UINT8
*PortNumber
173 UHCIGetRootHubPortStatus (
174 IN EFI_USB_HC_PROTOCOL
*This
,
176 OUT EFI_USB_PORT_STATUS
*PortStatus
181 UHCISetRootHubPortFeature (
182 IN EFI_USB_HC_PROTOCOL
*This
,
184 IN EFI_USB_PORT_FEATURE PortFeature
189 UHCIClearRootHubPortFeature (
190 IN EFI_USB_HC_PROTOCOL
*This
,
192 IN EFI_USB_PORT_FEATURE PortFeature
202 IN EFI_USB2_HC_PROTOCOL
* This
,
204 OUT UINT8
*PortNumber
,
205 OUT UINT8
*Is64BitCapable
211 IN EFI_USB2_HC_PROTOCOL
* This
,
218 IN EFI_USB2_HC_PROTOCOL
* This
,
219 OUT EFI_USB_HC_STATE
* State
225 IN EFI_USB2_HC_PROTOCOL
* This
,
226 IN EFI_USB_HC_STATE State
231 UHCI2ControlTransfer (
232 IN EFI_USB2_HC_PROTOCOL
* This
,
233 IN UINT8 DeviceAddress
,
234 IN UINT8 DeviceSpeed
,
235 IN UINTN MaximumPacketLength
,
236 IN EFI_USB_DEVICE_REQUEST
* Request
,
237 IN EFI_USB_DATA_DIRECTION TransferDirection
,
238 IN OUT VOID
*Data
, OPTIONAL
239 IN OUT UINTN
*DataLength
, OPTIONAL
241 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
242 OUT UINT32
*TransferResult
248 IN EFI_USB2_HC_PROTOCOL
* This
,
249 IN UINT8 DeviceAddress
,
250 IN UINT8 EndPointAddress
,
251 IN UINT8 DeviceSpeed
,
252 IN UINTN MaximumPacketLength
,
253 IN UINT8 DataBuffersNumber
,
254 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
255 IN OUT UINTN
*DataLength
,
256 IN OUT UINT8
*DataToggle
,
258 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
259 OUT UINT32
*TransferResult
264 UHCI2AsyncInterruptTransfer (
265 IN EFI_USB2_HC_PROTOCOL
* This
,
266 IN UINT8 DeviceAddress
,
267 IN UINT8 EndPointAddress
,
268 IN UINT8 DeviceSpeed
,
269 IN UINTN MaximumPacketLength
,
270 IN BOOLEAN IsNewTransfer
,
271 IN OUT UINT8
*DataToggle
,
272 IN UINTN PollingInterval
, OPTIONAL
273 IN UINTN DataLength
, OPTIONAL
274 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
275 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
276 IN VOID
*Context OPTIONAL
281 UHCI2SyncInterruptTransfer (
282 IN EFI_USB2_HC_PROTOCOL
* This
,
283 IN UINT8 DeviceAddress
,
284 IN UINT8 EndPointAddress
,
285 IN UINT8 DeviceSpeed
,
286 IN UINTN MaximumPacketLength
,
288 IN OUT UINTN
*DataLength
,
289 IN OUT UINT8
*DataToggle
,
291 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
292 OUT UINT32
*TransferResult
297 UHCI2IsochronousTransfer (
298 IN EFI_USB2_HC_PROTOCOL
* This
,
299 IN UINT8 DeviceAddress
,
300 IN UINT8 EndPointAddress
,
301 IN UINT8 DeviceSpeed
,
302 IN UINTN MaximumPacketLength
,
303 IN UINT8 DataBuffersNumber
,
304 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
306 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
307 OUT UINT32
*TransferResult
312 UHCI2AsyncIsochronousTransfer (
313 IN EFI_USB2_HC_PROTOCOL
* This
,
314 IN UINT8 DeviceAddress
,
315 IN UINT8 EndPointAddress
,
316 IN UINT8 DeviceSpeed
,
317 IN UINTN MaximumPacketLength
,
318 IN UINT8 DataBuffersNumber
,
319 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
321 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
322 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
323 IN VOID
*Context OPTIONAL
328 UHCI2GetRootHubPortStatus (
329 IN EFI_USB2_HC_PROTOCOL
* This
,
331 OUT EFI_USB_PORT_STATUS
* PortStatus
336 UHCI2SetRootHubPortFeature (
337 IN EFI_USB2_HC_PROTOCOL
* This
,
339 IN EFI_USB_PORT_FEATURE PortFeature
344 UHCI2ClearRootHubPortFeature (
345 IN EFI_USB2_HC_PROTOCOL
* This
,
347 IN EFI_USB_PORT_FEATURE PortFeature
351 // Asynchronous interrupt transfer monitor function
355 MonitorInterruptTrans (
361 // UHCI Driver Global Variables
363 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding
= {
364 UHCIDriverBindingSupported
,
365 UHCIDriverBindingStart
,
366 UHCIDriverBindingStop
,
374 UHCIDriverBindingSupported (
375 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
376 IN EFI_HANDLE Controller
,
377 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
382 Test to see if this driver supports ControllerHandle. Any ControllerHandle
383 that has UsbHcProtocol installed will be supported.
386 This - Protocol instance pointer.
387 Controller - Handle of device to test
388 RemainingDevicePath - Not used
391 EFI_SUCCESS - This driver supports this device.
392 EFI_UNSUPPORTED - This driver does not support this device.
396 EFI_STATUS OpenStatus
;
398 EFI_PCI_IO_PROTOCOL
*PciIo
;
399 USB_CLASSC UsbClassCReg
;
402 // Test whether there is PCI IO Protocol attached on the controller handle.
404 OpenStatus
= gBS
->OpenProtocol (
406 &gEfiPciIoProtocolGuid
,
408 This
->DriverBindingHandle
,
410 EFI_OPEN_PROTOCOL_BY_DRIVER
412 if (EFI_ERROR (OpenStatus
)) {
416 Status
= PciIo
->Pci
.Read (
420 sizeof (USB_CLASSC
) / sizeof (UINT8
),
423 if (EFI_ERROR (Status
)) {
426 &gEfiPciIoProtocolGuid
,
427 This
->DriverBindingHandle
,
430 return EFI_UNSUPPORTED
;
433 // Test whether the controller belongs to UHCI type
435 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
436 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
437 (UsbClassCReg
.PI
!= PCI_CLASSC_PI_UHCI
)) {
441 &gEfiPciIoProtocolGuid
,
442 This
->DriverBindingHandle
,
446 return EFI_UNSUPPORTED
;
450 &gEfiPciIoProtocolGuid
,
451 This
->DriverBindingHandle
,
460 UHCIDriverBindingStart (
461 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
462 IN EFI_HANDLE Controller
,
463 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
468 Starting the Usb UHCI Driver
471 This - Protocol instance pointer.
472 Controller - Handle of device to test
473 RemainingDevicePath - Not used
476 EFI_SUCCESS - This driver supports this device.
477 EFI_UNSUPPORTED - This driver does not support this device.
478 EFI_DEVICE_ERROR - This driver cannot be started due to device
486 EFI_PCI_IO_PROTOCOL
*PciIo
;
491 Status
= gBS
->OpenProtocol (
493 &gEfiPciIoProtocolGuid
,
495 This
->DriverBindingHandle
,
497 EFI_OPEN_PROTOCOL_BY_DRIVER
499 if (EFI_ERROR (Status
)) {
504 // Turn off USB emulation
506 TurnOffUSBEmulation (PciIo
);
509 // Enable the USB Host Controller
511 Status
= PciIo
->Attributes (
513 EfiPciIoAttributeOperationEnable
,
514 EFI_PCI_DEVICE_ENABLE
,
517 if (EFI_ERROR (Status
)) {
520 &gEfiPciIoProtocolGuid
,
521 This
->DriverBindingHandle
,
524 return EFI_UNSUPPORTED
;
528 // allocate memory for UHC private data structure
530 HcDev
= AllocateZeroPool (sizeof (USB_HC_DEV
));
534 &gEfiPciIoProtocolGuid
,
535 This
->DriverBindingHandle
,
538 return EFI_OUT_OF_RESOURCES
;
542 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
544 HcDev
->UsbHc
.Reset
= UHCIReset
;
545 HcDev
->UsbHc
.GetState
= UHCIGetState
;
546 HcDev
->UsbHc
.SetState
= UHCISetState
;
547 HcDev
->UsbHc
.ControlTransfer
= UHCIControlTransfer
;
548 HcDev
->UsbHc
.BulkTransfer
= UHCIBulkTransfer
;
549 HcDev
->UsbHc
.AsyncInterruptTransfer
= UHCIAsyncInterruptTransfer
;
550 HcDev
->UsbHc
.SyncInterruptTransfer
= UHCISyncInterruptTransfer
;
551 HcDev
->UsbHc
.IsochronousTransfer
= UHCIIsochronousTransfer
;
552 HcDev
->UsbHc
.AsyncIsochronousTransfer
= UHCIAsyncIsochronousTransfer
;
553 HcDev
->UsbHc
.GetRootHubPortNumber
= UHCIGetRootHubPortNumber
;
554 HcDev
->UsbHc
.GetRootHubPortStatus
= UHCIGetRootHubPortStatus
;
555 HcDev
->UsbHc
.SetRootHubPortFeature
= UHCISetRootHubPortFeature
;
556 HcDev
->UsbHc
.ClearRootHubPortFeature
= UHCIClearRootHubPortFeature
;
558 HcDev
->UsbHc
.MajorRevision
= 0x1;
559 HcDev
->UsbHc
.MinorRevision
= 0x1;
563 // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol
565 HcDev
->Usb2Hc
.GetCapability
= UHCI2GetCapability
;
566 HcDev
->Usb2Hc
.Reset
= UHCI2Reset
;
567 HcDev
->Usb2Hc
.GetState
= UHCI2GetState
;
568 HcDev
->Usb2Hc
.SetState
= UHCI2SetState
;
569 HcDev
->Usb2Hc
.ControlTransfer
= UHCI2ControlTransfer
;
570 HcDev
->Usb2Hc
.BulkTransfer
= UHCI2BulkTransfer
;
571 HcDev
->Usb2Hc
.AsyncInterruptTransfer
= UHCI2AsyncInterruptTransfer
;
572 HcDev
->Usb2Hc
.SyncInterruptTransfer
= UHCI2SyncInterruptTransfer
;
573 HcDev
->Usb2Hc
.IsochronousTransfer
= UHCI2IsochronousTransfer
;
574 HcDev
->Usb2Hc
.AsyncIsochronousTransfer
= UHCI2AsyncIsochronousTransfer
;
575 HcDev
->Usb2Hc
.GetRootHubPortStatus
= UHCI2GetRootHubPortStatus
;
576 HcDev
->Usb2Hc
.SetRootHubPortFeature
= UHCI2SetRootHubPortFeature
;
577 HcDev
->Usb2Hc
.ClearRootHubPortFeature
= UHCI2ClearRootHubPortFeature
;
579 HcDev
->Usb2Hc
.MajorRevision
= 0x1;
580 HcDev
->Usb2Hc
.MinorRevision
= 0x1;
583 // Init UHCI private data structures
585 HcDev
->Signature
= USB_HC_DEV_SIGNATURE
;
586 HcDev
->PciIo
= PciIo
;
588 FlBaseAddrReg
= USBFLBASEADD
;
591 // Allocate and Init Host Controller's Frame List Entry
593 Status
= CreateFrameList (HcDev
, (UINT32
) FlBaseAddrReg
);
594 if (EFI_ERROR (Status
)) {
597 gBS
->FreePool (HcDev
);
602 &gEfiPciIoProtocolGuid
,
603 This
->DriverBindingHandle
,
606 return EFI_OUT_OF_RESOURCES
;
610 // Init interrupt list head in the HcDev structure.
612 InitializeListHead (&(HcDev
->InterruptListHead
));
615 // Create timer for interrupt transfer result polling
617 Status
= gBS
->CreateEvent (
618 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
620 MonitorInterruptTrans
,
622 &HcDev
->InterruptTransTimer
624 if (EFI_ERROR (Status
)) {
626 FreeFrameListEntry (HcDev
);
629 gBS
->FreePool (HcDev
);
634 &gEfiPciIoProtocolGuid
,
635 This
->DriverBindingHandle
,
638 return EFI_UNSUPPORTED
;
642 // Here set interrupt transfer polling timer in 50ms unit.
644 Status
= gBS
->SetTimer (
645 HcDev
->InterruptTransTimer
,
647 INTERRUPT_POLLING_TIME
649 if (EFI_ERROR (Status
)) {
650 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
652 FreeFrameListEntry (HcDev
);
655 gBS
->FreePool (HcDev
);
660 &gEfiPciIoProtocolGuid
,
661 This
->DriverBindingHandle
,
664 return EFI_UNSUPPORTED
;
668 // QH,TD structures must in common buffer that will be
669 // accessed by both cpu and usb bus master at the same time.
670 // so, there must has memory management for QH,TD structures.
672 Status
= InitializeMemoryManagement (HcDev
);
673 if (EFI_ERROR (Status
)) {
675 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
677 FreeFrameListEntry (HcDev
);
680 gBS
->FreePool (HcDev
);
685 &gEfiPciIoProtocolGuid
,
686 This
->DriverBindingHandle
,
693 // Install Host Controller Protocol
695 Status
= gBS
->InstallProtocolInterface (
697 &gEfiUsbHcProtocolGuid
,
698 EFI_NATIVE_INTERFACE
,
701 if (EFI_ERROR (Status
)) {
702 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
703 FreeFrameListEntry (HcDev
);
704 DelMemoryManagement (HcDev
);
707 gBS
->FreePool (HcDev
);
712 &gEfiPciIoProtocolGuid
,
713 This
->DriverBindingHandle
,
720 // Install USB2.0 Host Controller Protocol
722 Status
= gBS
->InstallProtocolInterface (
724 &gEfiUsb2HcProtocolGuid
,
725 EFI_NATIVE_INTERFACE
,
728 if (EFI_ERROR (Status
)) {
729 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
730 FreeFrameListEntry (HcDev
);
731 DelMemoryManagement (HcDev
);
734 gBS
->FreePool (HcDev
);
739 &gEfiPciIoProtocolGuid
,
740 This
->DriverBindingHandle
,
748 // component name protocol.
751 HcDev
->ControllerNameTable
= NULL
;
754 gUhciComponentName
.SupportedLanguages
,
755 &HcDev
->ControllerNameTable
,
756 (CHAR16
*) L
"Usb Universal Host Controller"
764 UnInstallUHCInterface (
765 IN EFI_HANDLE Controller
,
766 IN EFI_USB_HC_PROTOCOL
*This
770 UnInstall UHCInterface
772 Controller - Controller handle
773 This - Protocol instance pointer.
781 HcDev
= USB_HC_DEV_FROM_THIS (This
);
783 gBS
->UninstallProtocolInterface (
785 &gEfiUsbHcProtocolGuid
,
789 gBS
->UninstallProtocolInterface (
791 &gEfiUsb2HcProtocolGuid
,
795 // first stop USB Host Controller
797 This
->SetState (This
, EfiUsbHcStateHalt
);
800 // Delete interrupt transfer polling timer
802 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
805 // Delete all the asynchronous interrupt transfers in the interrupt list
806 // and free associated memory
808 ReleaseInterruptList (HcDev
, &(HcDev
->InterruptListHead
));
811 // free Frame List Entry.
813 FreeFrameListEntry (HcDev
);
816 // Free common buffer allocated for QH,TD structures
818 DelMemoryManagement (HcDev
);
820 if (HcDev
->ControllerNameTable
) {
821 FreeUnicodeStringTable (HcDev
->ControllerNameTable
);
824 // Disable the USB Host Controller
826 HcDev
->PciIo
->Attributes (
828 EfiPciIoAttributeOperationDisable
,
829 EFI_PCI_DEVICE_ENABLE
,
833 gBS
->FreePool (HcDev
);
841 UHCIDriverBindingStop (
842 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
843 IN EFI_HANDLE Controller
,
844 IN UINTN NumberOfChildren
,
845 IN EFI_HANDLE
*ChildHandleBuffer
850 Stop this driver on ControllerHandle. Support stoping any child handles
851 created by this driver.
854 This - Protocol instance pointer.
855 Controller - Handle of device to stop driver on
856 NumberOfChildren - Number of Children in the ChildHandleBuffer
857 ChildHandleBuffer - List of handles for the children we need to stop.
865 EFI_USB_HC_PROTOCOL
*UsbHc
;
866 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
867 EFI_STATUS OpenStatus
;
869 OpenStatus
= gBS
->OpenProtocol (
871 &gEfiUsbHcProtocolGuid
,
873 This
->DriverBindingHandle
,
875 EFI_OPEN_PROTOCOL_GET_PROTOCOL
879 // Test whether the Controller handler passed in is a valid
880 // Usb controller handle that should be supported, if not,
881 // return the error status directly
883 if (EFI_ERROR (OpenStatus
)) {
887 OpenStatus
= gBS
->OpenProtocol (
889 &gEfiUsb2HcProtocolGuid
,
891 This
->DriverBindingHandle
,
893 EFI_OPEN_PROTOCOL_GET_PROTOCOL
897 // Test whether the Controller handler passed in is a valid
898 // Usb controller handle that should be supported, if not,
899 // return the error status directly
901 if (EFI_ERROR (OpenStatus
)) {
905 // free all the controller related memory and uninstall UHCI Protocol.
907 UnInstallUHCInterface (Controller
, UsbHc
);
911 &gEfiPciIoProtocolGuid
,
912 This
->DriverBindingHandle
,
924 IN EFI_USB_HC_PROTOCOL
*This
,
930 Provides software reset for the USB host controller.
934 This A pointer to the EFI_USB_HC_PROTOCOL instance.
936 Attributes A bit mask of the reset operation to perform.
937 See below for a list of the supported bit mask values.
939 #define EFI_USB_HC_RESET_GLOBAL 0x0001
940 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
942 EFI_USB_HC_RESET_GLOBAL
943 If this bit is set, a global reset signal will be sent to the USB bus.
944 This resets all of the USB bus logic, including the USB host
945 controller hardware and all the devices attached on the USB bus.
946 EFI_USB_HC_RESET_HOST_CONTROLLER
947 If this bit is set, the USB host controller hardware will be reset.
948 No reset signal will be sent to the USB bus.
952 The reset operation succeeded.
953 EFI_INVALID_PARAMETER
954 Attributes is not valid.
956 An error was encountered while attempting to perform
962 UINT32 CommandRegAddr
;
963 UINT32 FlBaseAddrReg
;
968 HcDev
= USB_HC_DEV_FROM_THIS (This
);
970 CommandRegAddr
= (UINT32
) (USBCMD
);
971 FlBaseAddrReg
= (UINT32
) (USBFLBASEADD
);
973 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
976 // set the Global Reset bit in the command register
978 Status
= ReadUHCCommandReg (
983 if (EFI_ERROR (Status
)) {
984 return EFI_DEVICE_ERROR
;
987 Command
|= USBCMD_GRESET
;
988 Status
= WriteUHCCommandReg (
993 if (EFI_ERROR (Status
)) {
994 return EFI_DEVICE_ERROR
;
998 // Wait 50ms for root port to let reset complete
999 // See UHCI spec page122 Reset signaling
1001 gBS
->Stall (ROOT_PORT_REST_TIME
);
1004 // Clear the Global Reset bit to zero.
1006 Command
&= ~USBCMD_GRESET
;
1007 Status
= WriteUHCCommandReg (
1012 if (EFI_ERROR (Status
)) {
1013 return EFI_DEVICE_ERROR
;
1016 // UHCI spec page120 reset recovery time
1018 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
1021 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
1024 // set Host Controller Reset bit to 1
1026 Status
= ReadUHCCommandReg (
1031 if (EFI_ERROR (Status
)) {
1032 return EFI_DEVICE_ERROR
;
1035 Command
|= USBCMD_HCRESET
;
1036 Status
= WriteUHCCommandReg (
1041 if (EFI_ERROR (Status
)) {
1042 return EFI_DEVICE_ERROR
;
1045 // this bit will be reset by Host Controller when reset is completed.
1046 // wait 10ms to let reset complete
1048 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
1052 return EFI_INVALID_PARAMETER
;
1056 // Delete all old transactions on the USB bus
1058 CleanUsbTransactions (HcDev
);
1061 // Initialize Universal Host Controller's Frame List Data Structure
1063 InitFrameList (HcDev
);
1066 // Reset may cause Frame List Base Address Register reset to zero,
1067 // so set the original value back again.
1069 SetFrameListBaseAddress (
1072 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
1081 IN EFI_USB_HC_PROTOCOL
*This
,
1082 OUT EFI_USB_HC_STATE
*State
1086 Routine Description:
1087 Retrieves current state of the USB host controller.
1091 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1093 State A pointer to the EFI_USB_HC_STATE data structure that
1094 indicates current state of the USB host controller.
1095 Type EFI_USB_HC_STATE is defined below.
1099 EfiUsbHcStateOperational,
1100 EfiUsbHcStateSuspend,
1101 EfiUsbHcStateMaximum
1106 The state information of the host controller was returned in State.
1107 EFI_INVALID_PARAMETER
1110 An error was encountered while attempting to retrieve the
1111 host controller's current state.
1115 UINT32 CommandRegAddr
;
1116 UINT32 StatusRegAddr
;
1121 if (State
== NULL
) {
1122 return EFI_INVALID_PARAMETER
;
1125 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1127 CommandRegAddr
= (UINT32
) (USBCMD
);
1128 StatusRegAddr
= (UINT32
) (USBSTS
);
1130 Status
= ReadUHCCommandReg (
1136 if (EFI_ERROR (Status
)) {
1137 return EFI_DEVICE_ERROR
;
1140 Status
= ReadUHCCommandReg (
1145 if (EFI_ERROR (Status
)) {
1146 return EFI_DEVICE_ERROR
;
1149 if (UhcCommand
& USBCMD_EGSM
) {
1150 *State
= EfiUsbHcStateSuspend
;
1154 if ((UhcStatus
& USBSTS_HCH
) == 0) {
1155 *State
= EfiUsbHcStateOperational
;
1157 *State
= EfiUsbHcStateHalt
;
1167 IN EFI_USB_HC_PROTOCOL
*This
,
1168 IN EFI_USB_HC_STATE State
1172 Routine Description:
1173 Sets the USB host controller to a specific state.
1177 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1179 State Indicates the state of the host controller that will be set.
1183 The USB host controller was successfully placed in the state
1185 EFI_INVALID_PARAMETER
1188 Failed to set the state specified by State due to device error.
1192 UINT32 CommandRegAddr
;
1193 UINT32 StatusRegAddr
;
1195 EFI_USB_HC_STATE CurrentState
;
1198 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1200 CommandRegAddr
= (UINT32
) (USBCMD
);
1201 StatusRegAddr
= (UINT32
) (USBSTS
);
1203 Status
= UHCIGetState (This
, &CurrentState
);
1204 if (EFI_ERROR (Status
)) {
1205 return EFI_DEVICE_ERROR
;
1210 case EfiUsbHcStateHalt
:
1211 if (CurrentState
== EfiUsbHcStateHalt
) {
1215 Status
= ReadUHCCommandReg (
1220 if (EFI_ERROR (Status
)) {
1221 return EFI_DEVICE_ERROR
;
1224 Command
&= ~USBCMD_RS
;
1226 Status
= WriteUHCCommandReg (
1231 if (EFI_ERROR (Status
)) {
1232 return EFI_DEVICE_ERROR
;
1235 StatusRegAddr
= (UINT32
) (USBSTS
);
1237 // ensure the HC is in halt status after send the stop command
1239 if (WaitForUHCHalt (HcDev
->PciIo
, StatusRegAddr
, STALL_1_SECOND
) == EFI_TIMEOUT
) {
1240 return EFI_DEVICE_ERROR
;
1244 case EfiUsbHcStateOperational
:
1245 if (IsHostSysOrProcessErr (HcDev
->PciIo
, StatusRegAddr
)) {
1246 return EFI_DEVICE_ERROR
;
1249 switch (CurrentState
) {
1251 case EfiUsbHcStateOperational
:
1254 case EfiUsbHcStateHalt
:
1256 // Set Run/Stop bit to 1.
1258 Status
= ReadUHCCommandReg (
1263 if (EFI_ERROR (Status
)) {
1264 return EFI_DEVICE_ERROR
;
1267 Command
|= USBCMD_RS
| USBCMD_MAXP
;
1268 Status
= WriteUHCCommandReg (
1273 if (EFI_ERROR (Status
)) {
1274 return EFI_DEVICE_ERROR
;
1279 case EfiUsbHcStateSuspend
:
1280 Status
= ReadUHCCommandReg (
1285 if (EFI_ERROR (Status
)) {
1286 return EFI_DEVICE_ERROR
;
1290 // FGR(Force Global Resume) bit is 0
1292 if ((Command
| (~USBCMD_FGR
)) != 0xFF) {
1294 // Write FGR bit to 1
1296 Command
|= USBCMD_FGR
;
1297 WriteUHCCommandReg (
1305 // wait 20ms to let resume complete
1306 // (20ms is specified by UHCI spec)
1308 gBS
->Stall (FORCE_GLOBAL_RESUME_TIME
);
1311 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
1313 Command
&= ~USBCMD_FGR
;
1314 Command
&= ~USBCMD_EGSM
;
1315 Command
|= USBCMD_RS
;
1316 WriteUHCCommandReg (
1328 case EfiUsbHcStateSuspend
:
1329 if (CurrentState
== EfiUsbHcStateSuspend
) {
1333 Status
= UHCISetState (This
, EfiUsbHcStateHalt
);
1334 if (EFI_ERROR (Status
)) {
1335 return EFI_DEVICE_ERROR
;
1338 // Set Enter Global Suspend Mode bit to 1.
1340 Status
= ReadUHCCommandReg (
1345 if (EFI_ERROR (Status
)) {
1346 return EFI_DEVICE_ERROR
;
1349 Command
|= USBCMD_EGSM
;
1350 Status
= WriteUHCCommandReg (
1355 if (EFI_ERROR (Status
)) {
1356 return EFI_DEVICE_ERROR
;
1361 return EFI_INVALID_PARAMETER
;
1369 UHCIGetRootHubPortNumber (
1370 IN EFI_USB_HC_PROTOCOL
*This
,
1371 OUT UINT8
*PortNumber
1375 Routine Description:
1376 Retrieves the number of root hub ports.
1380 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1382 PortNumber A pointer to the number of the root hub ports.
1386 The port number was retrieved successfully.
1387 EFI_INVALID_PARAMETER
1390 An error was encountered while attempting to
1391 retrieve the port number.
1396 UINT16 RHPortControl
;
1400 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1402 if (PortNumber
== NULL
) {
1403 return EFI_INVALID_PARAMETER
;
1408 for (Index
= 0; Index
< 2; Index
++) {
1409 PSAddr
= (UINT32
) (USBPORTSC1
+ Index
* 2);
1410 Status
= ReadRootPortReg (
1415 if (EFI_ERROR (Status
)) {
1416 return EFI_DEVICE_ERROR
;
1419 // Port Register content is valid
1421 if (RHPortControl
!= 0xff) {
1431 UHCIGetRootHubPortStatus (
1432 IN EFI_USB_HC_PROTOCOL
*This
,
1433 IN UINT8 PortNumber
,
1434 OUT EFI_USB_PORT_STATUS
*PortStatus
1438 Routine Description:
1439 Retrieves the current status of a USB root hub port.
1443 This A pointer to the EFI_USB_HC_PROTOCOL.
1445 PortNumber Specifies the root hub port from which the status
1446 is to be retrieved. This value is zero-based. For example,
1447 if a root hub has two ports, then the first port is numbered 0,
1448 and the second port is numbered 1.
1450 PortStatus A pointer to the current port status bits and
1451 port status change bits.
1455 The status of the USB root hub port specified by PortNumber
1456 was returned in PortStatus.
1457 EFI_INVALID_PARAMETER
1458 PortNumber is invalid.
1459 EFI_DEVICE_ERROR - Can't read register
1464 UINT16 RHPortStatus
;
1465 UINT8 TotalPortNumber
;
1468 if (PortStatus
== NULL
) {
1469 return EFI_INVALID_PARAMETER
;
1472 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1473 if (PortNumber
>= TotalPortNumber
) {
1474 return EFI_INVALID_PARAMETER
;
1477 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1478 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1481 // Clear port status
1483 PortStatus
->PortStatus
= 0;
1484 PortStatus
->PortChangeStatus
= 0;
1486 Status
= ReadRootPortReg (
1492 if (EFI_ERROR (Status
)) {
1493 return EFI_DEVICE_ERROR
;
1496 // Fill Port Status bits
1500 // Current Connect Status
1502 if (RHPortStatus
& USBPORTSC_CCS
) {
1503 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
1506 // Port Enabled/Disabled
1508 if (RHPortStatus
& USBPORTSC_PED
) {
1509 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
1515 if (RHPortStatus
& USBPORTSC_SUSP
) {
1516 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1522 if (RHPortStatus
& USBPORTSC_PR
) {
1523 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
1527 // Low Speed Device Attached
1529 if (RHPortStatus
& USBPORTSC_LSDA
) {
1530 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1533 // CHC will always return one in this bit
1535 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
1537 // Fill Port Status Change bits
1541 // Connect Status Change
1543 if (RHPortStatus
& USBPORTSC_CSC
) {
1544 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
1548 // Port Enabled/Disabled Change
1550 if (RHPortStatus
& USBPORTSC_PEDC
) {
1551 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
1559 UHCISetRootHubPortFeature (
1560 IN EFI_USB_HC_PROTOCOL
*This
,
1561 IN UINT8 PortNumber
,
1562 IN EFI_USB_PORT_FEATURE PortFeature
1566 Routine Description:
1567 Sets a feature for the specified root hub port.
1571 This A pointer to the EFI_USB_HC_PROTOCOL.
1573 PortNumber Specifies the root hub port whose feature
1574 is requested to be set.
1576 PortFeature Indicates the feature selector associated
1577 with the feature set request.
1581 The feature specified by PortFeature was set for the
1582 USB root hub port specified by PortNumber.
1583 EFI_INVALID_PARAMETER
1584 PortNumber is invalid or PortFeature is invalid.
1591 UINT32 CommandRegAddr
;
1593 // root hub port status
1595 UINT16 RHPortControl
;
1597 UINT8 TotalPortNumber
;
1600 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1601 if (PortNumber
>= TotalPortNumber
) {
1602 return EFI_INVALID_PARAMETER
;
1605 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1607 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1608 CommandRegAddr
= (UINT32
) (USBCMD
);
1610 Status
= ReadRootPortReg (
1615 if (EFI_ERROR (Status
)) {
1616 return EFI_DEVICE_ERROR
;
1619 switch (PortFeature
) {
1621 case EfiUsbPortSuspend
:
1622 Status
= ReadUHCCommandReg (
1627 if (EFI_ERROR (Status
)) {
1628 return EFI_DEVICE_ERROR
;
1631 if (!(Command
& USBCMD_EGSM
)) {
1633 // if global suspend is not active, can set port suspend
1635 RHPortControl
&= 0xfff5;
1636 RHPortControl
|= USBPORTSC_SUSP
;
1640 case EfiUsbPortReset
:
1641 RHPortControl
&= 0xfff5;
1643 // Set the reset bit
1645 RHPortControl
|= USBPORTSC_PR
;
1648 case EfiUsbPortPower
:
1651 case EfiUsbPortEnable
:
1652 RHPortControl
&= 0xfff5;
1653 RHPortControl
|= USBPORTSC_PED
;
1657 return EFI_INVALID_PARAMETER
;
1671 UHCIClearRootHubPortFeature (
1672 IN EFI_USB_HC_PROTOCOL
*This
,
1673 IN UINT8 PortNumber
,
1674 IN EFI_USB_PORT_FEATURE PortFeature
1678 Routine Description:
1679 Clears a feature for the specified root hub port.
1683 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1685 PortNumber Specifies the root hub port whose feature
1686 is requested to be cleared.
1688 PortFeature Indicates the feature selector associated with the
1689 feature clear request.
1693 The feature specified by PortFeature was cleared for the
1694 USB root hub port specified by PortNumber.
1695 EFI_INVALID_PARAMETER
1696 PortNumber is invalid or PortFeature is invalid.
1703 UINT16 RHPortControl
;
1704 UINT8 TotalPortNumber
;
1707 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1709 if (PortNumber
>= TotalPortNumber
) {
1710 return EFI_INVALID_PARAMETER
;
1713 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1714 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1716 Status
= ReadRootPortReg (
1721 if (EFI_ERROR (Status
)) {
1722 return EFI_DEVICE_ERROR
;
1725 switch (PortFeature
) {
1727 // clear PORT_ENABLE feature means disable port.
1729 case EfiUsbPortEnable
:
1730 RHPortControl
&= 0xfff5;
1731 RHPortControl
&= ~USBPORTSC_PED
;
1735 // clear PORT_SUSPEND feature means resume the port.
1736 // (cause a resume on the specified port if in suspend mode)
1738 case EfiUsbPortSuspend
:
1739 RHPortControl
&= 0xfff5;
1740 RHPortControl
&= ~USBPORTSC_SUSP
;
1746 case EfiUsbPortPower
:
1750 // clear PORT_RESET means clear the reset signal.
1752 case EfiUsbPortReset
:
1753 RHPortControl
&= 0xfff5;
1754 RHPortControl
&= ~USBPORTSC_PR
;
1758 // clear connect status change
1760 case EfiUsbPortConnectChange
:
1761 RHPortControl
&= 0xfff5;
1762 RHPortControl
|= USBPORTSC_CSC
;
1766 // clear enable/disable status change
1768 case EfiUsbPortEnableChange
:
1769 RHPortControl
&= 0xfff5;
1770 RHPortControl
|= USBPORTSC_PEDC
;
1774 // root hub does not support this request
1776 case EfiUsbPortSuspendChange
:
1780 // root hub does not support this request
1782 case EfiUsbPortOverCurrentChange
:
1786 // root hub does not support this request
1788 case EfiUsbPortResetChange
:
1792 return EFI_INVALID_PARAMETER
;
1806 UHCIControlTransfer (
1807 IN EFI_USB_HC_PROTOCOL
*This
,
1808 IN UINT8 DeviceAddress
,
1809 IN BOOLEAN IsSlowDevice
,
1810 IN UINT8 MaximumPacketLength
,
1811 IN EFI_USB_DEVICE_REQUEST
*Request
,
1812 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1813 IN OUT VOID
*Data
, OPTIONAL
1814 IN OUT UINTN
*DataLength
, OPTIONAL
1816 OUT UINT32
*TransferResult
1820 Routine Description:
1821 Submits control transfer to a target USB device.
1825 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1827 DeviceAddress Represents the address of the target device on the USB,
1828 which is assigned during USB enumeration.
1830 IsSlowDevice Indicates whether the target device is slow device
1831 or full-speed device.
1833 MaximumPacketLength Indicates the maximum packet size that the
1834 default control transfer endpoint is capable of
1835 sending or receiving.
1837 Request A pointer to the USB device request that will be sent
1840 TransferDirection Specifies the data direction for the transfer.
1841 There are three values available, DataIn, DataOut
1844 Data A pointer to the buffer of data that will be transmitted
1845 to USB device or received from USB device.
1847 DataLength Indicates the size, in bytes, of the data buffer
1850 TimeOut Indicates the maximum time, in microseconds,
1851 which the transfer is allowed to complete.
1853 TransferResult A pointer to the detailed result information generated
1854 by this control transfer.
1858 The control transfer was completed successfully.
1859 EFI_OUT_OF_RESOURCES
1860 The control transfer could not be completed due to a lack of resources.
1861 EFI_INVALID_PARAMETER
1862 Some parameters are invalid.
1864 The control transfer failed due to timeout.
1866 The control transfer failed due to host controller or device error.
1867 Caller should check TranferResult for detailed error information.
1877 TD_STRUCT
*PtrPreTD
;
1878 TD_STRUCT
*PtrSetupTD
;
1879 TD_STRUCT
*PtrStatusTD
;
1883 UINT8
*PtrDataSource
;
1886 UINT16 LoadFrameListIndex
;
1889 UINT8
*RequestMappedAddress
;
1890 VOID
*RequestMapping
;
1893 EFI_PHYSICAL_ADDRESS TempPtr
;
1896 TD_STRUCT
*PtrFirstDataTD
;
1897 TD_STRUCT
*ptrLastDataTD
;
1901 RequestMappedAddress
= NULL
;
1902 RequestMapping
= NULL
;
1904 PtrFirstDataTD
= NULL
;
1905 ptrLastDataTD
= NULL
;
1906 PktID
= INPUT_PACKET_ID
;
1908 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1909 StatusReg
= (UINT32
) (USBSTS
);
1910 FrameNumReg
= (UINT32
) (USBFRNUM
);
1915 // Parameters Checking
1917 if (Request
== NULL
|| TransferResult
== NULL
) {
1918 return EFI_INVALID_PARAMETER
;
1922 // if errors exist that cause host controller halt,
1923 // then return EFI_DEVICE_ERROR.
1925 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
1927 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
1928 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1929 return EFI_DEVICE_ERROR
;
1933 // low speed usb devices are limited to only an eight-byte
1934 // maximum data payload size
1936 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
1937 return EFI_INVALID_PARAMETER
;
1940 if (MaximumPacketLength
!= 8 &&
1941 MaximumPacketLength
!= 16 &&
1942 MaximumPacketLength
!= 32 &&
1943 MaximumPacketLength
!= 64) {
1944 return EFI_INVALID_PARAMETER
;
1947 if ((TransferDirection
!= EfiUsbNoData
) && (DataLength
== NULL
)) {
1948 return EFI_INVALID_PARAMETER
;
1951 switch (TransferDirection
) {
1954 PktID
= INPUT_PACKET_ID
;
1955 PtrDataSource
= Data
;
1956 DataLen
= *DataLength
;
1959 // map the source data buffer for bus master access.
1960 // BusMasterWrite means cpu read
1962 Status
= HcDev
->PciIo
->Map (
1964 EfiPciIoOperationBusMasterWrite
,
1970 if (EFI_ERROR (Status
)) {
1974 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
1978 PktID
= OUTPUT_PACKET_ID
;
1979 PtrDataSource
= Data
;
1980 DataLen
= *DataLength
;
1983 // map the source data buffer for bus master access.
1984 // BusMasterRead means cpu write
1986 Status
= HcDev
->PciIo
->Map (
1988 EfiPciIoOperationBusMasterRead
,
1994 if (EFI_ERROR (Status
)) {
1998 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2005 if ((DataLength
!= NULL
) && (*DataLength
!= 0)) {
2006 return EFI_INVALID_PARAMETER
;
2009 PktID
= OUTPUT_PACKET_ID
;
2010 PtrDataSource
= NULL
;
2016 return EFI_INVALID_PARAMETER
;
2019 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2020 if (EFI_ERROR (Status
)) {
2021 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2022 return EFI_DEVICE_ERROR
;
2025 // create QH structure and init
2027 Status
= CreateQH (HcDev
, &PtrQH
);
2028 if (EFI_ERROR (Status
)) {
2029 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2034 // map the Request for bus master access.
2035 // BusMasterRead means cpu write
2037 RequestLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
2038 Status
= HcDev
->PciIo
->Map (
2040 EfiPciIoOperationBusMasterRead
,
2047 if (EFI_ERROR (Status
)) {
2048 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2049 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2053 RequestMappedAddress
= (UINT8
*) ((UINTN
) TempPtr
);
2056 // generate Setup Stage TD
2058 Status
= GenSetupStageTD (
2063 (UINT8
*) RequestMappedAddress
,
2064 sizeof (EFI_USB_DEVICE_REQUEST
),
2068 if (EFI_ERROR (Status
)) {
2069 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2070 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2071 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2076 // Data Stage of Control Transfer
2080 while (DataLen
> 0) {
2082 // create TD structures and link together
2086 // PktSize is the data load size that each TD carries.
2088 PktSize
= (UINT8
) DataLen
;
2089 if (DataLen
> MaximumPacketLength
) {
2090 PktSize
= MaximumPacketLength
;
2093 Status
= GenDataTD (
2105 if (EFI_ERROR (Status
)) {
2107 // free all resources occupied
2109 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2110 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2111 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2112 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2113 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2118 // Link two TDs in vertical depth
2121 PtrFirstDataTD
= PtrTD
;
2122 PtrFirstDataTD
->ptrNextTD
= NULL
;
2125 LinkTDToTD (PtrPreTD
, PtrTD
);
2135 ptrLastDataTD
= PtrTD
;
2138 // Status Stage of Control Transfer
2140 if (PktID
== OUTPUT_PACKET_ID
) {
2141 PktID
= INPUT_PACKET_ID
;
2143 PktID
= OUTPUT_PACKET_ID
;
2147 // create Status Stage TD structure
2149 Status
= CreateStatusTD (
2158 if (EFI_ERROR (Status
)) {
2159 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2160 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2161 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2162 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2163 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2169 // link setup TD structures to QH structure
2171 LinkTDToQH (PtrQH
, PtrSetupTD
);
2173 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2176 // link QH-TDs to total 100 frame list entry to speed up the execution.
2178 for (Index
= 0; Index
< 100; Index
++) {
2180 HcDev
->FrameListEntry
,
2181 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2186 // Poll QH-TDs execution and get result.
2187 // detail status is returned
2189 Status
= ExecuteControlTransfer (
2198 // Remove Control Transfer QH-TDs structure from the frame list
2199 // and update the pointers in the Frame List
2200 // and other pointers in other related QH structures.
2202 for (Index
= 0; Index
< 100; Index
++) {
2206 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2212 // delete setup stage TD; the QH is reserved for the next stages.
2214 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2217 // if setup stage error, return error
2219 if (EFI_ERROR (Status
)) {
2223 // some control transfers do not have Data Stage
2225 if (PtrFirstDataTD
!= NULL
) {
2227 LinkTDToQH (PtrQH
, PtrFirstDataTD
);
2228 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2230 for (Index
= 0; Index
< 500; Index
++) {
2232 HcDev
->FrameListEntry
,
2233 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2238 Status
= ExecuteControlTransfer (
2247 for (Index
= 0; Index
< 500; Index
++) {
2251 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2257 // delete data stage TD; the QH is reserved for the next stage.
2259 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2262 // if data stage error, goto done and return error
2264 if (EFI_ERROR (Status
)) {
2268 LinkTDToQH (PtrQH
, PtrStatusTD
);
2270 // get the frame list index that the QH-TDs will be linked to.
2272 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2274 for (Index
= 0; Index
< 100; Index
++) {
2276 // put the QH-TDs directly or indirectly into the proper place
2277 // in the Frame List
2280 HcDev
->FrameListEntry
,
2281 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2286 // Poll QH-TDs execution and get result.
2287 // detail status is returned
2289 Status
= ExecuteControlTransfer (
2299 // Delete Control Transfer QH-TDs structure
2300 // and update the pointers in the Frame List
2301 // and other pointers in other related QH structures.
2303 // TRUE means must search other framelistindex
2305 for (Index
= 0; Index
< 100; Index
++) {
2309 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2315 DeleteQueuedTDs (HcDev
, PtrStatusTD
);
2319 // link setup stage TD with data stage TD
2321 PtrPreTD
= PtrSetupTD
;
2322 if (PtrFirstDataTD
!= NULL
) {
2323 LinkTDToTD (PtrSetupTD
, PtrFirstDataTD
);
2324 PtrPreTD
= ptrLastDataTD
;
2327 // link status TD with previous TD
2329 LinkTDToTD (PtrPreTD
, PtrStatusTD
);
2334 LinkTDToQH (PtrQH
, PtrSetupTD
);
2336 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2337 for (Index
= 0; Index
< 500; Index
++) {
2339 // put the QH-TDs directly or indirectly into the proper place
2340 // in the Frame List
2343 HcDev
->FrameListEntry
,
2344 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2349 // Poll QH-TDs execution and get result.
2350 // detail status is returned
2352 Status
= ExecuteControlTransfer (
2361 // Remove Control Transfer QH-TDs structure from the frame list
2362 // and update the pointers in the Frame List
2363 // and other pointers in other related QH structures.
2365 for (Index
= 0; Index
< 500; Index
++) {
2369 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2375 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2380 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2382 if (Mapping
!= NULL
) {
2383 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2386 if (RequestMapping
!= NULL
) {
2387 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2390 // if has errors that cause host controller halt,
2391 // then return EFI_DEVICE_ERROR directly.
2393 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2395 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2396 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2397 return EFI_DEVICE_ERROR
;
2400 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2401 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2408 IN EFI_USB_HC_PROTOCOL
*This
,
2409 IN UINT8 DeviceAddress
,
2410 IN UINT8 EndPointAddress
,
2411 IN UINT8 MaximumPacketLength
,
2413 IN OUT UINTN
*DataLength
,
2414 IN OUT UINT8
*DataToggle
,
2416 OUT UINT32
*TransferResult
2420 Routine Description:
2421 Submits bulk transfer to a bulk endpoint of a USB device.
2425 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2427 DeviceAddress Represents the address of the target device on the USB,
2428 which is assigned during USB enumeration.
2429 EndPointAddress The combination of an endpoint number and an
2430 endpoint direction of the target USB device.
2431 Each endpoint address supports data transfer in
2432 one direction except the control endpoint
2433 (whose default endpoint address is 0).
2434 It is the caller's responsibility to make sure that
2435 the EndPointAddress represents a bulk endpoint.
2437 MaximumPacketLength Indicates the maximum packet size the target endpoint
2438 is capable of sending or receiving.
2440 Data A pointer to the buffer of data that will be transmitted
2441 to USB device or received from USB device.
2442 DataLength When input, indicates the size, in bytes, of the data buffer
2443 specified by Data. When output, indicates the actually
2444 transferred data size.
2446 DataToggle A pointer to the data toggle value. On input, it indicates
2447 the initial data toggle value the bulk transfer should adopt;
2448 on output, it is updated to indicate the data toggle value
2449 of the subsequent bulk transfer.
2451 TimeOut Indicates the maximum time, in microseconds, which the
2452 transfer is allowed to complete.
2454 TransferResult A pointer to the detailed result information of the
2459 The bulk transfer was completed successfully.
2460 EFI_OUT_OF_RESOURCES
2461 The bulk transfer could not be submitted due to lack of resource.
2462 EFI_INVALID_PARAMETER
2463 Some parameters are invalid.
2465 The bulk transfer failed due to timeout.
2467 The bulk transfer failed due to host controller or device error.
2468 Caller should check TranferResult for detailed error information.
2477 TD_STRUCT
*PtrFirstTD
;
2479 TD_STRUCT
*PtrPreTD
;
2480 UINT16 LoadFrameListIndex
;
2481 UINT16 SavedFrameListIndex
;
2483 UINT8
*PtrDataSource
;
2490 EFI_USB_DATA_DIRECTION TransferDirection
;
2492 // Used to calculate how many entries are linked to the
2493 // specified bulk transfer QH-TDs
2497 BOOLEAN ShortPacketEnable
;
2498 EFI_PHYSICAL_ADDRESS TempPtr
;
2501 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2502 StatusReg
= (UINT32
) (USBSTS
);
2503 FrameNumReg
= (UINT32
) (USBFRNUM
);
2504 PktID
= INPUT_PACKET_ID
;
2511 ShortPacketEnable
= FALSE
;
2515 // Parameters Checking
2518 if ((DataLength
== NULL
) ||
2520 (TransferResult
== NULL
)) {
2521 return EFI_INVALID_PARAMETER
;
2525 // if has errors that cause host controller halt,
2526 // then return EFI_DEVICE_ERROR directly.
2528 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2530 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2531 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2532 return EFI_DEVICE_ERROR
;
2535 if (*DataLength
== 0) {
2536 return EFI_INVALID_PARAMETER
;
2539 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2540 return EFI_INVALID_PARAMETER
;
2543 if (MaximumPacketLength
!= 8 &&
2544 MaximumPacketLength
!= 16 &&
2545 MaximumPacketLength
!= 32 &&
2546 MaximumPacketLength
!= 64) {
2547 return EFI_INVALID_PARAMETER
;
2551 // Enable the maximum packet size (64bytes)
2552 // that can be used for full speed bandwidth reclamation
2553 // at the end of a frame.
2555 EnableMaxPacketSize (HcDev
);
2557 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2558 if (EFI_ERROR (Status
)) {
2559 return EFI_DEVICE_ERROR
;
2563 // construct QH and TD data structures,
2564 // and link them together
2566 if (EndPointAddress
& 0x80) {
2567 TransferDirection
= EfiUsbDataIn
;
2569 TransferDirection
= EfiUsbDataOut
;
2572 switch (TransferDirection
) {
2575 ShortPacketEnable
= TRUE
;
2576 PktID
= INPUT_PACKET_ID
;
2577 PtrDataSource
= Data
;
2578 DataLen
= *DataLength
;
2581 // BusMasterWrite means cpu read
2583 Status
= HcDev
->PciIo
->Map (
2585 EfiPciIoOperationBusMasterWrite
,
2591 if (EFI_ERROR (Status
)) {
2595 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2599 PktID
= OUTPUT_PACKET_ID
;
2600 PtrDataSource
= Data
;
2601 DataLen
= *DataLength
;
2604 // BusMasterRead means cpu write
2606 Status
= HcDev
->PciIo
->Map (
2608 EfiPciIoOperationBusMasterRead
,
2614 if (EFI_ERROR (Status
)) {
2618 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2622 return EFI_INVALID_PARAMETER
;
2626 // create QH structure and init
2628 Status
= CreateQH (HcDev
, &PtrQH
);
2629 if (EFI_ERROR (Status
)) {
2630 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2635 // i is used to calculate the total number of TDs.
2640 while (DataLen
> 0) {
2643 // create TD structures and link together
2646 PktSize
= (UINT8
) DataLen
;
2647 if (DataLen
> MaximumPacketLength
) {
2648 PktSize
= MaximumPacketLength
;
2651 Status
= GenDataTD (
2663 if (EFI_ERROR (Status
)) {
2664 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2665 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2666 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2671 // Enable short packet detection.
2672 // (default action is disabling short packet detection)
2674 if (ShortPacketEnable
) {
2675 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
2680 PtrFirstTD
->ptrNextTD
= NULL
;
2684 // Link two TDs in vertical depth
2686 LinkTDToTD (PtrPreTD
, PtrTD
);
2699 // link TD structures to QH structure
2701 LinkTDToQH (PtrQH
, PtrFirstTD
);
2704 // calculate how many entries are linked to the specified bulk transfer QH-TDs
2705 // the below values are referred to the USB spec revision1.1.
2707 switch (MaximumPacketLength
) {
2709 LinkTimes
= Index
/ 71 + 1;
2713 LinkTimes
= Index
/ 51 + 1;
2717 LinkTimes
= Index
/ 33 + 1;
2721 LinkTimes
= Index
/ 19 + 1;
2728 // put QH-TDs into Frame list
2730 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2731 SavedFrameListIndex
= LoadFrameListIndex
;
2733 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2736 // put the QH-TD directly or indirectly into the proper place
2737 // in the Frame List
2739 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
2741 LoadFrameListIndex
+= 1;
2742 LoadFrameListIndex
&= 0x3FF;
2745 LoadFrameListIndex
= SavedFrameListIndex
;
2748 // Execute QH-TD and get result
2751 // detail status is put into the Result field in the pIRP
2752 // the Data Toggle value is also re-updated to the value
2753 // of the last successful TD
2755 Status
= ExecBulkorSyncInterruptTransfer (
2766 // Delete Bulk transfer QH-TD structure
2767 // and maitain the pointers in the Frame List
2768 // and other pointers in related QH structure
2770 // TRUE means must search other framelistindex
2772 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2780 LoadFrameListIndex
+= 1;
2781 LoadFrameListIndex
&= 0x3FF;
2784 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2786 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2788 if (Mapping
!= NULL
) {
2789 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2793 // if has errors that cause host controller halt,
2794 // then return EFI_DEVICE_ERROR directly.
2796 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2798 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2799 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2800 return EFI_DEVICE_ERROR
;
2803 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2805 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2812 UHCIAsyncInterruptTransfer (
2813 IN EFI_USB_HC_PROTOCOL
* This
,
2814 IN UINT8 DeviceAddress
,
2815 IN UINT8 EndPointAddress
,
2816 IN BOOLEAN IsSlowDevice
,
2817 IN UINT8 MaximumPacketLength
,
2818 IN BOOLEAN IsNewTransfer
,
2819 IN OUT UINT8
*DataToggle
,
2820 IN UINTN PollingInterval
, OPTIONAL
2821 IN UINTN DataLength
, OPTIONAL
2822 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
2823 IN VOID
*Context OPTIONAL
2827 Routine Description:
2828 Submits an asynchronous interrupt transfer to an
2829 interrupt endpoint of a USB device.
2833 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2835 DeviceAddress Represents the address of the target device on the USB,
2836 which is assigned during USB enumeration.
2838 EndPointAddress The combination of an endpoint number and an endpoint
2839 direction of the target USB device. Each endpoint address
2840 supports data transfer in one direction except the
2841 control endpoint (whose default endpoint address is 0).
2842 It is the caller's responsibility to make sure that
2843 the EndPointAddress represents an interrupt endpoint.
2845 IsSlowDevice Indicates whether the target device is slow device
2846 or full-speed device.
2848 MaximumPacketLength Indicates the maximum packet size the target endpoint
2849 is capable of sending or receiving.
2851 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
2852 the host and the target interrupt endpoint.
2853 If FALSE, the specified asynchronous interrupt pipe
2856 DataToggle A pointer to the data toggle value. On input, it is valid
2857 when IsNewTransfer is TRUE, and it indicates the initial
2858 data toggle value the asynchronous interrupt transfer
2860 On output, it is valid when IsNewTransfer is FALSE,
2861 and it is updated to indicate the data toggle value of
2862 the subsequent asynchronous interrupt transfer.
2864 PollingInterval Indicates the interval, in milliseconds, that the
2865 asynchronous interrupt transfer is polled.
2866 This parameter is required when IsNewTransfer is TRUE.
2868 DataLength Indicates the length of data to be received at the
2869 rate specified by PollingInterval from the target
2870 asynchronous interrupt endpoint. This parameter
2871 is only required when IsNewTransfer is TRUE.
2873 CallBackFunction The Callback function.This function is called at the
2874 rate specified by PollingInterval.This parameter is
2875 only required when IsNewTransfer is TRUE.
2877 Context The context that is passed to the CallBackFunction.
2878 This is an optional parameter and may be NULL.
2882 The asynchronous interrupt transfer request has been successfully
2883 submitted or canceled.
2884 EFI_INVALID_PARAMETER
2885 Some parameters are invalid.
2886 EFI_OUT_OF_RESOURCES
2887 The request could not be completed due to a lack of resources.
2896 QH_STRUCT
*ptrFirstQH
;
2898 QH_STRUCT
*ptrPreQH
;
2899 TD_STRUCT
*PtrFirstTD
;
2901 TD_STRUCT
*PtrPreTD
;
2902 UINT16 LoadFrameListIndex
;
2910 BOOLEAN ShortPacketEnable
;
2911 UINT8 CurrentDataToggle
;
2912 EFI_PHYSICAL_ADDRESS TempPtr
;
2918 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2919 StatusReg
= (UINT32
) (USBSTS
);
2920 FrameNumReg
= (UINT32
) (USBFRNUM
);
2922 ShortPacketEnable
= FALSE
;
2924 PktID
= INPUT_PACKET_ID
;
2933 if ((EndPointAddress
& 0x80) == 0) {
2934 return EFI_INVALID_PARAMETER
;
2938 // delete Async interrupt transfer request
2940 if (!IsNewTransfer
) {
2942 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
2944 Status
= DeleteAsyncINTQHTDs (
2951 gBS
->RestoreTPL (OldTpl
);
2956 // if has errors that cause host controller halt,
2957 // then return EFI_DEVICE_ERROR directly.
2959 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2961 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2962 return EFI_DEVICE_ERROR
;
2965 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2968 // submit Async interrupt transfer request
2970 if (PollingInterval
< 1 || PollingInterval
> 255) {
2971 return EFI_INVALID_PARAMETER
;
2974 if (DataLength
== 0) {
2975 return EFI_INVALID_PARAMETER
;
2978 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2979 return EFI_INVALID_PARAMETER
;
2982 ShortPacketEnable
= TRUE
;
2983 PktID
= INPUT_PACKET_ID
;
2984 DataLen
= DataLength
;
2985 Ptr
= AllocatePool (DataLen
);
2987 return EFI_OUT_OF_RESOURCES
;
2991 // BusMasterWrite means cpu read
2993 Status
= HcDev
->PciIo
->Map (
2995 EfiPciIoOperationBusMasterWrite
,
3001 if (EFI_ERROR (Status
)) {
3002 gBS
->FreePool (Ptr
);
3006 MappedPtr
= (UINT8
*) ((UINTN
) TempPtr
);
3008 CurrentDataToggle
= *DataToggle
;
3012 while (DataLen
> 0) {
3014 // create TD structures and link together
3017 PktSize
= (UINT8
) DataLen
;
3018 if (DataLen
> MaximumPacketLength
) {
3019 PktSize
= MaximumPacketLength
;
3022 Status
= GenDataTD (
3033 if (EFI_ERROR (Status
)) {
3034 gBS
->FreePool (Ptr
);
3035 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3036 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3040 // Enable short packet detection.
3042 if (ShortPacketEnable
) {
3043 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
3048 PtrFirstTD
->ptrNextTD
= NULL
;
3052 // Link two TDs in vertical depth
3054 LinkTDToTD (PtrPreTD
, PtrTD
);
3059 CurrentDataToggle
^= 1;
3060 MappedPtr
+= PktSize
;
3065 // roll one value back
3067 CurrentDataToggle
^= 1;
3070 // create a list of QH structures and init,
3071 // link TDs to all the QHs, and link all the QHs together using internal
3072 // defined pointer of the QH_STRUCT.
3076 for (Index
= 0; Index
< 1024;) {
3078 Status
= CreateQH (HcDev
, &PtrQH
);
3079 if (EFI_ERROR (Status
)) {
3080 gBS
->FreePool (Ptr
);
3081 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3082 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3086 PtrQH
= TempQH
->ptrNextIntQH
;
3087 UhciFreePool (HcDev
, (UINT8
*) TempQH
, sizeof (QH_STRUCT
));
3094 // link TD structures to QH structure
3096 LinkTDToQH (PtrQH
, PtrFirstTD
);
3100 ptrFirstQH
->ptrNextIntQH
= NULL
;
3104 // link neighbor QH structures together
3106 ptrPreQH
->ptrNextIntQH
= PtrQH
;
3111 Index
= (UINT16
) (PollingInterval
+ Index
);
3114 // last QH in QH list should set its next QH pointer to NULL.
3116 PtrQH
->ptrNextIntQH
= NULL
;
3119 // Save QH-TD structures in Interrupt transfer list,
3120 // for monitor interrupt transfer execution routine use.
3122 InsertQHTDToINTList (
3138 // put QHs-TDs into Frame list
3140 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
3144 for (Index
= LoadFrameListIndex
; Index
< (1024 + LoadFrameListIndex
);) {
3147 // put the QH-TD directly or indirectly into the proper place
3148 // in the Frame List
3150 LinkQHToFrameList (HcDev
->FrameListEntry
, (UINT16
) (Index
& 0x3FF), PtrQH
);
3152 Index
= (UINT16
) (PollingInterval
+ Index
);
3154 PtrQH
= PtrQH
->ptrNextIntQH
;
3157 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
3164 UHCISyncInterruptTransfer (
3165 IN EFI_USB_HC_PROTOCOL
*This
,
3166 IN UINT8 DeviceAddress
,
3167 IN UINT8 EndPointAddress
,
3168 IN BOOLEAN IsSlowDevice
,
3169 IN UINT8 MaximumPacketLength
,
3171 IN OUT UINTN
*DataLength
,
3172 IN OUT UINT8
*DataToggle
,
3174 OUT UINT32
*TransferResult
3178 Routine Description:
3179 Submits synchronous interrupt transfer to an interrupt endpoint
3184 This A pointer to the EFI_USB_HC_PROTOCOL instance.
3186 DeviceAddress Represents the address of the target device on the USB,
3187 which is assigned during USB enumeration.
3189 EndPointAddress The combination of an endpoint number and an endpoint
3190 direction of the target USB device. Each endpoint
3191 address supports data transfer in one direction
3192 except the control endpoint (whose default
3193 endpoint address is 0). It is the caller's responsibility
3194 to make sure that the EndPointAddress represents
3195 an interrupt endpoint.
3197 IsSlowDevice Indicates whether the target device is slow device
3198 or full-speed device.
3200 MaximumPacketLength Indicates the maximum packet size the target endpoint
3201 is capable of sending or receiving.
3203 Data A pointer to the buffer of data that will be transmitted
3204 to USB device or received from USB device.
3206 DataLength On input, the size, in bytes, of the data buffer specified
3207 by Data. On output, the number of bytes transferred.
3209 DataToggle A pointer to the data toggle value. On input, it indicates
3210 the initial data toggle value the synchronous interrupt
3211 transfer should adopt;
3212 on output, it is updated to indicate the data toggle value
3213 of the subsequent synchronous interrupt transfer.
3215 TimeOut Indicates the maximum time, in microseconds, which the
3216 transfer is allowed to complete.
3218 TransferResult A pointer to the detailed result information from
3219 the synchronous interrupt transfer.
3223 The synchronous interrupt transfer was completed successfully.
3224 EFI_OUT_OF_RESOURCES
3225 The synchronous interrupt transfer could not be submitted due
3226 to lack of resource.
3227 EFI_INVALID_PARAMETER
3228 Some parameters are invalid.
3230 The synchronous interrupt transfer failed due to timeout.
3232 The synchronous interrupt transfer failed due to host controller
3233 or device error. Caller should check TranferResult for detailed
3242 TD_STRUCT
*PtrFirstTD
;
3244 TD_STRUCT
*PtrPreTD
;
3245 UINT16 LoadFrameListIndex
;
3246 UINT16 SavedFrameListIndex
;
3250 UINT8
*PtrDataSource
;
3254 BOOLEAN ShortPacketEnable
;
3255 EFI_PHYSICAL_ADDRESS TempPtr
;
3259 HcDev
= USB_HC_DEV_FROM_THIS (This
);
3260 StatusReg
= (UINT32
) (USBSTS
);
3261 FrameNumReg
= (UINT32
) (USBFRNUM
);
3262 ShortPacketEnable
= FALSE
;
3264 PktID
= INPUT_PACKET_ID
;
3274 // Parameters Checking
3277 if ((DataLength
== NULL
) ||
3279 (TransferResult
== NULL
)) {
3280 return EFI_INVALID_PARAMETER
;
3284 // if has errors that cause host controller halt,
3285 // then return EFI_DEVICE_ERROR directly.
3287 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3289 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3290 *TransferResult
= EFI_USB_ERR_SYSTEM
;
3291 return EFI_DEVICE_ERROR
;
3294 if ((EndPointAddress
& 0x80) == 0) {
3295 return EFI_INVALID_PARAMETER
;
3298 if (*DataLength
== 0) {
3299 return EFI_INVALID_PARAMETER
;
3302 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
3303 return EFI_INVALID_PARAMETER
;
3306 if (MaximumPacketLength
> 64) {
3307 return EFI_INVALID_PARAMETER
;
3310 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
3311 return EFI_INVALID_PARAMETER
;
3314 if (TransferResult
== NULL
) {
3315 return EFI_INVALID_PARAMETER
;
3318 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3321 // submit Sync interrupt transfer request
3323 ShortPacketEnable
= TRUE
;
3324 PktID
= INPUT_PACKET_ID
;
3325 DataLen
= *DataLength
;
3326 PtrDataSource
= Data
;
3329 // create QH structure and init
3331 Status
= CreateQH (HcDev
, &PtrQH
);
3332 if (EFI_ERROR (Status
)) {
3337 // BusMasterWrite means cpu read
3339 Status
= HcDev
->PciIo
->Map (
3341 EfiPciIoOperationBusMasterWrite
,
3347 if (EFI_ERROR (Status
)) {
3348 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3352 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
3355 while (DataLen
> 0) {
3357 // create TD structures and link together
3359 PktSize
= (UINT8
) DataLen
;
3360 if (DataLen
> MaximumPacketLength
) {
3361 PktSize
= MaximumPacketLength
;
3364 Status
= GenDataTD (
3375 if (EFI_ERROR (Status
)) {
3376 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3377 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3378 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3382 // Enable short packet detection.
3384 if (ShortPacketEnable
) {
3385 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
3390 PtrFirstTD
->ptrNextTD
= NULL
;
3394 // Link two TDs in vertical depth
3396 LinkTDToTD (PtrPreTD
, PtrTD
);
3409 // link TD structures to QH structure
3411 LinkTDToQH (PtrQH
, PtrFirstTD
);
3413 switch (MaximumPacketLength
) {
3415 LinkTimes
= Index
/ 71 + 1;
3419 LinkTimes
= Index
/ 51 + 1;
3423 LinkTimes
= Index
/ 33 + 1;
3427 LinkTimes
= Index
/ 19 + 1;
3433 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
3434 SavedFrameListIndex
= LoadFrameListIndex
;
3436 for (Index
= 0; Index
< LinkTimes
; Index
++) {
3439 // put the QH-TD directly or indirectly into the proper place
3440 // in the Frame List
3442 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
3444 LoadFrameListIndex
+= 1;
3445 LoadFrameListIndex
&= 0x3FF;
3448 LoadFrameListIndex
= SavedFrameListIndex
;
3450 // detail status is put into the Result field in the pIRP
3451 // the Data Toggle value is also re-updated to the value
3452 // of the last successful TD
3454 Status
= ExecBulkorSyncInterruptTransfer (
3464 // Delete Sync Interrupt transfer QH-TD structure
3465 // and maintain the pointers in the Frame List
3466 // and other pointers in related QH structure
3468 // TRUE means must search other framelistindex
3470 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
3478 LoadFrameListIndex
+= 1;
3479 LoadFrameListIndex
&= 0x3FF;
3482 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3484 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3486 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3489 // if has errors that cause host controller halt,
3490 // then return EFI_DEVICE_ERROR directly.
3492 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3494 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3495 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
3496 return EFI_DEVICE_ERROR
;
3499 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3501 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
3508 UHCIIsochronousTransfer (
3509 IN EFI_USB_HC_PROTOCOL
*This
,
3510 IN UINT8 DeviceAddress
,
3511 IN UINT8 EndPointAddress
,
3512 IN UINT8 MaximumPacketLength
,
3514 IN UINTN DataLength
,
3515 OUT UINT32
*TransferResult
3519 Routine Description:
3520 Submits isochronous transfer to a target USB device.
3524 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3525 DeviceAddress - Represents the address of the target device on the USB,
3526 which is assigned during USB enumeration.
3527 EndPointAddress - End point address
3528 MaximumPacketLength - Indicates the maximum packet size that the
3529 default control transfer endpoint is capable of
3530 sending or receiving.
3531 Data - A pointer to the buffer of data that will be transmitted
3532 to USB device or received from USB device.
3533 DataLength - Indicates the size, in bytes, of the data buffer
3535 TransferResult - A pointer to the detailed result information generated
3536 by this control transfer.
3542 return EFI_UNSUPPORTED
;
3548 UHCIAsyncIsochronousTransfer (
3549 IN EFI_USB_HC_PROTOCOL
* This
,
3550 IN UINT8 DeviceAddress
,
3551 IN UINT8 EndPointAddress
,
3552 IN UINT8 MaximumPacketLength
,
3554 IN UINTN DataLength
,
3555 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
3556 IN VOID
*Context OPTIONAL
3560 Routine Description:
3561 Submits Async isochronous transfer to a target USB device.
3565 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3567 DeviceAddress - Represents the address of the target device on the USB,
3568 which is assigned during USB enumeration.
3570 EndPointAddress - End point address
3572 MaximumPacketLength - Indicates the maximum packet size that the
3573 default control transfer endpoint is capable of
3574 sending or receiving.
3576 Data - A pointer to the buffer of data that will be transmitted
3577 to USB device or received from USB device.
3579 IsochronousCallBack - When the transfer complete, the call back function will be called
3581 Context - Pass to the call back function as parameter
3588 return EFI_UNSUPPORTED
;
3592 // UEFI 2.0 Protocol
3597 IN EFI_USB2_HC_PROTOCOL
* This
,
3598 OUT UINT8
*MaxSpeed
,
3599 OUT UINT8
*PortNumber
,
3600 OUT UINT8
*Is64BitCapable
3604 Routine Description:
3605 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
3608 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3610 MaxSpeed - A pointer to the max speed USB host controller supports.
3612 PortNumber - A pointer to the number of root hub ports.
3614 Is64BitCapable - A pointer to an integer to show whether USB host controller
3615 supports 64-bit memory addressing.
3618 The host controller capabilities were retrieved successfully.
3619 EFI_INVALID_PARAMETER
3620 MaxSpeed or PortNumber or Is64BitCapable is NULL.
3622 An error was encountered while attempting to retrieve the capabilities.
3628 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3630 if ((NULL
== MaxSpeed
)
3631 ||(NULL
== PortNumber
)
3632 || (NULL
== Is64BitCapable
))
3634 return EFI_INVALID_PARAMETER
;
3637 *MaxSpeed
= EFI_USB_SPEED_FULL
;
3638 *Is64BitCapable
= (UINT8
)FALSE
;
3639 return UHCIGetRootHubPortNumber(&HcDev
->UsbHc
, PortNumber
);
3645 IN EFI_USB2_HC_PROTOCOL
* This
,
3646 IN UINT16 Attributes
3650 Routine Description:
3651 Provides software reset for the USB host controller according to UEFI 2.0 spec.
3654 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3656 Attributes - A bit mask of the reset operation to perform.
3657 See below for a list of the supported bit mask values.
3659 #define EFI_USB_HC_RESET_GLOBAL 0x0001
3660 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
3661 #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004
3662 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
3664 EFI_USB_HC_RESET_GLOBAL
3665 If this bit is set, a global reset signal will be sent to the USB bus.
3666 This resets all of the USB bus logic, including the USB host
3667 controller hardware and all the devices attached on the USB bus.
3668 EFI_USB_HC_RESET_HOST_CONTROLLER
3669 If this bit is set, the USB host controller hardware will be reset.
3670 No reset signal will be sent to the USB bus.
3674 The reset operation succeeded.
3675 EFI_INVALID_PARAMETER
3676 Attributes is not valid.
3678 The type of reset specified by Attributes is not currently supported by the host controller hardware.
3680 Reset operation is rejected due to the debug port being configured and active.
3682 An error was encountered while attempting to perform
3683 the reset operation.
3688 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3690 if (Attributes
==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
|| Attributes
==EFI_USB_HC_RESET_HOST_WITH_DEBUG
)
3691 return EFI_UNSUPPORTED
;
3702 IN EFI_USB2_HC_PROTOCOL
* This
,
3703 OUT EFI_USB_HC_STATE
* State
3707 Routine Description:
3708 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
3712 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3714 State - A pointer to the EFI_USB_HC_STATE data structure that
3715 indicates current state of the USB host controller.
3716 Type EFI_USB_HC_STATE is defined below.
3720 EfiUsbHcStateOperational,
3721 EfiUsbHcStateSuspend,
3722 EfiUsbHcStateMaximum
3727 The state information of the host controller was returned in State.
3728 EFI_INVALID_PARAMETER
3731 An error was encountered while attempting to retrieve the
3732 host controller's current state.
3737 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3738 return UHCIGetState(
3747 IN EFI_USB2_HC_PROTOCOL
* This
,
3748 IN EFI_USB_HC_STATE State
3752 Routine Description:
3753 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
3757 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3759 State - Indicates the state of the host controller that will be set.
3763 The USB host controller was successfully placed in the state
3765 EFI_INVALID_PARAMETER
3768 Failed to set the state specified by State due to device error.
3773 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3774 return UHCISetState(
3782 UHCI2ControlTransfer (
3783 IN EFI_USB2_HC_PROTOCOL
* This
,
3784 IN UINT8 DeviceAddress
,
3785 IN UINT8 DeviceSpeed
,
3786 IN UINTN MaximumPacketLength
,
3787 IN EFI_USB_DEVICE_REQUEST
* Request
,
3788 IN EFI_USB_DATA_DIRECTION TransferDirection
,
3790 IN OUT UINTN
*DataLength
,
3792 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3793 OUT UINT32
*TransferResult
3797 Routine Description:
3798 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..
3802 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3804 DeviceAddress -Represents the address of the target device on the USB,
3805 which is assigned during USB enumeration.
3807 DeviceSpeed - Indicates transfer speed of device.
3809 MaximumPacketLength - Indicates the maximum packet size that the
3810 default control transfer endpoint is capable of
3811 sending or receiving.
3813 Request - A pointer to the USB device request that will be sent
3816 TransferDirection - Specifies the data direction for the transfer.
3817 There are three values available, DataIn, DataOut
3820 Data -A pointer to the buffer of data that will be transmitted
3821 to USB device or received from USB device.
3823 DataLength - Indicates the size, in bytes, of the data buffer
3826 TimeOut - Indicates the maximum time, in microseconds,
3827 which the transfer is allowed to complete.
3829 TransferResult - A pointer to the detailed result information generated
3830 by this control transfer.
3834 The control transfer was completed successfully.
3835 EFI_OUT_OF_RESOURCES
3836 The control transfer could not be completed due to a lack of resources.
3837 EFI_INVALID_PARAMETER
3838 Some parameters are invalid.
3840 The control transfer failed due to timeout.
3842 The control transfer failed due to host controller or device error.
3843 Caller should check TranferResult for detailed error information.
3848 BOOLEAN IsSlowDevice
= (EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
;
3850 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3852 return UHCIControlTransfer(
3856 (UINT8
) MaximumPacketLength
,
3869 IN EFI_USB2_HC_PROTOCOL
* This
,
3870 IN UINT8 DeviceAddress
,
3871 IN UINT8 EndPointAddress
,
3872 IN UINT8 DeviceSpeed
,
3873 IN UINTN MaximumPacketLength
,
3874 IN UINT8 DataBuffersNumber
,
3875 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
3876 IN OUT UINTN
*DataLength
,
3877 IN OUT UINT8
*DataToggle
,
3879 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3880 OUT UINT32
*TransferResult
3884 Routine Description:
3885 Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.
3889 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3891 DeviceAddress Represents the address of the target device on the USB,
3892 which is assigned during USB enumeration.
3894 EndPointAddress The combination of an endpoint number and an
3895 endpoint direction of the target USB device.
3896 Each endpoint address supports data transfer in
3897 one direction except the control endpoint
3898 (whose default endpoint address is 0).
3899 It is the caller's responsibility to make sure that
3900 the EndPointAddress represents a bulk endpoint.
3902 DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL
3903 and EFI_USB_SPEED_HIGH.
3905 MaximumPacketLength Indicates the maximum packet size the target endpoint
3906 is capable of sending or receiving.
3908 DataBuffersNumber Number of data buffers prepared for the transfer.
3910 Data Array of pointers to the buffers of data that will be transmitted
3911 to USB device or received from USB device.
3913 DataLength When input, indicates the size, in bytes, of the data buffer
3914 specified by Data. When output, indicates the actually
3915 transferred data size.
3917 DataToggle A pointer to the data toggle value. On input, it indicates
3918 the initial data toggle value the bulk transfer should adopt;
3919 on output, it is updated to indicate the data toggle value
3920 of the subsequent bulk transfer.
3922 Translator A pointr to the transaction translator data.
3924 TimeOut Indicates the maximum time, in microseconds, which the
3925 transfer is allowed to complete.
3927 TransferResult A pointer to the detailed result information of the
3932 The bulk transfer was completed successfully.
3934 EFI_OUT_OF_RESOURCES
3935 The bulk transfer could not be submitted due to lack of resource.
3937 EFI_INVALID_PARAMETER
3938 Some parameters are invalid.
3941 The bulk transfer failed due to timeout.
3944 The bulk transfer failed due to host controller or device error.
3945 Caller should check TranferResult for detailed error information.
3951 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3953 if( Data
== NULL
|| DeviceSpeed
==EFI_USB_SPEED_LOW
)
3954 return EFI_INVALID_PARAMETER
;
3955 /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */
3957 return UHCIBulkTransfer (
3961 (UINT8
) MaximumPacketLength
,
3972 UHCI2AsyncInterruptTransfer (
3973 IN EFI_USB2_HC_PROTOCOL
* This
,
3974 IN UINT8 DeviceAddress
,
3975 IN UINT8 EndPointAddress
,
3976 IN UINT8 DeviceSpeed
,
3977 IN UINTN MaximumPacketLength
,
3978 IN BOOLEAN IsNewTransfer
,
3979 IN OUT UINT8
*DataToggle
,
3980 IN UINTN PollingInterval
,
3981 IN UINTN DataLength
,
3982 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3983 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
3988 Routine Description:
3989 Submits an asynchronous interrupt transfer to an
3990 interrupt endpoint of a USB device according to UEFI 2.0 spec.
3994 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3996 DeviceAddress Represents the address of the target device on the USB,
3997 which is assigned during USB enumeration.
3999 EndPointAddress The combination of an endpoint number and an endpoint
4000 direction of the target USB device. Each endpoint address
4001 supports data transfer in one direction except the
4002 control endpoint (whose default endpoint address is 0).
4003 It is the caller's responsibility to make sure that
4004 the EndPointAddress represents an interrupt endpoint.
4006 DeviceSpeed Indicates device speed.
4008 MaximumPacketLength Indicates the maximum packet size the target endpoint
4009 is capable of sending or receiving.
4011 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
4012 the host and the target interrupt endpoint.
4013 If FALSE, the specified asynchronous interrupt pipe
4016 DataToggle A pointer to the data toggle value. On input, it is valid
4017 when IsNewTransfer is TRUE, and it indicates the initial
4018 data toggle value the asynchronous interrupt transfer
4020 On output, it is valid when IsNewTransfer is FALSE,
4021 and it is updated to indicate the data toggle value of
4022 the subsequent asynchronous interrupt transfer.
4024 PollingInterval Indicates the interval, in milliseconds, that the
4025 asynchronous interrupt transfer is polled.
4026 This parameter is required when IsNewTransfer is TRUE.
4028 DataLength Indicates the length of data to be received at the
4029 rate specified by PollingInterval from the target
4030 asynchronous interrupt endpoint. This parameter
4031 is only required when IsNewTransfer is TRUE.
4033 Translator A pointr to the transaction translator data.
4035 CallBackFunction The Callback function.This function is called at the
4036 rate specified by PollingInterval.This parameter is
4037 only required when IsNewTransfer is TRUE.
4039 Context The context that is passed to the CallBackFunction.
4040 This is an optional parameter and may be NULL.
4045 The asynchronous interrupt transfer request has been successfully
4046 submitted or canceled.
4048 EFI_INVALID_PARAMETER
4049 Some parameters are invalid.
4051 EFI_OUT_OF_RESOURCES
4052 The request could not be completed due to a lack of resources.
4059 BOOLEAN IsSlowDevice
= (EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
;
4061 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4062 return UHCIAsyncInterruptTransfer(
4067 (UINT8
) MaximumPacketLength
,
4079 UHCI2SyncInterruptTransfer (
4080 IN EFI_USB2_HC_PROTOCOL
* This
,
4081 IN UINT8 DeviceAddress
,
4082 IN UINT8 EndPointAddress
,
4083 IN UINT8 DeviceSpeed
,
4084 IN UINTN MaximumPacketLength
,
4086 IN OUT UINTN
*DataLength
,
4087 IN OUT UINT8
*DataToggle
,
4089 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4090 OUT UINT32
*TransferResult
4094 Routine Description:
4095 Submits synchronous interrupt transfer to an interrupt endpoint
4096 of a USB device according to UEFI 2.0 spec.
4100 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4102 DeviceAddress Represents the address of the target device on the USB,
4103 which is assigned during USB enumeration.
4105 EndPointAddress The combination of an endpoint number and an endpoint
4106 direction of the target USB device. Each endpoint
4107 address supports data transfer in one direction
4108 except the control endpoint (whose default
4109 endpoint address is 0). It is the caller's responsibility
4110 to make sure that the EndPointAddress represents
4111 an interrupt endpoint.
4113 DeviceSpeed Indicates device speed.
4115 MaximumPacketLength Indicates the maximum packet size the target endpoint
4116 is capable of sending or receiving.
4118 Data A pointer to the buffer of data that will be transmitted
4119 to USB device or received from USB device.
4121 DataLength On input, the size, in bytes, of the data buffer specified
4122 by Data. On output, the number of bytes transferred.
4124 DataToggle A pointer to the data toggle value. On input, it indicates
4125 the initial data toggle value the synchronous interrupt
4126 transfer should adopt;
4127 on output, it is updated to indicate the data toggle value
4128 of the subsequent synchronous interrupt transfer.
4130 TimeOut Indicates the maximum time, in microseconds, which the
4131 transfer is allowed to complete.
4132 Translator A pointr to the transaction translator data.
4133 TransferResult A pointer to the detailed result information from
4134 the synchronous interrupt transfer.
4138 The synchronous interrupt transfer was completed successfully.
4139 EFI_OUT_OF_RESOURCES
4140 The synchronous interrupt transfer could not be submitted due
4141 to lack of resource.
4142 EFI_INVALID_PARAMETER
4143 Some parameters are invalid.
4145 The synchronous interrupt transfer failed due to timeout.
4147 The synchronous interrupt transfer failed due to host controller
4148 or device error. Caller should check TranferResult for detailed
4153 BOOLEAN IsSlowDevice
;
4155 if(DeviceSpeed
==EFI_USB_SPEED_HIGH
)
4156 return EFI_INVALID_PARAMETER
;
4158 IsSlowDevice
= (EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
;
4159 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4161 return UHCISyncInterruptTransfer(
4166 (UINT8
) MaximumPacketLength
,
4177 UHCI2IsochronousTransfer (
4178 IN EFI_USB2_HC_PROTOCOL
* This
,
4179 IN UINT8 DeviceAddress
,
4180 IN UINT8 EndPointAddress
,
4181 IN UINT8 DeviceSpeed
,
4182 IN UINTN MaximumPacketLength
,
4183 IN UINT8 DataBuffersNumber
,
4184 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
4185 IN UINTN DataLength
,
4186 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4187 OUT UINT32
*TransferResult
4191 Routine Description:
4193 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
4197 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4199 DeviceAddress Represents the address of the target device on the USB,
4200 which is assigned during USB enumeration.
4202 EndPointAddress End point address
4204 DeviceSpeed Indicates device speed.
4206 MaximumPacketLength Indicates the maximum packet size that the
4207 default control transfer endpoint is capable of
4208 sending or receiving.
4210 DataBuffersNumber Number of data buffers prepared for the transfer.
4212 Data Array of pointers to the buffers of data that will be
4213 transmitted to USB device or received from USB device.
4215 DataLength Indicates the size, in bytes, of the data buffer
4218 Translator A pointr to the transaction translator data.
4220 TransferResult A pointer to the detailed result information generated
4221 by this control transfer.
4228 return EFI_UNSUPPORTED
;
4233 UHCI2AsyncIsochronousTransfer (
4234 IN EFI_USB2_HC_PROTOCOL
* This
,
4235 IN UINT8 DeviceAddress
,
4236 IN UINT8 EndPointAddress
,
4237 IN UINT8 DeviceSpeed
,
4238 IN UINTN MaximumPacketLength
,
4239 IN UINT8 DataBuffersNumber
,
4240 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
4241 IN UINTN DataLength
,
4242 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4243 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
4248 Routine Description:
4250 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
4254 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4256 DeviceAddress Represents the address of the target device on the USB,
4257 which is assigned during USB enumeration.
4259 EndPointAddress End point address
4261 DeviceSpeed Indicates device speed.
4263 MaximumPacketLength Indicates the maximum packet size that the
4264 default control transfer endpoint is capable of
4265 sending or receiving.
4267 DataBuffersNumber Number of data buffers prepared for the transfer.
4269 Data Array of pointers to the buffers of data that will be transmitted
4270 to USB device or received from USB device.
4272 Translator A pointr to the transaction translator data.
4274 IsochronousCallBack When the transfer complete, the call back function will be called
4276 Context Pass to the call back function as parameter
4284 return EFI_UNSUPPORTED
;
4289 UHCI2GetRootHubPortStatus (
4290 IN EFI_USB2_HC_PROTOCOL
* This
,
4291 IN UINT8 PortNumber
,
4292 OUT EFI_USB_PORT_STATUS
* PortStatus
4296 Routine Description:
4297 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
4301 This A pointer to the EFI_USB2_HC_PROTOCOL.
4303 PortNumber Specifies the root hub port from which the status
4304 is to be retrieved. This value is zero-based. For example,
4305 if a root hub has two ports, then the first port is numbered 0,
4306 and the second port is numbered 1.
4308 PortStatus A pointer to the current port status bits and
4309 port status change bits.
4313 The status of the USB root hub port specified by PortNumber
4314 was returned in PortStatus.
4315 EFI_INVALID_PARAMETER
4316 PortNumber is invalid.
4317 EFI_DEVICE_ERROR - Can't read register
4322 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4324 return UHCIGetRootHubPortStatus(
4333 UHCI2SetRootHubPortFeature (
4334 IN EFI_USB2_HC_PROTOCOL
* This
,
4335 IN UINT8 PortNumber
,
4336 IN EFI_USB_PORT_FEATURE PortFeature
4340 Routine Description:
4341 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
4345 This A pointer to the EFI_USB2_HC_PROTOCOL.
4347 PortNumber Specifies the root hub port whose feature
4348 is requested to be set.
4350 PortFeature Indicates the feature selector associated
4351 with the feature set request.
4355 The feature specified by PortFeature was set for the
4356 USB root hub port specified by PortNumber.
4357 EFI_INVALID_PARAMETER
4358 PortNumber is invalid or PortFeature is invalid.
4365 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4366 return UHCISetRootHubPortFeature(
4375 UHCI2ClearRootHubPortFeature (
4376 IN EFI_USB2_HC_PROTOCOL
* This
,
4377 IN UINT8 PortNumber
,
4378 IN EFI_USB_PORT_FEATURE PortFeature
4382 Routine Description:
4383 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
4387 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4389 PortNumber Specifies the root hub port whose feature
4390 is requested to be cleared.
4392 PortFeature Indicates the feature selector associated with the
4393 feature clear request.
4397 The feature specified by PortFeature was cleared for the
4398 USB root hub port specified by PortNumber.
4399 EFI_INVALID_PARAMETER
4400 PortNumber is invalid or PortFeature is invalid.
4407 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4408 return UHCIClearRootHubPortFeature(
4417 MonitorInterruptTrans (
4422 Routine Description:
4423 Interrupt transfer periodic check handler
4425 Event - Interrupt event
4426 Contex - Pointer to USB_HC_DEV
4433 INTERRUPT_LIST
*PtrList
;
4441 LIST_ENTRY
*NextLink
;
4443 HcDev
= (USB_HC_DEV
*) Context
;
4444 StatusAddr
= (UINT32
) (USBSTS
);
4447 // interrupt transfer list is empty, means that no interrupt transfer
4448 // is submitted by far.
4450 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
4454 NextLink
= HcDev
->InterruptListHead
.ForwardLink
;
4458 NextLink
= Link
->ForwardLink
;
4460 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
4463 // get TD execution results.
4464 // ErrTDPos is zero-based value indicating the first error TD's position
4465 // in the TDs' list.
4466 // This value is only valid when Result not equal NOERROR.
4468 ExecuteAsyncINTTDs (
4477 // interrupt transfer has not been executed yet.
4479 if (((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
) ||
4480 ((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
)) {
4484 // get actual data length transferred data and its data length.
4486 DataLen
= ActualLen
;
4487 DataBuffer
= AllocatePool (DataLen
);
4488 if (DataBuffer
== NULL
) {
4494 PtrList
->PtrFirstTD
->pTDBuffer
,
4499 // only if interrupt endpoint responds
4500 // and the interrupt transfer stops because of completion
4501 // or error, then we will call callback function.
4503 if (Result
== EFI_USB_NOERROR
) {
4505 // add for real platform debug
4507 if (PtrList
->InterruptCallBack
!= NULL
) {
4508 (PtrList
->InterruptCallBack
) (
4511 PtrList
->InterruptContext
,
4517 gBS
->FreePool (DataBuffer
);
4521 // update should done after data buffer got.
4523 UpdateAsyncINTQHTDs (PtrList
, Result
, (UINT32
) ErrTDPos
);
4527 DEBUG ((EFI_D_ERROR
, "interrupt transfer error code is %x\n", Result
));
4530 gBS
->FreePool (DataBuffer
);
4533 // leave error recovery to its related device driver.
4534 // A common case of the error recovery is to re-submit the interrupt
4536 // When an interrupt transfer is re-submitted, its position in the linked
4537 // list is changed. It is inserted to the head of the linked list, while
4538 // this function scans the whole list from head to tail. Thus, the
4539 // re-submitted interrupt transfer's callback function will not be called
4540 // again in this round.
4542 if (PtrList
->InterruptCallBack
!= NULL
) {
4543 (PtrList
->InterruptCallBack
) (
4546 PtrList
->InterruptContext
,
4551 } while (NextLink
!= &(HcDev
->InterruptListHead
));