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
;
492 Status
= gBS
->OpenProtocol (
494 &gEfiPciIoProtocolGuid
,
496 This
->DriverBindingHandle
,
498 EFI_OPEN_PROTOCOL_BY_DRIVER
500 if (EFI_ERROR (Status
)) {
505 // Turn off USB emulation
507 TurnOffUSBEmulation (PciIo
);
510 // Enable the USB Host Controller
512 Status
= PciIo
->Attributes (
514 EfiPciIoAttributeOperationSupported
,
518 if (!EFI_ERROR (Status
)) {
519 Supports
&= EFI_PCI_DEVICE_ENABLE
;
520 Status
= PciIo
->Attributes (
522 EfiPciIoAttributeOperationEnable
,
527 if (EFI_ERROR (Status
)) {
530 &gEfiPciIoProtocolGuid
,
531 This
->DriverBindingHandle
,
534 return EFI_UNSUPPORTED
;
538 // allocate memory for UHC private data structure
540 HcDev
= AllocateZeroPool (sizeof (USB_HC_DEV
));
544 &gEfiPciIoProtocolGuid
,
545 This
->DriverBindingHandle
,
548 return EFI_OUT_OF_RESOURCES
;
552 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
554 HcDev
->UsbHc
.Reset
= UHCIReset
;
555 HcDev
->UsbHc
.GetState
= UHCIGetState
;
556 HcDev
->UsbHc
.SetState
= UHCISetState
;
557 HcDev
->UsbHc
.ControlTransfer
= UHCIControlTransfer
;
558 HcDev
->UsbHc
.BulkTransfer
= UHCIBulkTransfer
;
559 HcDev
->UsbHc
.AsyncInterruptTransfer
= UHCIAsyncInterruptTransfer
;
560 HcDev
->UsbHc
.SyncInterruptTransfer
= UHCISyncInterruptTransfer
;
561 HcDev
->UsbHc
.IsochronousTransfer
= UHCIIsochronousTransfer
;
562 HcDev
->UsbHc
.AsyncIsochronousTransfer
= UHCIAsyncIsochronousTransfer
;
563 HcDev
->UsbHc
.GetRootHubPortNumber
= UHCIGetRootHubPortNumber
;
564 HcDev
->UsbHc
.GetRootHubPortStatus
= UHCIGetRootHubPortStatus
;
565 HcDev
->UsbHc
.SetRootHubPortFeature
= UHCISetRootHubPortFeature
;
566 HcDev
->UsbHc
.ClearRootHubPortFeature
= UHCIClearRootHubPortFeature
;
568 HcDev
->UsbHc
.MajorRevision
= 0x1;
569 HcDev
->UsbHc
.MinorRevision
= 0x1;
573 // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol
575 HcDev
->Usb2Hc
.GetCapability
= UHCI2GetCapability
;
576 HcDev
->Usb2Hc
.Reset
= UHCI2Reset
;
577 HcDev
->Usb2Hc
.GetState
= UHCI2GetState
;
578 HcDev
->Usb2Hc
.SetState
= UHCI2SetState
;
579 HcDev
->Usb2Hc
.ControlTransfer
= UHCI2ControlTransfer
;
580 HcDev
->Usb2Hc
.BulkTransfer
= UHCI2BulkTransfer
;
581 HcDev
->Usb2Hc
.AsyncInterruptTransfer
= UHCI2AsyncInterruptTransfer
;
582 HcDev
->Usb2Hc
.SyncInterruptTransfer
= UHCI2SyncInterruptTransfer
;
583 HcDev
->Usb2Hc
.IsochronousTransfer
= UHCI2IsochronousTransfer
;
584 HcDev
->Usb2Hc
.AsyncIsochronousTransfer
= UHCI2AsyncIsochronousTransfer
;
585 HcDev
->Usb2Hc
.GetRootHubPortStatus
= UHCI2GetRootHubPortStatus
;
586 HcDev
->Usb2Hc
.SetRootHubPortFeature
= UHCI2SetRootHubPortFeature
;
587 HcDev
->Usb2Hc
.ClearRootHubPortFeature
= UHCI2ClearRootHubPortFeature
;
589 HcDev
->Usb2Hc
.MajorRevision
= 0x1;
590 HcDev
->Usb2Hc
.MinorRevision
= 0x1;
593 // Init UHCI private data structures
595 HcDev
->Signature
= USB_HC_DEV_SIGNATURE
;
596 HcDev
->PciIo
= PciIo
;
598 FlBaseAddrReg
= USBFLBASEADD
;
601 // Allocate and Init Host Controller's Frame List Entry
603 Status
= CreateFrameList (HcDev
, (UINT32
) FlBaseAddrReg
);
604 if (EFI_ERROR (Status
)) {
607 gBS
->FreePool (HcDev
);
612 &gEfiPciIoProtocolGuid
,
613 This
->DriverBindingHandle
,
616 return EFI_OUT_OF_RESOURCES
;
620 // Init interrupt list head in the HcDev structure.
622 InitializeListHead (&(HcDev
->InterruptListHead
));
625 // Create timer for interrupt transfer result polling
627 Status
= gBS
->CreateEvent (
628 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
630 MonitorInterruptTrans
,
632 &HcDev
->InterruptTransTimer
634 if (EFI_ERROR (Status
)) {
636 FreeFrameListEntry (HcDev
);
639 gBS
->FreePool (HcDev
);
644 &gEfiPciIoProtocolGuid
,
645 This
->DriverBindingHandle
,
648 return EFI_UNSUPPORTED
;
652 // Here set interrupt transfer polling timer in 50ms unit.
654 Status
= gBS
->SetTimer (
655 HcDev
->InterruptTransTimer
,
657 INTERRUPT_POLLING_TIME
659 if (EFI_ERROR (Status
)) {
660 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
662 FreeFrameListEntry (HcDev
);
665 gBS
->FreePool (HcDev
);
670 &gEfiPciIoProtocolGuid
,
671 This
->DriverBindingHandle
,
674 return EFI_UNSUPPORTED
;
678 // QH,TD structures must in common buffer that will be
679 // accessed by both cpu and usb bus master at the same time.
680 // so, there must has memory management for QH,TD structures.
682 Status
= InitializeMemoryManagement (HcDev
);
683 if (EFI_ERROR (Status
)) {
685 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
687 FreeFrameListEntry (HcDev
);
690 gBS
->FreePool (HcDev
);
695 &gEfiPciIoProtocolGuid
,
696 This
->DriverBindingHandle
,
703 // Install Host Controller Protocol
705 Status
= gBS
->InstallProtocolInterface (
707 &gEfiUsbHcProtocolGuid
,
708 EFI_NATIVE_INTERFACE
,
711 if (EFI_ERROR (Status
)) {
712 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
713 FreeFrameListEntry (HcDev
);
714 DelMemoryManagement (HcDev
);
717 gBS
->FreePool (HcDev
);
722 &gEfiPciIoProtocolGuid
,
723 This
->DriverBindingHandle
,
730 // Install USB2.0 Host Controller Protocol
732 Status
= gBS
->InstallProtocolInterface (
734 &gEfiUsb2HcProtocolGuid
,
735 EFI_NATIVE_INTERFACE
,
738 if (EFI_ERROR (Status
)) {
739 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
740 FreeFrameListEntry (HcDev
);
741 DelMemoryManagement (HcDev
);
744 gBS
->FreePool (HcDev
);
749 &gEfiPciIoProtocolGuid
,
750 This
->DriverBindingHandle
,
758 // component name protocol.
761 HcDev
->ControllerNameTable
= NULL
;
764 gUhciComponentName
.SupportedLanguages
,
765 &HcDev
->ControllerNameTable
,
766 (CHAR16
*) L
"Usb Universal Host Controller"
774 UnInstallUHCInterface (
775 IN EFI_HANDLE Controller
,
776 IN EFI_USB_HC_PROTOCOL
*This
780 UnInstall UHCInterface
782 Controller - Controller handle
783 This - Protocol instance pointer.
793 HcDev
= USB_HC_DEV_FROM_THIS (This
);
795 gBS
->UninstallProtocolInterface (
797 &gEfiUsbHcProtocolGuid
,
801 gBS
->UninstallProtocolInterface (
803 &gEfiUsb2HcProtocolGuid
,
807 // first stop USB Host Controller
809 This
->SetState (This
, EfiUsbHcStateHalt
);
812 // Delete interrupt transfer polling timer
814 gBS
->CloseEvent (HcDev
->InterruptTransTimer
);
817 // Delete all the asynchronous interrupt transfers in the interrupt list
818 // and free associated memory
820 ReleaseInterruptList (HcDev
, &(HcDev
->InterruptListHead
));
823 // free Frame List Entry.
825 FreeFrameListEntry (HcDev
);
828 // Free common buffer allocated for QH,TD structures
830 DelMemoryManagement (HcDev
);
832 if (HcDev
->ControllerNameTable
) {
833 FreeUnicodeStringTable (HcDev
->ControllerNameTable
);
836 // Disable the USB Host Controller
838 Status
= HcDev
->PciIo
->Attributes (
840 EfiPciIoAttributeOperationSupported
,
844 if (!EFI_ERROR (Status
)) {
845 Supports
&= EFI_PCI_DEVICE_ENABLE
;
846 Status
= HcDev
->PciIo
->Attributes (
848 EfiPciIoAttributeOperationDisable
,
854 gBS
->FreePool (HcDev
);
862 UHCIDriverBindingStop (
863 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
864 IN EFI_HANDLE Controller
,
865 IN UINTN NumberOfChildren
,
866 IN EFI_HANDLE
*ChildHandleBuffer
871 Stop this driver on ControllerHandle. Support stoping any child handles
872 created by this driver.
875 This - Protocol instance pointer.
876 Controller - Handle of device to stop driver on
877 NumberOfChildren - Number of Children in the ChildHandleBuffer
878 ChildHandleBuffer - List of handles for the children we need to stop.
886 EFI_USB_HC_PROTOCOL
*UsbHc
;
887 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
888 EFI_STATUS OpenStatus
;
890 OpenStatus
= gBS
->OpenProtocol (
892 &gEfiUsbHcProtocolGuid
,
894 This
->DriverBindingHandle
,
896 EFI_OPEN_PROTOCOL_GET_PROTOCOL
900 // Test whether the Controller handler passed in is a valid
901 // Usb controller handle that should be supported, if not,
902 // return the error status directly
904 if (EFI_ERROR (OpenStatus
)) {
908 OpenStatus
= gBS
->OpenProtocol (
910 &gEfiUsb2HcProtocolGuid
,
912 This
->DriverBindingHandle
,
914 EFI_OPEN_PROTOCOL_GET_PROTOCOL
918 // Test whether the Controller handler passed in is a valid
919 // Usb controller handle that should be supported, if not,
920 // return the error status directly
922 if (EFI_ERROR (OpenStatus
)) {
926 // free all the controller related memory and uninstall UHCI Protocol.
928 UnInstallUHCInterface (Controller
, UsbHc
);
932 &gEfiPciIoProtocolGuid
,
933 This
->DriverBindingHandle
,
945 IN EFI_USB_HC_PROTOCOL
*This
,
951 Provides software reset for the USB host controller.
955 This A pointer to the EFI_USB_HC_PROTOCOL instance.
957 Attributes A bit mask of the reset operation to perform.
958 See below for a list of the supported bit mask values.
960 #define EFI_USB_HC_RESET_GLOBAL 0x0001
961 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
963 EFI_USB_HC_RESET_GLOBAL
964 If this bit is set, a global reset signal will be sent to the USB bus.
965 This resets all of the USB bus logic, including the USB host
966 controller hardware and all the devices attached on the USB bus.
967 EFI_USB_HC_RESET_HOST_CONTROLLER
968 If this bit is set, the USB host controller hardware will be reset.
969 No reset signal will be sent to the USB bus.
973 The reset operation succeeded.
974 EFI_INVALID_PARAMETER
975 Attributes is not valid.
977 An error was encountered while attempting to perform
983 UINT32 CommandRegAddr
;
984 UINT32 FlBaseAddrReg
;
989 HcDev
= USB_HC_DEV_FROM_THIS (This
);
991 CommandRegAddr
= (UINT32
) (USBCMD
);
992 FlBaseAddrReg
= (UINT32
) (USBFLBASEADD
);
994 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
997 // set the Global Reset bit in the command register
999 Status
= ReadUHCCommandReg (
1004 if (EFI_ERROR (Status
)) {
1005 return EFI_DEVICE_ERROR
;
1008 Command
|= USBCMD_GRESET
;
1009 Status
= WriteUHCCommandReg (
1014 if (EFI_ERROR (Status
)) {
1015 return EFI_DEVICE_ERROR
;
1019 // Wait 50ms for root port to let reset complete
1020 // See UHCI spec page122 Reset signaling
1022 gBS
->Stall (ROOT_PORT_REST_TIME
);
1025 // Clear the Global Reset bit to zero.
1027 Command
&= ~USBCMD_GRESET
;
1028 Status
= WriteUHCCommandReg (
1033 if (EFI_ERROR (Status
)) {
1034 return EFI_DEVICE_ERROR
;
1037 // UHCI spec page120 reset recovery time
1039 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
1042 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
1045 // set Host Controller Reset bit to 1
1047 Status
= ReadUHCCommandReg (
1052 if (EFI_ERROR (Status
)) {
1053 return EFI_DEVICE_ERROR
;
1056 Command
|= USBCMD_HCRESET
;
1057 Status
= WriteUHCCommandReg (
1062 if (EFI_ERROR (Status
)) {
1063 return EFI_DEVICE_ERROR
;
1066 // this bit will be reset by Host Controller when reset is completed.
1067 // wait 10ms to let reset complete
1069 gBS
->Stall (PORT_RESET_RECOVERY_TIME
);
1073 return EFI_INVALID_PARAMETER
;
1077 // Delete all old transactions on the USB bus
1079 CleanUsbTransactions (HcDev
);
1082 // Initialize Universal Host Controller's Frame List Data Structure
1084 InitFrameList (HcDev
);
1087 // Reset may cause Frame List Base Address Register reset to zero,
1088 // so set the original value back again.
1090 SetFrameListBaseAddress (
1093 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
1102 IN EFI_USB_HC_PROTOCOL
*This
,
1103 OUT EFI_USB_HC_STATE
*State
1107 Routine Description:
1108 Retrieves current state of the USB host controller.
1112 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1114 State A pointer to the EFI_USB_HC_STATE data structure that
1115 indicates current state of the USB host controller.
1116 Type EFI_USB_HC_STATE is defined below.
1120 EfiUsbHcStateOperational,
1121 EfiUsbHcStateSuspend,
1122 EfiUsbHcStateMaximum
1127 The state information of the host controller was returned in State.
1128 EFI_INVALID_PARAMETER
1131 An error was encountered while attempting to retrieve the
1132 host controller's current state.
1136 UINT32 CommandRegAddr
;
1137 UINT32 StatusRegAddr
;
1142 if (State
== NULL
) {
1143 return EFI_INVALID_PARAMETER
;
1146 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1148 CommandRegAddr
= (UINT32
) (USBCMD
);
1149 StatusRegAddr
= (UINT32
) (USBSTS
);
1151 Status
= ReadUHCCommandReg (
1157 if (EFI_ERROR (Status
)) {
1158 return EFI_DEVICE_ERROR
;
1161 Status
= ReadUHCCommandReg (
1166 if (EFI_ERROR (Status
)) {
1167 return EFI_DEVICE_ERROR
;
1170 if (UhcCommand
& USBCMD_EGSM
) {
1171 *State
= EfiUsbHcStateSuspend
;
1175 if ((UhcStatus
& USBSTS_HCH
) == 0) {
1176 *State
= EfiUsbHcStateOperational
;
1178 *State
= EfiUsbHcStateHalt
;
1188 IN EFI_USB_HC_PROTOCOL
*This
,
1189 IN EFI_USB_HC_STATE State
1193 Routine Description:
1194 Sets the USB host controller to a specific state.
1198 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1200 State Indicates the state of the host controller that will be set.
1204 The USB host controller was successfully placed in the state
1206 EFI_INVALID_PARAMETER
1209 Failed to set the state specified by State due to device error.
1213 UINT32 CommandRegAddr
;
1214 UINT32 StatusRegAddr
;
1216 EFI_USB_HC_STATE CurrentState
;
1219 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1221 CommandRegAddr
= (UINT32
) (USBCMD
);
1222 StatusRegAddr
= (UINT32
) (USBSTS
);
1224 Status
= UHCIGetState (This
, &CurrentState
);
1225 if (EFI_ERROR (Status
)) {
1226 return EFI_DEVICE_ERROR
;
1231 case EfiUsbHcStateHalt
:
1232 if (CurrentState
== EfiUsbHcStateHalt
) {
1236 Status
= ReadUHCCommandReg (
1241 if (EFI_ERROR (Status
)) {
1242 return EFI_DEVICE_ERROR
;
1245 Command
&= ~USBCMD_RS
;
1247 Status
= WriteUHCCommandReg (
1252 if (EFI_ERROR (Status
)) {
1253 return EFI_DEVICE_ERROR
;
1256 StatusRegAddr
= (UINT32
) (USBSTS
);
1258 // ensure the HC is in halt status after send the stop command
1260 if (WaitForUHCHalt (HcDev
->PciIo
, StatusRegAddr
, STALL_1_SECOND
) == EFI_TIMEOUT
) {
1261 return EFI_DEVICE_ERROR
;
1265 case EfiUsbHcStateOperational
:
1266 if (IsHostSysOrProcessErr (HcDev
->PciIo
, StatusRegAddr
)) {
1267 return EFI_DEVICE_ERROR
;
1270 switch (CurrentState
) {
1272 case EfiUsbHcStateOperational
:
1275 case EfiUsbHcStateHalt
:
1277 // Set Run/Stop bit to 1.
1279 Status
= ReadUHCCommandReg (
1284 if (EFI_ERROR (Status
)) {
1285 return EFI_DEVICE_ERROR
;
1288 Command
|= USBCMD_RS
| USBCMD_MAXP
;
1289 Status
= WriteUHCCommandReg (
1294 if (EFI_ERROR (Status
)) {
1295 return EFI_DEVICE_ERROR
;
1300 case EfiUsbHcStateSuspend
:
1301 Status
= ReadUHCCommandReg (
1306 if (EFI_ERROR (Status
)) {
1307 return EFI_DEVICE_ERROR
;
1311 // FGR(Force Global Resume) bit is 0
1313 if ((Command
| (~USBCMD_FGR
)) != 0xFF) {
1315 // Write FGR bit to 1
1317 Command
|= USBCMD_FGR
;
1318 WriteUHCCommandReg (
1326 // wait 20ms to let resume complete
1327 // (20ms is specified by UHCI spec)
1329 gBS
->Stall (FORCE_GLOBAL_RESUME_TIME
);
1332 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
1334 Command
&= ~USBCMD_FGR
;
1335 Command
&= ~USBCMD_EGSM
;
1336 Command
|= USBCMD_RS
;
1337 WriteUHCCommandReg (
1349 case EfiUsbHcStateSuspend
:
1350 if (CurrentState
== EfiUsbHcStateSuspend
) {
1354 Status
= UHCISetState (This
, EfiUsbHcStateHalt
);
1355 if (EFI_ERROR (Status
)) {
1356 return EFI_DEVICE_ERROR
;
1359 // Set Enter Global Suspend Mode bit to 1.
1361 Status
= ReadUHCCommandReg (
1366 if (EFI_ERROR (Status
)) {
1367 return EFI_DEVICE_ERROR
;
1370 Command
|= USBCMD_EGSM
;
1371 Status
= WriteUHCCommandReg (
1376 if (EFI_ERROR (Status
)) {
1377 return EFI_DEVICE_ERROR
;
1382 return EFI_INVALID_PARAMETER
;
1390 UHCIGetRootHubPortNumber (
1391 IN EFI_USB_HC_PROTOCOL
*This
,
1392 OUT UINT8
*PortNumber
1396 Routine Description:
1397 Retrieves the number of root hub ports.
1401 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1403 PortNumber A pointer to the number of the root hub ports.
1407 The port number was retrieved successfully.
1408 EFI_INVALID_PARAMETER
1411 An error was encountered while attempting to
1412 retrieve the port number.
1417 UINT16 RHPortControl
;
1421 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1423 if (PortNumber
== NULL
) {
1424 return EFI_INVALID_PARAMETER
;
1429 for (Index
= 0; Index
< 2; Index
++) {
1430 PSAddr
= (UINT32
) (USBPORTSC1
+ Index
* 2);
1431 Status
= ReadRootPortReg (
1436 if (EFI_ERROR (Status
)) {
1437 return EFI_DEVICE_ERROR
;
1440 // Port Register content is valid
1442 if (RHPortControl
!= 0xff) {
1452 UHCIGetRootHubPortStatus (
1453 IN EFI_USB_HC_PROTOCOL
*This
,
1454 IN UINT8 PortNumber
,
1455 OUT EFI_USB_PORT_STATUS
*PortStatus
1459 Routine Description:
1460 Retrieves the current status of a USB root hub port.
1464 This A pointer to the EFI_USB_HC_PROTOCOL.
1466 PortNumber Specifies the root hub port from which the status
1467 is to be retrieved. This value is zero-based. For example,
1468 if a root hub has two ports, then the first port is numbered 0,
1469 and the second port is numbered 1.
1471 PortStatus A pointer to the current port status bits and
1472 port status change bits.
1476 The status of the USB root hub port specified by PortNumber
1477 was returned in PortStatus.
1478 EFI_INVALID_PARAMETER
1479 PortNumber is invalid.
1480 EFI_DEVICE_ERROR - Can't read register
1485 UINT16 RHPortStatus
;
1486 UINT8 TotalPortNumber
;
1489 if (PortStatus
== NULL
) {
1490 return EFI_INVALID_PARAMETER
;
1493 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1494 if (PortNumber
>= TotalPortNumber
) {
1495 return EFI_INVALID_PARAMETER
;
1498 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1499 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1502 // Clear port status
1504 PortStatus
->PortStatus
= 0;
1505 PortStatus
->PortChangeStatus
= 0;
1507 Status
= ReadRootPortReg (
1513 if (EFI_ERROR (Status
)) {
1514 return EFI_DEVICE_ERROR
;
1517 // Fill Port Status bits
1521 // Current Connect Status
1523 if (RHPortStatus
& USBPORTSC_CCS
) {
1524 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
1527 // Port Enabled/Disabled
1529 if (RHPortStatus
& USBPORTSC_PED
) {
1530 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
1536 if (RHPortStatus
& USBPORTSC_SUSP
) {
1537 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1543 if (RHPortStatus
& USBPORTSC_PR
) {
1544 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
1548 // Low Speed Device Attached
1550 if (RHPortStatus
& USBPORTSC_LSDA
) {
1551 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1554 // CHC will always return one in this bit
1556 PortStatus
->PortStatus
|= USB_PORT_STAT_OWNER
;
1558 // Fill Port Status Change bits
1562 // Connect Status Change
1564 if (RHPortStatus
& USBPORTSC_CSC
) {
1565 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
1569 // Port Enabled/Disabled Change
1571 if (RHPortStatus
& USBPORTSC_PEDC
) {
1572 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
1580 UHCISetRootHubPortFeature (
1581 IN EFI_USB_HC_PROTOCOL
*This
,
1582 IN UINT8 PortNumber
,
1583 IN EFI_USB_PORT_FEATURE PortFeature
1587 Routine Description:
1588 Sets a feature for the specified root hub port.
1592 This A pointer to the EFI_USB_HC_PROTOCOL.
1594 PortNumber Specifies the root hub port whose feature
1595 is requested to be set.
1597 PortFeature Indicates the feature selector associated
1598 with the feature set request.
1602 The feature specified by PortFeature was set for the
1603 USB root hub port specified by PortNumber.
1604 EFI_INVALID_PARAMETER
1605 PortNumber is invalid or PortFeature is invalid.
1612 UINT32 CommandRegAddr
;
1614 // root hub port status
1616 UINT16 RHPortControl
;
1618 UINT8 TotalPortNumber
;
1621 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1622 if (PortNumber
>= TotalPortNumber
) {
1623 return EFI_INVALID_PARAMETER
;
1626 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1628 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1629 CommandRegAddr
= (UINT32
) (USBCMD
);
1631 Status
= ReadRootPortReg (
1636 if (EFI_ERROR (Status
)) {
1637 return EFI_DEVICE_ERROR
;
1640 switch (PortFeature
) {
1642 case EfiUsbPortSuspend
:
1643 Status
= ReadUHCCommandReg (
1648 if (EFI_ERROR (Status
)) {
1649 return EFI_DEVICE_ERROR
;
1652 if (!(Command
& USBCMD_EGSM
)) {
1654 // if global suspend is not active, can set port suspend
1656 RHPortControl
&= 0xfff5;
1657 RHPortControl
|= USBPORTSC_SUSP
;
1661 case EfiUsbPortReset
:
1662 RHPortControl
&= 0xfff5;
1664 // Set the reset bit
1666 RHPortControl
|= USBPORTSC_PR
;
1669 case EfiUsbPortPower
:
1672 case EfiUsbPortEnable
:
1673 RHPortControl
&= 0xfff5;
1674 RHPortControl
|= USBPORTSC_PED
;
1678 return EFI_INVALID_PARAMETER
;
1692 UHCIClearRootHubPortFeature (
1693 IN EFI_USB_HC_PROTOCOL
*This
,
1694 IN UINT8 PortNumber
,
1695 IN EFI_USB_PORT_FEATURE PortFeature
1699 Routine Description:
1700 Clears a feature for the specified root hub port.
1704 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1706 PortNumber Specifies the root hub port whose feature
1707 is requested to be cleared.
1709 PortFeature Indicates the feature selector associated with the
1710 feature clear request.
1714 The feature specified by PortFeature was cleared for the
1715 USB root hub port specified by PortNumber.
1716 EFI_INVALID_PARAMETER
1717 PortNumber is invalid or PortFeature is invalid.
1724 UINT16 RHPortControl
;
1725 UINT8 TotalPortNumber
;
1728 UHCIGetRootHubPortNumber (This
, &TotalPortNumber
);
1730 if (PortNumber
>= TotalPortNumber
) {
1731 return EFI_INVALID_PARAMETER
;
1734 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1735 PSAddr
= (UINT32
) (USBPORTSC1
+ PortNumber
* 2);
1737 Status
= ReadRootPortReg (
1742 if (EFI_ERROR (Status
)) {
1743 return EFI_DEVICE_ERROR
;
1746 switch (PortFeature
) {
1748 // clear PORT_ENABLE feature means disable port.
1750 case EfiUsbPortEnable
:
1751 RHPortControl
&= 0xfff5;
1752 RHPortControl
&= ~USBPORTSC_PED
;
1756 // clear PORT_SUSPEND feature means resume the port.
1757 // (cause a resume on the specified port if in suspend mode)
1759 case EfiUsbPortSuspend
:
1760 RHPortControl
&= 0xfff5;
1761 RHPortControl
&= ~USBPORTSC_SUSP
;
1767 case EfiUsbPortPower
:
1771 // clear PORT_RESET means clear the reset signal.
1773 case EfiUsbPortReset
:
1774 RHPortControl
&= 0xfff5;
1775 RHPortControl
&= ~USBPORTSC_PR
;
1779 // clear connect status change
1781 case EfiUsbPortConnectChange
:
1782 RHPortControl
&= 0xfff5;
1783 RHPortControl
|= USBPORTSC_CSC
;
1787 // clear enable/disable status change
1789 case EfiUsbPortEnableChange
:
1790 RHPortControl
&= 0xfff5;
1791 RHPortControl
|= USBPORTSC_PEDC
;
1795 // root hub does not support this request
1797 case EfiUsbPortSuspendChange
:
1801 // root hub does not support this request
1803 case EfiUsbPortOverCurrentChange
:
1807 // root hub does not support this request
1809 case EfiUsbPortResetChange
:
1813 return EFI_INVALID_PARAMETER
;
1827 UHCIControlTransfer (
1828 IN EFI_USB_HC_PROTOCOL
*This
,
1829 IN UINT8 DeviceAddress
,
1830 IN BOOLEAN IsSlowDevice
,
1831 IN UINT8 MaximumPacketLength
,
1832 IN EFI_USB_DEVICE_REQUEST
*Request
,
1833 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1834 IN OUT VOID
*Data
, OPTIONAL
1835 IN OUT UINTN
*DataLength
, OPTIONAL
1837 OUT UINT32
*TransferResult
1841 Routine Description:
1842 Submits control transfer to a target USB device.
1846 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1848 DeviceAddress Represents the address of the target device on the USB,
1849 which is assigned during USB enumeration.
1851 IsSlowDevice Indicates whether the target device is slow device
1852 or full-speed device.
1854 MaximumPacketLength Indicates the maximum packet size that the
1855 default control transfer endpoint is capable of
1856 sending or receiving.
1858 Request A pointer to the USB device request that will be sent
1861 TransferDirection Specifies the data direction for the transfer.
1862 There are three values available, DataIn, DataOut
1865 Data A pointer to the buffer of data that will be transmitted
1866 to USB device or received from USB device.
1868 DataLength Indicates the size, in bytes, of the data buffer
1871 TimeOut Indicates the maximum time, in microseconds,
1872 which the transfer is allowed to complete.
1874 TransferResult A pointer to the detailed result information generated
1875 by this control transfer.
1879 The control transfer was completed successfully.
1880 EFI_OUT_OF_RESOURCES
1881 The control transfer could not be completed due to a lack of resources.
1882 EFI_INVALID_PARAMETER
1883 Some parameters are invalid.
1885 The control transfer failed due to timeout.
1887 The control transfer failed due to host controller or device error.
1888 Caller should check TranferResult for detailed error information.
1898 TD_STRUCT
*PtrPreTD
;
1899 TD_STRUCT
*PtrSetupTD
;
1900 TD_STRUCT
*PtrStatusTD
;
1904 UINT8
*PtrDataSource
;
1907 UINT16 LoadFrameListIndex
;
1910 UINT8
*RequestMappedAddress
;
1911 VOID
*RequestMapping
;
1914 EFI_PHYSICAL_ADDRESS TempPtr
;
1917 TD_STRUCT
*PtrFirstDataTD
;
1918 TD_STRUCT
*ptrLastDataTD
;
1922 RequestMappedAddress
= NULL
;
1923 RequestMapping
= NULL
;
1925 PtrFirstDataTD
= NULL
;
1926 ptrLastDataTD
= NULL
;
1927 PktID
= INPUT_PACKET_ID
;
1929 HcDev
= USB_HC_DEV_FROM_THIS (This
);
1930 StatusReg
= (UINT32
) (USBSTS
);
1931 FrameNumReg
= (UINT32
) (USBFRNUM
);
1936 // Parameters Checking
1938 if (Request
== NULL
|| TransferResult
== NULL
) {
1939 return EFI_INVALID_PARAMETER
;
1943 // if errors exist that cause host controller halt,
1944 // then return EFI_DEVICE_ERROR.
1946 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
1948 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
1949 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1950 return EFI_DEVICE_ERROR
;
1954 // low speed usb devices are limited to only an eight-byte
1955 // maximum data payload size
1957 if (IsSlowDevice
&& (MaximumPacketLength
!= 8)) {
1958 return EFI_INVALID_PARAMETER
;
1961 if (MaximumPacketLength
!= 8 &&
1962 MaximumPacketLength
!= 16 &&
1963 MaximumPacketLength
!= 32 &&
1964 MaximumPacketLength
!= 64) {
1965 return EFI_INVALID_PARAMETER
;
1968 if ((TransferDirection
!= EfiUsbNoData
) && (DataLength
== NULL
)) {
1969 return EFI_INVALID_PARAMETER
;
1972 switch (TransferDirection
) {
1975 PktID
= INPUT_PACKET_ID
;
1976 PtrDataSource
= Data
;
1977 DataLen
= *DataLength
;
1980 // map the source data buffer for bus master access.
1981 // BusMasterWrite means cpu read
1983 Status
= HcDev
->PciIo
->Map (
1985 EfiPciIoOperationBusMasterWrite
,
1991 if (EFI_ERROR (Status
)) {
1995 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
1999 PktID
= OUTPUT_PACKET_ID
;
2000 PtrDataSource
= Data
;
2001 DataLen
= *DataLength
;
2004 // map the source data buffer for bus master access.
2005 // BusMasterRead means cpu write
2007 Status
= HcDev
->PciIo
->Map (
2009 EfiPciIoOperationBusMasterRead
,
2015 if (EFI_ERROR (Status
)) {
2019 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2026 if ((DataLength
!= NULL
) && (*DataLength
!= 0)) {
2027 return EFI_INVALID_PARAMETER
;
2030 PktID
= OUTPUT_PACKET_ID
;
2031 PtrDataSource
= NULL
;
2037 return EFI_INVALID_PARAMETER
;
2040 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2041 if (EFI_ERROR (Status
)) {
2042 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2043 return EFI_DEVICE_ERROR
;
2046 // create QH structure and init
2048 Status
= CreateQH (HcDev
, &PtrQH
);
2049 if (EFI_ERROR (Status
)) {
2050 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2055 // map the Request for bus master access.
2056 // BusMasterRead means cpu write
2058 RequestLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
2059 Status
= HcDev
->PciIo
->Map (
2061 EfiPciIoOperationBusMasterRead
,
2068 if (EFI_ERROR (Status
)) {
2069 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2070 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2074 RequestMappedAddress
= (UINT8
*) ((UINTN
) TempPtr
);
2077 // generate Setup Stage TD
2079 Status
= GenSetupStageTD (
2084 (UINT8
*) RequestMappedAddress
,
2085 sizeof (EFI_USB_DEVICE_REQUEST
),
2089 if (EFI_ERROR (Status
)) {
2090 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2091 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2092 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2097 // Data Stage of Control Transfer
2101 while (DataLen
> 0) {
2103 // create TD structures and link together
2107 // PktSize is the data load size that each TD carries.
2109 PktSize
= (UINT8
) DataLen
;
2110 if (DataLen
> MaximumPacketLength
) {
2111 PktSize
= MaximumPacketLength
;
2114 Status
= GenDataTD (
2126 if (EFI_ERROR (Status
)) {
2128 // free all resources occupied
2130 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2131 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2132 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2133 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2134 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2139 // Link two TDs in vertical depth
2142 PtrFirstDataTD
= PtrTD
;
2143 PtrFirstDataTD
->ptrNextTD
= NULL
;
2146 LinkTDToTD (PtrPreTD
, PtrTD
);
2156 ptrLastDataTD
= PtrTD
;
2159 // Status Stage of Control Transfer
2161 if (PktID
== OUTPUT_PACKET_ID
) {
2162 PktID
= INPUT_PACKET_ID
;
2164 PktID
= OUTPUT_PACKET_ID
;
2168 // create Status Stage TD structure
2170 Status
= CreateStatusTD (
2179 if (EFI_ERROR (Status
)) {
2180 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2181 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2182 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2183 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2184 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2190 // link setup TD structures to QH structure
2192 LinkTDToQH (PtrQH
, PtrSetupTD
);
2194 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2197 // link QH-TDs to total 100 frame list entry to speed up the execution.
2199 for (Index
= 0; Index
< 100; Index
++) {
2201 HcDev
->FrameListEntry
,
2202 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2207 // Poll QH-TDs execution and get result.
2208 // detail status is returned
2210 Status
= ExecuteControlTransfer (
2219 // Remove Control Transfer QH-TDs structure from the frame list
2220 // and update the pointers in the Frame List
2221 // and other pointers in other related QH structures.
2223 for (Index
= 0; Index
< 100; Index
++) {
2227 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2233 // delete setup stage TD; the QH is reserved for the next stages.
2235 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2238 // if setup stage error, return error
2240 if (EFI_ERROR (Status
)) {
2244 // some control transfers do not have Data Stage
2246 if (PtrFirstDataTD
!= NULL
) {
2248 LinkTDToQH (PtrQH
, PtrFirstDataTD
);
2249 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2251 for (Index
= 0; Index
< 500; Index
++) {
2253 HcDev
->FrameListEntry
,
2254 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2259 Status
= ExecuteControlTransfer (
2268 for (Index
= 0; Index
< 500; Index
++) {
2272 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2278 // delete data stage TD; the QH is reserved for the next stage.
2280 DeleteQueuedTDs (HcDev
, PtrFirstDataTD
);
2283 // if data stage error, goto done and return error
2285 if (EFI_ERROR (Status
)) {
2289 LinkTDToQH (PtrQH
, PtrStatusTD
);
2291 // get the frame list index that the QH-TDs will be linked to.
2293 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2295 for (Index
= 0; Index
< 100; Index
++) {
2297 // put the QH-TDs directly or indirectly into the proper place
2298 // in the Frame List
2301 HcDev
->FrameListEntry
,
2302 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2307 // Poll QH-TDs execution and get result.
2308 // detail status is returned
2310 Status
= ExecuteControlTransfer (
2320 // Delete Control Transfer QH-TDs structure
2321 // and update the pointers in the Frame List
2322 // and other pointers in other related QH structures.
2324 // TRUE means must search other framelistindex
2326 for (Index
= 0; Index
< 100; Index
++) {
2330 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2336 DeleteQueuedTDs (HcDev
, PtrStatusTD
);
2340 // link setup stage TD with data stage TD
2342 PtrPreTD
= PtrSetupTD
;
2343 if (PtrFirstDataTD
!= NULL
) {
2344 LinkTDToTD (PtrSetupTD
, PtrFirstDataTD
);
2345 PtrPreTD
= ptrLastDataTD
;
2348 // link status TD with previous TD
2350 LinkTDToTD (PtrPreTD
, PtrStatusTD
);
2355 LinkTDToQH (PtrQH
, PtrSetupTD
);
2357 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2358 for (Index
= 0; Index
< 500; Index
++) {
2360 // put the QH-TDs directly or indirectly into the proper place
2361 // in the Frame List
2364 HcDev
->FrameListEntry
,
2365 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2370 // Poll QH-TDs execution and get result.
2371 // detail status is returned
2373 Status
= ExecuteControlTransfer (
2382 // Remove Control Transfer QH-TDs structure from the frame list
2383 // and update the pointers in the Frame List
2384 // and other pointers in other related QH structures.
2386 for (Index
= 0; Index
< 500; Index
++) {
2390 (UINT16
) ((LoadFrameListIndex
+ Index
) & 0x3FF),
2396 DeleteQueuedTDs (HcDev
, PtrSetupTD
);
2401 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2403 if (Mapping
!= NULL
) {
2404 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2407 if (RequestMapping
!= NULL
) {
2408 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, RequestMapping
);
2411 // if has errors that cause host controller halt,
2412 // then return EFI_DEVICE_ERROR directly.
2414 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2416 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2417 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2418 return EFI_DEVICE_ERROR
;
2421 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2422 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2429 IN EFI_USB_HC_PROTOCOL
*This
,
2430 IN UINT8 DeviceAddress
,
2431 IN UINT8 EndPointAddress
,
2432 IN UINT8 MaximumPacketLength
,
2434 IN OUT UINTN
*DataLength
,
2435 IN OUT UINT8
*DataToggle
,
2437 OUT UINT32
*TransferResult
2441 Routine Description:
2442 Submits bulk transfer to a bulk endpoint of a USB device.
2446 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2448 DeviceAddress Represents the address of the target device on the USB,
2449 which is assigned during USB enumeration.
2450 EndPointAddress The combination of an endpoint number and an
2451 endpoint direction of the target USB device.
2452 Each endpoint address supports data transfer in
2453 one direction except the control endpoint
2454 (whose default endpoint address is 0).
2455 It is the caller's responsibility to make sure that
2456 the EndPointAddress represents a bulk endpoint.
2458 MaximumPacketLength Indicates the maximum packet size the target endpoint
2459 is capable of sending or receiving.
2461 Data A pointer to the buffer of data that will be transmitted
2462 to USB device or received from USB device.
2463 DataLength When input, indicates the size, in bytes, of the data buffer
2464 specified by Data. When output, indicates the actually
2465 transferred data size.
2467 DataToggle A pointer to the data toggle value. On input, it indicates
2468 the initial data toggle value the bulk transfer should adopt;
2469 on output, it is updated to indicate the data toggle value
2470 of the subsequent bulk transfer.
2472 TimeOut Indicates the maximum time, in microseconds, which the
2473 transfer is allowed to complete.
2475 TransferResult A pointer to the detailed result information of the
2480 The bulk transfer was completed successfully.
2481 EFI_OUT_OF_RESOURCES
2482 The bulk transfer could not be submitted due to lack of resource.
2483 EFI_INVALID_PARAMETER
2484 Some parameters are invalid.
2486 The bulk transfer failed due to timeout.
2488 The bulk transfer failed due to host controller or device error.
2489 Caller should check TranferResult for detailed error information.
2498 TD_STRUCT
*PtrFirstTD
;
2500 TD_STRUCT
*PtrPreTD
;
2501 UINT16 LoadFrameListIndex
;
2502 UINT16 SavedFrameListIndex
;
2504 UINT8
*PtrDataSource
;
2511 EFI_USB_DATA_DIRECTION TransferDirection
;
2513 // Used to calculate how many entries are linked to the
2514 // specified bulk transfer QH-TDs
2518 BOOLEAN ShortPacketEnable
;
2519 EFI_PHYSICAL_ADDRESS TempPtr
;
2522 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2523 StatusReg
= (UINT32
) (USBSTS
);
2524 FrameNumReg
= (UINT32
) (USBFRNUM
);
2525 PktID
= INPUT_PACKET_ID
;
2532 ShortPacketEnable
= FALSE
;
2536 // Parameters Checking
2539 if ((DataLength
== NULL
) ||
2541 (TransferResult
== NULL
)) {
2542 return EFI_INVALID_PARAMETER
;
2546 // if has errors that cause host controller halt,
2547 // then return EFI_DEVICE_ERROR directly.
2549 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2551 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2552 *TransferResult
= EFI_USB_ERR_SYSTEM
;
2553 return EFI_DEVICE_ERROR
;
2556 if (*DataLength
== 0) {
2557 return EFI_INVALID_PARAMETER
;
2560 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
2561 return EFI_INVALID_PARAMETER
;
2564 if (MaximumPacketLength
!= 8 &&
2565 MaximumPacketLength
!= 16 &&
2566 MaximumPacketLength
!= 32 &&
2567 MaximumPacketLength
!= 64) {
2568 return EFI_INVALID_PARAMETER
;
2572 // Enable the maximum packet size (64bytes)
2573 // that can be used for full speed bandwidth reclamation
2574 // at the end of a frame.
2576 EnableMaxPacketSize (HcDev
);
2578 Status
= ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2579 if (EFI_ERROR (Status
)) {
2580 return EFI_DEVICE_ERROR
;
2584 // construct QH and TD data structures,
2585 // and link them together
2587 if (EndPointAddress
& 0x80) {
2588 TransferDirection
= EfiUsbDataIn
;
2590 TransferDirection
= EfiUsbDataOut
;
2593 switch (TransferDirection
) {
2596 ShortPacketEnable
= TRUE
;
2597 PktID
= INPUT_PACKET_ID
;
2598 PtrDataSource
= Data
;
2599 DataLen
= *DataLength
;
2602 // BusMasterWrite means cpu read
2604 Status
= HcDev
->PciIo
->Map (
2606 EfiPciIoOperationBusMasterWrite
,
2612 if (EFI_ERROR (Status
)) {
2616 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2620 PktID
= OUTPUT_PACKET_ID
;
2621 PtrDataSource
= Data
;
2622 DataLen
= *DataLength
;
2625 // BusMasterRead means cpu write
2627 Status
= HcDev
->PciIo
->Map (
2629 EfiPciIoOperationBusMasterRead
,
2635 if (EFI_ERROR (Status
)) {
2639 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
2643 return EFI_INVALID_PARAMETER
;
2647 // create QH structure and init
2649 Status
= CreateQH (HcDev
, &PtrQH
);
2650 if (EFI_ERROR (Status
)) {
2651 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2656 // i is used to calculate the total number of TDs.
2661 while (DataLen
> 0) {
2664 // create TD structures and link together
2667 PktSize
= (UINT8
) DataLen
;
2668 if (DataLen
> MaximumPacketLength
) {
2669 PktSize
= MaximumPacketLength
;
2672 Status
= GenDataTD (
2684 if (EFI_ERROR (Status
)) {
2685 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2686 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2687 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2692 // Enable short packet detection.
2693 // (default action is disabling short packet detection)
2695 if (ShortPacketEnable
) {
2696 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
2701 PtrFirstTD
->ptrNextTD
= NULL
;
2705 // Link two TDs in vertical depth
2707 LinkTDToTD (PtrPreTD
, PtrTD
);
2720 // link TD structures to QH structure
2722 LinkTDToQH (PtrQH
, PtrFirstTD
);
2725 // calculate how many entries are linked to the specified bulk transfer QH-TDs
2726 // the below values are referred to the USB spec revision1.1.
2728 switch (MaximumPacketLength
) {
2730 LinkTimes
= Index
/ 71 + 1;
2734 LinkTimes
= Index
/ 51 + 1;
2738 LinkTimes
= Index
/ 33 + 1;
2742 LinkTimes
= Index
/ 19 + 1;
2749 // put QH-TDs into Frame list
2751 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
2752 SavedFrameListIndex
= LoadFrameListIndex
;
2754 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2757 // put the QH-TD directly or indirectly into the proper place
2758 // in the Frame List
2760 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
2762 LoadFrameListIndex
+= 1;
2763 LoadFrameListIndex
&= 0x3FF;
2766 LoadFrameListIndex
= SavedFrameListIndex
;
2769 // Execute QH-TD and get result
2772 // detail status is put into the Result field in the pIRP
2773 // the Data Toggle value is also re-updated to the value
2774 // of the last successful TD
2776 Status
= ExecBulkorSyncInterruptTransfer (
2787 // Delete Bulk transfer QH-TD structure
2788 // and maitain the pointers in the Frame List
2789 // and other pointers in related QH structure
2791 // TRUE means must search other framelistindex
2793 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
2801 LoadFrameListIndex
+= 1;
2802 LoadFrameListIndex
&= 0x3FF;
2805 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2807 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
2809 if (Mapping
!= NULL
) {
2810 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
2814 // if has errors that cause host controller halt,
2815 // then return EFI_DEVICE_ERROR directly.
2817 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2819 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2820 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
2821 return EFI_DEVICE_ERROR
;
2824 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2826 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
2833 UHCIAsyncInterruptTransfer (
2834 IN EFI_USB_HC_PROTOCOL
* This
,
2835 IN UINT8 DeviceAddress
,
2836 IN UINT8 EndPointAddress
,
2837 IN BOOLEAN IsSlowDevice
,
2838 IN UINT8 MaximumPacketLength
,
2839 IN BOOLEAN IsNewTransfer
,
2840 IN OUT UINT8
*DataToggle
,
2841 IN UINTN PollingInterval
, OPTIONAL
2842 IN UINTN DataLength
, OPTIONAL
2843 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
, OPTIONAL
2844 IN VOID
*Context OPTIONAL
2848 Routine Description:
2849 Submits an asynchronous interrupt transfer to an
2850 interrupt endpoint of a USB device.
2854 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2856 DeviceAddress Represents the address of the target device on the USB,
2857 which is assigned during USB enumeration.
2859 EndPointAddress The combination of an endpoint number and an endpoint
2860 direction of the target USB device. Each endpoint address
2861 supports data transfer in one direction except the
2862 control endpoint (whose default endpoint address is 0).
2863 It is the caller's responsibility to make sure that
2864 the EndPointAddress represents an interrupt endpoint.
2866 IsSlowDevice Indicates whether the target device is slow device
2867 or full-speed device.
2869 MaximumPacketLength Indicates the maximum packet size the target endpoint
2870 is capable of sending or receiving.
2872 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
2873 the host and the target interrupt endpoint.
2874 If FALSE, the specified asynchronous interrupt pipe
2877 DataToggle A pointer to the data toggle value. On input, it is valid
2878 when IsNewTransfer is TRUE, and it indicates the initial
2879 data toggle value the asynchronous interrupt transfer
2881 On output, it is valid when IsNewTransfer is FALSE,
2882 and it is updated to indicate the data toggle value of
2883 the subsequent asynchronous interrupt transfer.
2885 PollingInterval Indicates the interval, in milliseconds, that the
2886 asynchronous interrupt transfer is polled.
2887 This parameter is required when IsNewTransfer is TRUE.
2889 DataLength Indicates the length of data to be received at the
2890 rate specified by PollingInterval from the target
2891 asynchronous interrupt endpoint. This parameter
2892 is only required when IsNewTransfer is TRUE.
2894 CallBackFunction The Callback function.This function is called at the
2895 rate specified by PollingInterval.This parameter is
2896 only required when IsNewTransfer is TRUE.
2898 Context The context that is passed to the CallBackFunction.
2899 This is an optional parameter and may be NULL.
2903 The asynchronous interrupt transfer request has been successfully
2904 submitted or canceled.
2905 EFI_INVALID_PARAMETER
2906 Some parameters are invalid.
2907 EFI_OUT_OF_RESOURCES
2908 The request could not be completed due to a lack of resources.
2917 QH_STRUCT
*ptrFirstQH
;
2919 QH_STRUCT
*ptrPreQH
;
2920 TD_STRUCT
*PtrFirstTD
;
2922 TD_STRUCT
*PtrPreTD
;
2923 UINT16 LoadFrameListIndex
;
2931 BOOLEAN ShortPacketEnable
;
2932 UINT8 CurrentDataToggle
;
2933 EFI_PHYSICAL_ADDRESS TempPtr
;
2939 HcDev
= USB_HC_DEV_FROM_THIS (This
);
2940 StatusReg
= (UINT32
) (USBSTS
);
2941 FrameNumReg
= (UINT32
) (USBFRNUM
);
2943 ShortPacketEnable
= FALSE
;
2945 PktID
= INPUT_PACKET_ID
;
2954 if ((EndPointAddress
& 0x80) == 0) {
2955 return EFI_INVALID_PARAMETER
;
2959 // delete Async interrupt transfer request
2961 if (!IsNewTransfer
) {
2963 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
2965 Status
= DeleteAsyncINTQHTDs (
2972 gBS
->RestoreTPL (OldTpl
);
2977 // if has errors that cause host controller halt,
2978 // then return EFI_DEVICE_ERROR directly.
2980 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
2982 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2983 return EFI_DEVICE_ERROR
;
2986 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
2989 // submit Async interrupt transfer request
2991 if (PollingInterval
< 1 || PollingInterval
> 255) {
2992 return EFI_INVALID_PARAMETER
;
2995 if (DataLength
== 0) {
2996 return EFI_INVALID_PARAMETER
;
2999 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
3000 return EFI_INVALID_PARAMETER
;
3003 ShortPacketEnable
= TRUE
;
3004 PktID
= INPUT_PACKET_ID
;
3005 DataLen
= DataLength
;
3006 Ptr
= AllocatePool (DataLen
);
3008 return EFI_OUT_OF_RESOURCES
;
3012 // BusMasterWrite means cpu read
3014 Status
= HcDev
->PciIo
->Map (
3016 EfiPciIoOperationBusMasterWrite
,
3022 if (EFI_ERROR (Status
)) {
3023 gBS
->FreePool (Ptr
);
3027 MappedPtr
= (UINT8
*) ((UINTN
) TempPtr
);
3029 CurrentDataToggle
= *DataToggle
;
3033 while (DataLen
> 0) {
3035 // create TD structures and link together
3038 PktSize
= (UINT8
) DataLen
;
3039 if (DataLen
> MaximumPacketLength
) {
3040 PktSize
= MaximumPacketLength
;
3043 Status
= GenDataTD (
3054 if (EFI_ERROR (Status
)) {
3055 gBS
->FreePool (Ptr
);
3056 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3057 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3061 // Enable short packet detection.
3063 if (ShortPacketEnable
) {
3064 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
3069 PtrFirstTD
->ptrNextTD
= NULL
;
3073 // Link two TDs in vertical depth
3075 LinkTDToTD (PtrPreTD
, PtrTD
);
3080 CurrentDataToggle
^= 1;
3081 MappedPtr
+= PktSize
;
3086 // roll one value back
3088 CurrentDataToggle
^= 1;
3091 // create a list of QH structures and init,
3092 // link TDs to all the QHs, and link all the QHs together using internal
3093 // defined pointer of the QH_STRUCT.
3097 for (Index
= 0; Index
< 1024;) {
3099 Status
= CreateQH (HcDev
, &PtrQH
);
3100 if (EFI_ERROR (Status
)) {
3101 gBS
->FreePool (Ptr
);
3102 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3103 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3107 PtrQH
= TempQH
->ptrNextIntQH
;
3108 UhciFreePool (HcDev
, (UINT8
*) TempQH
, sizeof (QH_STRUCT
));
3115 // link TD structures to QH structure
3117 LinkTDToQH (PtrQH
, PtrFirstTD
);
3121 ptrFirstQH
->ptrNextIntQH
= NULL
;
3125 // link neighbor QH structures together
3127 ptrPreQH
->ptrNextIntQH
= PtrQH
;
3132 Index
= (UINT16
) (PollingInterval
+ Index
);
3135 // last QH in QH list should set its next QH pointer to NULL.
3137 PtrQH
->ptrNextIntQH
= NULL
;
3140 // Save QH-TD structures in Interrupt transfer list,
3141 // for monitor interrupt transfer execution routine use.
3143 InsertQHTDToINTList (
3159 // put QHs-TDs into Frame list
3161 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
3165 for (Index
= LoadFrameListIndex
; Index
< (1024 + LoadFrameListIndex
);) {
3168 // put the QH-TD directly or indirectly into the proper place
3169 // in the Frame List
3171 LinkQHToFrameList (HcDev
->FrameListEntry
, (UINT16
) (Index
& 0x3FF), PtrQH
);
3173 Index
= (UINT16
) (PollingInterval
+ Index
);
3175 PtrQH
= PtrQH
->ptrNextIntQH
;
3178 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
3185 UHCISyncInterruptTransfer (
3186 IN EFI_USB_HC_PROTOCOL
*This
,
3187 IN UINT8 DeviceAddress
,
3188 IN UINT8 EndPointAddress
,
3189 IN BOOLEAN IsSlowDevice
,
3190 IN UINT8 MaximumPacketLength
,
3192 IN OUT UINTN
*DataLength
,
3193 IN OUT UINT8
*DataToggle
,
3195 OUT UINT32
*TransferResult
3199 Routine Description:
3200 Submits synchronous interrupt transfer to an interrupt endpoint
3205 This A pointer to the EFI_USB_HC_PROTOCOL instance.
3207 DeviceAddress Represents the address of the target device on the USB,
3208 which is assigned during USB enumeration.
3210 EndPointAddress The combination of an endpoint number and an endpoint
3211 direction of the target USB device. Each endpoint
3212 address supports data transfer in one direction
3213 except the control endpoint (whose default
3214 endpoint address is 0). It is the caller's responsibility
3215 to make sure that the EndPointAddress represents
3216 an interrupt endpoint.
3218 IsSlowDevice Indicates whether the target device is slow device
3219 or full-speed device.
3221 MaximumPacketLength Indicates the maximum packet size the target endpoint
3222 is capable of sending or receiving.
3224 Data A pointer to the buffer of data that will be transmitted
3225 to USB device or received from USB device.
3227 DataLength On input, the size, in bytes, of the data buffer specified
3228 by Data. On output, the number of bytes transferred.
3230 DataToggle A pointer to the data toggle value. On input, it indicates
3231 the initial data toggle value the synchronous interrupt
3232 transfer should adopt;
3233 on output, it is updated to indicate the data toggle value
3234 of the subsequent synchronous interrupt transfer.
3236 TimeOut Indicates the maximum time, in microseconds, which the
3237 transfer is allowed to complete.
3239 TransferResult A pointer to the detailed result information from
3240 the synchronous interrupt transfer.
3244 The synchronous interrupt transfer was completed successfully.
3245 EFI_OUT_OF_RESOURCES
3246 The synchronous interrupt transfer could not be submitted due
3247 to lack of resource.
3248 EFI_INVALID_PARAMETER
3249 Some parameters are invalid.
3251 The synchronous interrupt transfer failed due to timeout.
3253 The synchronous interrupt transfer failed due to host controller
3254 or device error. Caller should check TranferResult for detailed
3263 TD_STRUCT
*PtrFirstTD
;
3265 TD_STRUCT
*PtrPreTD
;
3266 UINT16 LoadFrameListIndex
;
3267 UINT16 SavedFrameListIndex
;
3271 UINT8
*PtrDataSource
;
3275 BOOLEAN ShortPacketEnable
;
3276 EFI_PHYSICAL_ADDRESS TempPtr
;
3280 HcDev
= USB_HC_DEV_FROM_THIS (This
);
3281 StatusReg
= (UINT32
) (USBSTS
);
3282 FrameNumReg
= (UINT32
) (USBFRNUM
);
3283 ShortPacketEnable
= FALSE
;
3285 PktID
= INPUT_PACKET_ID
;
3295 // Parameters Checking
3298 if ((DataLength
== NULL
) ||
3300 (TransferResult
== NULL
)) {
3301 return EFI_INVALID_PARAMETER
;
3305 // if has errors that cause host controller halt,
3306 // then return EFI_DEVICE_ERROR directly.
3308 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3310 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3311 *TransferResult
= EFI_USB_ERR_SYSTEM
;
3312 return EFI_DEVICE_ERROR
;
3315 if ((EndPointAddress
& 0x80) == 0) {
3316 return EFI_INVALID_PARAMETER
;
3319 if (*DataLength
== 0) {
3320 return EFI_INVALID_PARAMETER
;
3323 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
3324 return EFI_INVALID_PARAMETER
;
3327 if (MaximumPacketLength
> 64) {
3328 return EFI_INVALID_PARAMETER
;
3331 if (IsSlowDevice
&& (MaximumPacketLength
> 8)) {
3332 return EFI_INVALID_PARAMETER
;
3335 if (TransferResult
== NULL
) {
3336 return EFI_INVALID_PARAMETER
;
3339 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3342 // submit Sync interrupt transfer request
3344 ShortPacketEnable
= TRUE
;
3345 PktID
= INPUT_PACKET_ID
;
3346 DataLen
= *DataLength
;
3347 PtrDataSource
= Data
;
3350 // create QH structure and init
3352 Status
= CreateQH (HcDev
, &PtrQH
);
3353 if (EFI_ERROR (Status
)) {
3358 // BusMasterWrite means cpu read
3360 Status
= HcDev
->PciIo
->Map (
3362 EfiPciIoOperationBusMasterWrite
,
3368 if (EFI_ERROR (Status
)) {
3369 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3373 Ptr
= (UINT8
*) ((UINTN
) TempPtr
);
3376 while (DataLen
> 0) {
3378 // create TD structures and link together
3380 PktSize
= (UINT8
) DataLen
;
3381 if (DataLen
> MaximumPacketLength
) {
3382 PktSize
= MaximumPacketLength
;
3385 Status
= GenDataTD (
3396 if (EFI_ERROR (Status
)) {
3397 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3398 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3399 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3403 // Enable short packet detection.
3405 if (ShortPacketEnable
) {
3406 EnableorDisableTDShortPacket (PtrTD
, TRUE
);
3411 PtrFirstTD
->ptrNextTD
= NULL
;
3415 // Link two TDs in vertical depth
3417 LinkTDToTD (PtrPreTD
, PtrTD
);
3430 // link TD structures to QH structure
3432 LinkTDToQH (PtrQH
, PtrFirstTD
);
3434 switch (MaximumPacketLength
) {
3436 LinkTimes
= Index
/ 71 + 1;
3440 LinkTimes
= Index
/ 51 + 1;
3444 LinkTimes
= Index
/ 33 + 1;
3448 LinkTimes
= Index
/ 19 + 1;
3454 LoadFrameListIndex
= (UINT16
) ((GetCurrentFrameNumber (HcDev
->PciIo
, FrameNumReg
)) & 0x3FF);
3455 SavedFrameListIndex
= LoadFrameListIndex
;
3457 for (Index
= 0; Index
< LinkTimes
; Index
++) {
3460 // put the QH-TD directly or indirectly into the proper place
3461 // in the Frame List
3463 LinkQHToFrameList (HcDev
->FrameListEntry
, LoadFrameListIndex
, PtrQH
);
3465 LoadFrameListIndex
+= 1;
3466 LoadFrameListIndex
&= 0x3FF;
3469 LoadFrameListIndex
= SavedFrameListIndex
;
3471 // detail status is put into the Result field in the pIRP
3472 // the Data Toggle value is also re-updated to the value
3473 // of the last successful TD
3475 Status
= ExecBulkorSyncInterruptTransfer (
3485 // Delete Sync Interrupt transfer QH-TD structure
3486 // and maintain the pointers in the Frame List
3487 // and other pointers in related QH structure
3489 // TRUE means must search other framelistindex
3491 for (Index
= 0; Index
<= LinkTimes
; Index
++) {
3499 LoadFrameListIndex
+= 1;
3500 LoadFrameListIndex
&= 0x3FF;
3503 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3505 DeleteQueuedTDs (HcDev
, PtrFirstTD
);
3507 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Mapping
);
3510 // if has errors that cause host controller halt,
3511 // then return EFI_DEVICE_ERROR directly.
3513 if (!IsStatusOK (HcDev
->PciIo
, StatusReg
)) {
3515 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3516 *TransferResult
|= EFI_USB_ERR_SYSTEM
;
3517 return EFI_DEVICE_ERROR
;
3520 ClearStatusReg (HcDev
->PciIo
, StatusReg
);
3522 HcDev
->PciIo
->Flush (HcDev
->PciIo
);
3529 UHCIIsochronousTransfer (
3530 IN EFI_USB_HC_PROTOCOL
*This
,
3531 IN UINT8 DeviceAddress
,
3532 IN UINT8 EndPointAddress
,
3533 IN UINT8 MaximumPacketLength
,
3535 IN UINTN DataLength
,
3536 OUT UINT32
*TransferResult
3540 Routine Description:
3541 Submits isochronous transfer to a target USB device.
3545 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3546 DeviceAddress - Represents the address of the target device on the USB,
3547 which is assigned during USB enumeration.
3548 EndPointAddress - End point address
3549 MaximumPacketLength - Indicates the maximum packet size that the
3550 default control transfer endpoint is capable of
3551 sending or receiving.
3552 Data - A pointer to the buffer of data that will be transmitted
3553 to USB device or received from USB device.
3554 DataLength - Indicates the size, in bytes, of the data buffer
3556 TransferResult - A pointer to the detailed result information generated
3557 by this control transfer.
3563 return EFI_UNSUPPORTED
;
3569 UHCIAsyncIsochronousTransfer (
3570 IN EFI_USB_HC_PROTOCOL
* This
,
3571 IN UINT8 DeviceAddress
,
3572 IN UINT8 EndPointAddress
,
3573 IN UINT8 MaximumPacketLength
,
3575 IN UINTN DataLength
,
3576 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
3577 IN VOID
*Context OPTIONAL
3581 Routine Description:
3582 Submits Async isochronous transfer to a target USB device.
3586 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3588 DeviceAddress - Represents the address of the target device on the USB,
3589 which is assigned during USB enumeration.
3591 EndPointAddress - End point address
3593 MaximumPacketLength - Indicates the maximum packet size that the
3594 default control transfer endpoint is capable of
3595 sending or receiving.
3597 Data - A pointer to the buffer of data that will be transmitted
3598 to USB device or received from USB device.
3600 IsochronousCallBack - When the transfer complete, the call back function will be called
3602 Context - Pass to the call back function as parameter
3609 return EFI_UNSUPPORTED
;
3613 // UEFI 2.0 Protocol
3618 IN EFI_USB2_HC_PROTOCOL
* This
,
3619 OUT UINT8
*MaxSpeed
,
3620 OUT UINT8
*PortNumber
,
3621 OUT UINT8
*Is64BitCapable
3625 Routine Description:
3626 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
3629 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3631 MaxSpeed - A pointer to the max speed USB host controller supports.
3633 PortNumber - A pointer to the number of root hub ports.
3635 Is64BitCapable - A pointer to an integer to show whether USB host controller
3636 supports 64-bit memory addressing.
3639 The host controller capabilities were retrieved successfully.
3640 EFI_INVALID_PARAMETER
3641 MaxSpeed or PortNumber or Is64BitCapable is NULL.
3643 An error was encountered while attempting to retrieve the capabilities.
3649 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3651 if ((NULL
== MaxSpeed
)
3652 ||(NULL
== PortNumber
)
3653 || (NULL
== Is64BitCapable
))
3655 return EFI_INVALID_PARAMETER
;
3658 *MaxSpeed
= EFI_USB_SPEED_FULL
;
3659 *Is64BitCapable
= (UINT8
)FALSE
;
3660 return UHCIGetRootHubPortNumber(&HcDev
->UsbHc
, PortNumber
);
3666 IN EFI_USB2_HC_PROTOCOL
* This
,
3667 IN UINT16 Attributes
3671 Routine Description:
3672 Provides software reset for the USB host controller according to UEFI 2.0 spec.
3675 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3677 Attributes - A bit mask of the reset operation to perform.
3678 See below for a list of the supported bit mask values.
3680 #define EFI_USB_HC_RESET_GLOBAL 0x0001
3681 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
3682 #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004
3683 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
3685 EFI_USB_HC_RESET_GLOBAL
3686 If this bit is set, a global reset signal will be sent to the USB bus.
3687 This resets all of the USB bus logic, including the USB host
3688 controller hardware and all the devices attached on the USB bus.
3689 EFI_USB_HC_RESET_HOST_CONTROLLER
3690 If this bit is set, the USB host controller hardware will be reset.
3691 No reset signal will be sent to the USB bus.
3695 The reset operation succeeded.
3696 EFI_INVALID_PARAMETER
3697 Attributes is not valid.
3699 The type of reset specified by Attributes is not currently supported by the host controller hardware.
3701 Reset operation is rejected due to the debug port being configured and active.
3703 An error was encountered while attempting to perform
3704 the reset operation.
3709 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3711 if (Attributes
==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
|| Attributes
==EFI_USB_HC_RESET_HOST_WITH_DEBUG
)
3712 return EFI_UNSUPPORTED
;
3723 IN EFI_USB2_HC_PROTOCOL
* This
,
3724 OUT EFI_USB_HC_STATE
* State
3728 Routine Description:
3729 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
3733 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3735 State - A pointer to the EFI_USB_HC_STATE data structure that
3736 indicates current state of the USB host controller.
3737 Type EFI_USB_HC_STATE is defined below.
3741 EfiUsbHcStateOperational,
3742 EfiUsbHcStateSuspend,
3743 EfiUsbHcStateMaximum
3748 The state information of the host controller was returned in State.
3749 EFI_INVALID_PARAMETER
3752 An error was encountered while attempting to retrieve the
3753 host controller's current state.
3758 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3759 return UHCIGetState(
3768 IN EFI_USB2_HC_PROTOCOL
* This
,
3769 IN EFI_USB_HC_STATE State
3773 Routine Description:
3774 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
3778 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3780 State - Indicates the state of the host controller that will be set.
3784 The USB host controller was successfully placed in the state
3786 EFI_INVALID_PARAMETER
3789 Failed to set the state specified by State due to device error.
3794 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3795 return UHCISetState(
3803 UHCI2ControlTransfer (
3804 IN EFI_USB2_HC_PROTOCOL
* This
,
3805 IN UINT8 DeviceAddress
,
3806 IN UINT8 DeviceSpeed
,
3807 IN UINTN MaximumPacketLength
,
3808 IN EFI_USB_DEVICE_REQUEST
* Request
,
3809 IN EFI_USB_DATA_DIRECTION TransferDirection
,
3811 IN OUT UINTN
*DataLength
,
3813 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3814 OUT UINT32
*TransferResult
3818 Routine Description:
3819 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..
3823 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3825 DeviceAddress -Represents the address of the target device on the USB,
3826 which is assigned during USB enumeration.
3828 DeviceSpeed - Indicates transfer speed of device.
3830 MaximumPacketLength - Indicates the maximum packet size that the
3831 default control transfer endpoint is capable of
3832 sending or receiving.
3834 Request - A pointer to the USB device request that will be sent
3837 TransferDirection - Specifies the data direction for the transfer.
3838 There are three values available, DataIn, DataOut
3841 Data -A pointer to the buffer of data that will be transmitted
3842 to USB device or received from USB device.
3844 DataLength - Indicates the size, in bytes, of the data buffer
3847 TimeOut - Indicates the maximum time, in microseconds,
3848 which the transfer is allowed to complete.
3850 TransferResult - A pointer to the detailed result information generated
3851 by this control transfer.
3855 The control transfer was completed successfully.
3856 EFI_OUT_OF_RESOURCES
3857 The control transfer could not be completed due to a lack of resources.
3858 EFI_INVALID_PARAMETER
3859 Some parameters are invalid.
3861 The control transfer failed due to timeout.
3863 The control transfer failed due to host controller or device error.
3864 Caller should check TranferResult for detailed error information.
3869 BOOLEAN IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
3871 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3873 return UHCIControlTransfer(
3877 (UINT8
) MaximumPacketLength
,
3890 IN EFI_USB2_HC_PROTOCOL
* This
,
3891 IN UINT8 DeviceAddress
,
3892 IN UINT8 EndPointAddress
,
3893 IN UINT8 DeviceSpeed
,
3894 IN UINTN MaximumPacketLength
,
3895 IN UINT8 DataBuffersNumber
,
3896 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
3897 IN OUT UINTN
*DataLength
,
3898 IN OUT UINT8
*DataToggle
,
3900 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
3901 OUT UINT32
*TransferResult
3905 Routine Description:
3906 Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.
3910 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3912 DeviceAddress Represents the address of the target device on the USB,
3913 which is assigned during USB enumeration.
3915 EndPointAddress The combination of an endpoint number and an
3916 endpoint direction of the target USB device.
3917 Each endpoint address supports data transfer in
3918 one direction except the control endpoint
3919 (whose default endpoint address is 0).
3920 It is the caller's responsibility to make sure that
3921 the EndPointAddress represents a bulk endpoint.
3923 DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL
3924 and EFI_USB_SPEED_HIGH.
3926 MaximumPacketLength Indicates the maximum packet size the target endpoint
3927 is capable of sending or receiving.
3929 DataBuffersNumber Number of data buffers prepared for the transfer.
3931 Data Array of pointers to the buffers of data that will be transmitted
3932 to USB device or received from USB device.
3934 DataLength When input, indicates the size, in bytes, of the data buffer
3935 specified by Data. When output, indicates the actually
3936 transferred data size.
3938 DataToggle A pointer to the data toggle value. On input, it indicates
3939 the initial data toggle value the bulk transfer should adopt;
3940 on output, it is updated to indicate the data toggle value
3941 of the subsequent bulk transfer.
3943 Translator A pointr to the transaction translator data.
3945 TimeOut Indicates the maximum time, in microseconds, which the
3946 transfer is allowed to complete.
3948 TransferResult A pointer to the detailed result information of the
3953 The bulk transfer was completed successfully.
3955 EFI_OUT_OF_RESOURCES
3956 The bulk transfer could not be submitted due to lack of resource.
3958 EFI_INVALID_PARAMETER
3959 Some parameters are invalid.
3962 The bulk transfer failed due to timeout.
3965 The bulk transfer failed due to host controller or device error.
3966 Caller should check TranferResult for detailed error information.
3972 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
3974 if( Data
== NULL
|| DeviceSpeed
==EFI_USB_SPEED_LOW
)
3975 return EFI_INVALID_PARAMETER
;
3976 /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */
3978 return UHCIBulkTransfer (
3982 (UINT8
) MaximumPacketLength
,
3993 UHCI2AsyncInterruptTransfer (
3994 IN EFI_USB2_HC_PROTOCOL
* This
,
3995 IN UINT8 DeviceAddress
,
3996 IN UINT8 EndPointAddress
,
3997 IN UINT8 DeviceSpeed
,
3998 IN UINTN MaximumPacketLength
,
3999 IN BOOLEAN IsNewTransfer
,
4000 IN OUT UINT8
*DataToggle
,
4001 IN UINTN PollingInterval
,
4002 IN UINTN DataLength
,
4003 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4004 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
4009 Routine Description:
4010 Submits an asynchronous interrupt transfer to an
4011 interrupt endpoint of a USB device according to UEFI 2.0 spec.
4015 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4017 DeviceAddress Represents the address of the target device on the USB,
4018 which is assigned during USB enumeration.
4020 EndPointAddress The combination of an endpoint number and an endpoint
4021 direction of the target USB device. Each endpoint address
4022 supports data transfer in one direction except the
4023 control endpoint (whose default endpoint address is 0).
4024 It is the caller's responsibility to make sure that
4025 the EndPointAddress represents an interrupt endpoint.
4027 DeviceSpeed Indicates device speed.
4029 MaximumPacketLength Indicates the maximum packet size the target endpoint
4030 is capable of sending or receiving.
4032 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
4033 the host and the target interrupt endpoint.
4034 If FALSE, the specified asynchronous interrupt pipe
4037 DataToggle A pointer to the data toggle value. On input, it is valid
4038 when IsNewTransfer is TRUE, and it indicates the initial
4039 data toggle value the asynchronous interrupt transfer
4041 On output, it is valid when IsNewTransfer is FALSE,
4042 and it is updated to indicate the data toggle value of
4043 the subsequent asynchronous interrupt transfer.
4045 PollingInterval Indicates the interval, in milliseconds, that the
4046 asynchronous interrupt transfer is polled.
4047 This parameter is required when IsNewTransfer is TRUE.
4049 DataLength Indicates the length of data to be received at the
4050 rate specified by PollingInterval from the target
4051 asynchronous interrupt endpoint. This parameter
4052 is only required when IsNewTransfer is TRUE.
4054 Translator A pointr to the transaction translator data.
4056 CallBackFunction The Callback function.This function is called at the
4057 rate specified by PollingInterval.This parameter is
4058 only required when IsNewTransfer is TRUE.
4060 Context The context that is passed to the CallBackFunction.
4061 This is an optional parameter and may be NULL.
4066 The asynchronous interrupt transfer request has been successfully
4067 submitted or canceled.
4069 EFI_INVALID_PARAMETER
4070 Some parameters are invalid.
4072 EFI_OUT_OF_RESOURCES
4073 The request could not be completed due to a lack of resources.
4080 BOOLEAN IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
4082 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4083 return UHCIAsyncInterruptTransfer(
4088 (UINT8
) MaximumPacketLength
,
4100 UHCI2SyncInterruptTransfer (
4101 IN EFI_USB2_HC_PROTOCOL
* This
,
4102 IN UINT8 DeviceAddress
,
4103 IN UINT8 EndPointAddress
,
4104 IN UINT8 DeviceSpeed
,
4105 IN UINTN MaximumPacketLength
,
4107 IN OUT UINTN
*DataLength
,
4108 IN OUT UINT8
*DataToggle
,
4110 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4111 OUT UINT32
*TransferResult
4115 Routine Description:
4116 Submits synchronous interrupt transfer to an interrupt endpoint
4117 of a USB device according to UEFI 2.0 spec.
4121 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4123 DeviceAddress Represents the address of the target device on the USB,
4124 which is assigned during USB enumeration.
4126 EndPointAddress The combination of an endpoint number and an endpoint
4127 direction of the target USB device. Each endpoint
4128 address supports data transfer in one direction
4129 except the control endpoint (whose default
4130 endpoint address is 0). It is the caller's responsibility
4131 to make sure that the EndPointAddress represents
4132 an interrupt endpoint.
4134 DeviceSpeed Indicates device speed.
4136 MaximumPacketLength Indicates the maximum packet size the target endpoint
4137 is capable of sending or receiving.
4139 Data A pointer to the buffer of data that will be transmitted
4140 to USB device or received from USB device.
4142 DataLength On input, the size, in bytes, of the data buffer specified
4143 by Data. On output, the number of bytes transferred.
4145 DataToggle A pointer to the data toggle value. On input, it indicates
4146 the initial data toggle value the synchronous interrupt
4147 transfer should adopt;
4148 on output, it is updated to indicate the data toggle value
4149 of the subsequent synchronous interrupt transfer.
4151 TimeOut Indicates the maximum time, in microseconds, which the
4152 transfer is allowed to complete.
4153 Translator A pointr to the transaction translator data.
4154 TransferResult A pointer to the detailed result information from
4155 the synchronous interrupt transfer.
4159 The synchronous interrupt transfer was completed successfully.
4160 EFI_OUT_OF_RESOURCES
4161 The synchronous interrupt transfer could not be submitted due
4162 to lack of resource.
4163 EFI_INVALID_PARAMETER
4164 Some parameters are invalid.
4166 The synchronous interrupt transfer failed due to timeout.
4168 The synchronous interrupt transfer failed due to host controller
4169 or device error. Caller should check TranferResult for detailed
4174 BOOLEAN IsSlowDevice
;
4176 if(DeviceSpeed
==EFI_USB_SPEED_HIGH
)
4177 return EFI_INVALID_PARAMETER
;
4179 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DeviceSpeed
) ? TRUE
: FALSE
);
4180 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4182 return UHCISyncInterruptTransfer(
4187 (UINT8
) MaximumPacketLength
,
4198 UHCI2IsochronousTransfer (
4199 IN EFI_USB2_HC_PROTOCOL
* This
,
4200 IN UINT8 DeviceAddress
,
4201 IN UINT8 EndPointAddress
,
4202 IN UINT8 DeviceSpeed
,
4203 IN UINTN MaximumPacketLength
,
4204 IN UINT8 DataBuffersNumber
,
4205 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
4206 IN UINTN DataLength
,
4207 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4208 OUT UINT32
*TransferResult
4212 Routine Description:
4214 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
4218 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4220 DeviceAddress Represents the address of the target device on the USB,
4221 which is assigned during USB enumeration.
4223 EndPointAddress End point address
4225 DeviceSpeed Indicates device speed.
4227 MaximumPacketLength Indicates the maximum packet size that the
4228 default control transfer endpoint is capable of
4229 sending or receiving.
4231 DataBuffersNumber Number of data buffers prepared for the transfer.
4233 Data Array of pointers to the buffers of data that will be
4234 transmitted to USB device or received from USB device.
4236 DataLength Indicates the size, in bytes, of the data buffer
4239 Translator A pointr to the transaction translator data.
4241 TransferResult A pointer to the detailed result information generated
4242 by this control transfer.
4249 return EFI_UNSUPPORTED
;
4254 UHCI2AsyncIsochronousTransfer (
4255 IN EFI_USB2_HC_PROTOCOL
* This
,
4256 IN UINT8 DeviceAddress
,
4257 IN UINT8 EndPointAddress
,
4258 IN UINT8 DeviceSpeed
,
4259 IN UINTN MaximumPacketLength
,
4260 IN UINT8 DataBuffersNumber
,
4261 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
4262 IN UINTN DataLength
,
4263 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
4264 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
4269 Routine Description:
4271 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
4275 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4277 DeviceAddress Represents the address of the target device on the USB,
4278 which is assigned during USB enumeration.
4280 EndPointAddress End point address
4282 DeviceSpeed Indicates device speed.
4284 MaximumPacketLength Indicates the maximum packet size that the
4285 default control transfer endpoint is capable of
4286 sending or receiving.
4288 DataBuffersNumber Number of data buffers prepared for the transfer.
4290 Data Array of pointers to the buffers of data that will be transmitted
4291 to USB device or received from USB device.
4293 Translator A pointr to the transaction translator data.
4295 IsochronousCallBack When the transfer complete, the call back function will be called
4297 Context Pass to the call back function as parameter
4305 return EFI_UNSUPPORTED
;
4310 UHCI2GetRootHubPortStatus (
4311 IN EFI_USB2_HC_PROTOCOL
* This
,
4312 IN UINT8 PortNumber
,
4313 OUT EFI_USB_PORT_STATUS
* PortStatus
4317 Routine Description:
4318 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
4322 This A pointer to the EFI_USB2_HC_PROTOCOL.
4324 PortNumber Specifies the root hub port from which the status
4325 is to be retrieved. This value is zero-based. For example,
4326 if a root hub has two ports, then the first port is numbered 0,
4327 and the second port is numbered 1.
4329 PortStatus A pointer to the current port status bits and
4330 port status change bits.
4334 The status of the USB root hub port specified by PortNumber
4335 was returned in PortStatus.
4336 EFI_INVALID_PARAMETER
4337 PortNumber is invalid.
4338 EFI_DEVICE_ERROR - Can't read register
4343 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4345 return UHCIGetRootHubPortStatus(
4354 UHCI2SetRootHubPortFeature (
4355 IN EFI_USB2_HC_PROTOCOL
* This
,
4356 IN UINT8 PortNumber
,
4357 IN EFI_USB_PORT_FEATURE PortFeature
4361 Routine Description:
4362 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
4366 This A pointer to the EFI_USB2_HC_PROTOCOL.
4368 PortNumber Specifies the root hub port whose feature
4369 is requested to be set.
4371 PortFeature Indicates the feature selector associated
4372 with the feature set request.
4376 The feature specified by PortFeature was set for the
4377 USB root hub port specified by PortNumber.
4378 EFI_INVALID_PARAMETER
4379 PortNumber is invalid or PortFeature is invalid.
4386 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4387 return UHCISetRootHubPortFeature(
4396 UHCI2ClearRootHubPortFeature (
4397 IN EFI_USB2_HC_PROTOCOL
* This
,
4398 IN UINT8 PortNumber
,
4399 IN EFI_USB_PORT_FEATURE PortFeature
4403 Routine Description:
4404 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
4408 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4410 PortNumber Specifies the root hub port whose feature
4411 is requested to be cleared.
4413 PortFeature Indicates the feature selector associated with the
4414 feature clear request.
4418 The feature specified by PortFeature was cleared for the
4419 USB root hub port specified by PortNumber.
4420 EFI_INVALID_PARAMETER
4421 PortNumber is invalid or PortFeature is invalid.
4428 HcDev
= USB2_HC_DEV_FROM_THIS (This
);
4429 return UHCIClearRootHubPortFeature(
4438 MonitorInterruptTrans (
4443 Routine Description:
4444 Interrupt transfer periodic check handler
4446 Event - Interrupt event
4447 Contex - Pointer to USB_HC_DEV
4454 INTERRUPT_LIST
*PtrList
;
4461 LIST_ENTRY
*NextLink
;
4463 HcDev
= (USB_HC_DEV
*) Context
;
4466 // interrupt transfer list is empty, means that no interrupt transfer
4467 // is submitted by far.
4469 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
4473 NextLink
= HcDev
->InterruptListHead
.ForwardLink
;
4477 NextLink
= Link
->ForwardLink
;
4479 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
4482 // get TD execution results.
4483 // ErrTDPos is zero-based value indicating the first error TD's position
4484 // in the TDs' list.
4485 // This value is only valid when Result not equal NOERROR.
4487 ExecuteAsyncINTTDs (
4496 // interrupt transfer has not been executed yet.
4498 if (((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
) ||
4499 ((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
)) {
4503 // get actual data length transferred data and its data length.
4505 DataLen
= ActualLen
;
4506 DataBuffer
= AllocatePool (DataLen
);
4507 if (DataBuffer
== NULL
) {
4513 PtrList
->PtrFirstTD
->pTDBuffer
,
4518 // only if interrupt endpoint responds
4519 // and the interrupt transfer stops because of completion
4520 // or error, then we will call callback function.
4522 if (Result
== EFI_USB_NOERROR
) {
4524 // add for real platform debug
4526 if (PtrList
->InterruptCallBack
!= NULL
) {
4527 (PtrList
->InterruptCallBack
) (
4530 PtrList
->InterruptContext
,
4536 gBS
->FreePool (DataBuffer
);
4540 // update should done after data buffer got.
4542 UpdateAsyncINTQHTDs (PtrList
, Result
, (UINT32
) ErrTDPos
);
4546 DEBUG ((EFI_D_ERROR
, "interrupt transfer error code is %x\n", Result
));
4549 gBS
->FreePool (DataBuffer
);
4552 // leave error recovery to its related device driver.
4553 // A common case of the error recovery is to re-submit the interrupt
4555 // When an interrupt transfer is re-submitted, its position in the linked
4556 // list is changed. It is inserted to the head of the linked list, while
4557 // this function scans the whole list from head to tail. Thus, the
4558 // re-submitted interrupt transfer's callback function will not be called
4559 // again in this round.
4561 if (PtrList
->InterruptCallBack
!= NULL
) {
4562 (PtrList
->InterruptCallBack
) (
4565 PtrList
->InterruptContext
,
4570 } while (NextLink
!= &(HcDev
->InterruptListHead
));