summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Bus
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Bus')
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c189
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c2821
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h2689
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa87
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c761
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c1539
-rw-r--r--EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c3072
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa3
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c148
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c1577
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h1733
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c2
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa5
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c2578
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h913
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c190
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c18
17 files changed, 17146 insertions, 1179 deletions
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c
new file mode 100644
index 0000000000..e0d2010cd4
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c
@@ -0,0 +1,189 @@
+/*++
+
+Copyright 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "Ehci.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+EhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+EhciComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gEhciComponentName = {
+ EhciComponentNameGetDriverName,
+ EhciComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mEhciDriverNameTable[] = {
+ { "eng", L"UEFI Usb Ehci Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+EhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gEhciComponentName.SupportedLanguages,
+ mEhciDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+EhciComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *EhciDev;
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
+ gEhciDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EhciDev = USB2_HC_DEV_FROM_THIS (Usb2Hc);
+
+ return LookupUnicodeString (
+ Language,
+ gEhciComponentName.SupportedLanguages,
+ EhciDev->ControllerNameTable,
+ ControllerName
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c
new file mode 100644
index 0000000000..e7d359ee24
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c
@@ -0,0 +1,2821 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Ehci.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+
+#include "Ehci.h"
+
+UINTN gEHCDebugLevel = EFI_D_INFO;
+UINTN gEHCErrorLevel = EFI_D_ERROR;
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+
+EFI_STATUS
+EFIAPI
+EhciDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+EhciDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+EhciDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Ehci protocol interface
+//
+EFI_STATUS
+EFIAPI
+EhciGetCapability (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ );
+
+EFI_STATUS
+EFIAPI
+EhciReset (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+EhciGetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ );
+
+EFI_STATUS
+EFIAPI
+EhciSetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ );
+
+EFI_STATUS
+EFIAPI
+EhciControlTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+EhciBulkTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+EhciAsyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaxiumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+EhciSyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+EhciIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+EhciAsyncIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+EhciGetRootHubPortStatus (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ );
+
+EFI_STATUS
+EFIAPI
+EhciSetRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+EFI_STATUS
+EFIAPI
+EhciClearRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+//
+// Ehci Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding = {
+ EhciDriverBindingSupported,
+ EhciDriverBindingStart,
+ EhciDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+UINT32 mUsbCapabilityLen;
+UINT32 mDeviceSpeed[16];
+
+EFI_STATUS
+EFIAPI
+EhciDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has Usb2HcProtocol installed will be supported.
+
+ Arguments:
+
+ This - Protocol instance pointer.
+ Controlle - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+
+ EFI_SUCCESS This driver supports this device.
+ EFI_UNSUPPORTED This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_CLASSC UsbClassCReg;
+
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto exit;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ CLASSC,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ Status = EFI_UNSUPPORTED;
+ goto exit;
+ }
+
+ //
+ // Test whether the controller belongs to Ehci type
+ //
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
+ (UsbClassCReg.PI != PCI_CLASSC_PI_EHCI)
+ ) {
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = EFI_UNSUPPORTED;
+ goto exit;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Starting the Usb EHCI Driver
+
+ Arguments:
+
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+
+ EFI_SUCCESS supports this device.
+ EFI_UNSUPPORTED do not support this device.
+ EFI_DEVICE_ERROR cannot be started due to device Error
+ EFI_OUT_OF_RESOURCES cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 MaxSpeed;
+ UINT8 PortNumber;
+ UINT8 Is64BitCapable;
+
+ //
+ // Open the PciIo Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ //
+ // Enable the USB Host Controller
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto close_pciio_protocol;
+ }
+
+ //
+ // Allocate memory for EHC private data structure
+ //
+ HcDev = AllocateZeroPool (sizeof (USB2_HC_DEV));
+ if (NULL == HcDev) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto close_pciio_protocol;
+ }
+
+ //
+ // Init EFI_USB2_HC_PROTOCOL interface and private data structure
+ //
+ HcDev->Usb2Hc.GetCapability = EhciGetCapability;
+ HcDev->Usb2Hc.Reset = EhciReset;
+ HcDev->Usb2Hc.GetState = EhciGetState;
+ HcDev->Usb2Hc.SetState = EhciSetState;
+ HcDev->Usb2Hc.ControlTransfer = EhciControlTransfer;
+ HcDev->Usb2Hc.BulkTransfer = EhciBulkTransfer;
+ HcDev->Usb2Hc.AsyncInterruptTransfer = EhciAsyncInterruptTransfer;
+ HcDev->Usb2Hc.SyncInterruptTransfer = EhciSyncInterruptTransfer;
+ HcDev->Usb2Hc.IsochronousTransfer = EhciIsochronousTransfer;
+ HcDev->Usb2Hc.AsyncIsochronousTransfer = EhciAsyncIsochronousTransfer;
+ HcDev->Usb2Hc.GetRootHubPortStatus = EhciGetRootHubPortStatus;
+ HcDev->Usb2Hc.SetRootHubPortFeature = EhciSetRootHubPortFeature;
+ HcDev->Usb2Hc.ClearRootHubPortFeature = EhciClearRootHubPortFeature;
+ HcDev->Usb2Hc.MajorRevision = 0x1;
+ HcDev->Usb2Hc.MinorRevision = 0x1;
+
+ HcDev->AsyncRequestList = NULL;
+ HcDev->ControllerNameTable = NULL;
+ HcDev->Signature = USB2_HC_DEV_SIGNATURE;
+ HcDev->PciIo = PciIo;
+
+ //
+ // Install USB2_HC_PROTOCOL
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiUsb2HcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &HcDev->Usb2Hc
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto free_pool;
+ }
+
+ //
+ // Get Capability Register Length
+ //
+ Status = GetCapabilityLen (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto uninstall_usb2hc_protocol;
+ }
+
+ //
+ // Create and Init Perodic Frame List
+ //
+ Status = EhciGetCapability (
+ &HcDev->Usb2Hc,
+ &MaxSpeed,
+ &PortNumber,
+ &Is64BitCapable
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto uninstall_usb2hc_protocol;
+ }
+ HcDev->Is64BitCapable = Is64BitCapable;
+
+ //
+ // Create and Init Perodic Frame List
+ //
+ Status = InitialPeriodicFrameList (
+ HcDev,
+ EHCI_MAX_FRAME_LIST_LENGTH
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto uninstall_usb2hc_protocol;
+ }
+
+ //
+ // Init memory pool management
+ //
+ Status = InitialMemoryManagement (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto deinit_perodic_frame_list;
+ }
+
+ //
+ // Create AsyncRequest Polling Timer
+ //
+ Status = CreatePollingTimer (HcDev, AsyncRequestMoniter);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto deinit_memory_management;
+ }
+
+ //
+ // Default Maxximum Interrupt Interval is 8,
+ // it means that 8 micro frame = 1ms
+ //
+
+ //
+ // Start the Host Controller
+ //
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto deinit_timer;
+ }
+ }
+
+ //
+ // Set all ports routing to EHC
+ //
+ Status = SetPortRoutingEhc (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto deinit_timer;
+ }
+
+ //
+ // Component name protocol
+ //
+ Status = AddUnicodeString (
+ "eng",
+ gEhciComponentName.SupportedLanguages,
+ &HcDev->ControllerNameTable,
+ L"Usb Enhanced Host Controller"
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto deinit_timer;
+ }
+
+ goto exit;
+
+ //
+ // Error handle process
+ //
+deinit_timer:
+ DestoryPollingTimer (HcDev);
+deinit_memory_management:
+ DeinitialMemoryManagement (HcDev);
+deinit_perodic_frame_list:
+ DeinitialPeriodicFrameList (HcDev);
+uninstall_usb2hc_protocol:
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &HcDev->Usb2Hc
+ );
+free_pool:
+ gBS->FreePool (HcDev);
+close_pciio_protocol:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+
+ This - Protocol instance pointer.
+ Controller - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
+ USB2_HC_DEV *HcDev;
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ HcDev = USB2_HC_DEV_FROM_THIS (Usb2Hc);
+
+ //
+ // free all the controller related memory and uninstall UHCI Protocol.
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ Usb2Hc
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Set Host Controller state as halt
+ //
+ Status = Usb2Hc->SetState (
+ Usb2Hc,
+ EfiUsbHcStateHalt
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Stop AsyncRequest Polling Timer
+ //
+ Status = StopPollingTimer (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Destroy Asynchronous Request Event
+ //
+ DestoryPollingTimer (HcDev);
+
+ //
+ // Destroy Perodic Frame List
+ //
+ DeinitialPeriodicFrameList (HcDev);
+
+ //
+ // Deinit Ehci pool memory management
+ //
+ DeinitialMemoryManagement (HcDev);
+
+ //
+ // Denint Unicode String Table
+ //
+ FreeUnicodeStringTable (HcDev->ControllerNameTable);
+
+ //
+ // Disable the USB Host Controller
+ //
+ Status = HcDev->PciIo->Attributes (
+ HcDev->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ gBS->FreePool (HcDev);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciGetCapability (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ )
+/*++
+
+ Routine Description:
+
+ Retrieves the capablility of root hub ports.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB_HC_PROTOCOL instance.
+ MaxSpeed - A pointer to the number of the host controller.
+ PortNumber - A pointer to the number of the root hub ports.
+ Is64BitCapable - A pointer to the flag for whether controller supports
+ 64-bit memory addressing.
+
+ Returns:
+
+ EFI_SUCCESS host controller capability were retrieved successfully.
+ EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.
+ EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the capabilities.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT32 HcStructParamsAddr;
+ UINT32 HcStructParamsReg;
+ UINT32 HcCapParamsAddr;
+ UINT32 HcCapParamsReg;
+
+ if (MaxSpeed == NULL || PortNumber == NULL || Is64BitCapable == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ HcStructParamsAddr = HCSPARAMS;
+ HcCapParamsAddr = HCCPARAMS;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ Status = ReadEhcCapabiltiyReg (
+ HcDev,
+ HcStructParamsAddr,
+ &HcStructParamsReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = ReadEhcCapabiltiyReg (
+ HcDev,
+ HcCapParamsAddr,
+ &HcCapParamsReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ *MaxSpeed = EFI_USB_SPEED_HIGH;
+ *PortNumber = (UINT8) (HcStructParamsReg & HCSP_NPORTS);
+ *Is64BitCapable = (UINT8) (HcCapParamsReg & HCCP_64BIT);
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciReset (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ )
+/*++
+
+ Routine Description:
+
+ Provides software reset for the USB host controller.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ Attributes - A bit mask of the reset operation to perform.
+ See below for a list of the supported bit mask values.
+
+ #define EFI_USB_HC_RESET_GLOBAL 0x0001
+ #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
+ #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004
+ #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
+
+ EFI_USB_HC_RESET_GLOBAL
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ EFI_USB_HC_RESET_HOST_CONTROLLER
+ If this bit is set, the USB host controller hardware will be reset.
+ No reset signal will be sent to the USB bus.
+ EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ If this is an EHCI controller and the debug port has configured, then
+ this is will still reset the host controller.
+ EFI_USB_HC_RESET_HOST_WITH_DEBUG
+ If this bit is set, the USB host controller hardware will be reset.
+ If this is an EHCI controller and the debug port has been configured,
+ then this will still reset the host controller.
+
+ Returns:
+
+ EFI_SUCCESS
+ The reset operation succeeded.
+ EFI_INVALID_PARAMETER
+ Attributes is not valid.
+ EFI_UNSUPPOURTED
+ The type of reset specified by Attributes is not currently supported by
+ the host controller hardware.
+ EFI_ACCESS_DENIED
+ Reset operation is rejected due to the debug port being configured and
+ active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or
+ EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
+ perform reset operation for this host controller.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to perform
+ the reset operation.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINTN FrameIndex;
+ FRAME_LIST_ENTRY *FrameEntryPtr;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ switch (Attributes) {
+
+ case EFI_USB_HC_RESET_GLOBAL:
+
+ //
+ // Same behavior as Host Controller Reset
+ //
+
+ case EFI_USB_HC_RESET_HOST_CONTROLLER:
+
+ //
+ // Host Controller must be Halt when Reset it
+ //
+ if (IsEhcHalted (HcDev)) {
+ Status = ResetEhc (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ //
+ // Set to zero by Host Controller when reset process completes
+ //
+ Status = WaitForEhcReset (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // only asynchronous interrupt transfers are always alive on the bus, need to cleanup
+ //
+ CleanUpAllAsyncRequestTransfer (HcDev);
+ Status = ClearEhcAllStatus (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Set appropriate 4G Segment Selector
+ //
+ Status = SetCtrlDataStructSeg (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Init Perodic List Base Addr and Frame List
+ //
+ Status = SetFrameListBaseAddr (
+ HcDev,
+ (UINT32) GET_0B_TO_31B (HcDev->PeriodicFrameListBuffer)
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
+ for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {
+ FrameEntryPtr->LinkTerminate = TRUE;
+ FrameEntryPtr++;
+ }
+
+ //
+ // Start the Host Controller
+ //
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ }
+
+ //
+ // Set all ports routing to EHC
+ //
+ Status = SetPortRoutingEhc (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ break;
+
+ case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
+
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
+
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciGetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ )
+/*++
+
+ Routine Description:
+
+ Retrieves current state of the USB host controller.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ State A pointer to the EFI_USB_HC_STATE data structure that
+ indicates current state of the USB host controller.
+ Type EFI_USB_HC_STATE is defined below.
+
+ typedef enum {
+ EfiUsbHcStateHalt,
+ EfiUsbHcStateOperational,
+ EfiUsbHcStateSuspend,
+ EfiUsbHcStateMaximum
+ } EFI_USB_HC_STATE;
+
+ Returns:
+
+ EFI_SUCCESS
+ The state information of the host controller was returned in State.
+ EFI_INVALID_PARAMETER
+ State is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the
+ host controller's current state.
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT32 UsbStatusAddr;
+ UINT32 UsbStatusReg;
+
+ if (State == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ UsbStatusAddr = USBSTS;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbStatusAddr,
+ &UsbStatusReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ if (UsbStatusReg & USBSTS_HCH) {
+ *State = EfiUsbHcStateHalt;
+ } else {
+ *State = EfiUsbHcStateOperational;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciSetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ )
+/*++
+
+ Routine Description:
+
+ Sets the USB host controller to a specific state.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ State - Indicates the state of the host controller that will be set.
+
+ Returns:
+
+ EFI_SUCCESS
+ The USB host controller was successfully placed in the state
+ specified by State.
+ EFI_INVALID_PARAMETER
+ State is invalid.
+ EFI_DEVICE_ERROR
+ Failed to set the state specified by State due to device error.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+ EFI_USB_HC_STATE CurrentState;
+
+ UsbCommandAddr = USBCMD;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ Status = EhciGetState (This, &CurrentState);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ switch (State) {
+
+ case EfiUsbHcStateHalt:
+
+ if (EfiUsbHcStateHalt == CurrentState) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ } else if (EfiUsbHcStateOperational == CurrentState) {
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ UsbCommandReg &= ~USBCMD_RS;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ //
+ // Ensure the HC is in halt status after send the stop command
+ //
+ Status = WaitForEhcHalt (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+ }
+ break;
+
+ case EfiUsbHcStateOperational:
+
+ if (IsEhcSysError (HcDev)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ if (EfiUsbHcStateOperational == CurrentState) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ } else if (EfiUsbHcStateHalt == CurrentState) {
+ //
+ // Set Host Controller Run
+ //
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbCommandReg |= USBCMD_RS;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ }
+ break;
+
+ case EfiUsbHcStateSuspend:
+
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ default:
+
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciGetRootHubPortStatus (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+/*++
+
+ Routine Description:
+
+ Retrieves the current status of a USB root hub port.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL.
+ PortNumber - Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+ PortStatus - A pointer to the current port status bits and
+ port status change bits.
+
+ Returns:
+
+ EFI_SUCCESS The status of the USB root hub port specified
+ by PortNumber was returned in PortStatus.
+ EFI_INVALID_PARAMETER PortNumber is invalid.
+ EFI_DEVICE_ERROR Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT32 PortStatusControlAddr;
+ UINT32 PortStatusControlReg;
+ UINT8 MaxSpeed;
+ UINT8 TotalPortNumber;
+ UINT8 Is64BitCapable;
+
+ if (PortStatus == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ EhciGetCapability (
+ This,
+ &MaxSpeed,
+ &TotalPortNumber,
+ &Is64BitCapable
+ );
+
+ if (PortNumber >= TotalPortNumber) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
+
+ //
+ // Clear port status
+ //
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ &PortStatusControlReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Fill Port Status bits
+ //
+
+ //
+ // Current Connect Status
+ //
+ if (PORTSC_CCS & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ //
+ // Port Enabled/Disabled
+ //
+ if (PORTSC_PED & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+ //
+ // Port Suspend
+ //
+ if (PORTSC_SUSP & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ //
+ // Over-current Active
+ //
+ if (PORTSC_OCA & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
+ }
+ //
+ // Port Reset
+ //
+ if (PORTSC_PR & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+ //
+ // Port Power
+ //
+ if (PORTSC_PP & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_POWER;
+ }
+ //
+ // Port Owner
+ //
+ if (PORTSC_PO & PortStatusControlReg) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
+ }
+ //
+ // Identify device speed
+ //
+ if (PORTSC_LS_KSTATE & PortStatusControlReg) {
+ //
+ // Low Speed Device Attached
+ //
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ } else {
+ //
+ // Not Low Speed Device Attached
+ //
+ if ((PORTSC_CCS & PortStatusControlReg) && (PORTSC_CSC & PortStatusControlReg)) {
+ mDeviceSpeed[PortNumber] = IsHighSpeedDevice (This, PortNumber) ? USB_PORT_STAT_HIGH_SPEED : 0;
+ }
+ PortStatus->PortStatus |= mDeviceSpeed[PortNumber];
+ }
+ //
+ // Fill Port Status Change bits
+ //
+ //
+ // Connect Status Change
+ //
+ if (PORTSC_CSC & PortStatusControlReg) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+ //
+ // Port Enabled/Disabled Change
+ //
+ if (PORTSC_PEDC & PortStatusControlReg) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ //
+ // Port Over Current Change
+ //
+ if (PORTSC_OCC & PortStatusControlReg) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciSetRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+
+ Sets a feature for the specified root hub port.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL.
+ PortNumber - Specifies the root hub port whose feature
+ is requested to be set.
+ PortFeature - Indicates the feature selector associated
+ with the feature set request.
+
+ Returns:
+
+ EFI_SUCCESS
+ The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT32 PortStatusControlAddr;
+ UINT32 PortStatusControlReg;
+ UINT8 MaxSpeed;
+ UINT8 TotalPortNumber;
+ UINT8 Is64BitCapable;
+
+ EhciGetCapability (
+ This,
+ &MaxSpeed,
+ &TotalPortNumber,
+ &Is64BitCapable
+ );
+
+ if (PortNumber >= TotalPortNumber) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ &PortStatusControlReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ switch (PortFeature) {
+
+ case EfiUsbPortEnable:
+
+ //
+ // Sofeware can't set this bit, Port can only be enable by the Host Controller
+ // as a part of the reset and enable
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_PED;
+ break;
+
+ case EfiUsbPortSuspend:
+
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_SUSP;
+ break;
+
+ case EfiUsbPortReset:
+
+ //
+ // Make sure Host Controller not halt before reset it
+ //
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ Status = WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCDebugLevel, "WaitForEhcNotHalt TimeOut\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ }
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_PR;
+ //
+ // Set one to PortReset bit must also set zero to PortEnable bit
+ //
+ PortStatusControlReg &= ~PORTSC_PED;
+ break;
+
+ case EfiUsbPortPower:
+
+ //
+ // No support, no operation
+ //
+ goto exit;
+
+ case EfiUsbPortOwner:
+
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_PO;
+ break;
+
+ default:
+
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ PortStatusControlReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciClearRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+
+ Clears a feature for the specified root hub port.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ PortNumber - Specifies the root hub port whose feature
+ is requested to be cleared.
+ PortFeature - Indicates the feature selector associated with the
+ feature clear request.
+
+ Returns:
+
+ EFI_SUCCESS
+ The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT32 PortStatusControlAddr;
+ UINT32 PortStatusControlReg;
+ UINT8 MaxSpeed;
+ UINT8 TotalPortNumber;
+ UINT8 Is64BitCapable;
+
+ EhciGetCapability (
+ This,
+ &MaxSpeed,
+ &TotalPortNumber,
+ &Is64BitCapable
+ );
+
+ if (PortNumber >= TotalPortNumber) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ &PortStatusControlReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ switch (PortFeature) {
+
+ case EfiUsbPortEnable:
+
+ //
+ // Clear PORT_ENABLE feature means disable port.
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg &= ~PORTSC_PED;
+ break;
+
+ case EfiUsbPortSuspend:
+
+ //
+ // A write of zero to this bit is ignored by the host controller.
+ // The host controller will unconditionally set this bit to a zero when:
+ // 1. software sets the Forct Port Resume bit to a zero from a one.
+ // 2. software sets the Port Reset bit to a one frome a zero.
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg &= ~PORTSC_FPR;
+ break;
+
+ case EfiUsbPortReset:
+
+ //
+ // Clear PORT_RESET means clear the reset signal.
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg &= ~PORTSC_PR;
+ break;
+
+ case EfiUsbPortPower:
+
+ //
+ // No support, no operation
+ //
+ goto exit;
+
+ case EfiUsbPortOwner:
+
+ //
+ // Clear port owner means this port owned by EHC
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg &= ~PORTSC_PO;
+ break;
+
+ case EfiUsbPortConnectChange:
+
+ //
+ // Clear connect status change
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_CSC;
+ break;
+
+ case EfiUsbPortEnableChange:
+
+ //
+ // Clear enable status change
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_PEDC;
+ break;
+
+ case EfiUsbPortSuspendChange:
+
+ //
+ // No related bit, no operation
+ //
+ goto exit;
+
+ case EfiUsbPortOverCurrentChange:
+
+ //
+ // Clear PortOverCurrent change
+ //
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_OCC;
+ break;
+
+ case EfiUsbPortResetChange:
+
+ //
+ // No related bit, no operation
+ //
+ goto exit;
+
+ default:
+
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ PortStatusControlReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciControlTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Submits control transfer to a target USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ DeviceSpeed - Indicates target device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ Request - A pointer to the USB device request that will be sent
+ to the USB device.
+ TransferDirection - Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ TimeOut - Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The control transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The control transfer could not be completed due to a lack of resources.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The control transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT8 PktId;
+ EHCI_QH_ENTITY *QhPtr;
+ EHCI_QTD_ENTITY *ControlQtdsPtr;
+ UINT8 *DataCursor;
+ VOID *DataMap;
+ UINT8 *RequestCursor;
+ VOID *RequestMap;
+
+ QhPtr = NULL;
+ ControlQtdsPtr = NULL;
+ DataCursor = NULL;
+ DataMap = NULL;
+ RequestCursor = NULL;
+ RequestMap = NULL;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ //
+ // Parameters Checking
+ //
+ if (TransferDirection != EfiUsbDataIn &&
+ TransferDirection != EfiUsbDataOut &&
+ TransferDirection != EfiUsbNoData
+ ) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EfiUsbNoData == TransferDirection) {
+ if (NULL != Data || 0 != *DataLength) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ } else {
+ if (NULL == Data || 0 == *DataLength) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+
+ if (Request == NULL || TransferResult == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EFI_USB_SPEED_LOW == DeviceSpeed) {
+ if (MaximumPacketLength != 8) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ } else if (MaximumPacketLength != 8 &&
+ MaximumPacketLength != 16 &&
+ MaximumPacketLength != 32 &&
+ MaximumPacketLength != 64
+ ) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // If errors exist that cause host controller halt,
+ // then return EFI_DEVICE_ERROR.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ ClearEhcAllStatus (HcDev);
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Map the Request for bus master access.
+ // BusMasterRead means cpu write
+ //
+ Status = MapRequestBuffer (
+ HcDev,
+ Request,
+ &RequestCursor,
+ &RequestMap
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Map the source data buffer for bus master access.
+ //
+ Status = MapDataBuffer (
+ HcDev,
+ TransferDirection,
+ Data,
+ DataLength,
+ &PktId,
+ &DataCursor,
+ &DataMap
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto unmap_request;
+ }
+
+ //
+ // Create and init control Qh
+ //
+ Status = CreateControlQh (
+ HcDev,
+ DeviceAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ Translator,
+ &QhPtr
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto unmap_data;
+ }
+
+ //
+ // Create and init control Qtds
+ //
+ Status = CreateControlQtds (
+ HcDev,
+ PktId,
+ RequestCursor,
+ DataCursor,
+ *DataLength,
+ Translator,
+ &ControlQtdsPtr
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto destory_qh;
+ }
+
+ //
+ // Link Qtds to Qh
+ //
+ LinkQtdToQh (QhPtr, ControlQtdsPtr);
+
+ ClearEhcAllStatus (HcDev);
+
+ //
+ // Link Qh and Qtds to Async Schedule List
+ //
+ Status = LinkQhToAsyncList (HcDev, QhPtr);
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto destory_qtds;
+ }
+
+ //
+ // Poll Qh-Qtds execution and get result.
+ // detail status is returned
+ //
+ Status = ExecuteTransfer (
+ HcDev,
+ TRUE,
+ QhPtr,
+ DataLength,
+ 0,
+ TimeOut,
+ TransferResult
+ );
+ if (EFI_ERROR (Status)) {
+ goto destory_qtds;
+ }
+
+ //
+ // If has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ }
+
+ ClearEhcAllStatus (HcDev);
+
+destory_qtds:
+ UnlinkQhFromAsyncList (HcDev, QhPtr);
+ DestoryQtds (HcDev, ControlQtdsPtr);
+destory_qh:
+ DestoryQh (HcDev, QhPtr);
+unmap_data:
+ HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
+unmap_request:
+ HcDev->PciIo->Unmap (HcDev->PciIo, RequestMap);
+exit:
+ HcDev->PciIo->Flush (HcDev->PciIo);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciBulkTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+ DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
+ and EFI_USB_SPEED_HIGH.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+ DataToggle - A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+ Translator - A pointr to the transaction translator data.
+ TimeOut - Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ TransferResult - A pointer to the detailed result information of the
+ bulk transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The bulk transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The bulk transfer could not be submitted due to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The bulk transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT8 PktId;
+ EHCI_QH_ENTITY *QhPtr;
+ EHCI_QTD_ENTITY *BulkQtdsPtr;
+ UINT8 *DataCursor;
+ VOID *DataMap;
+ EFI_USB_DATA_DIRECTION TransferDirection;
+
+ QhPtr = NULL;
+ BulkQtdsPtr = NULL;
+ DataCursor = NULL;
+ DataMap = NULL;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ //
+ // Parameters Checking
+ //
+ if (NULL == DataLength ||
+ NULL == Data ||
+ NULL == Data[0] ||
+ NULL == TransferResult
+ ) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (*DataLength == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (1 != *DataToggle && 0 != *DataToggle) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EFI_USB_SPEED_LOW == DeviceSpeed) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EFI_USB_SPEED_FULL == DeviceSpeed) {
+ if (MaximumPacketLength > 64) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+
+ if (EFI_USB_SPEED_HIGH == DeviceSpeed) {
+ if (MaximumPacketLength > 512) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ ClearEhcAllStatus (HcDev);
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = ClearEhcAllStatus (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // construct QH and TD data structures,
+ // and link them together
+ //
+ if (EndPointAddress & 0x80) {
+ TransferDirection = EfiUsbDataIn;
+ } else {
+ TransferDirection = EfiUsbDataOut;
+ }
+
+ Status = MapDataBuffer (
+ HcDev,
+ TransferDirection,
+ Data[0],
+ DataLength,
+ &PktId,
+ &DataCursor,
+ &DataMap
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Create and init Bulk Qh
+ //
+ Status = CreateBulkQh (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ *DataToggle,
+ MaximumPacketLength,
+ Translator,
+ &QhPtr
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto unmap_data;
+ }
+
+ //
+ // Create and init Bulk Qtds
+ //
+ Status = CreateBulkOrInterruptQtds (
+ HcDev,
+ PktId,
+ DataCursor,
+ *DataLength,
+ Translator,
+ &BulkQtdsPtr
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto destory_qh;
+ }
+
+ //
+ // Link Qtds to Qh
+ //
+ LinkQtdToQh (QhPtr, BulkQtdsPtr);
+
+ ClearEhcAllStatus (HcDev);
+
+ //
+ // Link Qh and qtds to Async Schedule List
+ //
+ Status = LinkQhToAsyncList (HcDev, QhPtr);
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto destory_qtds;
+ }
+
+ //
+ // Poll QH-TDs execution and get result.
+ // detail status is returned
+ //
+ Status = ExecuteTransfer (
+ HcDev,
+ FALSE,
+ QhPtr,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+ if (EFI_ERROR (Status)) {
+ goto destory_qtds;
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ }
+
+ ClearEhcAllStatus (HcDev);
+
+destory_qtds:
+ UnlinkQhFromAsyncList (HcDev, QhPtr);
+ DestoryQtds (HcDev, BulkQtdsPtr);
+destory_qh:
+ DestoryQh (HcDev, QhPtr);
+unmap_data:
+ HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
+exit:
+ HcDev->PciIo->Flush (HcDev->PciIo);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciAsyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+ Routine Description:
+
+ Submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ DataToggle - A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ PollingInterval - Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ DataLength - Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ Translator - A pointr to the transaction translator data.
+ CallBackFunction - The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ Context - The context that is passed to the CallBackFunction.
+ - This is an optional parameter and may be NULL.
+
+ Returns:
+
+ EFI_SUCCESS
+ The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_OUT_OF_RESOURCES
+ The request could not be completed due to a lack of resources.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT8 PktId;
+ EHCI_QH_ENTITY *QhPtr;
+ EHCI_QTD_ENTITY *InterruptQtdsPtr;
+ UINT8 *DataPtr;
+ UINT8 *DataCursor;
+ VOID *DataMap;
+ UINTN MappedLength;
+ EHCI_ASYNC_REQUEST *AsyncRequestPtr;
+ EFI_TPL OldTpl;
+
+ QhPtr = NULL;
+ InterruptQtdsPtr = NULL;
+ DataPtr = NULL;
+ DataCursor = NULL;
+ DataMap = NULL;
+ AsyncRequestPtr = NULL;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ //
+ // Parameters Checking
+ //
+ if (!IsDataInTransfer (EndPointAddress)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (IsNewTransfer) {
+ if (0 == DataLength) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (*DataToggle != 1 && *DataToggle != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (PollingInterval > 255 || PollingInterval < 1) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ ClearEhcAllStatus (HcDev);
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = ClearEhcAllStatus (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Delete Async interrupt transfer request
+ //
+ if (!IsNewTransfer) {
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+
+ Status = DeleteAsyncRequestTransfer (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ DataToggle
+ );
+
+ gBS->RestoreTPL (OldTpl);
+
+ goto exit;
+ }
+
+ Status = EhciAllocatePool (
+ HcDev,
+ (UINT8 **) &AsyncRequestPtr,
+ sizeof (EHCI_ASYNC_REQUEST)
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ Status = EhciAllocatePool (HcDev, &DataPtr, DataLength);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto free_request;
+ }
+
+ MappedLength = DataLength;
+ Status = MapDataBuffer (
+ HcDev,
+ EfiUsbDataIn,
+ DataPtr,
+ &MappedLength,
+ &PktId,
+ &DataCursor,
+ &DataMap
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto free_data;
+ }
+
+ //
+ // Create and init Interrupt Qh
+ //
+ Status = CreateInterruptQh (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ *DataToggle,
+ MaximumPacketLength,
+ PollingInterval,
+ Translator,
+ &QhPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto unmap_data;
+ }
+
+ //
+ // Create and init Interrupt Qtds
+ //
+ Status = CreateBulkOrInterruptQtds (
+ HcDev,
+ PktId,
+ DataCursor,
+ MappedLength,
+ Translator,
+ &InterruptQtdsPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto destory_qh;
+ }
+
+ //
+ // Link Qtds to Qh
+ //
+ LinkQtdToQh (QhPtr, InterruptQtdsPtr);
+
+ //
+ // Init AsyncRequest Entry
+ //
+ AsyncRequestPtr->Context = Context;
+ AsyncRequestPtr->CallBackFunc = CallBackFunction;
+ AsyncRequestPtr->TransferType = ASYNC_INTERRUPT_TRANSFER;
+ AsyncRequestPtr->QhPtr = QhPtr;
+ AsyncRequestPtr->Prev = NULL;
+ AsyncRequestPtr->Next = NULL;
+
+ if (NULL == HcDev->AsyncRequestList) {
+ Status = StartPollingTimer (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ CleanUpAllAsyncRequestTransfer (HcDev);
+ goto exit;
+ }
+ }
+
+ //
+ // Link Entry to AsyncRequest List
+ //
+ LinkToAsyncReqeust (HcDev, AsyncRequestPtr);
+
+ ClearEhcAllStatus (HcDev);
+
+ Status = DisablePeriodicSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ //
+ // Link Qh and Qtds to Periodic Schedule List
+ //
+ LinkQhToPeriodicList (HcDev, QhPtr);
+
+ Status = EnablePeriodicSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ }
+
+ HcDev->PciIo->Flush (HcDev->PciIo);
+ goto exit;
+
+destory_qh:
+ DestoryQh (HcDev, QhPtr);
+free_data:
+ EhciFreePool (HcDev, DataPtr, DataLength);
+free_request:
+ EhciFreePool (
+ HcDev,
+ (UINT8 *) AsyncRequestPtr,
+ sizeof (EHCI_ASYNC_REQUEST)
+ );
+unmap_data:
+ HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciSyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+ DataToggle - A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+ TimeOut - Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The synchronous interrupt transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The synchronous interrupt transfer could not be submitted due
+ to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The synchronous interrupt transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The synchronous interrupt transfer failed due to host controller
+ or device error. Caller should check TranferResult for detailed
+ error information.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ UINT8 PktId;
+ EHCI_QH_ENTITY *QhPtr;
+ EHCI_QTD_ENTITY *InterruptQtdsPtr;
+ UINT8 *DataCursor;
+ VOID *DataMap;
+
+ QhPtr = NULL;
+ InterruptQtdsPtr = NULL;
+ DataCursor = NULL;
+ DataMap = NULL;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ //
+ // Parameters Checking
+ //
+ if (DataLength == NULL ||
+ Data == NULL ||
+ TransferResult == NULL
+ ) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (!IsDataInTransfer (EndPointAddress)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (0 == *DataLength) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (*DataToggle != 1 && *DataToggle != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EFI_USB_SPEED_LOW == DeviceSpeed && 8 != MaximumPacketLength) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EFI_USB_SPEED_FULL == DeviceSpeed && MaximumPacketLength > 64) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (EFI_USB_SPEED_HIGH == DeviceSpeed && MaximumPacketLength > 3072) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ ClearEhcAllStatus (HcDev);
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = ClearEhcAllStatus (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = MapDataBuffer (
+ HcDev,
+ EfiUsbDataIn,
+ Data,
+ DataLength,
+ &PktId,
+ &DataCursor,
+ &DataMap
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ //
+ // Create and init Interrupt Qh
+ //
+ Status = CreateInterruptQh (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ *DataToggle,
+ MaximumPacketLength,
+ 0,
+ Translator,
+ &QhPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto unmap_data;
+ }
+
+ //
+ // Create and init Interrupt Qtds
+ //
+ Status = CreateBulkOrInterruptQtds (
+ HcDev,
+ PktId,
+ DataCursor,
+ *DataLength,
+ Translator,
+ &InterruptQtdsPtr
+ );
+ if (EFI_ERROR (Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto destory_qh;
+ }
+
+ //
+ // Link Qtds to Qh
+ //
+ LinkQtdToQh (QhPtr, InterruptQtdsPtr);
+
+ ClearEhcAllStatus (HcDev);
+
+ Status = DisablePeriodicSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ //
+ // Link Qh and Qtds to Periodic Schedule List
+ //
+ LinkQhToPeriodicList (HcDev, QhPtr);
+
+ Status = EnablePeriodicSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ }
+
+ //
+ // Poll QH-TDs execution and get result.
+ // detail status is returned
+ //
+ Status = ExecuteTransfer (
+ HcDev,
+ FALSE,
+ QhPtr,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+ if (EFI_ERROR (Status)) {
+ goto destory_qtds;
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ }
+
+ ClearEhcAllStatus (HcDev);
+
+destory_qtds:
+ UnlinkQhFromPeriodicList (HcDev, QhPtr, 0);
+ DestoryQtds (HcDev, InterruptQtdsPtr);
+destory_qh:
+ DestoryQh (HcDev, QhPtr);
+unmap_data:
+ HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
+exit:
+ HcDev->PciIo->Flush (HcDev->PciIo);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EhciIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Submits isochronous transfer to a target USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be
+ transmitted to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+EhciAsyncIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+
+ Submits Async isochronous transfer to a target USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+ Translator - A pointr to the transaction translator data.
+ IsochronousCallBack - When the transfer complete, the call back function will be called
+ Context - Pass to the call back function as parameter
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h
new file mode 100644
index 0000000000..a5fa2be394
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h
@@ -0,0 +1,2689 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Ehci.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _EHCI_H
+#define _EHCI_H
+
+//
+// Universal Host Controller Interface data structures and defines
+//
+#include <IndustryStandard/pci22.h>
+
+#ifdef EFI_DEBUG
+extern UINTN gEHCDebugLevel;
+extern UINTN gEHCErrorLevel;
+#endif
+
+#define STALL_1_MACRO_SECOND 1
+#define STALL_1_MILLI_SECOND 1000 * STALL_1_MACRO_SECOND
+#define STALL_1_SECOND 1000 * STALL_1_MILLI_SECOND
+
+#define SETUP_PACKET_PID_CODE 0x02
+#define INPUT_PACKET_PID_CODE 0x01
+#define OUTPUT_PACKET_PID_CODE 0x0
+
+#define ITD_SELECT_TYPE 0x0
+#define QH_SELECT_TYPE 0x01
+#define SITD_SELECT_TYPE 0x02
+#define FSTN_SELECT_TYPE 0x03
+
+#define EHCI_SET_PORT_RESET_RECOVERY_TIME 50 * STALL_1_MILLI_SECOND
+#define EHCI_CLEAR_PORT_RESET_RECOVERY_TIME STALL_1_MILLI_SECOND
+#define EHCI_GENERIC_TIMEOUT 50 * STALL_1_MILLI_SECOND
+#define EHCI_GENERIC_RECOVERY_TIME 50 * STALL_1_MACRO_SECOND
+#define EHCI_SYNC_REQUEST_POLLING_TIME 50 * STALL_1_MACRO_SECOND
+#define EHCI_ASYNC_REQUEST_POLLING_TIME 50 * STALL_1_MILLI_SECOND
+
+#define USB_BAR_INDEX 0 /* how many bytes away from USB_BASE to 0x10 */
+
+#define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 1
+
+#define EHCI_MIN_PACKET_SIZE 8
+#define EHCI_MAX_PACKET_SIZE 1024
+#define EHCI_MAX_FRAME_LIST_LENGTH 1024
+#define EHCI_BLOCK_SIZE_WITH_TT 64
+#define EHCI_BLOCK_SIZE 512
+#define EHCI_MAX_QTD_CAPACITY (EFI_PAGE_SIZE * 5)
+
+#define NAK_COUNT_RELOAD 3
+#define QTD_ERROR_COUNTER 1
+#define HIGH_BANDWIDTH_PIPE_MULTIPLIER 1
+
+#define QTD_STATUS_ACTIVE 0x80
+#define QTD_STATUS_HALTED 0x40
+#define QTD_STATUS_BUFFER_ERR 0x20
+#define QTD_STATUS_BABBLE_ERR 0x10
+#define QTD_STATUS_TRANSACTION_ERR 0x08
+#define QTD_STATUS_DO_STOP_SPLIT 0x02
+#define QTD_STATUS_DO_START_SPLIT 0
+#define QTD_STATUS_DO_PING 0x01
+#define QTD_STATUS_DO_OUT 0
+
+#define DATA0 0
+#define DATA1 1
+
+#define MICRO_FRAME_0_CHANNEL 0x01
+#define MICRO_FRAME_1_CHANNEL 0x02
+#define MICRO_FRAME_2_CHANNEL 0x04
+#define MICRO_FRAME_3_CHANNEL 0x08
+#define MICRO_FRAME_4_CHANNEL 0x10
+#define MICRO_FRAME_5_CHANNEL 0x20
+#define MICRO_FRAME_6_CHANNEL 0x40
+#define MICRO_FRAME_7_CHANNEL 0x80
+
+#define CONTROL_TRANSFER 0x01
+#define BULK_TRANSFER 0x02
+#define SYNC_INTERRUPT_TRANSFER 0x04
+#define ASYNC_INTERRUPT_TRANSFER 0x08
+#define SYNC_ISOCHRONOUS_TRANSFER 0x10
+#define ASYNC_ISOCHRONOUS_TRANSFER 0x20
+
+
+//
+// Enhanced Host Controller Registers definitions
+//
+extern UINT32 mUsbCapabilityLen;
+extern EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gEhciComponentName;
+
+#define USBCMD 0x0 /* Command Register Offset 00-03h */
+#define USBCMD_RS 0x01 /* Run / Stop */
+#define USBCMD_HCRESET 0x02 /* Host controller reset */
+#define USBCMD_FLS_512 0x04 /* 512 elements (2048bytes) in Frame List */
+#define USBCMD_FLS_256 0x08 /* 256 elements (1024bytes) in Frame List */
+#define USBCMD_PSE 0x10 /* Periodic schedule enable */
+#define USBCMD_ASE 0x20 /* Asynchronous schedule enable */
+#define USBCMD_IAAD 0x40 /* Interrupt on async advance doorbell */
+
+#define USBSTS 0x04 /* Statue Register Offset 04-07h */
+#define USBSTS_HSE 0x10 /* Host system error */
+#define USBSTS_IAA 0x20 /* Interrupt on async advance */
+#define USBSTS_HCH 0x1000 /* Host controller halted */
+#define USBSTS_PSS 0x4000 /* Periodic schedule status */
+#define USBSTS_ASS 0x8000 /* Asynchronous schedule status */
+
+#define USBINTR 0x08 /* Command Register Offset 08-0bh */
+
+#define FRINDEX 0x0c /* Frame Index Offset 0c-0fh */
+
+#define CTRLDSSGMENT 0x10 /* 4G Segment Selector Offset 10-13h */
+
+#define PERIODICLISTBASE 0x14 /* Frame List Base Address Offset 14-17h */
+
+#define ASYNCLISTADDR 0x18 /* Next Asynchronous List Address Offset 18-1bh */
+
+#define CONFIGFLAG 0x40 /* Configured Flag Register Offset 40-43h */
+#define CONFIGFLAG_CF 0x01 /* Configure Flag */
+
+#define PORTSC 0x44 /* Port Status/Control Offset 44-47h */
+#define PORTSC_CCS 0x01 /* Current Connect Status*/
+#define PORTSC_CSC 0x02 /* Connect Status Change */
+#define PORTSC_PED 0x04 /* Port Enable / Disable */
+#define PORTSC_PEDC 0x08 /* Port Enable / Disable Change */
+#define PORTSC_OCA 0x10 /* Over current Active */
+#define PORTSC_OCC 0x20 /* Over current Change */
+#define PORTSC_FPR 0x40 /* Force Port Resume */
+#define PORTSC_SUSP 0x80 /* Port Suspend State */
+#define PORTSC_PR 0x100 /* Port Reset */
+#define PORTSC_LS_KSTATE 0x400 /* Line Status K-state */
+#define PORTSC_LS_JSTATE 0x800 /* Line Status J-state */
+#define PORTSC_PP 0x1000 /* Port Power */
+#define PORTSC_PO 0x2000 /* Port Owner */
+
+#define CAPLENGTH 0 /* Capability Register Length 00h */
+
+#define HCIVERSION 0x02 /* Interface Version Number 02-03h */
+
+#define HCSPARAMS 0x04 /* Structural Parameters 04-07h */
+#define HCSP_NPORTS 0x0f /* Number of physical downstream ports on host controller */
+
+#define HCCPARAMS 0x08 /* Capability Parameters 08-0bh */
+#define HCCP_64BIT 0x01 /* 64-bit Addressing Capability */
+#define HCCP_PFLF 0x02 /* Programmable Frame List Flag */
+#define HCCP_EECP 0xff00 /* EHCI Extemded Capabilities Pointer */
+
+#define HCSPPORTROUTE 0x0c /* Companion Port Route Description 60b */
+
+#define CLASSC 0x09 /* Class Code 09-0bh */
+
+#define USBBASE 0x10 /* Base Address to Memory-mapped Host Controller Register Space 10-13h */
+
+#define SBRN 0x60 /* Serial Bus Release Number 60h */
+
+#define FLADJ 0x61 /* Frame Length Adjustment Register 61h */
+
+#define PORTWAKECAP 0x62 /* Port wake capablilities register(OPIONAL) 61-62h */
+
+//
+// PCI Configuration Registers
+//
+#define EHCI_PCI_CLASSC 0x09
+#define EHCI_PCI_MEMORY_BASE 0x10
+
+//
+// Memory Offset Registers
+//
+#define EHCI_MEMORY_CAPLENGTH 0x0
+#define EHCI_MEMORY_CONFIGFLAG 0x40
+
+//
+// USB Base Class Code,Sub-Class Code and Programming Interface
+//
+#define PCI_CLASSC_PI_EHCI 0x20
+
+#define SETUP_PACKET_ID 0x2D
+#define INPUT_PACKET_ID 0x69
+#define OUTPUT_PACKET_ID 0xE1
+#define ERROR_PACKET_ID 0x55
+
+#define bit(a) 1 << (a)
+
+#define GET_0B_TO_31B(Addr) (((UINTN) Addr) & (0xffffffff))
+#define GET_32B_TO_63B(Addr) ((((UINTN) Addr) >> 32) & (0xffffffff))
+
+
+//
+// Ehci Data and Ctrl Structures
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 PI;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} USB_CLASSC;
+
+typedef struct {
+ UINT32 NextQtdTerminate : 1;
+ UINT32 Rsvd1 : 4;
+ UINT32 NextQtdPointer : 27;
+
+ UINT32 AltNextQtdTerminate : 1;
+ UINT32 Rsvd2 : 4;
+ UINT32 AltNextQtdPointer : 27;
+
+ UINT32 Status : 8;
+ UINT32 PidCode : 2;
+ UINT32 ErrorCount : 2;
+ UINT32 CurrentPage : 3;
+ UINT32 InterruptOnComplete : 1;
+ UINT32 TotalBytes : 15;
+ UINT32 DataToggle : 1;
+
+ UINT32 CurrentOffset : 12;
+ UINT32 BufferPointer0 : 20;
+
+ UINT32 Rsvd3 : 12;
+ UINT32 BufferPointer1 : 20;
+
+ UINT32 Rsvd4 : 12;
+ UINT32 BufferPointer2 : 20;
+
+ UINT32 Rsvd5 : 12;
+ UINT32 BufferPointer3 : 20;
+
+ UINT32 Rsvd6 : 12;
+ UINT32 BufferPointer4 : 20;
+
+ UINT32 ExtBufferPointer0;
+ UINT32 ExtBufferPointer1;
+ UINT32 ExtBufferPointer2;
+ UINT32 ExtBufferPointer3;
+ UINT32 ExtBufferPointer4;
+} EHCI_QTD_HW;
+
+typedef struct {
+ UINT32 QhTerminate : 1;
+ UINT32 SelectType : 2;
+ UINT32 Rsvd1 : 2;
+ UINT32 QhHorizontalPointer : 27;
+
+ UINT32 DeviceAddr : 7;
+ UINT32 Inactive : 1;
+ UINT32 EndpointNum : 4;
+ UINT32 EndpointSpeed : 2;
+ UINT32 DataToggleControl : 1;
+ UINT32 HeadReclamationFlag : 1;
+ UINT32 MaxPacketLen : 11;
+ UINT32 ControlEndpointFlag : 1;
+ UINT32 NakCountReload : 4;
+
+ UINT32 InerruptScheduleMask : 8;
+ UINT32 SplitComletionMask : 8;
+ UINT32 HubAddr : 7;
+ UINT32 PortNum : 7;
+ UINT32 Multiplier : 2;
+
+ UINT32 Rsvd2 : 5;
+ UINT32 CurrentQtdPointer : 27;
+
+ UINT32 NextQtdTerminate : 1;
+ UINT32 Rsvd3 : 4;
+ UINT32 NextQtdPointer : 27;
+
+ UINT32 AltNextQtdTerminate : 1;
+ UINT32 NakCount : 4;
+ UINT32 AltNextQtdPointer : 27;
+
+ UINT32 Status : 8;
+ UINT32 PidCode : 2;
+ UINT32 ErrorCount : 2;
+ UINT32 CurrentPage : 3;
+ UINT32 InterruptOnComplete : 1;
+ UINT32 TotalBytes : 15;
+ UINT32 DataToggle : 1;
+
+ UINT32 CurrentOffset : 12;
+ UINT32 BufferPointer0 : 20;
+
+ UINT32 CompleteSplitMask : 8;
+ UINT32 Rsvd4 : 4;
+ UINT32 BufferPointer1 : 20;
+
+ UINT32 FrameTag : 5;
+ UINT32 SplitBytes : 7;
+ UINT32 BufferPointer2 : 20;
+
+ UINT32 Rsvd5 : 12;
+ UINT32 BufferPointer3 : 20;
+
+ UINT32 Rsvd6 : 12;
+ UINT32 BufferPointer4 : 20;
+
+ UINT32 ExtBufferPointer0;
+ UINT32 ExtBufferPointer1;
+ UINT32 ExtBufferPointer2;
+ UINT32 ExtBufferPointer3;
+ UINT32 ExtBufferPointer4;
+} EHCI_QH_HW;
+
+typedef struct {
+ UINT32 LinkTerminate : 1;
+ UINT32 SelectType : 2;
+ UINT32 Rsvd : 2;
+ UINT32 LinkPointer : 27;
+} FRAME_LIST_ENTRY;
+
+#pragma pack()
+
+typedef struct _EHCI_QTD_ENTITY EHCI_QTD_ENTITY;
+typedef struct _EHCI_QH_ENTITY EHCI_QH_ENTITY;
+typedef struct _EHCI_ASYNC_REQUEST EHCI_ASYNC_REQUEST;
+
+typedef struct _EHCI_QTD_ENTITY {
+ EHCI_QTD_HW Qtd;
+ UINT32 TotalBytes;
+ UINT32 StaticTotalBytes;
+ UINT32 StaticCurrentOffset;
+ EHCI_QTD_ENTITY *Prev;
+ EHCI_QTD_ENTITY *Next;
+ EHCI_QTD_ENTITY *AltNext;
+ EHCI_QH_ENTITY *SelfQh;
+} EHCI_QTD_ENTITY;
+
+typedef struct _EHCI_QH_ENTITY {
+ EHCI_QH_HW Qh;
+ EHCI_QH_ENTITY *Next;
+ EHCI_QH_ENTITY *Prev;
+ EHCI_QTD_ENTITY *FirstQtdPtr;
+ EHCI_QTD_ENTITY *LastQtdPtr;
+ EHCI_QTD_ENTITY *AltQtdPtr;
+ UINTN Interval;
+ UINT8 TransferType;
+} EHCI_QH_ENTITY;
+
+#define GET_QH_ENTITY_ADDR(a) ((EHCI_QH_ENTITY *) a)
+#define GET_QTD_ENTITY_ADDR(a) ((EHCI_QTD_ENTITY *) a)
+
+
+//
+// Ehci Managment Structures
+//
+#define USB2_HC_DEV_FROM_THIS(a) CR (a, USB2_HC_DEV, Usb2Hc, USB2_HC_DEV_SIGNATURE)
+
+#define USB2_HC_DEV_SIGNATURE EFI_SIGNATURE_32 ('e', 'h', 'c', 'i')
+
+typedef struct _LIST_HEAD {
+ struct _LIST_HEAD *pre;
+ struct _LIST_HEAD *next;
+} LIST_HEAD;
+
+typedef struct _EHCI_ASYNC_REQUEST {
+ UINT8 TransferType;
+ EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunc;
+ VOID *Context;
+ EHCI_ASYNC_REQUEST *Prev;
+ EHCI_ASYNC_REQUEST *Next;
+ EHCI_QH_ENTITY *QhPtr;
+} EHCI_ASYNC_REQUEST;
+
+typedef struct _MEMORY_MANAGE_HEADER {
+ UINT8 *BitArrayPtr;
+ UINTN BitArraySizeInBytes;
+ UINT8 *MemoryBlockPtr;
+ UINTN MemoryBlockSizeInBytes;
+ VOID *Mapping;
+ struct _MEMORY_MANAGE_HEADER *Next;
+} MEMORY_MANAGE_HEADER;
+
+typedef struct _USB2_HC_DEV {
+ UINTN Signature;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_USB2_HC_PROTOCOL Usb2Hc;
+ UINTN PeriodicFrameListLength;
+ VOID *PeriodicFrameListBuffer;
+ VOID *PeriodicFrameListMap;
+ VOID *AsyncList;
+ EHCI_ASYNC_REQUEST *AsyncRequestList;
+ EFI_EVENT AsyncRequestEvent;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ UINT8 Is64BitCapable;
+ UINT32 High32BitAddr;
+} USB2_HC_DEV;
+
+
+//
+// Internal Functions Declaration
+//
+
+//
+// EhciMem Functions
+//
+EFI_STATUS
+CreateMemoryBlock (
+ IN USB2_HC_DEV *HcDev,
+ OUT MEMORY_MANAGE_HEADER **MemoryHeader,
+ IN UINTN MemoryBlockSizeInPages
+ )
+/*++
+
+Routine Description:
+
+ Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
+ and use PciIo->Map to map the common buffer for Bus Master Read/Write.
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ MemoryHeader - MEMORY_MANAGE_HEADER to output
+ MemoryBlockSizeInPages - MemoryBlockSizeInPages
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Fail for no resources
+ EFI_UNSUPPORTED Unsupported currently
+
+--*/
+;
+
+EFI_STATUS
+FreeMemoryHeader (
+ IN USB2_HC_DEV *HcDev,
+ IN MEMORY_MANAGE_HEADER *MemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Free Memory Header
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ MemoryHeader - MemoryHeader to be freed
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_INVALID_PARAMETER Parameter is error
+
+--*/
+;
+
+VOID
+InsertMemoryHeaderToList (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NewMemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Insert Memory Header To List
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ NewMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+AllocMemInMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ OUT VOID **Pool,
+ IN UINTN NumberOfMemoryUnit
+ )
+/*++
+
+Routine Description:
+
+ Alloc Memory In MemoryBlock
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ Pool - Place to store pointer to memory
+ NumberOfMemoryUnit - Number Of Memory Unit
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_NOT_FOUND Can't find the free memory
+
+--*/
+;
+
+BOOLEAN
+IsMemoryBlockEmptied (
+ IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr
+ )
+/*++
+
+Routine Description:
+
+ Is Memory Block Emptied
+
+Arguments:
+
+ MemoryHeaderPtr - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ TRUE Empty
+ FALSE Not Empty
+
+--*/
+;
+
+VOID
+DelinkMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Delink Memory Block
+
+Arguments:
+
+ FirstMemoryHeader - MEMORY_MANAGE_HEADER
+ NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+InitialMemoryManagement (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Initialize Memory Management
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+DeinitialMemoryManagement (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Deinitialize Memory Management
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+EhciAllocatePool (
+ IN USB2_HC_DEV *HcDev,
+ OUT UINT8 **Pool,
+ IN UINTN AllocSize
+ )
+/*++
+
+Routine Description:
+
+ Ehci Allocate Pool
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Pool - Place to store pointer to the memory buffer
+ AllocSize - Alloc Size
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+EhciFreePool (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *Pool,
+ IN UINTN AllocSize
+ )
+/*++
+
+Routine Description:
+
+ Uhci Free Pool
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ Pool - Pool to free
+ AllocSize - Pool size
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+//
+// EhciReg Functions
+//
+EFI_STATUS
+ReadEhcCapabiltiyReg (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 CapabiltiyRegAddr,
+ IN OUT UINT32 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read Ehc Capabitlity register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ CapabiltiyRegAddr - Ehc Capability register address
+ Data - A pointer to data read from register
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+ReadEhcOperationalReg (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 OperationalRegAddr,
+ IN OUT UINT32 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read Ehc Operation register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ OperationalRegAddr - Ehc Operation register address
+ Data - A pointer to data read from register
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+WriteEhcOperationalReg (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 OperationalRegAddr,
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ Write Ehc Operation register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ OperationalRegAddr - Ehc Operation register address
+ Data - 32bit write to register
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+SetEhcDoorbell (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Set Ehc door bell bit
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+SetFrameListLen (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Set the length of Frame List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Length - the required length of frame list
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_INVALID_PARAMETER Invalid parameter
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+BOOLEAN
+IsFrameListProgrammable (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether frame list is programmable
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Programmable
+ FALSE Unprogrammable
+
+--*/
+;
+
+BOOLEAN
+IsPeriodicScheduleEnabled (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether periodic schedule is enabled
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Enabled
+ FALSE Disabled
+
+--*/
+;
+
+BOOLEAN
+IsAsyncScheduleEnabled (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether asynchronous schedule is enabled
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Enabled
+ FALSE Disabled
+
+--*/
+;
+
+BOOLEAN
+IsEhcPortEnabled (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PortNum
+ )
+/*++
+
+Routine Description:
+
+ Whether port is enabled
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Enabled
+ FALSE Disabled
+
+--*/
+;
+
+BOOLEAN
+IsEhcReseted (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether Ehc is halted
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Reseted
+ FALSE Unreseted
+
+--*/
+;
+
+BOOLEAN
+IsEhcHalted (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether Ehc is halted
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Halted
+ FALSE Not halted
+
+--*/
+;
+
+BOOLEAN
+IsEhcSysError (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether Ehc is system error
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE System error
+ FALSE No system error
+
+--*/
+;
+
+BOOLEAN
+IsHighSpeedDevice (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNum
+ )
+/*++
+
+Routine Description:
+
+ Whether high speed device attached
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE High speed
+ FALSE Full speed
+
+--*/
+;
+
+EFI_STATUS
+WaitForEhcReset (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ wait for Ehc reset or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForEhcHalt (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ wait for Ehc halt or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForEhcNotHalt (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ wait for Ehc not halt or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForEhcDoorbell (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for periodic schedule disable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForAsyncScheduleEnable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for Ehc asynchronous schedule enable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForAsyncScheduleDisable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for Ehc asynchronous schedule disable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForPeriodicScheduleEnable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for Ehc periodic schedule enable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+WaitForPeriodicScheduleDisable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for periodic schedule disable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+;
+
+EFI_STATUS
+GetCapabilityLen (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Get the length of capability register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+SetFrameListBaseAddr (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 FrameBuffer
+ )
+/*++
+
+Routine Description:
+
+ Set base address of frame list first entry
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ FrameBuffer - base address of first entry of frame list
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+SetAsyncListAddr (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Set address of first Async schedule Qh
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to first Qh in the Async schedule
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+SetCtrlDataStructSeg (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Set address of first Async schedule Qh
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to first Qh in the Async schedule
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+SetPortRoutingEhc (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Set Ehc port routing bit
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+EnablePeriodicSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Enable periodic schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+DisablePeriodicSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Disable periodic schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+EnableAsynchronousSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Enable asynchrounous schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+DisableAsynchronousSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Disable asynchrounous schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+StartScheduleExecution (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Start Ehc schedule execution
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+ResetEhc (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Reset Ehc
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+ClearEhcAllStatus (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Clear Ehc all status bits
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+//
+// EhciSched Functions
+//
+EFI_STATUS
+InitialPeriodicFrameList (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Initialize Periodic Schedule Frame List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Length - Frame List Length
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+DeinitialPeriodicFrameList (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Deinitialize Periodic Schedule Frame List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+CreatePollingTimer (
+ IN USB2_HC_DEV *HcDev,
+ IN EFI_EVENT_NOTIFY NotifyFunction
+ )
+/*++
+
+Routine Description:
+
+ Create Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ NotifyFunction - Timer Notify Function
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+DestoryPollingTimer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Destory Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+StartPollingTimer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Start Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+StopPollingTimer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Stop Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+CreateQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaxPacketLen,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh Structure and Pre-Initialize
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ Endpoint - Endpoint Number
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+CreateControlQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaxPacketLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh for Control Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ Translator - Translator Transaction for SplitX
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+CreateBulkQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 EndPointAddr,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 DataToggle,
+ IN UINTN MaxPacketLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh for Bulk Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ EndPointAddr - Address of Endpoint
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ Translator - Translator Transaction for SplitX
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+CreateInterruptQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 EndPointAddr,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 DataToggle,
+ IN UINTN MaxPacketLen,
+ IN UINTN Interval,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh for Control Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ EndPointAddr - Address of Endpoint
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ Interval - value of interval
+ Translator - Translator Transaction for SplitX
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+DestoryQh (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Destory Qh Structure
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+CreateQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *DataPtr,
+ IN UINTN DataLen,
+ IN UINT8 PktId,
+ IN UINT8 Toggle,
+ IN UINT8 QtdStatus,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure and Pre-Initialize it
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DataPtr - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ PktId - Packet Identification of this Qtd
+ Toggle - Data Toggle of this Qtd
+ QtdStatus - Default value of status of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+;
+
+EFI_STATUS
+CreateSetupQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *DevReqPtr,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for Setup
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DevReqPtr - A pointer to Device Request Data
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+;
+
+EFI_STATUS
+CreateDataQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *DataPtr,
+ IN UINTN DataLen,
+ IN UINT8 PktId,
+ IN UINT8 Toggle,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for data
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DataPtr - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ PktId - Packet Identification of this Qtd
+ Toggle - Data Toggle of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+;
+
+EFI_STATUS
+CreateStatusQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PktId,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for status
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ PktId - Packet Identification of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+;
+
+EFI_STATUS
+CreateAltQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PktId,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for Alternative
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ PktId - Packet Identification of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+;
+
+EFI_STATUS
+CreateControlQtds (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DataPktId,
+ IN UINT8 *RequestCursor,
+ IN UINT8 *DataCursor,
+ IN UINTN DataLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QTD_ENTITY **ControlQtdsHead
+ )
+/*++
+
+Routine Description:
+
+ Create Qtds list for Control Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DataPktId - Packet Identification of Data Qtds
+ RequestCursor - A pointer to request structure buffer to transfer
+ DataCursor - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+CreateBulkOrInterruptQtds (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PktId,
+ IN UINT8 *DataCursor,
+ IN UINTN DataLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QTD_ENTITY **QtdsHead
+ )
+/*++
+
+Routine Description:
+
+ Create Qtds list for Bulk or Interrupt Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ PktId - Packet Identification of Qtds
+ DataCursor - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ DataToggle - Data Toggle to start
+ Translator - Translator Transaction for SplitX
+ QtdsHead - A pointer of pointer to first Qtd for control tranfer for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+DestoryQtds (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QTD_ENTITY *FirstQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Destory all Qtds in the list
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ FirstQtdPtr - A pointer to first Qtd in the list
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID
+LinkQtdToQtd (
+ IN EHCI_QTD_ENTITY *PreQtdPtr,
+ IN EHCI_QTD_ENTITY *QtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qtds together
+
+Arguments:
+
+ PreQtdPtr - A pointer to pre Qtd
+ QtdPtr - A pointer to next Qtd
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID
+LinkQtdsToAltQtd (
+ IN EHCI_QTD_ENTITY *FirstQtdPtr,
+ IN EHCI_QTD_ENTITY *AltQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Link AlterQtds together
+
+Arguments:
+
+ FirstQtdPtr - A pointer to first Qtd in the list
+ AltQtdPtr - A pointer to alternative Qtd
+
+Returns:
+ VOID
+
+--*/
+;
+
+VOID
+LinkQtdToQh (
+ IN EHCI_QH_ENTITY *QhPtr,
+ IN EHCI_QTD_ENTITY *QtdEntryPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qtds list to Qh
+
+Arguments:
+
+ QhPtr - A pointer to Qh
+ QtdPtr - A pointer to first Qtd in the list
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+LinkQhToAsyncList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qh to Async Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+UnlinkQhFromAsyncList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Unlink Qh from Async Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+LinkQhToPeriodicList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qh to Periodic Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID
+UnlinkQhFromPeriodicList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr,
+ IN UINTN Interval
+ )
+/*++
+
+Routine Description:
+
+ Unlink Qh from Periodic Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+ Interval - Interval of this periodic transfer
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID
+LinkToAsyncReqeust (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
+ )
+/*++
+
+Routine Description:
+
+ Llink AsyncRequest Entry to Async Request List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ AsyncRequestPtr - A pointer to Async Request Entry
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID
+UnlinkFromAsyncReqeust (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
+ )
+/*++
+
+Routine Description:
+
+ Unlink AsyncRequest Entry from Async Request List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ AsyncRequestPtr - A pointer to Async Request Entry
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+UINTN
+GetNumberOfQtd (
+ IN EHCI_QTD_ENTITY *FirstQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Number of Qtds in the list
+
+Arguments:
+
+ FirstQtdPtr - A pointer to first Qtd in the list
+
+Returns:
+
+ Number of Qtds in the list
+
+--*/
+;
+
+UINTN
+GetNumberOfTransaction (
+ IN UINTN SizeOfData,
+ IN UINTN SizeOfTransaction
+ )
+/*++
+
+Routine Description:
+
+ Number of Transactions in one Qtd
+
+Arguments:
+
+ SizeOfData - Size of one Qtd
+ SizeOfTransaction - Size of one Transaction
+
+Returns:
+
+ Number of Transactions in this Qtd
+
+--*/
+;
+
+UINTN
+GetCapacityOfQtd (
+ IN UINT8 *BufferCursor
+ )
+/*++
+
+Routine Description:
+
+ Get Capacity of Qtd
+
+Arguments:
+
+ BufferCursor - BufferCursor of the Qtd
+
+Returns:
+
+ Capacity of Qtd
+
+--*/
+;
+
+UINTN
+GetApproxiOfInterval (
+ IN UINTN Interval
+ )
+/*++
+
+Routine Description:
+
+ Get the approximate value in the 2 index sequence
+
+Arguments:
+
+ Interval - the value of interval
+
+Returns:
+
+ approximate value of interval in the 2 index sequence
+
+--*/
+;
+
+EHCI_QTD_HW *
+GetQtdNextPointer (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Get Qtd next pointer field
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ A pointer to next hardware Qtd structure
+
+--*/
+;
+
+BOOLEAN
+IsQtdStatusActive (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is active or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Active
+ FALSE Inactive
+
+--*/
+;
+
+BOOLEAN
+IsQtdStatusHalted (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is halted or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Halted
+ FALSE Not halted
+
+--*/
+;
+
+BOOLEAN
+IsQtdStatusBufferError (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is buffer error or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Buffer error
+ FALSE No buffer error
+
+--*/
+;
+
+BOOLEAN
+IsQtdStatusBabbleError (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is babble error or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Babble error
+ FALSE No babble error
+
+--*/
+;
+
+BOOLEAN
+IsQtdStatusTransactionError (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is transaction error or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Transaction error
+ FALSE No transaction error
+
+--*/
+;
+
+BOOLEAN
+IsDataInTransfer (
+ IN UINT8 EndPointAddress
+ )
+/*++
+
+Routine Description:
+
+ Whether is a DataIn direction transfer
+
+Arguments:
+
+ EndPointAddress - address of the endpoint
+
+Returns:
+
+ TRUE DataIn
+ FALSE DataOut
+
+--*/
+;
+
+EFI_STATUS
+MapDataBuffer (
+ IN USB2_HC_DEV *HcDev,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ OUT UINT8 *PktId,
+ OUT UINT8 **DataCursor,
+ OUT VOID **DataMap
+ )
+/*++
+
+Routine Description:
+
+ Map address of user data buffer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ TransferDirection - direction of transfer
+ Data - A pointer to user data buffer
+ DataLength - length of user data
+ PktId - Packte Identificaion
+ DataCursor - mapped address to return
+ DataMap - identificaion of this mapping to return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+EFI_STATUS
+MapRequestBuffer (
+ IN USB2_HC_DEV *HcDev,
+ IN OUT VOID *Request,
+ OUT UINT8 **RequestCursor,
+ OUT VOID **RequestMap
+ )
+/*++
+
+Routine Description:
+
+ Map address of request structure buffer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Request - A pointer to request structure
+ RequestCursor - Mapped address of request structure to return
+ RequestMap - Identificaion of this mapping to return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+SetQtdBufferPointer (
+ IN EHCI_QTD_HW *QtdHwPtr,
+ IN VOID *DataPtr,
+ IN UINTN DataLen
+ )
+/*++
+
+Routine Description:
+
+ Set data buffer pointers in Qtd
+
+Arguments:
+
+ QtdHwPtr - A pointer to Qtd hardware structure
+ DataPtr - A pointer to user data buffer
+ DataLen - Length of the user data buffer
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+EHCI_QTD_HW *
+GetQtdAlternateNextPointer (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Get Qtd alternate next pointer field
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ A pointer to hardware alternate Qtd
+
+--*/
+;
+
+VOID
+ZeroOutQhOverlay (
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Zero out the fields in Qh structure
+
+Arguments:
+
+ QhPtr - A pointer to Qh structure
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID
+UpdateAsyncRequestTransfer (
+ IN EHCI_ASYNC_REQUEST *AsyncRequestPtr,
+ IN UINT32 TransferResult,
+ IN UINTN ErrTDPos
+ )
+/*++
+
+Routine Description:
+
+ Update asynchronous request transfer
+
+Arguments:
+
+ AsyncRequestPtr - A pointer to async request
+ TransferResult - transfer result
+ ErrQtdPos - postion of error Qtd
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+
+EFI_STATUS
+DeleteAsyncRequestTransfer (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ OUT UINT8 *DataToggle
+ )
+/*++
+
+Routine Description:
+
+ Delete all asynchronous request transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddress - address of usb device
+ EndPointAddress - address of endpoint
+ DataToggle - stored data toggle
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+VOID
+CleanUpAllAsyncRequestTransfer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Clean up all asynchronous request transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+ExecuteTransfer (
+ IN USB2_HC_DEV *HcDev,
+ IN BOOLEAN IsControl,
+ IN EHCI_QH_ENTITY *QhPtr,
+ IN OUT UINTN *ActualLen,
+ OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+Routine Description:
+
+ Execute Bulk or SyncInterrupt Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ IsControl - Is control transfer or not
+ QhPtr - A pointer to Qh
+ ActualLen - Actual transfered Len
+ DataToggle - Data Toggle
+ TimeOut - TimeOut threshold
+ TransferResult - Transfer result
+
+Returns:
+
+ EFI_SUCCESS Sucess
+ EFI_DEVICE_ERROR Error
+
+--*/
+;
+
+BOOLEAN
+CheckQtdsTransferResult (
+ IN BOOLEAN IsControl,
+ IN EHCI_QH_ENTITY *QhPtr,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrQtdPos,
+ OUT UINTN *ActualLen
+ )
+/*++
+
+Routine Description:
+
+ Check transfer result of Qtds
+
+Arguments:
+
+ IsControl - Is control transfer or not
+ QhPtr - A pointer to Qh
+ Result - Transfer result
+ ErrQtdPos - Error TD Position
+ ActualLen - Actual Transfer Size
+
+Returns:
+
+ TRUE Qtds finished
+ FALSE Not finish
+
+--*/
+;
+
+EFI_STATUS
+AsyncRequestMoniter (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Interrupt transfer periodic check handler
+
+Arguments:
+
+ Event - Interrupt event
+ Context - Pointer to USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa
new file mode 100644
index 0000000000..a44b5a4a75
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0">
+ <MsaHeader>
+ <ModuleName>Ehci</ModuleName>
+ <ModuleType>UEFI_DRIVER</ModuleType>
+ <GuidValue>BDFE430E-8F2A-4db0-9991-6F856594777E</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for Ehci module</Abstract>
+ <Description>This module provides USB2 Host Controller Protocol implementation for Enhanced Host Controller Interface</Description>
+ <Copyright>Copyright (c) 2006, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>Ehci</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverModelLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Ehci.c</Filename>
+ <Filename>EhciMem.c</Filename>
+ <Filename>EhciReg.c</Filename>
+ <Filename>EhciSched.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>Ehci.h</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiUsb2HcProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <DriverBinding>gEhciDriverBinding</DriverBinding>
+ </Extern>
+ <Extern>
+ <ComponentName>gEhciComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c
new file mode 100644
index 0000000000..2f35f77848
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c
@@ -0,0 +1,761 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EhciMem.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "Ehci.h"
+
+
+EFI_STATUS
+CreateMemoryBlock (
+ IN USB2_HC_DEV *HcDev,
+ OUT MEMORY_MANAGE_HEADER **MemoryHeader,
+ IN UINTN MemoryBlockSizeInPages
+ )
+/*++
+
+Routine Description:
+
+ Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
+ and use PciIo->Map to map the common buffer for Bus Master Read/Write.
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ MemoryHeader - MEMORY_MANAGE_HEADER to output
+ MemoryBlockSizeInPages - MemoryBlockSizeInPages
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Fail for no resources
+ EFI_UNSUPPORTED Unsupported currently
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *CommonBuffer;
+ EFI_PHYSICAL_ADDRESS MappedAddress;
+ UINTN MemoryBlockSizeInBytes;
+ VOID *Mapping;
+
+ //
+ // Allocate memory for MemoryHeader
+ //
+ *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));
+ if (*MemoryHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (*MemoryHeader)->Next = NULL;
+
+ //
+ // set Memory block size
+ //
+ (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
+
+ //
+ // each bit in Bit Array will manage 32 bytes memory in memory block
+ //
+ (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8;
+
+ //
+ // Allocate memory for BitArray
+ //
+ (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);
+ if ((*MemoryHeader)->BitArrayPtr == NULL) {
+ gBS->FreePool (*MemoryHeader);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Memory Block uses MemoryBlockSizeInPages pages,
+ // and it is allocated as common buffer use.
+ //
+ Status = HcDev->PciIo->AllocateBuffer (
+ HcDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ MemoryBlockSizeInPages,
+ &CommonBuffer,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
+ gBS->FreePool (*MemoryHeader);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ CommonBuffer,
+ &MemoryBlockSizeInBytes,
+ &MappedAddress,
+ &Mapping
+ );
+ //
+ // If returned Mapped size is less than the size
+ // we request,do not support.
+ //
+ if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {
+ HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);
+ gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
+ gBS->FreePool (*MemoryHeader);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Data structure involved by host controller
+ // should be restricted into the same 4G
+ //
+ if (HcDev->Is64BitCapable != 0) {
+ if (HcDev->High32BitAddr != GET_32B_TO_63B (MappedAddress)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);
+ gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
+ gBS->FreePool (*MemoryHeader);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Set Memory block initial address
+ //
+ (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);
+ (*MemoryHeader)->Mapping = Mapping;
+
+ ZeroMem (
+ (*MemoryHeader)->MemoryBlockPtr,
+ EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreeMemoryHeader (
+ IN USB2_HC_DEV *HcDev,
+ IN MEMORY_MANAGE_HEADER *MemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Free Memory Header
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ MemoryHeader - MemoryHeader to be freed
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_INVALID_PARAMETER Parameter is error
+
+--*/
+{
+ if ((MemoryHeader == NULL) || (HcDev == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // unmap the common buffer used by the memory block
+ //
+ HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);
+
+ //
+ // free common buffer
+ //
+ HcDev->PciIo->FreeBuffer (
+ HcDev->PciIo,
+ EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),
+ MemoryHeader->MemoryBlockPtr
+ );
+ //
+ // free bit array
+ //
+ gBS->FreePool (MemoryHeader->BitArrayPtr);
+ //
+ // free memory header
+ //
+ gBS->FreePool (MemoryHeader);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciAllocatePool (
+ IN USB2_HC_DEV *HcDev,
+ OUT UINT8 **Pool,
+ IN UINTN AllocSize
+ )
+/*++
+
+Routine Description:
+
+ Ehci Allocate Pool
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Pool - Place to store pointer to the memory buffer
+ AllocSize - Alloc Size
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+ MEMORY_MANAGE_HEADER *NewMemoryHeader;
+ UINTN RealAllocSize;
+ UINTN MemoryBlockSizeInPages;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ *Pool = NULL;
+
+ MemoryHeader = HcDev->MemoryHeader;
+ ASSERT (MemoryHeader != NULL);
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
+
+ //
+ // allocate unit is 32 bytes (align on 32 byte)
+ //
+ if (AllocSize & 0x1F) {
+ RealAllocSize = (AllocSize / 32 + 1) * 32;
+ } else {
+ RealAllocSize = AllocSize;
+ }
+
+ //
+ // There may be linked MemoryHeaders.
+ // To allocate a free pool in Memory blocks,
+ // must search in the MemoryHeader link list
+ // until enough free pool is found.
+ //
+ Status = EFI_NOT_FOUND;
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
+
+ Status = AllocMemInMemoryBlock (
+ TempHeaderPtr,
+ Pool,
+ RealAllocSize / 32
+ );
+ if (!EFI_ERROR (Status)) {
+ ZeroMem (*Pool, AllocSize);
+ gBS->RestoreTPL (OldTpl);
+ return EFI_SUCCESS;
+ }
+ }
+
+ gBS->RestoreTPL (OldTpl);
+
+ //
+ // There is no enough memory,
+ // Create a new Memory Block
+ //
+
+ //
+ // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,
+ // just allocate a large enough memory block.
+ //
+ if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {
+ MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;
+ } else {
+ MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
+ }
+
+ Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
+
+ //
+ // Link the new Memory Block to the Memory Header list
+ //
+ InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);
+
+ Status = AllocMemInMemoryBlock (
+ NewMemoryHeader,
+ Pool,
+ RealAllocSize / 32
+ );
+ if (!EFI_ERROR (Status)) {
+ ZeroMem (*Pool, AllocSize);
+ }
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+VOID
+EhciFreePool (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *Pool,
+ IN UINTN AllocSize
+ )
+/*++
+
+Routine Description:
+
+ Uhci Free Pool
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ Pool - Pool to free
+ AllocSize - Pool size
+
+Returns:
+
+ VOID
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+ UINTN StartBytePos;
+ UINTN Index;
+ UINT8 StartBitPos;
+ UINT8 Index2;
+ UINTN Count;
+ UINTN RealAllocSize;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
+
+ MemoryHeader = HcDev->MemoryHeader;
+
+ //
+ // allocate unit is 32 byte (align on 32 byte)
+ //
+ if (AllocSize & 0x1F) {
+ RealAllocSize = (AllocSize / 32 + 1) * 32;
+ } else {
+ RealAllocSize = AllocSize;
+ }
+
+ //
+ // scan the memory header linked list for
+ // the asigned memory to free.
+ //
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
+
+ if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&
+ ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))
+ ) {
+ //
+ // Pool is in the Memory Block area,
+ // find the start byte and bit in the bit array
+ //
+ StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8;
+ StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7);
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {
+ TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2));
+ Index2++;
+ if (Index2 == 8) {
+ Index += 1;
+ Index2 = 0;
+ }
+ }
+ //
+ // break the loop
+ //
+ break;
+ }
+ }
+
+ //
+ // Release emptied memory blocks (only if the memory block is not
+ // the first one in the memory header list
+ //
+ for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {
+
+ ASSERT (MemoryHeader->Next != NULL);
+
+ if (IsMemoryBlockEmptied (TempHeaderPtr)) {
+
+ DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);
+ //
+ // when the TempHeaderPtr is freed in FreeMemoryHeader(),
+ // the TempHeaderPtr is pointing to nonsense content.
+ //
+ gBS->RestoreTPL (OldTpl);
+ FreeMemoryHeader (HcDev, TempHeaderPtr);
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
+ //
+ // reset the TempHeaderPtr, continue search for
+ // another empty memory block.
+ //
+ TempHeaderPtr = MemoryHeader->Next;
+ continue;
+ }
+
+ TempHeaderPtr = TempHeaderPtr->Next;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+}
+
+VOID
+InsertMemoryHeaderToList (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NewMemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Insert Memory Header To List
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ NewMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
+ if (TempHeaderPtr->Next == NULL) {
+ TempHeaderPtr->Next = NewMemoryHeader;
+ break;
+ }
+ }
+}
+
+EFI_STATUS
+AllocMemInMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ OUT VOID **Pool,
+ IN UINTN NumberOfMemoryUnit
+ )
+/*++
+
+Routine Description:
+
+ Alloc Memory In MemoryBlock
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ Pool - Place to store pointer to memory
+ NumberOfMemoryUnit - Number Of Memory Unit
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_NOT_FOUND Can't find the free memory
+
+--*/
+{
+ UINTN TempBytePos;
+ UINTN FoundBytePos;
+ UINT8 Index;
+ UINT8 FoundBitPos;
+ UINT8 ByteValue;
+ UINT8 BitValue;
+ UINTN NumberOfZeros;
+ UINTN Count;
+
+ FoundBytePos = 0;
+ FoundBitPos = 0;
+ ByteValue = MemoryHeader->BitArrayPtr[0];
+ NumberOfZeros = 0;
+ Index = 0;
+
+ for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {
+
+ //
+ // Pop out BitValue from a byte in TempBytePos.
+ //
+ BitValue = (UINT8) (ByteValue & 0x1);
+
+ //
+ // right shift the byte
+ //
+ ByteValue /= 2;
+
+ if (BitValue == 0) {
+ //
+ // Found a free bit, the NumberOfZeros only record the number
+ // of those consecutive zeros
+ //
+ NumberOfZeros++;
+ //
+ // Found enough consecutive free space, break the loop
+ //
+ if (NumberOfZeros >= NumberOfMemoryUnit) {
+ break;
+ }
+ } else {
+ //
+ // Encountering a '1', meant the bit is ocupied.
+ //
+ if (NumberOfZeros >= NumberOfMemoryUnit) {
+ //
+ // Found enough consecutive free space,break the loop
+ //
+ break;
+ } else {
+ //
+ // the NumberOfZeros only record the number of those consecutive zeros,
+ // so reset the NumberOfZeros to 0 when encountering '1' before finding
+ // enough consecutive '0's
+ //
+ NumberOfZeros = 0;
+ //
+ // reset the (FoundBytePos,FoundBitPos) to the position of '1'
+ //
+ FoundBytePos = TempBytePos;
+ FoundBitPos = Index;
+ }
+ }
+
+ //
+ // step forward a bit
+ //
+ Index++;
+ if (Index == 8) {
+ //
+ // step forward a byte, getting the byte value,
+ // and reset the bit pos.
+ //
+ TempBytePos += 1;
+ ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];
+ Index = 0;
+ }
+ }
+
+ if (NumberOfZeros < NumberOfMemoryUnit) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Found enough free space.
+ //
+
+ //
+ // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:
+ // 1)(FoundBytePos,FoundBitPos) record the position
+ // of the last '1' before the consecutive '0's, it must
+ // be adjusted to the start position of the consecutive '0's.
+ // 2)the start address of the consecutive '0's is just the start of
+ // the bitarray. so no need to adjust the values of
+ // (FoundBytePos,FoundBitPos).
+ //
+ if ((MemoryHeader->BitArrayPtr[FoundBytePos] & bit (FoundBitPos)) != 0) {
+ FoundBitPos += 1;
+ }
+
+ //
+ // Have the (FoundBytePos,FoundBitPos) make sense.
+ //
+ if (FoundBitPos > 7) {
+ FoundBytePos += 1;
+ FoundBitPos -= 8;
+ }
+
+ //
+ // Set the memory as allocated
+ //
+ for (TempBytePos = FoundBytePos, Index = FoundBitPos, Count = 0; Count < NumberOfMemoryUnit; Count++) {
+
+ MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);
+ Index++;
+ if (Index == 8) {
+ TempBytePos += 1;
+ Index = 0;
+ }
+ }
+
+ *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsMemoryBlockEmptied (
+ IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr
+ )
+/*++
+
+Routine Description:
+
+ Is Memory Block Emptied
+
+Arguments:
+
+ MemoryHeaderPtr - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ TRUE Empty
+ FALSE Not Empty
+
+--*/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {
+ if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+VOID
+DelinkMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Delink Memory Block
+
+Arguments:
+
+ FirstMemoryHeader - MEMORY_MANAGE_HEADER
+ NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {
+ return ;
+ }
+
+ for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
+
+ if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {
+ //
+ // Link the before and after
+ //
+ TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;
+ break;
+ }
+ }
+}
+
+EFI_STATUS
+InitialMemoryManagement (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Initialize Memory Management
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ UINTN MemPages;
+
+ MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
+ Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ HcDev->MemoryHeader = MemoryHeader;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+DeinitialMemoryManagement (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Deinitialize Memory Management
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {
+
+ DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);
+ //
+ // when the TempHeaderPtr is freed in FreeMemoryHeader(),
+ // the TempHeaderPtr is pointing to nonsense content.
+ //
+ FreeMemoryHeader (HcDev, TempHeaderPtr);
+ //
+ // reset the TempHeaderPtr,continue free another memory block.
+ //
+ TempHeaderPtr = HcDev->MemoryHeader->Next;
+ }
+
+ FreeMemoryHeader (HcDev, HcDev->MemoryHeader);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c
new file mode 100644
index 0000000000..9ce816ecc9
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c
@@ -0,0 +1,1539 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Ehchlp.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "Ehci.h"
+
+
+EFI_STATUS
+ReadEhcCapabiltiyReg (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 CapabiltiyRegAddr,
+ IN OUT UINT32 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read Ehc Capabitlity register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ CapabiltiyRegAddr - Ehc Capability register address
+ Data - A pointer to data read from register
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ return HcDev->PciIo->Mem.Read (
+ HcDev->PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) CapabiltiyRegAddr,
+ 1,
+ Data
+ );
+}
+
+EFI_STATUS
+ReadEhcOperationalReg (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 OperationalRegAddr,
+ IN OUT UINT32 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read Ehc Operation register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ OperationalRegAddr - Ehc Operation register address
+ Data - A pointer to data read from register
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ ASSERT (mUsbCapabilityLen);
+ return HcDev->PciIo->Mem.Read (
+ HcDev->PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) (OperationalRegAddr + mUsbCapabilityLen),
+ 1,
+ Data
+ );
+}
+
+EFI_STATUS
+WriteEhcOperationalReg (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 OperationalRegAddr,
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ Write Ehc Operation register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ OperationalRegAddr - Ehc Operation register address
+ Data - 32bit write to register
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ ASSERT (mUsbCapabilityLen);
+ return HcDev->PciIo->Mem.Write (
+ HcDev->PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) (OperationalRegAddr + mUsbCapabilityLen),
+ 1,
+ &Data
+ );
+}
+
+EFI_STATUS
+GetCapabilityLen (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Get the length of capability register
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 CapabilityLenAddr;
+
+ CapabilityLenAddr = CAPLENGTH;
+
+ Status = ReadEhcCapabiltiyReg (
+ HcDev,
+ CapabilityLenAddr,
+ &mUsbCapabilityLen
+ );
+ mUsbCapabilityLen = (UINT8) mUsbCapabilityLen;
+
+ return Status;
+}
+
+EFI_STATUS
+SetFrameListLen (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Set the length of Frame List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Length - the required length of frame list
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_INVALID_PARAMETER Invalid parameter
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ if (256 != Length && 512 != Length) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ if (256 == Length) {
+ UsbCommandReg |= USBCMD_FLS_256;
+ } else {
+ UsbCommandReg |= USBCMD_FLS_512;
+ }
+
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+SetFrameListBaseAddr (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT32 FrameBuffer
+ )
+/*++
+
+Routine Description:
+
+ Set base address of frame list first entry
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ FrameBuffer - base address of first entry of frame list
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 PeriodicListBaseAddr;
+ UINT32 PeriodicListBaseReg;
+
+ Status = EFI_SUCCESS;
+ PeriodicListBaseAddr = PERIODICLISTBASE;
+ PeriodicListBaseReg = FrameBuffer & 0xfffff000;
+
+ if (IsEhcHalted (HcDev)) {
+
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ PeriodicListBaseAddr,
+ PeriodicListBaseReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+SetAsyncListAddr (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Set address of first Async schedule Qh
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to first Qh in the Async schedule
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 AsyncListAddr;
+ UINT32 AsyncListReg;
+
+ AsyncListAddr = ASYNCLISTADDR;
+ AsyncListReg = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh));
+
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ AsyncListAddr,
+ AsyncListReg
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+SetCtrlDataStructSeg (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Set register of control and data structure segment
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 CtrlDsSegmentAddr;
+ UINT32 CtrlDsSegmentReg;
+
+ CtrlDsSegmentAddr = CTRLDSSGMENT;
+ CtrlDsSegmentReg = HcDev->High32BitAddr;
+
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ CtrlDsSegmentAddr,
+ CtrlDsSegmentReg
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+SetPortRoutingEhc (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Set Ehc port routing bit
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 ConfigFlagAddr;
+ UINT32 ConfigFlagReg;
+
+ ConfigFlagAddr = CONFIGFLAG;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ ConfigFlagAddr,
+ &ConfigFlagReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ ConfigFlagReg |= CONFIGFLAG_CF;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ ConfigFlagAddr,
+ ConfigFlagReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+SetEhcDoorbell (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Set Ehc door bell bit
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ UsbCommandReg |= USBCMD_IAAD;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+ClearEhcAllStatus (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Clear Ehc all status bits
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ UINT32 UsbStatusAddr;
+
+ UsbStatusAddr = USBSTS;
+
+ return WriteEhcOperationalReg (
+ HcDev,
+ UsbStatusAddr,
+ 0x003F
+ );
+}
+
+EFI_STATUS
+EnablePeriodicSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Enable periodic schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ UsbCommandReg |= USBCMD_PSE;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+DisablePeriodicSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Disable periodic schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbCommandReg &= ~USBCMD_PSE;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EnableAsynchronousSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Enable asynchrounous schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ UsbCommandReg |= USBCMD_ASE;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+DisableAsynchronousSchedule (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Disable asynchrounous schedule
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbCommandReg &= ~USBCMD_ASE;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+ResetEhc (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Reset Ehc
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ UsbCommandReg |= USBCMD_HCRESET;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+StartScheduleExecution (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Start Ehc schedule execution
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ UsbCommandReg |= USBCMD_RS;
+ Status = WriteEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+BOOLEAN
+IsFrameListProgrammable (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether frame list is programmable
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Programmable
+ FALSE Unprogrammable
+
+--*/
+{
+ BOOLEAN Value;
+ UINT32 HcCapParamsAddr;
+ UINT32 HcCapParamsReg;
+
+ HcCapParamsAddr = HCCPARAMS;
+
+ ReadEhcOperationalReg (
+ HcDev,
+ HcCapParamsAddr,
+ &HcCapParamsReg
+ );
+
+ if (HcCapParamsReg & HCCP_PFLF) {
+ Value = TRUE;
+ } else {
+ Value = FALSE;
+ }
+
+ return Value;
+}
+
+BOOLEAN
+IsPeriodicScheduleEnabled (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether periodic schedule is enabled
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Enabled
+ FALSE Disabled
+
+--*/
+{
+ BOOLEAN Value;
+ UINT32 UsbStatusAddr;
+ UINT32 UsbStatusReg;
+
+ UsbStatusAddr = USBSTS;
+
+ ReadEhcOperationalReg (
+ HcDev,
+ UsbStatusAddr,
+ &UsbStatusReg
+ );
+
+ if (UsbStatusReg & USBSTS_PSS) {
+ Value = TRUE;
+ } else {
+ Value = FALSE;
+ }
+
+ return Value;
+}
+
+BOOLEAN
+IsAsyncScheduleEnabled (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether asynchronous schedule is enabled
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Enabled
+ FALSE Disabled
+
+--*/
+{
+ BOOLEAN Value;
+ UINT32 UsbStatusAddr;
+ UINT32 UsbStatusReg;
+
+ UsbStatusAddr = USBSTS;
+
+ ReadEhcOperationalReg (
+ HcDev,
+ UsbStatusAddr,
+ &UsbStatusReg
+ );
+
+ if (UsbStatusReg & USBSTS_ASS) {
+ Value = TRUE;
+ } else {
+ Value = FALSE;
+ }
+
+ return Value;
+}
+
+BOOLEAN
+IsEhcPortEnabled (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PortNum
+ )
+/*++
+
+Routine Description:
+
+ Whether port is enabled
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Enabled
+ FALSE Disabled
+
+--*/
+{
+ UINT32 PortStatusControlAddr;
+ UINT32 PortStatusControlReg;
+
+ PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));
+
+ ReadEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ &PortStatusControlReg
+ );
+
+ return ((PortStatusControlReg & PORTSC_PED) ? TRUE : FALSE);
+}
+
+BOOLEAN
+IsEhcReseted (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether Ehc is reseted
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Reseted
+ FALSE Unreseted
+
+--*/
+{
+ BOOLEAN Value;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+
+ UsbCommandAddr = USBCMD;
+
+ ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+
+ if (UsbCommandReg & USBCMD_HCRESET) {
+ Value = FALSE;
+ } else {
+ Value = TRUE;
+ }
+
+ return Value;
+}
+
+BOOLEAN
+IsEhcHalted (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether Ehc is halted
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE Halted
+ FALSE Not halted
+
+--*/
+{
+ BOOLEAN Value;
+ UINT32 UsbStatusAddr;
+ UINT32 UsbStatusReg;
+
+ UsbStatusAddr = USBSTS;
+
+ ReadEhcOperationalReg (
+ HcDev,
+ UsbStatusAddr,
+ &UsbStatusReg
+ );
+
+ if (UsbStatusReg & USBSTS_HCH) {
+ Value = TRUE;
+ } else {
+ Value = FALSE;
+ }
+
+ return Value;
+}
+
+BOOLEAN
+IsEhcSysError (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Whether Ehc is system error
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE System error
+ FALSE No system error
+
+--*/
+{
+ BOOLEAN Value;
+ UINT32 UsbStatusAddr;
+ UINT32 UsbStatusReg;
+
+ UsbStatusAddr = USBSTS;
+
+ ReadEhcOperationalReg (
+ HcDev,
+ UsbStatusAddr,
+ &UsbStatusReg
+ );
+
+ if (UsbStatusReg & USBSTS_HSE) {
+ Value = TRUE;
+ } else {
+ Value = FALSE;
+ }
+
+ return Value;
+}
+
+BOOLEAN
+IsHighSpeedDevice (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNum
+ )
+/*++
+
+Routine Description:
+
+ Whether high speed device attached
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ TRUE High speed
+ FALSE Full speed
+
+--*/
+{
+ USB2_HC_DEV *HcDev;
+ UINT32 PortStatusControlAddr;
+ UINT32 PortStatusControlReg;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));
+
+ //
+ // Set port reset bit
+ //
+ ReadEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ &PortStatusControlReg
+ );
+ //
+ // Make sure Host Controller not halt before reset it
+ //
+ if (IsEhcHalted (HcDev)) {
+ StartScheduleExecution (HcDev);
+ WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);
+ }
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg |= PORTSC_PR;
+ //
+ // Set one to PortReset bit must also set zero to PortEnable bit
+ //
+ PortStatusControlReg &= ~PORTSC_PED;
+ WriteEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ PortStatusControlReg
+ );
+
+ //
+ // Set Port reset recovery time
+ //
+ gBS->Stall (EHCI_SET_PORT_RESET_RECOVERY_TIME);
+
+ //
+ // Clear port reset bit
+ //
+ ReadEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ &PortStatusControlReg
+ );
+ PortStatusControlReg &= 0xffffffd5;
+ PortStatusControlReg &= ~PORTSC_PR;
+ WriteEhcOperationalReg (
+ HcDev,
+ PortStatusControlAddr,
+ PortStatusControlReg
+ );
+
+ //
+ // Clear port reset recovery time
+ //
+ gBS->Stall (EHCI_CLEAR_PORT_RESET_RECOVERY_TIME);
+
+ return (IsEhcPortEnabled (HcDev, PortNum) ? TRUE : FALSE);
+}
+
+EFI_STATUS
+WaitForEhcReset (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ wait for Ehc reset or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (IsEhcReseted (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForEhcHalt (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ wait for Ehc halt or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (IsEhcHalted (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForEhcNotHalt (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ wait for Ehc not halt or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (!IsEhcHalted (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForAsyncScheduleEnable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for Ehc asynchronous schedule enable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (IsAsyncScheduleEnabled (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForAsyncScheduleDisable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for Ehc asynchronous schedule disable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (!IsAsyncScheduleEnabled (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForPeriodicScheduleEnable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for Ehc periodic schedule enable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (IsPeriodicScheduleEnabled (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForPeriodicScheduleDisable (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for periodic schedule disable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+
+ //
+ // Timeout is in US unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+
+ if (!IsPeriodicScheduleEnabled (HcDev)) {
+ Status = EFI_SUCCESS;
+ goto exit;
+ }
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
+
+ } while (Delay--);
+
+ Status = EFI_TIMEOUT;
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+WaitForEhcDoorbell (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait for periodic schedule disable or timeout
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Timeout - timeout threshold
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_TIMEOUT Timeout
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 UsbCommandAddr;
+ UINT32 UsbCommandReg;
+ UINTN Delay;
+
+ UsbCommandAddr = USBCMD;
+ Delay = (Timeout / 50) + 1;
+
+ do {
+ Status = ReadEhcOperationalReg (
+ HcDev,
+ UsbCommandAddr,
+ &UsbCommandReg
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ if (!(UsbCommandReg & USBCMD_IAAD)) {
+ break;
+ }
+
+ } while (--Delay);
+
+ if (0 == Delay) {
+ Status = EFI_TIMEOUT;
+ }
+
+exit:
+ return Status;
+}
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c
new file mode 100644
index 0000000000..3dc1ff74af
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c
@@ -0,0 +1,3072 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EhciSched.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "Ehci.h"
+
+EFI_STATUS
+InitialPeriodicFrameList (
+ IN USB2_HC_DEV *HcDev,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Initialize Periodic Schedule Frame List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Length - Frame List Length
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *CommonBuffer;
+ EFI_PHYSICAL_ADDRESS FrameBuffer;
+ VOID *Map;
+ UINTN BufferSizeInPages;
+ UINTN BufferSizeInBytes;
+ UINTN FrameIndex;
+ FRAME_LIST_ENTRY *FrameEntryPtr;
+
+ //
+ // The Frame List is a common buffer that will be
+ // accessed by both the cpu and the usb bus master
+ // at the same time.
+ // The Frame List ocupies 4K bytes,
+ // and must be aligned on 4-Kbyte boundaries.
+ //
+ if (EHCI_MAX_FRAME_LIST_LENGTH != Length && IsFrameListProgrammable (HcDev)) {
+ Status = SetFrameListLen (HcDev, Length);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+
+ BufferSizeInBytes = EFI_PAGE_SIZE;
+ BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);
+ Status = HcDev->PciIo->AllocateBuffer (
+ HcDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ BufferSizeInPages,
+ &CommonBuffer,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCErrorLevel, "PciIo->AllocateBuffer Failed\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ CommonBuffer,
+ &BufferSizeInBytes,
+ &FrameBuffer,
+ &Map
+ );
+ if (EFI_ERROR (Status) || (BufferSizeInBytes != EFI_PAGE_SIZE)) {
+ DEBUG ((gEHCErrorLevel, "PciIo->MapBuffer Failed\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto free_buffer;
+ }
+
+ //
+ // Put high 32bit into CtrlDataStructSeg reg
+ // when 64bit addressing range capability
+ //
+ if (HcDev->Is64BitCapable != 0) {
+ HcDev->High32BitAddr = (UINT32) GET_32B_TO_63B (FrameBuffer);
+
+ Status = SetCtrlDataStructSeg (HcDev);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCErrorLevel, "SetCtrlDataStructSeg Failed\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto unmap_buffer;
+ }
+ }
+
+ //
+ // Tell the Host Controller where the Frame List lies,
+ // by set the Frame List Base Address Register.
+ //
+ Status = SetFrameListBaseAddr (HcDev, (UINT32) FrameBuffer);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto unmap_buffer;
+ }
+
+ HcDev->PeriodicFrameListLength = Length;
+ HcDev->PeriodicFrameListBuffer = (VOID *) ((UINTN) FrameBuffer);
+ HcDev->PeriodicFrameListMap = Map;
+
+ //
+ // Init Frame List Array fields
+ //
+ FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
+ for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {
+ FrameEntryPtr->LinkPointer = 0;
+ FrameEntryPtr->Rsvd = 0;
+ FrameEntryPtr->SelectType = 0;
+ FrameEntryPtr->LinkTerminate = TRUE;
+ FrameEntryPtr++;
+ }
+
+ goto exit;
+
+unmap_buffer:
+ HcDev->PciIo->Unmap (HcDev->PciIo, Map);
+free_buffer:
+ HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);
+exit:
+ return Status;
+}
+
+VOID
+DeinitialPeriodicFrameList (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Deinitialize Periodic Schedule Frame List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ VOID
+
+--*/
+{
+ HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->PeriodicFrameListMap);
+ HcDev->PciIo->FreeBuffer (HcDev->PciIo, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE), HcDev->PeriodicFrameListBuffer);
+ return ;
+}
+
+EFI_STATUS
+CreatePollingTimer (
+ IN USB2_HC_DEV *HcDev,
+ IN EFI_EVENT_NOTIFY NotifyFunction
+ )
+/*++
+
+Routine Description:
+
+ Create Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ NotifyFunction - Timer Notify Function
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ return gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_NOTIFY,
+ NotifyFunction,
+ HcDev,
+ &HcDev->AsyncRequestEvent
+ );
+}
+
+EFI_STATUS
+DestoryPollingTimer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Destory Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ return gBS->CloseEvent (HcDev->AsyncRequestEvent);
+}
+
+EFI_STATUS
+StartPollingTimer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Start Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ return gBS->SetTimer (
+ HcDev->AsyncRequestEvent,
+ TimerPeriodic,
+ EHCI_ASYNC_REQUEST_POLLING_TIME
+ );
+}
+
+EFI_STATUS
+StopPollingTimer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Stop Async Request Polling Timer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ return gBS->SetTimer (
+ HcDev->AsyncRequestEvent,
+ TimerCancel,
+ EHCI_ASYNC_REQUEST_POLLING_TIME
+ );
+}
+
+EFI_STATUS
+CreateQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaxPacketLen,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh Structure and Pre-Initialize
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ Endpoint - Endpoint Number
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+ EHCI_QH_HW *QhHwPtr;
+
+ ASSERT (HcDev);
+ ASSERT (QhPtrPtr);
+
+ *QhPtrPtr = NULL;
+
+ //
+ // Allocate memory for Qh structure
+ //
+ Status = EhciAllocatePool (
+ HcDev,
+ (UINT8 **) QhPtrPtr,
+ sizeof (EHCI_QH_ENTITY)
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+ //
+ // Init fields in Qh
+ //
+ gBS->SetMem (*QhPtrPtr, sizeof (EHCI_QH_ENTITY), 0);
+
+ //
+ // Software field
+ //
+ (*QhPtrPtr)->Next = NULL;
+ (*QhPtrPtr)->Prev = NULL;
+ (*QhPtrPtr)->FirstQtdPtr = NULL;
+ (*QhPtrPtr)->AltQtdPtr = NULL;
+ (*QhPtrPtr)->LastQtdPtr = NULL;
+
+ //
+ // Hardware field
+ //
+ QhHwPtr = &((*QhPtrPtr)->Qh);
+ QhHwPtr->QhHorizontalPointer = 0;
+ QhHwPtr->SelectType = 0;
+ QhHwPtr->MaxPacketLen = (UINT32) MaxPacketLen;
+ QhHwPtr->EndpointSpeed = (DeviceSpeed & 0x3);
+ QhHwPtr->EndpointNum = (Endpoint & 0x0f);
+ QhHwPtr->DeviceAddr = (DeviceAddr & 0x7f);
+ QhHwPtr->Multiplier = HIGH_BANDWIDTH_PIPE_MULTIPLIER;
+ QhHwPtr->Rsvd1 = 0;
+ QhHwPtr->Rsvd2 = 0;
+ QhHwPtr->Rsvd3 = 0;
+ QhHwPtr->Rsvd4 = 0;
+ QhHwPtr->Rsvd5 = 0;
+ QhHwPtr->Rsvd6 = 0;
+
+exit:
+ return Status;
+}
+
+VOID
+DestoryQh (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Destory Qh Structure
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ ASSERT (HcDev);
+ ASSERT (QhPtr);
+
+ EhciFreePool (HcDev, (UINT8 *) QhPtr, sizeof (EHCI_QH_ENTITY));
+ return ;
+}
+
+EFI_STATUS
+CreateControlQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaxPacketLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh for Control Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ Translator - Translator Transaction for SplitX
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Create and init Control Qh
+ //
+ Status = CreateQh (
+ HcDev,
+ DeviceAddr,
+ 0,
+ DeviceSpeed,
+ MaxPacketLen,
+ QhPtrPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+ //
+ // Software field
+ //
+ (*QhPtrPtr)->Next = (*QhPtrPtr);
+ (*QhPtrPtr)->Prev = (*QhPtrPtr);
+ (*QhPtrPtr)->TransferType = CONTROL_TRANSFER;
+
+ //
+ // Hardware field
+ //
+ // Control Transfer use DataToggleControl
+ //
+ (*QhPtrPtr)->Qh.DataToggleControl = TRUE;
+ (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);
+ (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE;
+ (*QhPtrPtr)->Qh.QhTerminate = FALSE;
+ (*QhPtrPtr)->Qh.ControlEndpointFlag = TRUE;
+ (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD;
+ if (NULL != Translator) {
+ (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
+ (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
+ (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+CreateBulkQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 EndPointAddr,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 DataToggle,
+ IN UINTN MaxPacketLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh for Bulk Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ EndPointAddr - Address of Endpoint
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ Translator - Translator Transaction for SplitX
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Create and init Bulk Qh
+ //
+ Status = CreateQh (
+ HcDev,
+ DeviceAddr,
+ EndPointAddr,
+ DeviceSpeed,
+ MaxPacketLen,
+ QhPtrPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ //
+ // Software fields
+ //
+ (*QhPtrPtr)->Next = (*QhPtrPtr);
+ (*QhPtrPtr)->Prev = (*QhPtrPtr);
+ (*QhPtrPtr)->TransferType = BULK_TRANSFER;
+
+ //
+ // Hardware fields
+ //
+ // BulkTransfer don't use DataToggleControl
+ //
+ (*QhPtrPtr)->Qh.DataToggleControl = FALSE;
+ (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);
+ (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE;
+ (*QhPtrPtr)->Qh.QhTerminate = FALSE;
+ (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD;
+ (*QhPtrPtr)->Qh.DataToggle = DataToggle;
+ if (NULL != Translator) {
+ (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
+ (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
+ (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+CreateInterruptQh (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddr,
+ IN UINT8 EndPointAddr,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 DataToggle,
+ IN UINTN MaxPacketLen,
+ IN UINTN Interval,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QH_ENTITY **QhPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qh for Control Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddr - Address of Device
+ EndPointAddr - Address of Endpoint
+ DeviceSpeed - Device Speed
+ MaxPacketLen - Max Length of one Packet
+ Interval - value of interval
+ Translator - Translator Transaction for SplitX
+ QhPtrPtr - A pointer of pointer to Qh for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Create and init InterruptQh
+ //
+ Status = CreateQh (
+ HcDev,
+ DeviceAddr,
+ EndPointAddr,
+ DeviceSpeed,
+ MaxPacketLen,
+ QhPtrPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ //
+ // Software fields
+ //
+ if (Interval == 0) {
+ (*QhPtrPtr)->TransferType = SYNC_INTERRUPT_TRANSFER;
+ } else {
+ (*QhPtrPtr)->TransferType = ASYNC_INTERRUPT_TRANSFER;
+ }
+ (*QhPtrPtr)->Interval = GetApproxiOfInterval (Interval);
+
+ //
+ // Hardware fields
+ //
+ // InterruptTranfer don't use DataToggleControl
+ //
+ (*QhPtrPtr)->Qh.DataToggleControl = FALSE;
+ (*QhPtrPtr)->Qh.QhHorizontalPointer = 0;
+ (*QhPtrPtr)->Qh.QhTerminate = TRUE;
+ (*QhPtrPtr)->Qh.NakCountReload = 0;
+ (*QhPtrPtr)->Qh.InerruptScheduleMask = MICRO_FRAME_0_CHANNEL;
+ (*QhPtrPtr)->Qh.SplitComletionMask = (MICRO_FRAME_2_CHANNEL | MICRO_FRAME_3_CHANNEL | MICRO_FRAME_4_CHANNEL);
+ (*QhPtrPtr)->Qh.DataToggle = DataToggle;
+ if (NULL != Translator) {
+ (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
+ (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
+ (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+CreateQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *DataPtr,
+ IN UINTN DataLen,
+ IN UINT8 PktId,
+ IN UINT8 Toggle,
+ IN UINT8 QtdStatus,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure and Pre-Initialize it
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DataPtr - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ PktId - Packet Identification of this Qtd
+ Toggle - Data Toggle of this Qtd
+ QtdStatus - Default value of status of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+ EHCI_QTD_HW *QtdHwPtr;
+
+ ASSERT (HcDev);
+ ASSERT (QtdPtrPtr);
+
+ //
+ // Create memory for Qtd structure
+ //
+ Status = EhciAllocatePool (
+ HcDev,
+ (UINT8 **) QtdPtrPtr,
+ sizeof (EHCI_QTD_ENTITY)
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+ //
+ // Init fields in Qtd
+ //
+ gBS->SetMem (*QtdPtrPtr, sizeof (EHCI_QTD_ENTITY), 0);
+
+ //
+ // Software field
+ //
+ (*QtdPtrPtr)->TotalBytes = (UINT32) DataLen;
+ (*QtdPtrPtr)->StaticTotalBytes = (UINT32) DataLen;
+ (*QtdPtrPtr)->Prev = NULL;
+ (*QtdPtrPtr)->Next = NULL;
+
+ //
+ // Hardware field
+ //
+ QtdHwPtr = &((*QtdPtrPtr)->Qtd);
+ QtdHwPtr->NextQtdPointer = 0;
+ QtdHwPtr->NextQtdTerminate = TRUE;
+ QtdHwPtr->AltNextQtdPointer = 0;
+ QtdHwPtr->AltNextQtdTerminate = TRUE;
+ QtdHwPtr->DataToggle = Toggle;
+ QtdHwPtr->TotalBytes = (UINT32) DataLen;
+ QtdHwPtr->CurrentPage = 0;
+ QtdHwPtr->ErrorCount = QTD_ERROR_COUNTER;
+ QtdHwPtr->Status = QtdStatus;
+ QtdHwPtr->Rsvd1 = 0;
+ QtdHwPtr->Rsvd2 = 0;
+ QtdHwPtr->Rsvd3 = 0;
+ QtdHwPtr->Rsvd4 = 0;
+ QtdHwPtr->Rsvd5 = 0;
+ QtdHwPtr->Rsvd6 = 0;
+
+ //
+ // Set PacketID [Setup/Data/Status]
+ //
+ switch (PktId) {
+ case SETUP_PACKET_ID:
+ QtdHwPtr->PidCode = SETUP_PACKET_PID_CODE;
+ break;
+
+ case INPUT_PACKET_ID:
+ QtdHwPtr->PidCode = INPUT_PACKET_PID_CODE;
+ break;
+
+ case OUTPUT_PACKET_ID:
+ QtdHwPtr->PidCode = OUTPUT_PACKET_PID_CODE;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Set Data Buffer Pointers
+ //
+ if (NULL != DataPtr) {
+ SetQtdBufferPointer (
+ QtdHwPtr,
+ DataPtr,
+ DataLen
+ );
+ (*QtdPtrPtr)->StaticCurrentOffset = QtdHwPtr->CurrentOffset;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+CreateSetupQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *DevReqPtr,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for Setup
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DevReqPtr - A pointer to Device Request Data
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ return CreateQtd (
+ HcDev,
+ DevReqPtr,
+ sizeof (EFI_USB_DEVICE_REQUEST),
+ SETUP_PACKET_ID,
+ DATA0,
+ QTD_STATUS_ACTIVE,
+ QtdPtrPtr
+ );
+}
+
+EFI_STATUS
+CreateDataQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 *DataPtr,
+ IN UINTN DataLen,
+ IN UINT8 PktId,
+ IN UINT8 Toggle,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for data
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DataPtr - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ PktId - Packet Identification of this Qtd
+ Toggle - Data Toggle of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ return CreateQtd (
+ HcDev,
+ DataPtr,
+ DataLen,
+ PktId,
+ Toggle,
+ QTD_STATUS_ACTIVE,
+ QtdPtrPtr
+ );
+}
+
+EFI_STATUS
+CreateAltQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PktId,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for Alternative
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ PktId - Packet Identification of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ return CreateQtd (
+ HcDev,
+ NULL,
+ 0,
+ PktId,
+ 0,
+ QTD_STATUS_ACTIVE,
+ QtdPtrPtr
+ );
+}
+
+EFI_STATUS
+CreateStatusQtd (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PktId,
+ OUT EHCI_QTD_ENTITY **QtdPtrPtr
+ )
+/*++
+
+Routine Description:
+
+ Create Qtd Structure for status
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ PktId - Packet Identification of this Qtd
+ QtdPtrPtr - A pointer of pointer to Qtd for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ return CreateQtd (
+ HcDev,
+ NULL,
+ 0,
+ PktId,
+ DATA1,
+ QTD_STATUS_ACTIVE,
+ QtdPtrPtr
+ );
+}
+
+EFI_STATUS
+CreateControlQtds (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DataPktId,
+ IN UINT8 *RequestCursor,
+ IN UINT8 *DataCursor,
+ IN UINTN DataLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QTD_ENTITY **ControlQtdsHead
+ )
+/*++
+
+Routine Description:
+
+ Create Qtds list for Control Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DataPktId - Packet Identification of Data Qtds
+ RequestCursor - A pointer to request structure buffer to transfer
+ DataCursor - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+ EHCI_QTD_ENTITY *QtdPtr;
+ EHCI_QTD_ENTITY *PreQtdPtr;
+ EHCI_QTD_ENTITY *SetupQtdPtr;
+ EHCI_QTD_ENTITY *FirstDataQtdPtr;
+ EHCI_QTD_ENTITY *LastDataQtdPtr;
+ EHCI_QTD_ENTITY *StatusQtdPtr;
+ UINT8 DataToggle;
+ UINT8 StatusPktId;
+ UINTN CapacityOfQtd;
+ UINTN SizePerQtd;
+ UINTN DataCount;
+ UINTN Xnum;
+
+ QtdPtr = NULL;
+ PreQtdPtr = NULL;
+ SetupQtdPtr = NULL;
+ FirstDataQtdPtr = NULL;
+ LastDataQtdPtr = NULL;
+ StatusQtdPtr = NULL;
+ CapacityOfQtd = 0;
+
+ //
+ // Setup Stage of Control Transfer
+ //
+ Status = CreateSetupQtd (
+ HcDev,
+ RequestCursor,
+ &SetupQtdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ //
+ // Data Stage of Control Transfer
+ //
+ DataToggle = 1;
+ DataCount = DataLen;
+
+ //
+ // Create Qtd structure and link together
+ //
+ while (DataCount > 0) {
+ //
+ // PktSize is the data load size that each Qtd.
+ //
+ CapacityOfQtd = GetCapacityOfQtd (DataCursor);
+ SizePerQtd = DataCount;
+ if (DataCount > CapacityOfQtd) {
+ SizePerQtd = CapacityOfQtd;
+ }
+
+ Status = CreateDataQtd (
+ HcDev,
+ DataCursor,
+ SizePerQtd,
+ DataPktId,
+ DataToggle,
+ &QtdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ if (NULL == FirstDataQtdPtr) {
+ goto destory_setup_qtd;
+ } else {
+ goto destory_qtds;
+ }
+ }
+
+ if (NULL == FirstDataQtdPtr) {
+ FirstDataQtdPtr = QtdPtr;
+ } else {
+ LinkQtdToQtd (PreQtdPtr, QtdPtr);
+ }
+
+ //
+ // Reverse Data Toggle or not determined by parity of transactions of one qtd
+ //
+ Xnum = Translator ? GetNumberOfTransaction (SizePerQtd, EHCI_BLOCK_SIZE_WITH_TT) : GetNumberOfTransaction (SizePerQtd, EHCI_BLOCK_SIZE);
+ if (Xnum % 2 != 0) {
+ DataToggle ^= 1;
+ }
+
+ PreQtdPtr = QtdPtr;
+ DataCursor += SizePerQtd;
+ DataCount -= SizePerQtd;
+ }
+
+ LastDataQtdPtr = QtdPtr;
+
+ //
+ // Status Stage of Control Transfer
+ //
+ if (OUTPUT_PACKET_ID == DataPktId) {
+ StatusPktId = INPUT_PACKET_ID;
+ } else {
+ StatusPktId = OUTPUT_PACKET_ID;
+ }
+
+ Status = CreateStatusQtd (
+ HcDev,
+ StatusPktId,
+ &StatusQtdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto destory_qtds;
+ }
+
+ //
+ // Link setup Qtd -> data Qtds -> status Qtd
+ //
+ if (FirstDataQtdPtr != NULL) {
+ LinkQtdToQtd (SetupQtdPtr, FirstDataQtdPtr);
+ LinkQtdToQtd (LastDataQtdPtr, StatusQtdPtr);
+ } else {
+ LinkQtdToQtd (SetupQtdPtr, StatusQtdPtr);
+ }
+
+ *ControlQtdsHead = SetupQtdPtr;
+
+ goto exit;
+
+destory_qtds:
+ DestoryQtds (HcDev, FirstDataQtdPtr);
+destory_setup_qtd:
+ DestoryQtds (HcDev, SetupQtdPtr);
+exit:
+ return Status;
+}
+
+EFI_STATUS
+CreateBulkOrInterruptQtds (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 PktId,
+ IN UINT8 *DataCursor,
+ IN UINTN DataLen,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT EHCI_QTD_ENTITY **QtdsHead
+ )
+/*++
+
+Routine Description:
+
+ Create Qtds list for Bulk or Interrupt Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ PktId - Packet Identification of Qtds
+ DataCursor - A pointer to user data buffer to transfer
+ DataLen - Length of user data to transfer
+ DataToggle - Data Toggle to start
+ Translator - Translator Transaction for SplitX
+ QtdsHead - A pointer of pointer to first Qtd for control tranfer for return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ EFI_STATUS Status;
+ EHCI_QTD_ENTITY *QtdPtr;
+ EHCI_QTD_ENTITY *PreQtdPtr;
+ EHCI_QTD_ENTITY *FirstQtdPtr;
+ EHCI_QTD_ENTITY *AltQtdPtr;
+ UINTN DataCount;
+ UINTN CapacityOfQtd;
+ UINTN SizePerQtd;
+
+ Status = EFI_SUCCESS;
+ QtdPtr = NULL;
+ PreQtdPtr = NULL;
+ FirstQtdPtr = NULL;
+ AltQtdPtr = NULL;
+ CapacityOfQtd = 0;
+
+ DataCount = DataLen;
+ while (DataCount > 0) {
+
+ CapacityOfQtd = GetCapacityOfQtd (DataCursor);
+ SizePerQtd = DataCount;
+ if (DataCount > CapacityOfQtd) {
+ SizePerQtd = CapacityOfQtd;
+ }
+
+ Status = CreateDataQtd (
+ HcDev,
+ DataCursor,
+ SizePerQtd,
+ PktId,
+ 0,
+ &QtdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ if (NULL == FirstQtdPtr) {
+ goto exit;
+ } else {
+ goto destory_qtds;
+ }
+ }
+
+ if (NULL == FirstQtdPtr) {
+ FirstQtdPtr = QtdPtr;
+ } else {
+ LinkQtdToQtd (PreQtdPtr, QtdPtr);
+ }
+
+ PreQtdPtr = QtdPtr;
+ DataCursor += SizePerQtd;
+ DataCount -= SizePerQtd;
+ }
+
+ //
+ // Set Alternate Qtd
+ //
+ if (INPUT_PACKET_ID == PktId && 1 < GetNumberOfQtd (FirstQtdPtr)) {
+ Status = CreateAltQtd (
+ HcDev,
+ PktId,
+ &AltQtdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto destory_qtds;
+ }
+
+ LinkQtdsToAltQtd (FirstQtdPtr, AltQtdPtr);
+ }
+
+ *QtdsHead = FirstQtdPtr;
+ goto exit;
+
+destory_qtds:
+ DestoryQtds (HcDev, FirstQtdPtr);
+exit:
+ return Status;
+}
+
+VOID
+DestoryQtds (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QTD_ENTITY *FirstQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Destory all Qtds in the list
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ FirstQtdPtr - A pointer to first Qtd in the list
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_QTD_ENTITY *PrevQtd;
+ EHCI_QTD_ENTITY *NextQtd;
+
+ if (!FirstQtdPtr) {
+ goto exit;
+ }
+
+ PrevQtd = FirstQtdPtr;
+
+ //
+ // Delete all the Qtds.
+ //
+ do {
+ NextQtd = PrevQtd->Next;
+ EhciFreePool (HcDev, (UINT8 *) PrevQtd, sizeof (EHCI_QTD_ENTITY));
+ PrevQtd = NextQtd;
+ } while (NULL != PrevQtd);
+
+exit:
+ return ;
+}
+
+UINTN
+GetNumberOfQtd (
+ IN EHCI_QTD_ENTITY *FirstQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Number of Qtds in the list
+
+Arguments:
+
+ FirstQtdPtr - A pointer to first Qtd in the list
+
+Returns:
+
+ Number of Qtds in the list
+
+--*/
+{
+ UINTN Count;
+ EHCI_QTD_ENTITY *QtdPtr;
+ Count = 0;
+ QtdPtr = FirstQtdPtr;
+
+ ;
+
+ while (NULL != QtdPtr) {
+ Count++;
+ QtdPtr = QtdPtr->Next;
+ }
+
+ return Count;
+}
+
+UINTN
+GetNumberOfTransaction (
+ IN UINTN SizeOfData,
+ IN UINTN SizeOfTransaction
+ )
+/*++
+
+Routine Description:
+
+ Number of Transactions in one Qtd
+
+Arguments:
+
+ SizeOfData - Size of one Qtd
+ SizeOfTransaction - Size of one Transaction
+
+Returns:
+
+ Number of Transactions in this Qtd
+
+--*/
+{
+
+ return ((SizeOfData & (SizeOfTransaction - 1)) ? SizeOfData / SizeOfTransaction + 1 : SizeOfData / SizeOfTransaction);
+
+}
+
+UINTN
+GetCapacityOfQtd (
+ IN UINT8 *BufferCursor
+ )
+/*++
+
+Routine Description:
+
+ Get Size of First Qtd
+
+Arguments:
+
+ BufferCursor - BufferCursor of the Qtd
+
+Returns:
+
+ Size of First Qtd
+
+--*/
+{
+
+ return (EHCI_MAX_QTD_CAPACITY - (EHCI_BLOCK_SIZE * GetNumberOfTransaction (EFI_PAGE_MASK & GET_0B_TO_31B (BufferCursor), EHCI_BLOCK_SIZE)));
+
+}
+
+UINTN
+GetApproxiOfInterval (
+ IN UINTN Interval
+ )
+/*++
+
+Routine Description:
+
+ Get the approximate value in the 2 index sequence
+
+Arguments:
+
+ Interval - the value of interval
+
+Returns:
+
+ approximate value of interval in the 2 index sequence
+
+--*/
+{
+ UINTN Orignate;
+ UINTN Approxi;
+
+ Orignate = Interval;
+ Approxi = 1;
+
+ while (Orignate != 1 && Orignate != 0) {
+ Orignate = Orignate >> 1;
+ Approxi = Approxi << 1;
+ }
+
+ if (Interval & (Approxi >> 1)) {
+ Approxi = Approxi << 1;
+ }
+
+ return Approxi;
+}
+
+EHCI_QTD_HW *
+GetQtdAlternateNextPointer (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Get Qtd alternate next pointer field
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ A pointer to hardware alternate Qtd
+
+--*/
+{
+ EHCI_QTD_HW *Value;
+
+ Value = NULL;
+
+ if (!HwQtdPtr->AltNextQtdTerminate) {
+ Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->AltNextQtdPointer << 5);
+ }
+
+ return Value;
+}
+
+EHCI_QTD_HW *
+GetQtdNextPointer (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Get Qtd next pointer field
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ A pointer to next hardware Qtd structure
+
+--*/
+{
+ EHCI_QTD_HW *Value;
+
+ Value = NULL;
+
+ if (!HwQtdPtr->NextQtdTerminate) {
+ Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->NextQtdPointer << 5);
+ }
+
+ return Value;
+}
+
+VOID LinkQtdToQtd (
+ IN EHCI_QTD_ENTITY * PreQtdPtr,
+ IN EHCI_QTD_ENTITY * QtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qtds together
+
+Arguments:
+
+ PreQtdPtr - A pointer to pre Qtd
+ QtdPtr - A pointer to next Qtd
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_QTD_HW *QtdHwPtr;
+
+ ASSERT(PreQtdPtr);
+ ASSERT(QtdPtr);
+
+ //
+ // Software link
+ //
+ PreQtdPtr->Next = QtdPtr;
+ QtdPtr->Prev = PreQtdPtr;
+
+ //
+ // Hardware link
+ //
+ QtdHwPtr = &(QtdPtr->Qtd);
+ PreQtdPtr->Qtd.NextQtdPointer = (UINT32) (GET_0B_TO_31B(QtdHwPtr) >> 5);
+ PreQtdPtr->Qtd.NextQtdTerminate = FALSE;
+
+ return ;
+}
+
+
+VOID LinkQtdsToAltQtd (
+ IN EHCI_QTD_ENTITY * FirstQtdPtr,
+ IN EHCI_QTD_ENTITY * AltQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Link AlterQtds together
+
+Arguments:
+
+ FirstQtdPtr - A pointer to first Qtd in the list
+ AltQtdPtr - A pointer to alternative Qtd
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_QTD_ENTITY *QtdPtr;
+ EHCI_QTD_HW *AltQtdHwPtr;
+
+ ASSERT(FirstQtdPtr);
+ ASSERT(AltQtdPtr);
+
+ AltQtdHwPtr = &(AltQtdPtr->Qtd);
+ QtdPtr = FirstQtdPtr;
+
+ while (NULL != QtdPtr) {
+ //
+ // Software link
+ //
+ QtdPtr->AltNext = AltQtdPtr;
+ //
+ // Hardware link
+ //
+ QtdPtr->Qtd.AltNextQtdPointer = (UINT32) (GET_0B_TO_31B(AltQtdHwPtr) >> 5);
+ QtdPtr->Qtd.AltNextQtdTerminate = FALSE;
+ QtdPtr = QtdPtr->Next;
+ }
+
+ return ;
+}
+
+VOID
+LinkQtdToQh (
+ IN EHCI_QH_ENTITY *QhPtr,
+ IN EHCI_QTD_ENTITY *QtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qtds list to Qh
+
+Arguments:
+
+ QhPtr - A pointer to Qh
+ QtdPtr - A pointer to first Qtd in the list
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_QTD_ENTITY *Cursor;
+ EHCI_QTD_HW *QtdHwPtr;
+
+ ASSERT (QhPtr);
+ ASSERT (QtdPtr);
+
+ QhPtr->FirstQtdPtr = QtdPtr;
+ if (NULL != QtdPtr->AltNext) {
+ QhPtr->AltQtdPtr = QtdPtr->AltNext;
+ }
+
+ Cursor = QtdPtr;
+ while (NULL != Cursor) {
+ Cursor->SelfQh = QhPtr;
+ if (NULL == Cursor->Next) {
+ QhPtr->LastQtdPtr = Cursor;
+ }
+
+ Cursor = Cursor->Next;
+ }
+
+ QtdHwPtr = &(QtdPtr->Qtd);
+ QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (QtdHwPtr) >> 5);
+ QhPtr->Qh.NextQtdTerminate = FALSE;
+
+ return ;
+}
+
+EFI_STATUS
+LinkQhToAsyncList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qh to Async Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+
+ ASSERT (HcDev);
+ ASSERT (QhPtr);
+
+ QhPtr->Qh.HeadReclamationFlag = TRUE;
+
+ Status = SetAsyncListAddr (HcDev, QhPtr);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ if (!IsAsyncScheduleEnabled (HcDev)) {
+
+ Status = EnableAsynchronousSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForAsyncScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCDebugLevel, "WaitForAsyncScheduleEnable TimeOut"));
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+UnlinkQhFromAsyncList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Unlink Qh from Async Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (HcDev);
+ ASSERT (QhPtr);
+
+ if (QhPtr == QhPtr->Next) {
+
+ Status = DisableAsynchronousSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForAsyncScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCErrorLevel, "WaitForAsyncScheduleDisable TimeOut\n"));
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ }
+
+exit:
+ return Status;
+}
+
+VOID
+LinkQhToPeriodicList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Link Qh to Periodic Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+
+Returns:
+
+ VOID
+
+--*/
+{
+ FRAME_LIST_ENTRY *FrameEntryPtr;
+ EHCI_QH_ENTITY *FindQhPtr;
+ EHCI_QH_HW *FindQhHwPtr;
+ UINTN FrameIndex;
+
+ ASSERT (HcDev);
+ ASSERT (QhPtr);
+
+ FindQhPtr = NULL;
+ FindQhHwPtr = NULL;
+ FrameIndex = 0;
+ FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
+
+ QhPtr->Qh.HeadReclamationFlag = FALSE;
+
+ if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {
+
+ //
+ // AsyncInterruptTransfer Qh
+ //
+
+ //
+ // Link to Frame[0] List
+ //
+ if (!FrameEntryPtr->LinkTerminate) {
+ //
+ // Not Null FrameList
+ //
+ FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
+ FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
+ //
+ // FindQh is Left/Right to Qh
+ //
+ while ((NULL != FindQhPtr->Next) && (FindQhPtr->Interval > QhPtr->Interval)) {
+ FindQhPtr = FindQhPtr->Next;
+ }
+
+ if (FindQhPtr->Interval == QhPtr->Interval) {
+ //
+ // Link Qh after FindQh
+ //
+ if (NULL != FindQhPtr->Next) {
+ FindQhPtr->Next->Prev = QhPtr;
+ QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Next->Qh) >> 5);
+ QhPtr->Qh.SelectType = QH_SELECT_TYPE;
+ QhPtr->Qh.QhTerminate = FALSE;
+ }
+
+ FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;
+ FindQhPtr->Qh.QhTerminate = FALSE;
+
+ QhPtr->Prev = FindQhPtr;
+ QhPtr->Next = FindQhPtr->Next;
+ FindQhPtr->Next = QhPtr;
+ } else if (FindQhPtr->Interval < QhPtr->Interval) {
+ //
+ // Link Qh before FindQh
+ //
+ if (NULL == FindQhPtr->Prev) {
+ //
+ // Qh is the First one in Frame[0] List
+ //
+ FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FrameEntryPtr->SelectType = QH_SELECT_TYPE;
+ FrameEntryPtr->LinkTerminate = FALSE;
+ } else {
+ //
+ // Qh is not the First one in Frame[0] List
+ //
+ FindQhPtr->Prev->Next = QhPtr;
+ FindQhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
+ FindQhPtr->Prev->Qh.QhTerminate = FALSE;
+ }
+
+ QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Qh) >> 5);
+ QhPtr->Qh.SelectType = QH_SELECT_TYPE;
+ QhPtr->Qh.QhTerminate = FALSE;
+
+ QhPtr->Next = FindQhPtr;
+ QhPtr->Prev = FindQhPtr->Prev;
+ FindQhPtr->Prev = QhPtr;
+ } else {
+ //
+ // Link Qh after FindQh, Qh is the Last one
+ //
+ FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
+ FindQhPtr->Qh.QhTerminate = FALSE;
+
+ QhPtr->Prev = FindQhPtr;
+ QhPtr->Next = NULL;
+ FindQhPtr->Next = QhPtr;
+ }
+ } else {
+ //
+ // Null FrameList
+ //
+ FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FrameEntryPtr->SelectType = QH_SELECT_TYPE;
+ FrameEntryPtr->LinkTerminate = FALSE;
+ }
+ //
+ // Other Frame[X]
+ //
+ if (NULL == QhPtr->Prev) {
+ //
+ // Qh is the First one in Frame[0] List
+ //
+ FrameIndex += QhPtr->Interval;
+ while (FrameIndex < HcDev->PeriodicFrameListLength) {
+ FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
+ FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FrameEntryPtr->SelectType = QH_SELECT_TYPE;
+ FrameEntryPtr->LinkTerminate = FALSE;
+ FrameIndex += QhPtr->Interval;
+ }
+ } else if (QhPtr->Interval < QhPtr->Prev->Interval) {
+ //
+ // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval
+ //
+ FrameIndex += QhPtr->Interval;
+ while (FrameIndex < HcDev->PeriodicFrameListLength) {
+ FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
+ if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
+ FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FrameEntryPtr->SelectType = QH_SELECT_TYPE;
+ FrameEntryPtr->LinkTerminate = FALSE;
+ }
+
+ FrameIndex += QhPtr->Interval;
+ }
+ }
+ } else {
+
+ //
+ // SyncInterruptTransfer Qh
+ //
+
+ if (!FrameEntryPtr->LinkTerminate) {
+ //
+ // Not Null FrameList
+ //
+ FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
+ FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
+ //
+ // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh
+ //
+ while (NULL != FindQhPtr->Next) {
+ FindQhPtr = FindQhPtr->Next;
+ }
+
+ FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;
+ FindQhPtr->Qh.QhTerminate = FALSE;
+
+ FindQhPtr->Next = QhPtr;
+ QhPtr->Prev = FindQhPtr;
+ } else {
+ //
+ // Null FrameList
+ //
+ FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
+ FrameEntryPtr->SelectType = QH_SELECT_TYPE;
+ FrameEntryPtr->LinkTerminate = FALSE;
+ }
+ }
+
+ return ;
+}
+
+VOID
+UnlinkQhFromPeriodicList (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_QH_ENTITY *QhPtr,
+ IN UINTN Interval
+ )
+/*++
+
+Routine Description:
+
+ Unlink Qh from Periodic Schedule List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ QhPtr - A pointer to Qh
+ Interval - Interval of this periodic transfer
+
+Returns:
+
+ VOID
+
+--*/
+{
+ FRAME_LIST_ENTRY *FrameEntryPtr;
+ UINTN FrameIndex;
+
+ FrameIndex = 0;
+
+ ASSERT (HcDev);
+ ASSERT (QhPtr);
+
+ FrameIndex = 0;
+ FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
+
+ if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {
+
+ //
+ // AsyncInterruptTransfer Qh
+ //
+
+ if (NULL == QhPtr->Prev) {
+ //
+ // Qh is the First one on Frame[0] List
+ //
+ if (NULL == QhPtr->Next) {
+ //
+ // Only one on Frame[0] List
+ //
+ while (FrameIndex < HcDev->PeriodicFrameListLength) {
+ FrameEntryPtr->LinkPointer = 0;
+ FrameEntryPtr->SelectType = 0;
+ FrameEntryPtr->LinkTerminate = TRUE;
+ FrameEntryPtr += Interval;
+ FrameIndex += Interval;
+ }
+ } else {
+ while (FrameIndex < HcDev->PeriodicFrameListLength) {
+ FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
+ FrameEntryPtr->SelectType = QH_SELECT_TYPE;
+ FrameEntryPtr->LinkTerminate = FALSE;
+ FrameEntryPtr += Interval;
+ FrameIndex += Interval;
+ }
+ }
+ } else {
+
+ //
+ // Not First one on Frame[0] List
+ //
+ if (NULL == QhPtr->Next) {
+ //
+ // Qh is the Last one on Frame[0] List
+ //
+ QhPtr->Prev->Qh.QhHorizontalPointer = 0;
+ QhPtr->Prev->Qh.SelectType = 0;
+ QhPtr->Prev->Qh.QhTerminate = TRUE;
+ } else {
+ QhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
+ QhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
+ QhPtr->Prev->Qh.QhTerminate = FALSE;
+ }
+
+ if (Interval == QhPtr->Prev->Interval) {
+ //
+ // Interval is the same as Prev
+ // Not involed Frame[X]
+ //
+ } else {
+ //
+ // Other Frame[X]
+ //
+ while (FrameIndex < HcDev->PeriodicFrameListLength) {
+ if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
+ FrameEntryPtr->LinkPointer = QhPtr->Prev->Qh.QhHorizontalPointer;
+ FrameEntryPtr->SelectType = QhPtr->Prev->Qh.SelectType;
+ FrameEntryPtr->LinkTerminate = QhPtr->Prev->Qh.QhTerminate;
+ }
+ FrameEntryPtr += Interval;
+ FrameIndex += Interval;
+ }
+ }
+ }
+
+ if (NULL != QhPtr->Next) {
+ QhPtr->Next->Prev = QhPtr->Prev;
+ }
+
+ if (NULL != QhPtr->Prev) {
+ QhPtr->Prev->Next = QhPtr->Next;
+ }
+ } else {
+ //
+ // SyncInterruptTransfer Qh
+ //
+ if (NULL == QhPtr->Prev) {
+ //
+ // Qh is the only one Qh on Frame[0] List
+ //
+ FrameEntryPtr->LinkPointer = 0;
+ FrameEntryPtr->SelectType = 0;
+ FrameEntryPtr->LinkTerminate = TRUE;
+ } else {
+ QhPtr->Prev->Qh.QhHorizontalPointer = 0;
+ QhPtr->Prev->Qh.SelectType = 0;
+ QhPtr->Prev->Qh.QhTerminate = TRUE;
+ }
+
+ if (NULL != QhPtr->Prev) {
+ QhPtr->Prev->Next = NULL;
+ }
+ }
+
+ return ;
+}
+
+VOID
+LinkToAsyncReqeust (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
+ )
+/*++
+
+Routine Description:
+
+ Llink AsyncRequest Entry to Async Request List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ AsyncRequestPtr - A pointer to Async Request Entry
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_ASYNC_REQUEST *CurrentPtr;
+
+ CurrentPtr = HcDev->AsyncRequestList;
+ HcDev->AsyncRequestList = AsyncRequestPtr;
+ AsyncRequestPtr->Prev = NULL;
+ AsyncRequestPtr->Next = CurrentPtr;
+
+ if (NULL != CurrentPtr) {
+ CurrentPtr->Prev = AsyncRequestPtr;
+ }
+
+ return ;
+}
+
+VOID
+UnlinkFromAsyncReqeust (
+ IN USB2_HC_DEV *HcDev,
+ IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
+ )
+/*++
+
+Routine Description:
+
+ Unlink AsyncRequest Entry from Async Request List
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ AsyncRequestPtr - A pointer to Async Request Entry
+
+Returns:
+
+ VOID
+
+--*/
+{
+ if (NULL == AsyncRequestPtr->Prev) {
+ HcDev->AsyncRequestList = AsyncRequestPtr->Next;
+ if (NULL != AsyncRequestPtr->Next) {
+ AsyncRequestPtr->Next->Prev = NULL;
+ }
+ } else {
+ AsyncRequestPtr->Prev->Next = AsyncRequestPtr->Next;
+ if (NULL != AsyncRequestPtr->Next) {
+ AsyncRequestPtr->Next->Prev = AsyncRequestPtr->Prev;
+ }
+ }
+
+ return ;
+}
+
+VOID
+SetQtdBufferPointer (
+ IN EHCI_QTD_HW *QtdHwPtr,
+ IN VOID *DataPtr,
+ IN UINTN DataLen
+ )
+/*++
+
+Routine Description:
+
+ Set data buffer pointers in Qtd
+
+Arguments:
+
+ QtdHwPtr - A pointer to Qtd hardware structure
+ DataPtr - A pointer to user data buffer
+ DataLen - Length of the user data buffer
+
+Returns:
+
+ VOID
+
+--*/
+{
+ UINTN RemainLen;
+
+ RemainLen = DataLen;
+ ASSERT (QtdHwPtr);
+
+ //
+ // Set BufferPointer0, ExtBufferPointer0 and Offset
+ //
+ QtdHwPtr->BufferPointer0 = (UINT32) (GET_0B_TO_31B (DataPtr) >> 12);
+ QtdHwPtr->CurrentOffset = (UINT32) (GET_0B_TO_31B (DataPtr) & EFI_PAGE_MASK);
+ QtdHwPtr->ExtBufferPointer0 = (UINT32) GET_32B_TO_63B (DataPtr);
+
+ //
+ // Set BufferPointer1 and ExtBufferPointer1
+ //
+ RemainLen = RemainLen > (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset) ? (RemainLen - (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset)) : 0;
+ if (RemainLen == 0) {
+ goto exit;
+ }
+
+ QtdHwPtr->BufferPointer1 = QtdHwPtr->BufferPointer0 + 1;
+ QtdHwPtr->ExtBufferPointer1 = QtdHwPtr->ExtBufferPointer0;
+
+ //
+ // Set BufferPointer2 and ExtBufferPointer2
+ //
+ RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
+ if (RemainLen == 0) {
+ goto exit;
+ }
+
+ QtdHwPtr->BufferPointer2 = QtdHwPtr->BufferPointer1 + 1;
+ QtdHwPtr->ExtBufferPointer2 = QtdHwPtr->ExtBufferPointer0;
+
+ //
+ // Set BufferPointer3 and ExtBufferPointer3
+ //
+ RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
+ if (RemainLen == 0) {
+ goto exit;
+ }
+
+ QtdHwPtr->BufferPointer3 = QtdHwPtr->BufferPointer2 + 1;
+ QtdHwPtr->ExtBufferPointer3 = QtdHwPtr->ExtBufferPointer0;
+
+ //
+ // Set BufferPointer4 and ExtBufferPointer4
+ //
+ RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
+ if (RemainLen == 0) {
+ goto exit;
+ }
+
+ QtdHwPtr->BufferPointer4 = QtdHwPtr->BufferPointer3 + 1;
+ QtdHwPtr->ExtBufferPointer4 = QtdHwPtr->ExtBufferPointer0;
+
+exit:
+ return ;
+}
+
+BOOLEAN
+IsQtdStatusActive (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is active or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Active
+ FALSE Inactive
+
+--*/
+{
+ UINT8 QtdStatus;
+ BOOLEAN Value;
+
+ QtdStatus = (UINT8) (HwQtdPtr->Status);
+ Value = (BOOLEAN) (QtdStatus & QTD_STATUS_ACTIVE);
+
+ return Value;
+}
+
+BOOLEAN
+IsQtdStatusHalted (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is halted or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Halted
+ FALSE Not halted
+
+--*/
+{
+ UINT8 QtdStatus;
+ BOOLEAN Value;
+
+ QtdStatus = (UINT8) (HwQtdPtr->Status);
+ Value = (BOOLEAN) (QtdStatus & QTD_STATUS_HALTED);
+
+ return Value;
+}
+
+BOOLEAN
+IsQtdStatusBufferError (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is buffer error or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Buffer error
+ FALSE No buffer error
+
+--*/
+{
+ UINT8 QtdStatus;
+ BOOLEAN Value;
+
+ QtdStatus = (UINT8) (HwQtdPtr->Status);
+ Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BUFFER_ERR);
+
+ return Value;
+}
+
+BOOLEAN
+IsQtdStatusBabbleError (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is babble error or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Babble error
+ FALSE No babble error
+
+--*/
+{
+ UINT8 QtdStatus;
+ BOOLEAN Value;
+
+ QtdStatus = (UINT8) (HwQtdPtr->Status);
+ Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BABBLE_ERR);
+
+ return Value;
+}
+
+BOOLEAN
+IsQtdStatusTransactionError (
+ IN EHCI_QTD_HW *HwQtdPtr
+ )
+/*++
+
+Routine Description:
+
+ Whether Qtd status is transaction error or not
+
+Arguments:
+
+ HwQtdPtr - A pointer to hardware Qtd structure
+
+Returns:
+
+ TRUE Transaction error
+ FALSE No transaction error
+
+--*/
+{
+ UINT8 QtdStatus;
+ BOOLEAN Value;
+
+ QtdStatus = (UINT8) (HwQtdPtr->Status);
+ Value = (BOOLEAN) (QtdStatus & QTD_STATUS_TRANSACTION_ERR);
+
+ return Value;
+}
+
+BOOLEAN
+IsDataInTransfer (
+ IN UINT8 EndPointAddress
+ )
+/*++
+
+Routine Description:
+
+ Whether is a DataIn direction transfer
+
+Arguments:
+
+ EndPointAddress - address of the endpoint
+
+Returns:
+
+ TRUE DataIn
+ FALSE DataOut
+
+--*/
+{
+ BOOLEAN Value;
+
+ if (EndPointAddress & 0x80) {
+ Value = TRUE;
+ } else {
+ Value = FALSE;
+ }
+
+ return Value;
+}
+
+EFI_STATUS
+MapDataBuffer (
+ IN USB2_HC_DEV *HcDev,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN VOID *Data,
+ IN OUT UINTN *DataLength,
+ OUT UINT8 *PktId,
+ OUT UINT8 **DataCursor,
+ OUT VOID **DataMap
+ )
+/*++
+
+Routine Description:
+
+ Map address of user data buffer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ TransferDirection - direction of transfer
+ Data - A pointer to user data buffer
+ DataLength - length of user data
+ PktId - Packte Identificaion
+ DataCursor - mapped address to return
+ DataMap - identificaion of this mapping to return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPhysicalAddr;
+
+ Status = EFI_SUCCESS;
+
+ switch (TransferDirection) {
+
+ case EfiUsbDataIn:
+
+ *PktId = INPUT_PACKET_ID;
+ //
+ // BusMasterWrite means cpu read
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ Data,
+ DataLength,
+ &TempPhysicalAddr,
+ DataMap
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCDebugLevel, "MapDataBuffer Failed\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
+ break;
+
+ case EfiUsbDataOut:
+
+ *PktId = OUTPUT_PACKET_ID;
+ //
+ // BusMasterRead means cpu write
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ Data,
+ DataLength,
+ &TempPhysicalAddr,
+ DataMap
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
+ break;
+
+ case EfiUsbNoData:
+
+ *PktId = OUTPUT_PACKET_ID;
+ Data = NULL;
+ *DataLength = 0;
+ *DataCursor = NULL;
+ *DataMap = NULL;
+ break;
+
+ default:
+
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+MapRequestBuffer (
+ IN USB2_HC_DEV *HcDev,
+ IN OUT VOID *Request,
+ OUT UINT8 **RequestCursor,
+ OUT VOID **RequestMap
+ )
+/*++
+
+Routine Description:
+
+ Map address of request structure buffer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ Request - A pointer to request structure
+ RequestCursor - Mapped address of request structure to return
+ RequestMap - Identificaion of this mapping to return
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN RequestLen;
+ EFI_PHYSICAL_ADDRESS TempPhysicalAddr;
+
+ RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ (UINT8 *) Request,
+ (UINTN *) &RequestLen,
+ &TempPhysicalAddr,
+ RequestMap
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ *RequestCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+DeleteAsyncRequestTransfer (
+ IN USB2_HC_DEV *HcDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ OUT UINT8 *DataToggle
+ )
+/*++
+
+Routine Description:
+
+ Delete all asynchronous request transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ DeviceAddress - address of usb device
+ EndPointAddress - address of endpoint
+ DataToggle - stored data toggle
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ EHCI_ASYNC_REQUEST *AsyncRequestPtr;
+ EHCI_ASYNC_REQUEST *MatchPtr;
+ EHCI_QH_HW *QhHwPtr;
+ UINT8 EndPointNum;
+
+ if (NULL == HcDev->AsyncRequestList) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ MatchPtr = NULL;
+ QhHwPtr = NULL;
+ EndPointNum = EndPointAddress & 0x0f;
+ AsyncRequestPtr = HcDev->AsyncRequestList;
+
+ //
+ // Find QH of AsyncRequest by DeviceAddress and EndPointNum
+ //
+ do {
+
+ QhHwPtr = &(AsyncRequestPtr->QhPtr->Qh);
+ if (QhHwPtr->DeviceAddr == DeviceAddress && QhHwPtr->EndpointNum == EndPointNum) {
+ MatchPtr = AsyncRequestPtr;
+ break;
+ }
+
+ AsyncRequestPtr = AsyncRequestPtr->Next;
+
+ } while (NULL != AsyncRequestPtr);
+
+ if (NULL == MatchPtr) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ Status = DisablePeriodicSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCErrorLevel, "WaitForPeriodicScheduleDisable TimeOut\n"));
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ *DataToggle = (UINT8) MatchPtr->QhPtr->Qh.DataToggle;
+ UnlinkQhFromPeriodicList (HcDev, MatchPtr->QhPtr, MatchPtr->QhPtr->Interval);
+ UnlinkFromAsyncReqeust (HcDev, MatchPtr);
+
+ if (NULL == HcDev->AsyncRequestList) {
+
+ Status = StopPollingTimer (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ } else {
+
+ Status = EnablePeriodicSchedule (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+
+ Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gEHCErrorLevel, "WaitForPeriodicScheduleEnable TimeOut\n"));
+ Status = EFI_TIMEOUT;
+ goto exit;
+ }
+
+ if (IsEhcHalted (HcDev)) {
+ Status = StartScheduleExecution (HcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit;
+ }
+ }
+
+ }
+
+ DestoryQtds (HcDev, MatchPtr->QhPtr->FirstQtdPtr);
+ DestoryQh (HcDev, MatchPtr->QhPtr);
+ EhciFreePool (HcDev, (UINT8 *) MatchPtr, sizeof (EHCI_ASYNC_REQUEST));
+
+exit:
+ return Status;
+}
+
+VOID
+CleanUpAllAsyncRequestTransfer (
+ IN USB2_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Clean up all asynchronous request transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_ASYNC_REQUEST *AsyncRequestPtr;
+ EHCI_ASYNC_REQUEST *FreePtr;
+
+ AsyncRequestPtr = NULL;
+ FreePtr = NULL;
+
+ StopPollingTimer (HcDev);
+
+ AsyncRequestPtr = HcDev->AsyncRequestList;
+ while (NULL != AsyncRequestPtr) {
+
+ FreePtr = AsyncRequestPtr;
+ AsyncRequestPtr = AsyncRequestPtr->Next;
+ UnlinkFromAsyncReqeust (HcDev, FreePtr);
+ UnlinkQhFromPeriodicList (HcDev, FreePtr->QhPtr, FreePtr->QhPtr->Interval);
+ DestoryQtds (HcDev, FreePtr->QhPtr->FirstQtdPtr);
+ DestoryQh (HcDev, FreePtr->QhPtr);
+ EhciFreePool (HcDev, (UINT8 *) FreePtr, sizeof (EHCI_ASYNC_REQUEST));
+
+ }
+
+ return ;
+}
+
+VOID
+ZeroOutQhOverlay (
+ IN EHCI_QH_ENTITY *QhPtr
+ )
+/*++
+
+Routine Description:
+
+ Zero out the fields in Qh structure
+
+Arguments:
+
+ QhPtr - A pointer to Qh structure
+
+Returns:
+
+ VOID
+
+--*/
+{
+ QhPtr->Qh.CurrentQtdPointer = 0;
+ QhPtr->Qh.AltNextQtdPointer = 0;
+ QhPtr->Qh.NakCount = 0;
+ QhPtr->Qh.AltNextQtdTerminate = 0;
+ QhPtr->Qh.TotalBytes = 0;
+ QhPtr->Qh.InterruptOnComplete = 0;
+ QhPtr->Qh.CurrentPage = 0;
+ QhPtr->Qh.ErrorCount = 0;
+ QhPtr->Qh.PidCode = 0;
+ QhPtr->Qh.Status = 0;
+ QhPtr->Qh.BufferPointer0 = 0;
+ QhPtr->Qh.CurrentOffset = 0;
+ QhPtr->Qh.BufferPointer1 = 0;
+ QhPtr->Qh.CompleteSplitMask = 0;
+ QhPtr->Qh.BufferPointer2 = 0;
+ QhPtr->Qh.SplitBytes = 0;
+ QhPtr->Qh.FrameTag = 0;
+ QhPtr->Qh.BufferPointer3 = 0;
+ QhPtr->Qh.BufferPointer4 = 0;
+ QhPtr->Qh.ExtBufferPointer0 = 0;
+ QhPtr->Qh.ExtBufferPointer1 = 0;
+ QhPtr->Qh.ExtBufferPointer2 = 0;
+ QhPtr->Qh.ExtBufferPointer3 = 0;
+ QhPtr->Qh.ExtBufferPointer4 = 0;
+}
+
+VOID
+UpdateAsyncRequestTransfer (
+ IN EHCI_ASYNC_REQUEST *AsyncRequestPtr,
+ IN UINT32 TransferResult,
+ IN UINTN ErrQtdPos
+ )
+/*++
+
+Routine Description:
+
+ Update asynchronous request transfer
+
+Arguments:
+
+ AsyncRequestPtr - A pointer to async request
+ TransferResult - transfer result
+ ErrQtdPos - postion of error Qtd
+
+Returns:
+
+ VOID
+
+--*/
+{
+ EHCI_QTD_ENTITY *QtdPtr;
+
+ QtdPtr = NULL;
+
+ if (EFI_USB_NOERROR == TransferResult) {
+
+ //
+ // Update Qh for next trigger
+ //
+
+ QtdPtr = AsyncRequestPtr->QhPtr->FirstQtdPtr;
+
+ //
+ // Update fields in Qh
+ //
+
+ //
+ // Get DataToggle from Overlay in Qh
+ //
+ // ZeroOut Overlay in Qh except DataToggle, HostController will update this field
+ //
+ ZeroOutQhOverlay (AsyncRequestPtr->QhPtr);
+ AsyncRequestPtr->QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (&(QtdPtr->Qtd)) >> 5);
+ AsyncRequestPtr->QhPtr->Qh.NextQtdTerminate = FALSE;
+
+ //
+ // Update fields in Qtd
+ //
+ while (NULL != QtdPtr) {
+ QtdPtr->Qtd.TotalBytes = QtdPtr->StaticTotalBytes;
+ QtdPtr->Qtd.CurrentOffset = QtdPtr->StaticCurrentOffset;
+ QtdPtr->Qtd.CurrentPage = 0;
+ QtdPtr->Qtd.ErrorCount = QTD_ERROR_COUNTER;
+ QtdPtr->Qtd.Status = QTD_STATUS_ACTIVE;
+
+ QtdPtr->TotalBytes = QtdPtr->StaticTotalBytes;
+ QtdPtr = QtdPtr->Next;
+ }
+ }
+
+ return ;
+}
+
+BOOLEAN
+CheckQtdsTransferResult (
+ IN BOOLEAN IsControl,
+ IN EHCI_QH_ENTITY *QhPtr,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrQtdPos,
+ OUT UINTN *ActualLen
+ )
+/*++
+
+Routine Description:
+
+ Check transfer result of Qtds
+
+Arguments:
+
+ IsControl - Is control transfer or not
+ QhPtr - A pointer to Qh
+ Result - Transfer result
+ ErrQtdPos - Error TD Position
+ ActualLen - Actual Transfer Size
+
+Returns:
+
+ TRUE Qtds finished
+ FALSE Not finish
+
+--*/
+{
+ UINTN ActualLenPerQtd;
+ EHCI_QTD_ENTITY *QtdPtr;
+ EHCI_QTD_HW *QtdHwPtr;
+ BOOLEAN Value;
+
+ ASSERT (QhPtr);
+ ASSERT (Result);
+ ASSERT (ErrQtdPos);
+ ASSERT (ActualLen);
+
+ Value = TRUE;
+ QtdPtr = QhPtr->FirstQtdPtr;
+ QtdHwPtr = &(QtdPtr->Qtd);
+
+ while (NULL != QtdHwPtr) {
+
+ if (IsQtdStatusActive (QtdHwPtr)) {
+ *Result |= EFI_USB_ERR_NOTEXECUTE;
+ }
+
+ if (IsQtdStatusHalted (QtdHwPtr)) {
+ *Result |= EFI_USB_ERR_STALL;
+ }
+
+ if (IsQtdStatusBufferError (QtdHwPtr)) {
+ *Result |= EFI_USB_ERR_BUFFER;
+ }
+
+ if (IsQtdStatusBabbleError (QtdHwPtr)) {
+ *Result |= EFI_USB_ERR_BABBLE;
+ }
+
+ if (IsQtdStatusTransactionError (QtdHwPtr)) {
+ *Result |= EFI_USB_ERR_TIMEOUT;
+ }
+
+ ActualLenPerQtd = QtdPtr->TotalBytes - QtdHwPtr->TotalBytes;
+ QtdPtr->TotalBytes = QtdHwPtr->TotalBytes;
+ //
+ // Accumulate actual transferred data length in each DataQtd.
+ //
+ if (SETUP_PACKET_PID_CODE != QtdHwPtr->PidCode) {
+ *ActualLen += ActualLenPerQtd;
+ }
+
+ if (*Result) {
+ Value = FALSE;
+ break;
+ }
+
+ if ((!IsControl) && (QtdPtr->TotalBytes > 0)) {
+ //
+ // Did something, but isn't full workload
+ //
+ break;
+ }
+
+ (*ErrQtdPos)++;
+ QtdHwPtr = GetQtdNextPointer (QtdHwPtr);
+ QtdPtr = (EHCI_QTD_ENTITY *) GET_QTD_ENTITY_ADDR (QtdHwPtr);
+
+ }
+
+ return Value;
+}
+
+EFI_STATUS
+ExecuteTransfer (
+ IN USB2_HC_DEV *HcDev,
+ IN BOOLEAN IsControl,
+ IN EHCI_QH_ENTITY *QhPtr,
+ IN OUT UINTN *ActualLen,
+ OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+Routine Description:
+
+ Execute Bulk or SyncInterrupt Transfer
+
+Arguments:
+
+ HcDev - USB2_HC_DEV
+ IsControl - Is control transfer or not
+ QhPtr - A pointer to Qh
+ ActualLen - Actual transfered Len
+ DataToggle - Data Toggle
+ TimeOut - TimeOut threshold
+ TransferResult - Transfer result
+
+Returns:
+
+ EFI_SUCCESS Sucess
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN ErrQtdPos;
+ UINTN Delay;
+ UINTN RequireLen;
+ BOOLEAN Finished;
+
+ Status = EFI_SUCCESS;
+ ErrQtdPos = 0;
+ *TransferResult = EFI_USB_NOERROR;
+ RequireLen = *ActualLen;
+ *ActualLen = 0;
+ Finished = FALSE;
+
+ Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+ *TransferResult = 0;
+ Finished = CheckQtdsTransferResult (
+ IsControl,
+ QhPtr,
+ TransferResult,
+ &ErrQtdPos,
+ ActualLen
+ );
+ if (Finished) {
+ break;
+ }
+ //
+ // Qtd is inactive, which means bulk or interrupt transfer's end.
+ //
+ if (!(*TransferResult & EFI_USB_ERR_NOTEXECUTE)) {
+ break;
+ }
+
+ gBS->Stall (EHCI_SYNC_REQUEST_POLLING_TIME);
+
+ } while (--Delay);
+
+ if (EFI_USB_NOERROR != *TransferResult) {
+ if (0 == Delay) {
+ Status = EFI_TIMEOUT;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Special for Bulk and Interrupt Transfer
+ //
+ *DataToggle = (UINT8) QhPtr->Qh.DataToggle;
+
+ return Status;
+}
+
+EFI_STATUS
+AsyncRequestMoniter (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+Routine Description:
+
+ Interrupt transfer periodic check handler
+
+Arguments:
+ Event - Interrupt event
+ Context - Pointer to USB2_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *HcDev;
+ EHCI_ASYNC_REQUEST *AsyncRequestPtr;
+ EHCI_QTD_HW *QtdHwPtr;
+ UINTN ErrQtdPos;
+ UINTN ActualLen;
+ UINT32 TransferResult;
+ UINT8 *ReceiveBuffer;
+ UINT8 *ProcessBuffer;
+
+ Status = EFI_SUCCESS;
+ QtdHwPtr = NULL;
+ ReceiveBuffer = NULL;
+ ProcessBuffer = NULL;
+ HcDev = (USB2_HC_DEV *) Context;
+ AsyncRequestPtr = HcDev->AsyncRequestList;
+
+ while (NULL != AsyncRequestPtr) {
+
+ TransferResult = 0;
+ ErrQtdPos = 0;
+ ActualLen = 0;
+
+ CheckQtdsTransferResult (
+ FALSE,
+ AsyncRequestPtr->QhPtr,
+ &TransferResult,
+ &ErrQtdPos,
+ &ActualLen
+ );
+
+ if ((TransferResult & EFI_USB_ERR_NAK) || (TransferResult & EFI_USB_ERR_NOTEXECUTE)) {
+ AsyncRequestPtr = AsyncRequestPtr->Next;
+ continue;
+ }
+ //
+ // Allocate memory for EHC private data structure
+ //
+ ProcessBuffer = AllocateZeroPool (ActualLen);
+ if (NULL == ProcessBuffer) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ QtdHwPtr = &(AsyncRequestPtr->QhPtr->FirstQtdPtr->Qtd);
+ ReceiveBuffer = (UINT8 *) GET_0B_TO_31B ((QtdHwPtr->BufferPointer0 << 12) | AsyncRequestPtr->QhPtr->FirstQtdPtr->StaticCurrentOffset);
+ CopyMem (
+ ProcessBuffer,
+ ReceiveBuffer,
+ ActualLen
+ );
+
+ UpdateAsyncRequestTransfer (AsyncRequestPtr, TransferResult, ErrQtdPos);
+
+ if (EFI_USB_NOERROR == TransferResult) {
+
+ if (AsyncRequestPtr->CallBackFunc != NULL) {
+ (AsyncRequestPtr->CallBackFunc) (ProcessBuffer, ActualLen, AsyncRequestPtr->Context, TransferResult);
+ }
+
+ } else {
+
+ //
+ // leave error recovery to its related device driver. A common case of
+ // the error recovery is to re-submit the interrupt transfer.
+ // When an interrupt transfer is re-submitted, its position in the linked
+ // list is changed. It is inserted to the head of the linked list, while
+ // this function scans the whole list from head to tail. Thus, the
+ // re-submitted interrupt transfer's callback function will not be called
+ // again in this round.
+ //
+ if (AsyncRequestPtr->CallBackFunc != NULL) {
+ (AsyncRequestPtr->CallBackFunc) (NULL, 0, AsyncRequestPtr->Context, TransferResult);
+ }
+
+ }
+
+ if (NULL != ProcessBuffer) {
+ gBS->FreePool (ProcessBuffer);
+ }
+
+ AsyncRequestPtr = AsyncRequestPtr->Next;
+
+ }
+
+exit:
+ return Status;
+}
+
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa
index 66a41d9319..3d24744f12 100644
--- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa
@@ -71,6 +71,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
<Protocol Usage="BY_START">
<ProtocolCName>gEfiUsbHcProtocolGuid</ProtocolCName>
</Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiUsb2HcProtocolGuid</ProtocolCName>
+ </Protocol>
</Protocols>
<Externs>
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c
index 62d58eed78..74ddc6bb12 100644
--- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c
@@ -49,13 +49,13 @@ Returns:
// Perform 16bit Read in PCI IO Space
//
return PciIo->Io.Read (
- PciIo,
- EfiPciIoWidthUint16,
- USB_BAR_INDEX,
- (UINT64) PortOffset,
- 1,
- Data
- );
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ Data
+ );
}
EFI_STATUS
@@ -86,13 +86,13 @@ Returns:
// Perform 32bit Read in PCI IO Space
//
return PciIo->Io.Read (
- PciIo,
- EfiPciIoWidthUint32,
- USB_BAR_INDEX,
- (UINT64) PortOffset,
- 1,
- Data
- );
+ PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ Data
+ );
}
EFI_STATUS
@@ -123,13 +123,13 @@ Returns:
// Perform 16bit Write in PCI IO Space
//
return PciIo->Io.Write (
- PciIo,
- EfiPciIoWidthUint16,
- USB_BAR_INDEX,
- (UINT64) PortOffset,
- 1,
- &Data
- );
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ &Data
+ );
}
EFI_STATUS
@@ -160,13 +160,13 @@ Returns:
// Perform 32bit Write in PCI IO Space
//
return PciIo->Io.Write (
- PciIo,
- EfiPciIoWidthUint32,
- USB_BAR_INDEX,
- (UINT64) PortOffset,
- 1,
- &Data
- );
+ PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ &Data
+ );
}
//
// USB register-base helper functions
@@ -657,10 +657,10 @@ Returns:
EFI_STATUS Status;
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- (UINT32) (USBCMD),
- &CommandContent
- );
+ HcDev->PciIo,
+ (UINT32) (USBCMD),
+ &CommandContent
+ );
if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) {
CommandContent |= USBCMD_MAXP;
@@ -715,25 +715,25 @@ Returns:
BufferSizeInBytes = 4096;
BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);
Status = HcDev->PciIo->AllocateBuffer (
- HcDev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- BufferSizeInPages,
- &CommonBuffer,
- 0
- );
+ HcDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ BufferSizeInPages,
+ &CommonBuffer,
+ 0
+ );
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterCommonBuffer,
- CommonBuffer,
- &BufferSizeInBytes,
- &MappedAddress,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ CommonBuffer,
+ &BufferSizeInBytes,
+ &MappedAddress,
+ &Mapping
+ );
if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) {
HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);
return EFI_UNSUPPORTED;
@@ -3589,13 +3589,13 @@ Returns:
// and it is allocated as common buffer use.
//
Status = HcDev->PciIo->AllocateBuffer (
- HcDev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- MemoryBlockSizeInPages,
- &CommonBuffer,
- 0
- );
+ HcDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ MemoryBlockSizeInPages,
+ &CommonBuffer,
+ 0
+ );
if (EFI_ERROR (Status)) {
gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
gBS->FreePool (*MemoryHeader);
@@ -3604,13 +3604,13 @@ Returns:
MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterCommonBuffer,
- CommonBuffer,
- &MemoryBlockSizeInBytes,
- &MappedAddress,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ CommonBuffer,
+ &MemoryBlockSizeInBytes,
+ &MappedAddress,
+ &Mapping
+ );
//
// if returned Mapped size is less than the size we request,do not support.
//
@@ -3741,10 +3741,10 @@ Returns:
TempHeaderPtr = TempHeaderPtr->Next) {
Status = AllocMemInMemoryBlock (
- TempHeaderPtr,
- (VOID **) Pool,
- RealAllocSize / 32
- );
+ TempHeaderPtr,
+ (VOID **) Pool,
+ RealAllocSize / 32
+ );
if (!EFI_ERROR (Status)) {
ZeroMem (*Pool, AllocSize);
return EFI_SUCCESS;
@@ -3777,10 +3777,10 @@ Returns:
InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);
Status = AllocMemInMemoryBlock (
- NewMemoryHeader,
- (VOID **) Pool,
- RealAllocSize / 32
- );
+ NewMemoryHeader,
+ (VOID **) Pool,
+ RealAllocSize / 32
+ );
if (!EFI_ERROR (Status)) {
ZeroMem (*Pool, AllocSize);
@@ -4226,12 +4226,12 @@ TurnOffUSBEmulation (
//
Command = 0;
PciIo->Pci.Write (
- PciIo,
- EfiPciIoWidthUint16,
- USB_EMULATION,
- 1,
- &Command
- );
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_EMULATION,
+ 1,
+ &Command
+ );
return ;
}
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
index 1eba8bed5b..14f8bf2790 100644
--- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
@@ -28,13 +28,6 @@ Revision History
EFI_STATUS
EFIAPI
-UHCIDriverEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- );
-
-EFI_STATUS
-EFIAPI
UHCIDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
@@ -119,7 +112,7 @@ UHCIAsyncInterruptTransfer (
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN BOOLEAN IsSlowDevice,
- IN UINT8 MaxiumPacketLength,
+ IN UINT8 MaximumPacketLength,
IN BOOLEAN IsNewTransfer,
IN OUT UINT8 *DataToggle,
IN UINTN PollingInterval, OPTIONAL
@@ -200,6 +193,161 @@ UHCIClearRootHubPortFeature (
);
//
+// UEFI 2.0 Protocol
+//
+
+EFI_STATUS
+EFIAPI
+UHCI2GetCapability(
+ IN EFI_USB2_HC_PROTOCOL * This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2Reset (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT16 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2GetState (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ OUT EFI_USB_HC_STATE * State
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2SetState (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN EFI_USB_HC_STATE State
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2ControlTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST * Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataLength, OPTIONAL
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2BulkTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2AsyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL
+ IN VOID *Context OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2SyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2IsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2AsyncIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2GetRootHubPortStatus (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS * PortStatus
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2SetRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+EFI_STATUS
+EFIAPI
+UHCI2ClearRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+//
// Asynchronous interrupt transfer monitor function
//
VOID
@@ -236,7 +384,7 @@ UHCIDriverBindingSupported (
Arguments:
This - Protocol instance pointer.
- Controller, - Handle of device to test
+ Controller - Handle of device to test
RemainingDevicePath - Not used
Returns:
@@ -289,20 +437,20 @@ UHCIDriverBindingSupported (
(UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) {
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_UNSUPPORTED;
}
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_SUCCESS;
}
@@ -351,6 +499,7 @@ UHCIDriverBindingStart (
if (EFI_ERROR (Status)) {
return Status;
}
+
//
// Turn off USB emulation
//
@@ -367,11 +516,11 @@ UHCIDriverBindingStart (
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_UNSUPPORTED;
}
@@ -381,14 +530,14 @@ UHCIDriverBindingStart (
HcDev = AllocateZeroPool (sizeof (USB_HC_DEV));
if (HcDev == NULL) {
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_OUT_OF_RESOURCES;
}
-
+
//
// init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
//
@@ -410,6 +559,27 @@ UHCIDriverBindingStart (
HcDev->UsbHc.MinorRevision = 0x1;
//
+ //
+ // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol
+ //
+ HcDev->Usb2Hc.GetCapability = UHCI2GetCapability;
+ HcDev->Usb2Hc.Reset = UHCI2Reset;
+ HcDev->Usb2Hc.GetState = UHCI2GetState;
+ HcDev->Usb2Hc.SetState = UHCI2SetState;
+ HcDev->Usb2Hc.ControlTransfer = UHCI2ControlTransfer;
+ HcDev->Usb2Hc.BulkTransfer = UHCI2BulkTransfer;
+ HcDev->Usb2Hc.AsyncInterruptTransfer = UHCI2AsyncInterruptTransfer;
+ HcDev->Usb2Hc.SyncInterruptTransfer = UHCI2SyncInterruptTransfer;
+ HcDev->Usb2Hc.IsochronousTransfer = UHCI2IsochronousTransfer;
+ HcDev->Usb2Hc.AsyncIsochronousTransfer = UHCI2AsyncIsochronousTransfer;
+ HcDev->Usb2Hc.GetRootHubPortStatus = UHCI2GetRootHubPortStatus;
+ HcDev->Usb2Hc.SetRootHubPortFeature = UHCI2SetRootHubPortFeature;
+ HcDev->Usb2Hc.ClearRootHubPortFeature = UHCI2ClearRootHubPortFeature;
+
+ HcDev->Usb2Hc.MajorRevision = 0x1;
+ HcDev->Usb2Hc.MinorRevision = 0x1;
+
+ //
// Init UHCI private data structures
//
HcDev->Signature = USB_HC_DEV_SIGNATURE;
@@ -428,14 +598,14 @@ UHCIDriverBindingStart (
}
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_OUT_OF_RESOURCES;
}
-
+
//
// Init interrupt list head in the HcDev structure.
//
@@ -460,11 +630,11 @@ UHCIDriverBindingStart (
}
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_UNSUPPORTED;
}
@@ -486,11 +656,11 @@ UHCIDriverBindingStart (
}
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_UNSUPPORTED;
}
@@ -518,7 +688,7 @@ UHCIDriverBindingStart (
);
return Status;
}
-
+
//
// Install Host Controller Protocol
//
@@ -538,17 +708,46 @@ UHCIDriverBindingStart (
}
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ //
+ // Install USB2.0 Host Controller Protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiUsb2HcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &HcDev->Usb2Hc
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (HcDev->InterruptTransTimer);
+ FreeFrameListEntry (HcDev);
+ DelMemoryManagement (HcDev);
+
+ if (HcDev != NULL) {
+ gBS->FreePool (HcDev);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
return Status;
}
//
// component name protocol.
//
+
HcDev->ControllerNameTable = NULL;
AddUnicodeString (
"eng",
@@ -582,12 +781,17 @@ UnInstallUHCInterface (
HcDev = USB_HC_DEV_FROM_THIS (This);
gBS->UninstallProtocolInterface (
- Controller,
- &gEfiUsbHcProtocolGuid,
- &HcDev->UsbHc
- );
-
- //
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ &HcDev->UsbHc
+ );
+
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &HcDev->Usb2Hc
+ );
+ //
// first stop USB Host Controller
//
This->SetState (This, EfiUsbHcStateHalt);
@@ -659,12 +863,31 @@ UHCIDriverBindingStop (
--*/
{
EFI_USB_HC_PROTOCOL *UsbHc;
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
EFI_STATUS OpenStatus;
OpenStatus = gBS->OpenProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
- (VOID **) &UsbHc,
+ (VOID **)&UsbHc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
@@ -684,11 +907,11 @@ UHCIDriverBindingStop (
UnInstallUHCInterface (Controller, UsbHc);
gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_SUCCESS;
@@ -753,20 +976,20 @@ UHCIReset (
// set the Global Reset bit in the command register
//
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Command |= USBCMD_GRESET;
Status = WriteUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -782,10 +1005,10 @@ UHCIReset (
//
Command &= ~USBCMD_GRESET;
Status = WriteUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -801,20 +1024,20 @@ UHCIReset (
// set Host Controller Reset bit to 1
//
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Command |= USBCMD_HCRESET;
Status = WriteUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -905,20 +1128,20 @@ UHCIGetState (
StatusRegAddr = (UINT32) (USBSTS);
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &UhcCommand
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &UhcCommand
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- StatusRegAddr,
- &UhcStatus
- );
+ HcDev->PciIo,
+ StatusRegAddr,
+ &UhcStatus
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -990,10 +1213,10 @@ UHCISetState (
}
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1001,10 +1224,10 @@ UHCISetState (
Command &= ~USBCMD_RS;
Status = WriteUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1033,20 +1256,20 @@ UHCISetState (
// Set Run/Stop bit to 1.
//
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Command |= USBCMD_RS | USBCMD_MAXP;
Status = WriteUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1055,10 +1278,10 @@ UHCISetState (
case EfiUsbHcStateSuspend:
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1115,20 +1338,20 @@ UHCISetState (
// Set Enter Global Suspend Mode bit to 1.
//
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Command |= USBCMD_EGSM;
Status = WriteUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1185,10 +1408,10 @@ UHCIGetRootHubPortNumber (
for (Index = 0; Index < 2; Index++) {
PSAddr = (UINT32) (USBPORTSC1 + Index * 2);
Status = ReadRootPortReg (
- HcDev->PciIo,
- PSAddr,
- &RHPortControl
- );
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortControl
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1261,10 +1484,10 @@ UHCIGetRootHubPortStatus (
PortStatus->PortChangeStatus = 0;
Status = ReadRootPortReg (
- HcDev->PciIo,
- PSAddr,
- &RHPortStatus
- );
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortStatus
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
@@ -1307,6 +1530,10 @@ UHCIGetRootHubPortStatus (
PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
}
//
+ // CHC will always return one in this bit
+ //
+ PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
+ //
// Fill Port Status Change bits
//
@@ -1393,10 +1620,10 @@ UHCISetRootHubPortFeature (
case EfiUsbPortSuspend:
Status = ReadUHCCommandReg (
- HcDev->PciIo,
- CommandRegAddr,
- &Command
- );
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1487,10 +1714,10 @@ UHCIClearRootHubPortFeature (
PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
Status = ReadRootPortReg (
- HcDev->PciIo,
- PSAddr,
- &RHPortControl
- );
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortControl
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -1733,13 +1960,13 @@ UHCIControlTransfer (
// BusMasterWrite means cpu read
//
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterWrite,
- PtrDataSource,
- &DataLen,
- &TempPtr,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1757,13 +1984,13 @@ UHCIControlTransfer (
// BusMasterRead means cpu write
//
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterRead,
- PtrDataSource,
- &DataLen,
- &TempPtr,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1809,13 +2036,13 @@ UHCIControlTransfer (
//
RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterRead,
- (UINT8 *) Request,
- &RequestLen,
- &TempPtr,
- &RequestMapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ (UINT8 *) Request,
+ &RequestLen,
+ &TempPtr,
+ &RequestMapping
+ );
if (EFI_ERROR (Status)) {
HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
@@ -1829,14 +2056,14 @@ UHCIControlTransfer (
// generate Setup Stage TD
//
Status = GenSetupStageTD (
- HcDev,
- DeviceAddress,
- 0,
- IsSlowDevice,
- (UINT8 *) RequestMappedAddress,
- sizeof (EFI_USB_DEVICE_REQUEST),
- &PtrSetupTD
- );
+ HcDev,
+ DeviceAddress,
+ 0,
+ IsSlowDevice,
+ (UINT8 *) RequestMappedAddress,
+ sizeof (EFI_USB_DEVICE_REQUEST),
+ &PtrSetupTD
+ );
if (EFI_ERROR (Status)) {
HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
@@ -1864,16 +2091,16 @@ UHCIControlTransfer (
}
Status = GenDataTD (
- HcDev,
- DeviceAddress,
- 0,
- Ptr,
- PktSize,
- PktID,
- DataToggle,
- IsSlowDevice,
- &PtrTD
- );
+ HcDev,
+ DeviceAddress,
+ 0,
+ Ptr,
+ PktSize,
+ PktID,
+ DataToggle,
+ IsSlowDevice,
+ &PtrTD
+ );
if (EFI_ERROR (Status)) {
//
@@ -1920,13 +2147,13 @@ UHCIControlTransfer (
// create Status Stage TD structure
//
Status = CreateStatusTD (
- HcDev,
- DeviceAddress,
- 0,
- PktID,
- IsSlowDevice,
- &PtrStatusTD
- );
+ HcDev,
+ DeviceAddress,
+ 0,
+ PktID,
+ IsSlowDevice,
+ &PtrStatusTD
+ );
if (EFI_ERROR (Status)) {
HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
@@ -2009,13 +2236,13 @@ UHCIControlTransfer (
}
Status = ExecuteControlTransfer (
- HcDev,
- PtrFirstDataTD,
- LoadFrameListIndex,
- DataLength,
- TimeOut,
- TransferResult
- );
+ HcDev,
+ PtrFirstDataTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
for (Index = 0; Index < 500; Index++) {
DelLinkSingleQH (
@@ -2060,13 +2287,13 @@ UHCIControlTransfer (
// detail status is returned
//
Status = ExecuteControlTransfer (
- HcDev,
- PtrStatusTD,
- LoadFrameListIndex,
- DataLength,
- TimeOut,
- TransferResult
- );
+ HcDev,
+ PtrStatusTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
//
// Delete Control Transfer QH-TDs structure
@@ -2123,13 +2350,13 @@ UHCIControlTransfer (
// detail status is returned
//
Status = ExecuteControlTransfer (
- HcDev,
- PtrSetupTD,
- LoadFrameListIndex,
- DataLength,
- TimeOut,
- TransferResult
- );
+ HcDev,
+ PtrSetupTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
//
// Remove Control Transfer QH-TDs structure from the frame list
// and update the pointers in the Frame List
@@ -2354,13 +2581,13 @@ UHCIBulkTransfer (
// BusMasterWrite means cpu read
//
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterWrite,
- PtrDataSource,
- &DataLen,
- &TempPtr,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2377,13 +2604,13 @@ UHCIBulkTransfer (
// BusMasterRead means cpu write
//
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterRead,
- PtrDataSource,
- &DataLen,
- &TempPtr,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2422,16 +2649,16 @@ UHCIBulkTransfer (
}
Status = GenDataTD (
- HcDev,
- DeviceAddress,
- EndPointAddress,
- Ptr,
- PktSize,
- PktID,
- *DataToggle,
- FALSE,
- &PtrTD
- );
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ Ptr,
+ PktSize,
+ PktID,
+ *DataToggle,
+ FALSE,
+ &PtrTD
+ );
if (EFI_ERROR (Status)) {
HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
@@ -2526,14 +2753,14 @@ UHCIBulkTransfer (
// of the last successful TD
//
Status = ExecBulkorSyncInterruptTransfer (
- HcDev,
- PtrFirstTD,
- LoadFrameListIndex,
- DataLength,
- DataToggle,
- TimeOut,
- TransferResult
- );
+ HcDev,
+ PtrFirstTD,
+ LoadFrameListIndex,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
//
// Delete Bulk transfer QH-TD structure
@@ -2587,7 +2814,7 @@ UHCIAsyncInterruptTransfer (
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN BOOLEAN IsSlowDevice,
- IN UINT8 MaxiumPacketLength,
+ IN UINT8 MaximumPacketLength,
IN BOOLEAN IsNewTransfer,
IN OUT UINT8 *DataToggle,
IN UINTN PollingInterval, OPTIONAL
@@ -2618,7 +2845,7 @@ UHCIAsyncInterruptTransfer (
IsSlowDevice Indicates whether the target device is slow device
or full-speed device.
- MaxiumPacketLength Indicates the maximum packet size the target endpoint
+ MaximumPacketLength Indicates the maximum packet size the target endpoint
is capable of sending or receiving.
IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
@@ -2715,11 +2942,11 @@ UHCIAsyncInterruptTransfer (
OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
Status = DeleteAsyncINTQHTDs (
- HcDev,
- DeviceAddress,
- EndPointAddress,
- DataToggle
- );
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ DataToggle
+ );
gBS->RestoreTPL (OldTpl);
@@ -2764,13 +2991,13 @@ UHCIAsyncInterruptTransfer (
// BusMasterWrite means cpu read
//
Status = HcDev->PciIo->Map (
- HcDev->PciIo,
- EfiPciIoOperationBusMasterWrite,
- Ptr,
- &DataLen,
- &TempPtr,
- &Mapping
- );
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ Ptr,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
if (EFI_ERROR (Status)) {
gBS->FreePool (Ptr);
return Status;
@@ -2788,21 +3015,21 @@ UHCIAsyncInterruptTransfer (
//
PktSize = (UINT8) DataLen;
- if (DataLen > MaxiumPacketLength) {
- PktSize = MaxiumPacketLength;
+ if (DataLen > MaximumPacketLength) {
+ PktSize = MaximumPacketLength;
}
Status = GenDataTD (
- HcDev,
- DeviceAddress,
- EndPointAddress,
- MappedPtr,
- PktSize,
- PktID,
- CurrentDataToggle,
- IsSlowDevice,
- &PtrTD
- );
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ MappedPtr,
+ PktSize,
+ PktID,
+ CurrentDataToggle,
+ IsSlowDevice,
+ &PtrTD
+ );
if (EFI_ERROR (Status)) {
gBS->FreePool (Ptr);
HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
@@ -3084,6 +3311,10 @@ UHCISyncInterruptTransfer (
return EFI_INVALID_PARAMETER;
}
+ if (TransferResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
ClearStatusReg (HcDev->PciIo, StatusReg);
//
@@ -3357,6 +3588,830 @@ UHCIAsyncIsochronousTransfer (
return EFI_UNSUPPORTED;
}
+//
+// UEFI 2.0 Protocol
+//
+EFI_STATUS
+EFIAPI
+UHCI2GetCapability(
+ IN EFI_USB2_HC_PROTOCOL * This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ )
+/*++
+
+ Routine Description:
+ Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
+
+ Arguments:
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ MaxSpeed - A pointer to the max speed USB host controller supports.
+
+ PortNumber - A pointer to the number of root hub ports.
+
+ Is64BitCapable - A pointer to an integer to show whether USB host controller
+ supports 64-bit memory addressing.
+ Returns:
+ EFI_SUCCESS
+ The host controller capabilities were retrieved successfully.
+ EFI_INVALID_PARAMETER
+ MaxSpeed or PortNumber or Is64BitCapable is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the capabilities.
+
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ if ((NULL == MaxSpeed)
+ ||(NULL == PortNumber)
+ || (NULL == Is64BitCapable))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *MaxSpeed = EFI_USB_SPEED_FULL;
+ *Is64BitCapable = (UINT8)FALSE;
+ return UHCIGetRootHubPortNumber(&HcDev->UsbHc, PortNumber);
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2Reset (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT16 Attributes
+ )
+/*++
+
+ Routine Description:
+ Provides software reset for the USB host controller according to UEFI 2.0 spec.
+
+ Arguments:
+ This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ Attributes - A bit mask of the reset operation to perform.
+ See below for a list of the supported bit mask values.
+
+ #define EFI_USB_HC_RESET_GLOBAL 0x0001
+ #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
+ #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004
+ #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
+
+ EFI_USB_HC_RESET_GLOBAL
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ EFI_USB_HC_RESET_HOST_CONTROLLER
+ If this bit is set, the USB host controller hardware will be reset.
+ No reset signal will be sent to the USB bus.
+
+ Returns:
+ EFI_SUCCESS
+ The reset operation succeeded.
+ EFI_INVALID_PARAMETER
+ Attributes is not valid.
+ EFI_UNSUPPORTED
+ The type of reset specified by Attributes is not currently supported by the host controller hardware.
+ EFI_ACCESS_DENIED
+ Reset operation is rejected due to the debug port being configured and active.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to perform
+ the reset operation.
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ if (Attributes==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG || Attributes==EFI_USB_HC_RESET_HOST_WITH_DEBUG)
+ return EFI_UNSUPPORTED;
+
+ return UHCIReset(
+ &HcDev->UsbHc,
+ Attributes
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2GetState (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ OUT EFI_USB_HC_STATE * State
+ )
+/*++
+
+ Routine Description:
+ Retrieves current state of the USB host controller according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ State - A pointer to the EFI_USB_HC_STATE data structure that
+ indicates current state of the USB host controller.
+ Type EFI_USB_HC_STATE is defined below.
+
+ typedef enum {
+ EfiUsbHcStateHalt,
+ EfiUsbHcStateOperational,
+ EfiUsbHcStateSuspend,
+ EfiUsbHcStateMaximum
+ } EFI_USB_HC_STATE;
+
+ Returns:
+ EFI_SUCCESS
+ The state information of the host controller was returned in State.
+ EFI_INVALID_PARAMETER
+ State is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the
+ host controller's current state.
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ return UHCIGetState(
+ &HcDev->UsbHc,
+ State
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2SetState (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN EFI_USB_HC_STATE State
+ )
+/*++
+
+ Routine Description:
+ Sets the USB host controller to a specific state according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ State - Indicates the state of the host controller that will be set.
+
+ Returns:
+ EFI_SUCCESS
+ The USB host controller was successfully placed in the state
+ specified by State.
+ EFI_INVALID_PARAMETER
+ State is invalid.
+ EFI_DEVICE_ERROR
+ Failed to set the state specified by State due to device error.
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ return UHCISetState(
+ &HcDev->UsbHc,
+ State
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2ControlTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST * Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits control transfer to a target USB device accroding to UEFI 2.0 spec..
+
+ Arguments:
+
+ This - A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ DeviceAddress -Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ DeviceSpeed - Indicates transfer speed of device.
+
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+
+ Request - A pointer to the USB device request that will be sent
+ to the USB device.
+
+ TransferDirection - Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+
+ Data -A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+
+ TimeOut - Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+ EFI_SUCCESS
+ The control transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The control transfer could not be completed due to a lack of resources.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The control transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ USB_HC_DEV *HcDev;
+ BOOLEAN IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ return UHCIControlTransfer(
+ &HcDev->UsbHc,
+ DeviceAddress,
+ IsSlowDevice,
+ (UINT8) MaximumPacketLength,
+ Request,
+ TransferDirection,
+ Data,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2BulkTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+
+ DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL
+ and EFI_USB_SPEED_HIGH.
+
+ MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+
+ DataBuffersNumber Number of data buffers prepared for the transfer.
+
+ Data Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+
+ DataLength When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+
+ DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+
+ Translator A pointr to the transaction translator data.
+
+ TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+
+ TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ Returns:
+ EFI_SUCCESS
+ The bulk transfer was completed successfully.
+
+ EFI_OUT_OF_RESOURCES
+ The bulk transfer could not be submitted due to lack of resource.
+
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+
+ EFI_TIMEOUT
+ The bulk transfer failed due to timeout.
+
+ EFI_DEVICE_ERROR
+ The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ if( Data == NULL || DeviceSpeed==EFI_USB_SPEED_LOW)
+ return EFI_INVALID_PARAMETER;
+ /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */
+
+ return UHCIBulkTransfer (
+ &HcDev->UsbHc,
+ DeviceAddress,
+ EndPointAddress,
+ (UINT8) MaximumPacketLength,
+ *Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2AsyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ Submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+
+ DeviceSpeed Indicates device speed.
+
+ MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+
+ IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+
+ DataToggle A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+
+ PollingInterval Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+
+ DataLength Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+
+ Translator A pointr to the transaction translator data.
+
+ CallBackFunction The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+
+ Context The context that is passed to the CallBackFunction.
+ This is an optional parameter and may be NULL.
+
+ Returns:
+
+ EFI_SUCCESS
+ The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+
+ EFI_OUT_OF_RESOURCES
+ The request could not be completed due to a lack of resources.
+
+ EFI_DEVICE_ERROR
+ Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+ BOOLEAN IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ return UHCIAsyncInterruptTransfer(
+ &HcDev->UsbHc,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ (UINT8) MaximumPacketLength,
+ IsNewTransfer,
+ DataToggle,
+ PollingInterval,
+ DataLength,
+ CallBackFunction,
+ Context
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2SyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+
+ DeviceSpeed Indicates device speed.
+
+ MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+
+ Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+
+ DataLength On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+
+ DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+
+ TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ Translator A pointr to the transaction translator data.
+ TransferResult A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ Returns:
+ EFI_SUCCESS
+ The synchronous interrupt transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The synchronous interrupt transfer could not be submitted due
+ to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The synchronous interrupt transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The synchronous interrupt transfer failed due to host controller
+ or device error. Caller should check TranferResult for detailed
+ error information.
+--*/
+{
+ USB_HC_DEV *HcDev;
+ BOOLEAN IsSlowDevice;
+
+ if(DeviceSpeed==EFI_USB_SPEED_HIGH)
+ return EFI_INVALID_PARAMETER;
+
+ IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ return UHCISyncInterruptTransfer(
+ &HcDev->UsbHc,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ (UINT8) MaximumPacketLength,
+ Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2IsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress End point address
+
+ DeviceSpeed Indicates device speed.
+
+ MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+
+ DataBuffersNumber Number of data buffers prepared for the transfer.
+
+ Data Array of pointers to the buffers of data that will be
+ transmitted to USB device or received from USB device.
+
+ DataLength Indicates the size, in bytes, of the data buffer
+ specified by Data.
+
+ Translator A pointr to the transaction translator data.
+
+ TransferResult A pointer to the detailed result information generated
+ by this control transfer.
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2AsyncIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+
+ Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress End point address
+
+ DeviceSpeed Indicates device speed.
+
+ MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+
+ DataBuffersNumber Number of data buffers prepared for the transfer.
+
+ Data Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+
+ Translator A pointr to the transaction translator data.
+
+ IsochronousCallBack When the transfer complete, the call back function will be called
+
+ Context Pass to the call back function as parameter
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2GetRootHubPortStatus (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS * PortStatus
+ )
+/*++
+
+ Routine Description:
+ Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL.
+
+ PortNumber Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+
+ PortStatus A pointer to the current port status bits and
+ port status change bits.
+
+ Returns:
+ EFI_SUCCESS
+ The status of the USB root hub port specified by PortNumber
+ was returned in PortStatus.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid.
+ EFI_DEVICE_ERROR - Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+
+ return UHCIGetRootHubPortStatus(
+ &HcDev->UsbHc,
+ PortNumber,
+ PortStatus
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2SetRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+ Sets a feature for the specified root hub port according to UEFI 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL.
+
+ PortNumber Specifies the root hub port whose feature
+ is requested to be set.
+
+ PortFeature Indicates the feature selector associated
+ with the feature set request.
+
+ Returns:
+ EFI_SUCCESS
+ The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ return UHCISetRootHubPortFeature(
+ &HcDev->UsbHc,
+ PortNumber,
+ PortFeature
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UHCI2ClearRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+ Clears a feature for the specified root hub port according to Uefi 2.0 spec.
+
+ Arguments:
+
+ This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+
+ PortNumber Specifies the root hub port whose feature
+ is requested to be cleared.
+
+ PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ Returns:
+ EFI_SUCCESS
+ The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB2_HC_DEV_FROM_THIS (This);
+ return UHCIClearRootHubPortFeature(
+ &HcDev->UsbHc,
+ PortNumber,
+ PortFeature
+ );
+}
+
VOID
EFIAPI
MonitorInterruptTrans (
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h
index d6f841bf40..c5ae155f90 100644
--- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h
@@ -28,7 +28,7 @@ Revision History
#include <IndustryStandard/pci22.h>
-#define EFI_D_UHCI EFI_D_INFO
+#define EFI_D_UHCI EFI_D_INFO
//
// stall time
@@ -45,21 +45,20 @@ Revision History
//
// 50 ms
//
-#define INTERRUPT_POLLING_TIME 50 * 1000 * 10
+#define INTERRUPT_POLLING_TIME 50 * 1000 * 10
//
// UHCI IO Space Address Register Register locates at
// offset 20 ~ 23h of PCI Configuration Space (UHCI spec, Revision 1.1),
// so, its BAR Index is 4.
//
-#define USB_BAR_INDEX 4
+#define USB_BAR_INDEX 4
//
// One memory block uses 1 page (common buffer for QH,TD use.)
//
#define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 1
-
#define bit(a) 1 << (a)
//
@@ -82,13 +81,13 @@ extern UINT16 USBBaseAddr;
#define USBCMD_MAXP bit (7) /* Max Packet (0 = 32, 1 = 64) */
/* Status register */
-#define USBSTS 2 /* Status Register Offset 02-03h */
-#define USBSTS_USBINT bit (0) /* Interrupt due to IOC */
-#define USBSTS_ERROR bit (1) /* Interrupt due to error */
-#define USBSTS_RD bit (2) /* Resume Detect */
-#define USBSTS_HSE bit (3) /* Host System Error*/
-#define USBSTS_HCPE bit (4) /* Host Controller Process Error*/
-#define USBSTS_HCH bit (5) /* HC Halted */
+#define USBSTS 2 /* Status Register Offset 02-03h */
+#define USBSTS_USBINT bit (0) /* Interrupt due to IOC */
+#define USBSTS_ERROR bit (1) /* Interrupt due to error */
+#define USBSTS_RD bit (2) /* Resume Detect */
+#define USBSTS_HSE bit (3) /* Host System Error*/
+#define USBSTS_HCPE bit (4) /* Host Controller Process Error*/
+#define USBSTS_HCH bit (5) /* HC Halted */
/* Interrupt enable register */
#define USBINTR 4 /* Interrupt Enable Register 04-05h */
@@ -98,13 +97,13 @@ extern UINT16 USBBaseAddr;
#define USBINTR_SP bit (3) /* Short packet interrupt enable */
/* Frame Number Register Offset 06-08h */
-#define USBFRNUM 6
+#define USBFRNUM 6
/* Frame List Base Address Register Offset 08-0Bh */
-#define USBFLBASEADD 8
+#define USBFLBASEADD 8
/* Start of Frame Modify Register Offset 0Ch */
-#define USBSOF 0x0c
+#define USBSOF 0x0c
/* USB port status and control registers */
#define USBPORTSC1 0x10 /*Port 1 offset 10-11h */
@@ -126,16 +125,16 @@ extern UINT16 USBBaseAddr;
//
// Class Code Register offset
//
-#define CLASSC 0x09
+#define CLASSC 0x09
//
// USB IO Space Base Address Register offset
//
-#define USBBASE 0x20
+#define USBBASE 0x20
//
// USB legacy Support
//
-#define USB_EMULATION 0xc0
+#define USB_EMULATION 0xc0
//
// USB Base Class Code,Sub-Class Code and Programming Interface.
@@ -224,6 +223,7 @@ typedef struct {
//
//////////////////////////////////////////////////////////////////////////
#define USB_HC_DEV_FROM_THIS(a) CR (a, USB_HC_DEV, UsbHc, USB_HC_DEV_SIGNATURE)
+#define USB2_HC_DEV_FROM_THIS(a) CR (a, USB_HC_DEV, Usb2Hc, USB_HC_DEV_SIGNATURE)
#define USB_HC_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'h', 'c', 'i')
#define INTERRUPT_LIST_SIGNATURE EFI_SIGNATURE_32 ('i', 'n', 't', 's')
@@ -267,6 +267,7 @@ typedef struct _MEMORY_MANAGE_HEADER {
typedef struct {
UINTN Signature;
EFI_USB_HC_PROTOCOL UsbHc;
+ EFI_USB2_HC_PROTOCOL Usb2Hc;
EFI_PCI_IO_PROTOCOL *PciIo;
//
@@ -289,196 +290,683 @@ WriteUHCCommandReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 CmdAddrOffset,
IN UINT16 UsbCmd
- );
+ )
+/*++
+
+Routine Description:
+
+ Write UHCI Command Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ CmdAddrOffset - Command address offset
+ UsbCmd - Data to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
ReadUHCCommandReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 CmdAddrOffset,
IN OUT UINT16 *Data
- );
+ )
+/*++
+
+Routine Description:
+
+ Read UHCI Command Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ CmdAddrOffset - Command address offset
+ Data - Data to return
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
WriteUHCStatusReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusAddrOffset,
IN UINT16 UsbSts
- );
+ )
+/*++
+
+Routine Description:
+
+ Write UHCI Staus Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusAddrOffset - Status address offset
+ UsbSts - Data to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
ReadUHCStatusReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusAddrOffset,
IN OUT UINT16 *Data
- );
+ )
+/*++
+
+Routine Description:
+
+ Read UHCI Staus Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusAddrOffset - Status address offset
+ UsbSts - Data to return
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
ClearStatusReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusAddrOffset
- );
+ )
+/*++
+
+Routine Description:
+
+ Clear the content of UHC's Status Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusAddrOffset - Status address offset
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
ReadUHCFrameNumberReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FrameNumAddrOffset,
IN OUT UINT16 *Data
- );
+ )
+/*++
+
+Routine Description:
+
+ Read from UHC's Frame Number Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FrameNumAddrOffset - Frame number register offset
+ Data - Data to return
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
WriteUHCFrameListBaseReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FlBaseAddrOffset,
IN UINT32 UsbFrameListBaseAddr
- );
+ )
+/*++
+
+Routine Description:
+
+ Write to UHC's Frame List Base Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FlBaseAddrOffset - Frame Base address register
+ UsbFrameListBaseAddr - Address to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
ReadRootPortReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortAddrOffset,
IN OUT UINT16 *Data
- );
+ )
+/*++
+
+Routine Description:
+
+ Read from UHC's Root Port Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortAddrOffset - Port Addrress Offset,
+ Data - Data to return
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
WriteRootPortReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortAddrOffset,
IN UINT16 ControlBits
- );
+ )
+/*++
+
+Routine Description:
+
+ Write to UHC's Root Port Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortAddrOffset - Port Addrress Offset,
+ ControlBits - Data to write
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
EFI_STATUS
WaitForUHCHalt (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr,
IN UINTN Timeout
- );
+ )
+/*++
+
+Routine Description:
+
+ Wait until UHCI halt or timeout
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusRegAddr - Status Register Address
+ Timeout - Time out value in us
+
+Returns:
+
+ EFI_DEVICE_ERROR - Unable to read the status register
+ EFI_TIMEOUT - Time out
+ EFI_SUCCESS - Success
+
+--*/
+;
BOOLEAN
IsStatusOK (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
- );
+ )
+/*++
+
+Routine Description:
+
+ Judge whether the host controller operates well
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusRegAddr - Status register address
+
+Returns:
+
+ TRUE - Status is good
+ FALSE - Status is bad
+
+--*/
+;
BOOLEAN
IsHostSysOrProcessErr (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
- );
+ )
+/*++
-//
-// This routine programs the USB frame number register. We assume that the
-// HC schedule execution is stopped.
-//
-EFI_STATUS
-SetFrameNumberReg (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT32 FRNUMAddr,
- IN UINT16 Index
- );
+Routine Description:
+
+ Judge the status is HostSys,ProcessErr error or good
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusRegAddr - Status register address
+
+Returns:
+
+ TRUE - Status is good
+ FALSE - Status is bad
+
+--*/
+;
UINT16
GetCurrentFrameNumber (
IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT32 FRNUMAddr
- );
+ IN UINT32 FrameNumAddrOffset
+ )
+/*++
+
+Routine Description:
+
+ Get Current Frame Number
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FrameNumAddrOffset - FrameNum register AddrOffset
+
+Returns:
+
+ Frame number
+
+--*/
+;
EFI_STATUS
SetFrameListBaseAddress (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FLBASEADDRReg,
IN UINT32 Addr
- );
+ )
+/*++
+
+Routine Description:
+
+ Set FrameListBase Address
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FlBaseAddrReg - FrameListBase register
+ Addr - Address to set
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+;
UINT32
GetFrameListBaseAddress (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FLBAddr
- );
+ )
+/*++
+
+Routine Description:
+
+ Get Current Frame Number
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FrameNumAddrOffset - FrameNum register AddrOffset
+
+Returns:
+
+ Frame number
+
+--*/
+;
EFI_STATUS
CreateFrameList (
IN USB_HC_DEV *HcDev,
IN UINT32 FLBASEADDRReg
- );
+ )
+/*++
+
+Routine Description:
+
+ CreateFrameList
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ FlBaseAddrReg - Frame List register
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory resources
+ EFI_UNSUPPORTED - Map memory fail
+ EFI_SUCCESS - Success
+
+--*/
+;
EFI_STATUS
FreeFrameListEntry (
IN USB_HC_DEV *UhcDev
- );
+ )
+/*++
+
+Routine Description:
+
+ Free FrameList buffer
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS - success
+
+--*/
+;
VOID
InitFrameList (
IN USB_HC_DEV *HcDev
- );
+ )
+/*++
+
+Routine Description:
+
+ Initialize FrameList
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+Returns:
+ VOID
+
+--*/
+;
EFI_STATUS
CreateQH (
IN USB_HC_DEV *HcDev,
OUT QH_STRUCT **pptrQH
- );
+ )
+/*++
+
+Routine Description:
+
+ CreateQH
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ pptrQH - QH_STRUCT content to return
+Returns:
+
+ EFI_SUCCESS - Success
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+
+--*/
+;
VOID
SetQHHorizontalLinkPtr (
IN QH_STRUCT *ptrQH,
IN VOID *ptrNext
- );
+ )
+/*++
+
+Routine Description:
+
+ Set QH Horizontal Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ ptrNext - Data to write
-VOID *
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID *
GetQHHorizontalLinkPtr (
IN QH_STRUCT *ptrQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Get QH Horizontal Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+
+Returns:
+
+ Data to return
+
+--*/
+;
VOID
SetQHHorizontalQHorTDSelect (
IN QH_STRUCT *ptrQH,
IN BOOLEAN bQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Set QH Horizontal QH or TD
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ bQH - TRUE is QH FALSE is TD
+
+Returns:
+ VOID
+
+--*/
+;
VOID
SetQHHorizontalValidorInvalid (
IN QH_STRUCT *ptrQH,
IN BOOLEAN bValid
- );
+ )
+/*++
+
+Routine Description:
+
+ Set QH Horizontal Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ bValid - TRUE is Valid FALSE is Invalid
+
+Returns:
+ VOID
+
+--*/
+;
VOID
SetQHVerticalLinkPtr (
IN QH_STRUCT *ptrQH,
IN VOID *ptrNext
- );
+ )
+/*++
+
+Routine Description:
-VOID *
+ Set QH Vertical Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ ptrNext - Data to write
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID *
GetQHVerticalLinkPtr (
IN QH_STRUCT *ptrQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Get QH Vertical Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ Data to return
+
+--*/
+;
VOID
SetQHVerticalQHorTDSelect (
IN QH_STRUCT *ptrQH,
IN BOOLEAN bQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Set QH Vertical QH or TD
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ bQH - TRUE is QH FALSE is TD
+
+Returns:
+
+ VOID
+
+--*/
+;
BOOLEAN
IsQHHorizontalQHSelect (
IN QH_STRUCT *ptrQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Is QH Horizontal QH Select
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ TRUE - QH
+ FALSE - TD
+
+--*/
+;
VOID
SetQHVerticalValidorInvalid (
IN QH_STRUCT *ptrQH,
IN BOOLEAN bValid
- );
+ )
+/*++
+
+Routine Description:
+
+ Set QH Vertical Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ IsValid - TRUE is valid FALSE is invalid
+
+Returns:
+
+ VOID
+
+--*/
+;
BOOLEAN
GetQHVerticalValidorInvalid (
IN QH_STRUCT *ptrQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Get QH Vertical Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ TRUE - Valid
+ FALSE - Invalid
+
+--*/
+;
EFI_STATUS
AllocateTDStruct (
IN USB_HC_DEV *HcDev,
OUT TD_STRUCT **ppTDStruct
- );
+ )
/*++
Routine Description:
@@ -494,12 +982,13 @@ Returns:
EFI_SUCCESS
--*/
+;
EFI_STATUS
CreateTD (
IN USB_HC_DEV *HcDev,
OUT TD_STRUCT **pptrTD
- );
+ )
/*++
Routine Description:
@@ -517,6 +1006,7 @@ Returns:
EFI_SUCCESS - Success
--*/
+;
EFI_STATUS
@@ -528,7 +1018,7 @@ GenSetupStageTD (
IN UINT8 *pDevReq,
IN UINT8 RequestLen,
OUT TD_STRUCT **ppTD
- );
+ )
/*++
Routine Description:
@@ -550,6 +1040,7 @@ Returns:
EFI_SUCCESS - Success
--*/
+;
EFI_STATUS
GenDataTD (
@@ -562,7 +1053,7 @@ GenDataTD (
IN UINT8 Toggle,
IN BOOLEAN bSlow,
OUT TD_STRUCT **ppTD
- );
+ )
/*++
Routine Description:
@@ -586,6 +1077,7 @@ Returns:
EFI_SUCCESS - Success
--*/
+;
EFI_STATUS
CreateStatusTD (
@@ -595,7 +1087,7 @@ CreateStatusTD (
IN UINT8 PktID,
IN BOOLEAN bSlow,
OUT TD_STRUCT **ppTD
- );
+ )
/*++
Routine Description:
@@ -617,237 +1109,918 @@ Returns:
EFI_SUCCESS - Success
--*/
+;
VOID
SetTDLinkPtrValidorInvalid (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bValid
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer Valid or Invalid
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bValid - TRUE is valid FALSE is invalid
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDLinkPtrQHorTDSelect (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer QH or TD Select
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bQH - TRUE is QH FALSE is TD
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDLinkPtrDepthorBreadth (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bDepth
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer depth or bread priority
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bDepth - TRUE is Depth FALSE is Breadth
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDLinkPtr (
IN TD_STRUCT *ptrTDStruct,
IN VOID *ptrNext
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer
+
+Arguments:
-VOID *
+ ptrTDStruct - TD_STRUCT
+ ptrNext - Pointer to set
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID *
GetTDLinkPtr (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD Link Pointer
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+
+Returns:
+
+ Pointer to get
+
+--*/
+;
VOID
EnableorDisableTDShortPacket (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bEnable
- );
+ )
+/*++
+
+Routine Description:
+
+ Enable or Disable TD ShortPacket
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bEnable - TRUE is Enanble FALSE is Disable
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDControlErrorCounter (
IN TD_STRUCT *ptrTDStruct,
IN UINT8 nMaxErrors
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Control ErrorCounter
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ nMaxErrors - Error counter number
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDLoworFullSpeedDevice (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bLowSpeedDevice
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD status low speed or full speed
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ bLowSpeedDevice - Show low speed or full speed
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDControlIsochronousorNot (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bIsochronous
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD status Isochronous or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ IsIsochronous - Show Isochronous or not
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetorClearTDControlIOC (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bSet
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD status IOC IsSet
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ IsSet - Show IOC set or not
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDStatusActiveorInactive (
IN TD_STRUCT *ptrTDStruct,
IN BOOLEAN bActive
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD status active or not
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ IsActive - Active or not
+
+Returns:
+
+ VOID
+
+--*/
+;
UINT16
SetTDTokenMaxLength (
IN TD_STRUCT *ptrTDStruct,
IN UINT16 nMaxLen
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Token maxlength
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ MaximumLength - Maximum length of TD Token
+
+Returns:
+
+ Real maximum length set to TD Token
+
+--*/
+;
VOID
SetTDTokenDataToggle1 (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Token data toggle1
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDTokenDataToggle0 (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Token data toggle0
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ VOID
+
+--*/
+;
UINT8
GetTDTokenDataToggle (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD Token data toggle
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ data toggle value
+
+--*/
+;
VOID
SetTDTokenEndPoint (
IN TD_STRUCT *ptrTDStruct,
IN UINTN nEndPoint
- );
+ )
+/*++
+
+Routine Description:
+
+ Set Data Token endpoint number
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ EndPoint - End point number
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDTokenDeviceAddress (
IN TD_STRUCT *ptrTDStruct,
IN UINTN nDevAddr
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Token device address
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ DeviceAddress - Device address
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDTokenPacketID (
IN TD_STRUCT *ptrTDStruct,
IN UINT8 nPID
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD Token packet ID
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+ PID - Packet ID
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetTDDataBuffer (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Set TD data buffer
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ VOID
+
+--*/
+;
BOOLEAN
IsTDStatusActive (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status active or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - Active
+ FALSE - Inactive
+
+--*/
+;
BOOLEAN
IsTDStatusStalled (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status stalled or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - Stalled
+ FALSE - not stalled
+
+--*/
+;
BOOLEAN
IsTDStatusBufferError (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status buffer error or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - Buffer error
+ FALSE - No error
+
+--*/
+;
BOOLEAN
IsTDStatusBabbleError (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status babble error or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - Babble error
+ FALSE - No error
+
+--*/
+;
BOOLEAN
IsTDStatusNAKReceived (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status NAK received
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - NAK received
+ FALSE - NAK not received
+
+--*/
+;
BOOLEAN
IsTDStatusCRCTimeOutError (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status CRC timeout error or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - CRC timeout error
+ FALSE - CRC timeout no error
+
+--*/
+;
BOOLEAN
IsTDStatusBitStuffError (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Indicate whether TD status bit stuff error or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - Bit stuff error
+ FALSE - Bit stuff no error
+
+--*/
+;
UINT16
GetTDStatusActualLength (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD status length
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ Return Td status length
+
+--*/
+;
UINT16
GetTDTokenMaxLength (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD Token maximum length
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ Return TD token maximum length
+
+--*/
+;
UINT8
GetTDTokenEndPoint (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD Token endpoint number
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ Return TD Token endpoint number
+
+--*/
+;
UINT8
GetTDTokenDeviceAddress (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD Token device address
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ Return TD Token device address
+
+--*/
+;
UINT8
GetTDTokenPacketID (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD Token packet ID
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ Return TD Token packet ID
-UINT8 *
+--*/
+;
+
+UINT8 *
GetTDDataBuffer (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get the point to TD data buffer
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ Return a point to TD data buffer
+
+--*/
+;
BOOLEAN
GetTDLinkPtrValidorInvalid (
IN TD_STRUCT *ptrTDStruct
- );
+ )
+/*++
+
+Routine Description:
+
+ Get TD LinkPtr valid or not
+
+Arguments:
+
+ ptrTDStruct - A point to TD_STRUCT
+
+Returns:
+
+ TRUE - Invalid
+ FALSE - Valid
+
+--*/
+;
UINTN
CountTDsNumber (
IN TD_STRUCT *ptrFirstTD
- );
+ )
+/*++
+
+Routine Description:
+
+ Get the number of TDs
+
+Arguments:
+
+ PtrFirstTD - A point to the first TD_STRUCT
+
+Returns:
+
+ Return the number of TDs
+
+--*/
+;
VOID
LinkTDToQH (
IN QH_STRUCT *ptrQH,
IN TD_STRUCT *ptrTD
- );
+ )
+/*++
+
+Routine Description:
+
+ Link TD To QH
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ PtrTD - TD_STRUCT
+Returns:
+
+ VOID
+
+--*/
+;
VOID
LinkTDToTD (
IN TD_STRUCT *ptrPreTD,
IN TD_STRUCT *ptrTD
- );
+ )
+/*++
+
+Routine Description:
+
+ Link TD To TD
+
+Arguments:
+
+ ptrPreTD - Previous TD_STRUCT to be linked
+ PtrTD - TD_STRUCT to link
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetorClearCurFrameListTerminate (
IN FRAMELIST_ENTRY *pCurEntry,
IN BOOLEAN bSet
- );
+ )
+/*++
+
+Routine Description:
+
+ Set or clear current framelist terminate
+
+Arguments:
+
+ pCurEntry - A point to FRAMELIST_ENTITY
+ IsSet - TRUE to empty the frame and indicate the Pointer field is valid
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
SetCurFrameListQHorTD (
IN FRAMELIST_ENTRY *pCurEntry,
IN BOOLEAN bQH
- );
+ )
+/*++
+
+Routine Description:
+
+ Set current framelist QH or TD
+
+Arguments:
+
+ pCurEntry - A point to FRAMELIST_ENTITY
+ IsQH - TRUE to set QH and FALSE to set TD
+
+Returns:
+
+ VOID
+
+--*/
+;
BOOLEAN
GetCurFrameListTerminate (
IN FRAMELIST_ENTRY *pCurEntry
- );
+ )
+/*++
+
+Routine Description:
+
+ Get current framelist terminate
+
+Arguments:
+
+ pCurEntry - A point to FRAMELIST_ENTITY
+
+Returns:
+
+ TRUE - Terminate
+ FALSE - Not terminate
+
+--*/
+;
VOID
SetCurFrameListPointer (
IN FRAMELIST_ENTRY *pCurEntry,
IN UINT8 *ptr
- );
+ )
+/*++
-VOID *
+Routine Description:
+
+ Set current framelist pointer
+
+Arguments:
+
+ pCurEntry - A point to FRAMELIST_ENTITY
+ ptr - A point to FrameListPtr point to
+
+Returns:
+
+ VOID
+
+--*/
+;
+
+VOID *
GetCurFrameListPointer (
IN FRAMELIST_ENTRY *pCurEntry
- );
+ )
+/*++
+
+Routine Description:
+
+ Get current framelist pointer
+
+Arguments:
+
+ pCurEntry - A point to FRAMELIST_ENTITY
+
+Returns:
+
+ A point FrameListPtr point to
+
+--*/
+;
VOID
LinkQHToFrameList (
IN FRAMELIST_ENTRY *pEntry,
IN UINT16 FrameListIndex,
IN QH_STRUCT *ptrQH
- );
+ )
/*++
Routine Description:
@@ -864,14 +2037,7 @@ Returns:
VOID
--*/
-VOID
-DeleteQHTDs (
- IN FRAMELIST_ENTRY *pEntry,
- IN QH_STRUCT *ptrQH,
- IN TD_STRUCT *ptrFirstTD,
- IN UINT16 FrameListIndex,
- IN BOOLEAN SearchOther
- );
+;
VOID
DelLinkSingleQH (
@@ -880,13 +2046,50 @@ DelLinkSingleQH (
IN UINT16 FrameListIndex,
IN BOOLEAN SearchOther,
IN BOOLEAN Delete
- );
+ )
+/*++
+
+Routine Description:
+
+ Unlink from frame list and delete single QH
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrQH - QH_STRUCT
+ FrameListIndex - Frame List Index
+ SearchOther - Search Other QH
+ Delete - TRUE is to delete the QH
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
DeleteQueuedTDs (
IN USB_HC_DEV *HcDev,
IN TD_STRUCT *ptrFirstTD
- );
+ )
+/*++
+
+Routine Description:
+
+ Delete Queued TDs
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrFirstTD - TD link list head
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
InsertQHTDToINTList (
@@ -902,10 +2105,12 @@ InsertQHTDToINTList (
IN UINT8 *DataBuffer,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
IN VOID *Context
- );
+ )
/*++
Routine Description:
+
Insert QH and TD To Interrupt List
+
Arguments:
HcDev - USB_HC_DEV
@@ -920,11 +2125,14 @@ Arguments:
DataBuffer - Data buffer
CallBackFunction- CallBackFunction after interrupt transfeer
Context - CallBackFunction Context passed as function parameter
+
Returns:
+
EFI_SUCCESS - Sucess
EFI_INVALID_PARAMETER - Paremeter is error
--*/
+;
EFI_STATUS
DeleteAsyncINTQHTDs (
@@ -932,11 +2140,12 @@ DeleteAsyncINTQHTDs (
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
OUT UINT8 *DataToggle
- );
+ )
/*++
Routine Description:
Delete Async INT QH and TDs
+
Arguments:
HcDev - USB_HC_DEV
@@ -945,10 +2154,13 @@ Arguments:
DataToggle - Data Toggle
Returns:
+
EFI_SUCCESS - Sucess
EFI_INVALID_PARAMETER - Paremeter is error
--*/
+;
+
BOOLEAN
CheckTDsResults (
IN TD_STRUCT *ptrTD,
@@ -956,7 +2168,7 @@ CheckTDsResults (
OUT UINT32 *Result,
OUT UINTN *ErrTDPos,
OUT UINTN *ActualTransferSize
- );
+ )
/*++
Routine Description:
@@ -977,6 +2189,8 @@ Returns:
FALSE - Fail
--*/
+;
+
VOID
ExecuteAsyncINTTDs (
IN USB_HC_DEV *HcDev,
@@ -984,7 +2198,7 @@ ExecuteAsyncINTTDs (
OUT UINT32 *Result,
OUT UINTN *ErrTDPos,
OUT UINTN *ActualLen
- ) ;
+ )
/*++
Routine Description:
@@ -1004,12 +2218,14 @@ Returns:
VOID
--*/
+;
+
VOID
UpdateAsyncINTQHTDs (
IN INTERRUPT_LIST *ptrList,
IN UINT32 Result,
IN UINT32 ErrTDPos
- );
+ )
/*++
Routine Description:
@@ -1027,16 +2243,19 @@ Returns:
VOID
--*/
+;
+
VOID
ReleaseInterruptList (
IN USB_HC_DEV *HcDev,
IN LIST_ENTRY *ListHead
- );
+ )
/*++
Routine Description:
Release Interrupt List
+
Arguments:
HcDev - USB_HC_DEV
@@ -1047,6 +2266,8 @@ Returns:
VOID
--*/
+;
+
EFI_STATUS
ExecuteControlTransfer (
IN USB_HC_DEV *HcDev,
@@ -1055,7 +2276,7 @@ ExecuteControlTransfer (
OUT UINTN *ActualLen,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
- );
+ )
/*++
Routine Description:
@@ -1077,6 +2298,8 @@ Returns:
--*/
+;
+
EFI_STATUS
ExecBulkorSyncInterruptTransfer (
IN USB_HC_DEV *HcDev,
@@ -1086,7 +2309,7 @@ ExecBulkorSyncInterruptTransfer (
OUT UINT8 *DataToggle,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
- );
+ )
/*++
Routine Description:
@@ -1107,81 +2330,311 @@ Returns:
EFI_SUCCESS - Sucess
EFI_DEVICE_ERROR - Error
--*/
+;
EFI_STATUS
InitializeMemoryManagement (
IN USB_HC_DEV *HcDev
- );
+ )
+/*++
+
+Routine Description:
+
+ Initialize Memory Management
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+;
EFI_STATUS
CreateMemoryBlock (
IN USB_HC_DEV *HcDev,
IN MEMORY_MANAGE_HEADER **MemoryHeader,
IN UINTN MemoryBlockSizeInPages
- );
+ )
+/*++
+
+Routine Description:
+
+ Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
+ and use PciIo->Map to map the common buffer for Bus Master Read/Write.
+
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ MemoryHeader - MEMORY_MANAGE_HEADER to output
+ MemoryBlockSizeInPages - MemoryBlockSizeInPages
+
+Returns:
+
+ EFI_SUCCESS - Success
+ EFI_OUT_OF_RESOURCES - Out of resources
+ EFI_UNSUPPORTED - Unsupported
+
+--*/
+;
EFI_STATUS
FreeMemoryHeader (
IN USB_HC_DEV *HcDev,
IN MEMORY_MANAGE_HEADER *MemoryHeader
- );
+ )
+/*++
+
+Routine Description:
+
+ Free Memory Header
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ MemoryHeader - MemoryHeader to be freed
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+
+--*/
+;
EFI_STATUS
UhciAllocatePool (
IN USB_HC_DEV *UhcDev,
IN UINT8 **Pool,
IN UINTN AllocSize
- );
+ )
+/*++
+
+Routine Description:
+
+ Uhci Allocate Pool
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ Pool - Place to store pointer to the memory buffer
+ AllocSize - Alloc Size
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+;
VOID
UhciFreePool (
IN USB_HC_DEV *HcDev,
IN UINT8 *Pool,
IN UINTN AllocSize
- );
+ )
+/*++
+
+Routine Description:
+
+ Uhci Free Pool
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ Pool - Pool to free
+ AllocSize - Pool size
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
InsertMemoryHeaderToList (
IN MEMORY_MANAGE_HEADER *MemoryHeader,
IN MEMORY_MANAGE_HEADER *NewMemoryHeader
- );
+ )
+/*++
+
+Routine Description:
+
+ Insert Memory Header To List
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ NewMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+;
EFI_STATUS
AllocMemInMemoryBlock (
IN MEMORY_MANAGE_HEADER *MemoryHeader,
IN VOID **Pool,
IN UINTN NumberOfMemoryUnit
- );
+ )
+/*++
+
+Routine Description:
+
+ Alloc Memory In MemoryBlock
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ Pool - Place to store pointer to memory
+ NumberOfMemoryUnit - Number Of Memory Unit
+
+Returns:
+
+ EFI_NOT_FOUND - Can't find the free memory
+ EFI_SUCCESS - Success
+
+--*/
+;
BOOLEAN
IsMemoryBlockEmptied (
IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr
- );
+ )
+/*++
+
+/*++
+
+Routine Description:
+
+ Is Memory Block Emptied
+
+Arguments:
+
+ MemoryHeaderPtr - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ TRUE - Empty
+ FALSE - Not Empty
+
+--*/
+;
VOID
DelinkMemoryBlock (
IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,
IN MEMORY_MANAGE_HEADER *FreeMemoryHeader
- );
+ )
+/*++
+
+Routine Description:
+
+ Delink Memory Block
+
+Arguments:
+
+ FirstMemoryHeader - MEMORY_MANAGE_HEADER
+ NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+;
EFI_STATUS
DelMemoryManagement (
IN USB_HC_DEV *HcDev
- );
+ )
+/*++
+
+Routine Description:
+
+ Delete Memory Management
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+;
VOID
EnableMaxPacketSize (
IN USB_HC_DEV *HcDev
- );
+ )
+/*++
+
+Routine Description:
+
+ Enable Max Packet Size
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
CleanUsbTransactions (
IN USB_HC_DEV *HcDev
- );
+ )
+/*++
+
+Routine Description:
+
+ Clean USB Transactions
+
+Arguments:
+
+ HcDev - A point to USB_HC_DEV
+
+Returns:
+
+ VOID
+
+--*/
+;
VOID
TurnOffUSBEmulation (
IN EFI_PCI_IO_PROTOCOL *PciIo
- );
+ )
+/*++
+
+Routine Description:
+
+ Set current framelist QH or TD
+
+Arguments:
+
+ pCurEntry - A point to FRAMELIST_ENTITY
+ IsQH - TRUE to set QH and FALSE to set TD
+
+Returns:
+
+ VOID
+
+--*/
+;
#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
index 0aa0507c2a..8cd6b8e6f6 100644
--- a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
@@ -710,7 +710,7 @@ BotDataPhase (
BufferPtr = (UINT8 *) DataBuffer;
TransferredSize = 0;
MaxRetry = 10;
- PackageNum = 15;
+ PackageNum = 128;
//
// retrieve the the max packet length of the given endpoint
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa
index 54a79ecd9a..d7101dce0e 100644
--- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa
@@ -83,7 +83,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
<Protocol Usage="BY_START">
<ProtocolCName>gEfiUsbIoProtocolGuid</ProtocolCName>
</Protocol>
- <Protocol Usage="TO_START">
+ <Protocol Usage="SOMETIMES_CONSUMED">
+ <ProtocolCName>gEfiUsb2HcProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="SOMETIMES_CONSUMED">
<ProtocolCName>gEfiUsbHcProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="TO_START">
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
index f4ac69e13f..1d1f44d638 100644
--- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
@@ -23,10 +23,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "usbbus.h"
-//#ifdef EFI_DEBUG
-UINTN gUSBDebugLevel = EFI_D_ERROR;
+UINTN gUSBDebugLevel = EFI_D_INFO;
UINTN gUSBErrorLevel = EFI_D_ERROR;
-//#endif
+
//
// The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER
// structure in the UsbBusDriverControllerDriverStop(). Then we can
@@ -121,17 +120,52 @@ UsbDeviceConfiguration (
//
STATIC
VOID
-EFIAPI
-UsbEnumeration (
+RootHubEnumeration (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+STATIC
+VOID
+HubEnumeration (
IN EFI_EVENT Event,
IN VOID *Context
);
+STATIC
+EFI_STATUS
+UsbSetTransactionTranslator (
+ IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
+ IN UINT8 ParentPort,
+ IN OUT USB_IO_DEVICE *Device
+ );
+
+STATIC
+EFI_STATUS
+UsbUnsetTransactionTranslator (
+ USB_IO_DEVICE *Device
+ );
+
+STATIC
+EFI_STATUS
+IdentifyDeviceSpeed (
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ USB_IO_DEVICE *NewDevice,
+ UINT8 Index
+ );
+
+STATIC
+EFI_STATUS
+ReleasePortToCHC (
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ UINT8 PortNum
+ );
+
EFI_STATUS
ResetRootPort (
- IN EFI_USB_HC_PROTOCOL *UsbHCInterface,
- IN UINT8 PortNum,
- IN UINT8 RetryTimes
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNum,
+ IN UINT8 RetryTimes
);
EFI_STATUS
@@ -140,12 +174,6 @@ ResetHubPort (
IN UINT8 PortIndex
);
-EFI_STATUS
-ClearRootPortConnectionChangeStatus (
- IN UINT8 PortNum,
- IN EFI_USB_HC_PROTOCOL *UsbHCInterface
- );
-
STATIC
EFI_STATUS
ParentPortReset (
@@ -162,6 +190,18 @@ UINT8
UsbAllocateAddress (
IN UINT8 *AddressPool
)
+/*++
+
+ Routine Description:
+ Allocate address for usb device
+
+ Arguments:
+ AddressPool - Pool of usb device address
+
+ Returns:
+ Usb device address
+
+--*/
{
UINT8 ByteIndex;
UINT8 BitIndex;
@@ -188,6 +228,19 @@ UsbFreeAddress (
IN UINT8 DevAddress,
IN UINT8 *AddressPool
)
+/*++
+
+ Routine Description:
+ Free address for usb device
+
+ Arguments:
+ DevAddress - Usb device address
+ AddressPool - Pool of usb device address
+
+ Returns:
+ VOID
+
+--*/
{
UINT8 WhichByte;
UINT8 WhichBit;
@@ -215,8 +268,8 @@ UsbBusControllerDriverSupported (
Arguments:
This - Protocol instance pointer.
- Controller - Handle of device to test
- RemainingDevicePath - Not used
+ Controller - Handle of device to test
+ RemainingDevicePath - Device Path Protocol instance pointer
Returns:
EFI_SUCCESS - This driver supports this device.
@@ -224,30 +277,103 @@ UsbBusControllerDriverSupported (
--*/
{
- EFI_STATUS OpenStatus;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
+ EFI_USB_HC_PROTOCOL *UsbHc;
+ EFI_DEV_PATH_PTR Node;
//
+ // Check Device Path
+ //
+ if (RemainingDevicePath != NULL) {
+ Node.DevPath = RemainingDevicePath;
+ if (Node.DevPath->Type != MESSAGING_DEVICE_PATH ||
+ Node.DevPath->SubType != MSG_USB_DP ||
+ DevicePathNodeLength(Node.DevPath) != sizeof(USB_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
// Check whether USB Host Controller Protocol is already
// installed on this handle. If it is installed, we can start
// USB Bus Driver now.
//
- OpenStatus = gBS->OpenProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- NULL,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &UsbHc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
- if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
- return EFI_UNSUPPORTED;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
}
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
- return OpenStatus;
+ return EFI_SUCCESS;
}
-
EFI_STATUS
EFIAPI
UsbBusControllerDriverStart (
@@ -270,11 +396,8 @@ UsbBusControllerDriverStart (
Returns:
EFI_SUCCESS - This driver supports this device.
- EFI_UNSUPPORTED - This driver does not support this device.
EFI_DEVICE_ERROR - This driver cannot be started due to device
- Error
EFI_OUT_OF_RESOURCES- Can't allocate memory resources
- EFI_ALREADY_STARTED - This driver has been started
--*/
{
@@ -283,7 +406,9 @@ UsbBusControllerDriverStart (
USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
USB_IO_DEVICE *RootHub;
USB_IO_CONTROLLER_DEVICE *RootHubController;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ UINT8 MaxSpeed;
+ UINT8 PortNumber;
+ UINT8 Is64BitCapable;
//
// Allocate USB_BUS_CONTROLLER_DEVICE structure
@@ -311,54 +436,56 @@ UsbBusControllerDriverStart (
if (EFI_ERROR (OpenStatus)) {
gBS->FreePool (UsbBusDev);
- return EFI_UNSUPPORTED;
+ return OpenStatus;
}
//
// Locate the Host Controller Interface
//
OpenStatus = gBS->OpenProtocol (
Controller,
- &gEfiUsbHcProtocolGuid,
- (VOID **) &UsbHCInterface,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &(UsbBusDev->Usb2HCInterface),
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
+ if (EFI_ERROR (OpenStatus)) {
- if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
-
- //
- // Report Status Code here since we will reset the host controller
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_ERROR_CODE | EFI_ERROR_MINOR,
- EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,
- UsbBusDev->DevicePath
- );
+ UsbBusDev->Hc2ProtocolSupported = FALSE;
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &(UsbBusDev->UsbHCInterface),
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (OpenStatus)) {
+ //
+ // Report Status Code here since we will reset the host controller
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,
+ UsbBusDev->DevicePath
+ );
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- gBS->FreePool (UsbBusDev);
- return EFI_UNSUPPORTED;
- }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBusDev);
+ return OpenStatus;
+ }
- if (OpenStatus == EFI_ALREADY_STARTED) {
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- gBS->FreePool (UsbBusDev);
- return EFI_ALREADY_STARTED;
+ DEBUG ((gUSBDebugLevel, "UsbHcProtocol Opened.\n"));
+ } else {
+ DEBUG ((gUSBDebugLevel, "Usb2HcProtocol Opened.\n"));
+ UsbBusDev->Hc2ProtocolSupported = TRUE;
}
- UsbBusDev->UsbHCInterface = UsbHCInterface;
-
//
// Attach EFI_USB_BUS_PROTOCOL to controller handle,
// for locate UsbBusDev later
@@ -378,12 +505,22 @@ UsbBusControllerDriverStart (
This->DriverBindingHandle,
Controller
);
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
gBS->FreePool (UsbBusDev);
return Status;
}
@@ -404,12 +541,22 @@ UsbBusControllerDriverStart (
This->DriverBindingHandle,
Controller
);
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
gBS->FreePool (UsbBusDev);
return EFI_OUT_OF_RESOURCES;
}
@@ -435,28 +582,41 @@ UsbBusControllerDriverStart (
This->DriverBindingHandle,
Controller
);
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
gBS->FreePool (UsbBusDev);
gBS->FreePool (RootHub);
return EFI_OUT_OF_RESOURCES;
}
- UsbHCInterface->GetRootHubPortNumber (
- UsbHCInterface,
- &RootHubController->DownstreamPorts
- );
- RootHubController->UsbDevice = RootHub;
- RootHubController->IsUsbHub = TRUE;
- RootHubController->DevicePath = UsbBusDev->DevicePath;
- RootHubController->HostController = Controller;
+ UsbVirtualHcGetCapability (
+ UsbBusDev,
+ &MaxSpeed,
+ &PortNumber,
+ &Is64BitCapable
+ );
+ RootHubController->DownstreamPorts = PortNumber;
+ RootHubController->UsbDevice = RootHub;
+ RootHubController->IsUsbHub = TRUE;
+ RootHubController->DevicePath = UsbBusDev->DevicePath;
+ RootHubController->HostController = Controller;
- RootHub->NumOfControllers = 1;
- RootHub->UsbController[0] = RootHubController;
+ RootHub->NumOfControllers = 1;
+ RootHub->UsbController[0] = RootHubController;
+ RootHub->DeviceSpeed = MaxSpeed;
//
// Report Status Code here since we will reset the host controller
@@ -470,10 +630,10 @@ UsbBusControllerDriverStart (
//
// Reset USB Host Controller
//
- UsbHCInterface->Reset (
- UsbHCInterface,
- EFI_USB_HC_RESET_GLOBAL
- );
+ UsbVirtualHcReset (
+ UsbBusDev,
+ EFI_USB_HC_RESET_GLOBAL
+ );
//
// Report Status Code while we are going to bring up the Host Controller
@@ -488,10 +648,10 @@ UsbBusControllerDriverStart (
//
// Start USB Host Controller
//
- UsbHCInterface->SetState (
- UsbHCInterface,
- EfiUsbHcStateOperational
- );
+ UsbVirtualHcSetState (
+ UsbBusDev,
+ EfiUsbHcStateOperational
+ );
//
// Create a timer to query root ports periodically
@@ -499,7 +659,7 @@ UsbBusControllerDriverStart (
Status = gBS->CreateEvent (
EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
EFI_TPL_CALLBACK,
- UsbEnumeration,
+ RootHubEnumeration,
RootHubController,
&RootHubController->HubNotify
);
@@ -517,17 +677,26 @@ UsbBusControllerDriverStart (
Controller
);
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
gBS->FreePool (RootHubController);
gBS->FreePool (RootHub);
gBS->FreePool (UsbBusDev);
- return EFI_UNSUPPORTED;
+ return EFI_OUT_OF_RESOURCES;
}
//
@@ -556,22 +725,32 @@ UsbBusControllerDriverStart (
Controller
);
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
gBS->CloseEvent (RootHubController->HubNotify);
gBS->FreePool (RootHubController);
gBS->FreePool (RootHub);
gBS->FreePool (UsbBusDev);
- return EFI_UNSUPPORTED;
+ return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
+
//
// Stop the bus controller
//
@@ -608,7 +787,6 @@ UsbBusControllerDriverStop (
USB_BUS_CONTROLLER_DEVICE *UsbBusController;
EFI_USB_BUS_PROTOCOL *UsbIdentifier;
UINT8 Index2;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
USB_IO_CONTROLLER_DEVICE *UsbController;
USB_IO_DEVICE *UsbIoDevice;
USB_IO_CONTROLLER_DEVICE *HubController;
@@ -678,7 +856,6 @@ UsbBusControllerDriverStop (
//
// Stop USB Host Controller
//
- UsbHCInterface = UsbBusController->UsbHCInterface;
//
// Report Status Code here since we will reset the host controller
@@ -689,10 +866,10 @@ UsbBusControllerDriverStop (
EFI_IO_BUS_USB | EFI_IOB_PC_RESET
);
- UsbHCInterface->SetState (
- UsbHCInterface,
- EfiUsbHcStateHalt
- );
+ UsbVirtualHcSetState (
+ UsbBusController,
+ EfiUsbHcStateHalt
+ );
//
// Deconfiguration all its devices
@@ -725,12 +902,21 @@ UsbBusControllerDriverStop (
// Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL
// Opened by this Controller
//
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ if (UsbBusController->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
gBS->CloseProtocol (
Controller,
@@ -786,6 +972,13 @@ UsbDeviceConfiguration (
USB_IO_CONTROLLER_DEVICE *UsbIoController;
UsbBusDev = UsbIoDevice->BusController;
+
+ UsbSetTransactionTranslator (
+ ParentHubController,
+ ParentPort,
+ UsbIoDevice
+ );
+
//
// Since a USB device must have at least on interface,
// so create this instance first
@@ -807,6 +1000,8 @@ UsbDeviceConfiguration (
//
UsbIo = &FirstController->UsbIo;
+ ParentPortReset (FirstController, FALSE, 0);
+
//
// First retrieve the 1st 8 bytes of
// in order to get the MaxPacketSize for Endpoint 0
@@ -815,7 +1010,7 @@ UsbDeviceConfiguration (
UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;
- ParentPortReset (FirstController, FALSE, Index);
+ gBS->Stall (100 * 1000);
Result = UsbGetDescriptor (
UsbIo,
@@ -826,7 +1021,8 @@ UsbDeviceConfiguration (
&Status
);
if (!EFI_ERROR (Result)) {
- DEBUG ((gUSBDebugLevel,
+ DEBUG (
+ (gUSBDebugLevel,
"Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",
UsbIoDevice->DeviceDescriptor.MaxPacketSize0)
);
@@ -875,6 +1071,11 @@ UsbDeviceConfiguration (
UsbIoDevice->DeviceAddress = DevAddress;
//
+ // SetAddress Complete Time by Spec, Max 50ms
+ //
+ gBS->Stall (10 * 1000);
+
+ //
// Get the whole device descriptor
//
Result = UsbGetDescriptor (
@@ -1049,7 +1250,6 @@ UsbDeviceConfiguration (
//
// USB Device DeConfiguration
//
-
EFI_STATUS
UsbDeviceDeConfiguration (
IN USB_IO_DEVICE *UsbIoDevice
@@ -1074,8 +1274,6 @@ UsbDeviceDeConfiguration (
UINT8 Index;
EFI_USB_IO_PROTOCOL *UsbIo;
- DEBUG ((gUSBDebugLevel, "Enter Usb Device Deconfiguration\n"));
-
//
// Double check UsbIoDevice exists
//
@@ -1083,6 +1281,8 @@ UsbDeviceDeConfiguration (
return EFI_SUCCESS;
}
+ UsbUnsetTransactionTranslator (UsbIoDevice);
+
for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {
//
// Check if it is a hub, if so, de configuration all its
@@ -1143,13 +1343,21 @@ UsbDeviceDeConfiguration (
//
// remove child handle reference to the USB_HC_PROTOCOL
//
- gBS->CloseProtocol (
- UsbController->HostController,
- &gEfiUsbHcProtocolGuid,
- gUsbBusDriverBinding.DriverBindingHandle,
- UsbController->Handle
- );
-
+ if (UsbIoDevice->BusController->Hc2ProtocolSupported) {
+ gBS->CloseProtocol (
+ UsbController->HostController,
+ &gEfiUsb2HcProtocolGuid,
+ gUsbBusDriverBinding.DriverBindingHandle,
+ UsbController->Handle
+ );
+ } else {
+ gBS->CloseProtocol (
+ UsbController->HostController,
+ &gEfiUsbHcProtocolGuid,
+ gUsbBusDriverBinding.DriverBindingHandle,
+ UsbController->Handle
+ );
+ }
//
// Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL
// installed on this handle
@@ -1314,30 +1522,31 @@ OnHubInterruptComplete (
STATIC
VOID
EFIAPI
-UsbEnumeration (
+RootHubEnumeration (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
- This is USB enumerator
+
+ This is USB RootHub enumerator
Arguments:
+
Event - Indicating which event is signaled
Context - actually it is a USB_IO_DEVICE
Returns:
- EFI_SUCCESS
- Others
-
+
+ VOID
+
--*/
{
USB_IO_CONTROLLER_DEVICE *HubController;
EFI_USB_PORT_STATUS HubPortStatus;
EFI_STATUS Status;
UINT8 Index;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
USB_IO_DEVICE *UsbIoDev;
USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
EFI_HANDLE HostController;
@@ -1346,476 +1555,561 @@ UsbEnumeration (
USB_IO_CONTROLLER_DEVICE *NewController;
UINT8 Index2;
EFI_USB_IO_PROTOCOL *UsbIo;
- UINT8 StatusChangePort;
HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
HostController = HubController->HostController;
UsbBusDev = HubController->UsbDevice->BusController;
- if (HubController->UsbDevice->DeviceAddress == 1) {
+ //
+ // Root hub has the address 1
+ //
+ UsbIoDev = HubController->UsbDevice;
+
+ for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
+
+ UsbVirtualHcGetRootHubPortStatus (
+ UsbBusDev,
+ Index,
+ (EFI_USB_PORT_STATUS *) &HubPortStatus
+ );
+
+ if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
+ continue;
+ }
//
- // Root hub has the address 1
+ // Clear root hub status change status
//
- UsbIoDev = HubController->UsbDevice;
- UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
-
- for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
- UsbHCInterface->GetRootHubPortStatus (
- UsbHCInterface,
- Index,
- (EFI_USB_PORT_STATUS *) &HubPortStatus
- );
+ UsbVirtualHcClearRootHubPortFeature (
+ UsbBusDev,
+ Index,
+ EfiUsbPortConnectChange
+ );
- if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
- continue;
- }
+ gBS->Stall (100 * 1000);
+
+ UsbVirtualHcGetRootHubPortStatus (
+ UsbBusDev,
+ Index,
+ (EFI_USB_PORT_STATUS *) &HubPortStatus
+ );
+
+ if (IsPortConnect (HubPortStatus.PortStatus)) {
+
//
- // Clear root hub status change status
+ // There is something connected to this port
//
- ClearRootPortConnectionChangeStatus (
- Index,
- UsbHCInterface
+ DEBUG ((gUSBDebugLevel, "Something connected to Root Hub at Port0x%x\n", Index));
+
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
);
+ //
+ // if there is something physically detached, but still logically
+ // attached...
+ //
+ OldUsbIoDevice = HubController->Children[Index];
- gBS->Stall (100 * 1000);
+ if (NULL != OldUsbIoDevice) {
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
+ HubController->Children[Index] = NULL;
+ }
- UsbHCInterface->GetRootHubPortStatus (
- UsbHCInterface,
- Index,
- (EFI_USB_PORT_STATUS *) &HubPortStatus
- );
+ NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
+ if (NewDevice == NULL) {
+ return ;
+ }
+ //
+ // Initialize some fields by copying data from
+ // its parents
+ //
+ NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;
+ NewDevice->BusController = UsbIoDev->BusController;
- if (IsPortConnect (HubPortStatus.PortStatus)) {
-
- //
- // There is something connected to this port
- //
- DEBUG ((gUSBDebugLevel, "Something attached from Root Hub in 0x%x\n", Index));
+ //
+ // Process of identify device speed
+ //
+ Status = IdentifyDeviceSpeed (
+ UsbBusDev,
+ NewDevice,
+ Index
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDevice);
+ continue;
+ }
- ReportUsbStatusCode (
- UsbBusDev,
- EFI_PROGRESS_CODE,
- EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
- );
+ //
+ // Configure that device
+ //
+ Status = UsbDeviceConfiguration (
+ HubController,
+ HostController,
+ Index,
+ NewDevice
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDevice);
+ return ;
+ }
+ //
+ // Add this device to the usb bus tree
+ //
+ HubController->Children[Index] = NewDevice;
+
+ for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
//
- // if there is something physically detached, but still logically
- // attached...
+ // If this device is hub, add to the hub index
//
- OldUsbIoDevice = HubController->Children[Index];
+ NewController = NewDevice->UsbController[Index2];
- if (NULL != OldUsbIoDevice) {
- UsbDeviceDeConfiguration (OldUsbIoDevice);
- HubController->Children[Index] = NULL;
- }
-
- NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
- if (NewDevice == NULL) {
- return ;
- }
+ Status = gBS->ConnectController (
+ NewController->Handle,
+ NULL,
+ NULL,
+ TRUE
+ );
//
- // Initialize some fields by copying data from
- // its parents
+ // If connect success, we need to disconnect when
+ // stop the controller, otherwise we need not call
+ // gBS->DisconnectController ()
+ // This is used by those usb devices we don't plan
+ // to support. We can allocate
+ // controller handles for them, but we don't have
+ // device drivers to manage them.
//
- NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);
+ NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
- DEBUG ((gUSBDebugLevel, "DeviceSpeed 0x%x\n", NewDevice->IsSlowDevice));
+ if (IsHub (NewController)) {
- NewDevice->BusController = UsbIoDev->BusController;
+ NewController->IsUsbHub = TRUE;
- //
- // Configure that device
- //
- Status = UsbDeviceConfiguration (
- HubController,
- HostController,
- Index,
- NewDevice
- );
- if (EFI_ERROR (Status)) {
- gBS->FreePool (NewDevice);
- return ;
- }
- //
- // Add this device to the usb bus tree
- //
- HubController->Children[Index] = NewDevice;
-
- for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
//
- // If this device is hub, add to the hub index
+ // Configure Hub Controller
//
- NewController = NewDevice->UsbController[Index2];
-
- Status = gBS->ConnectController (
- NewController->Handle,
- NULL,
- NULL,
- TRUE
- );
+ Status = DoHubConfig (NewController);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
//
- // If connect success, we need to disconnect when
- // stop the controller, otherwise we need not call
- // gBS->DisconnectController ()
- // This is used by those usb devices we don't plan
- // to support. We can allocate
- // controller handles for them, but we don't have
- // device drivers to manage them.
+ // Create an event to do hub enumeration
//
- NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
-
- if (IsHub (NewController)) {
-
- NewController->IsUsbHub = TRUE;
-
- //
- // Configure Hub Controller
- //
- Status = DoHubConfig (NewController);
- if (EFI_ERROR (Status)) {
- continue;
- }
- //
- // Create an event to do hub enumeration
- //
- gBS->CreateEvent (
- EFI_EVENT_NOTIFY_SIGNAL,
- EFI_TPL_CALLBACK,
- UsbEnumeration,
- NewController,
- &NewController->HubNotify
- );
+ gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ HubEnumeration,
+ NewController,
+ &NewController->HubNotify
+ );
- //
- // Add request to do query hub status
- // change endpoint
- // Hub ports < 7
- //
- UsbIo = &NewController->UsbIo;
- UsbIo->UsbAsyncInterruptTransfer (
- UsbIo,
- NewController->HubEndpointAddress,
- TRUE,
- 100,
- 1,
- OnHubInterruptComplete,
- NewController
- );
+ //
+ // Add request to do query hub status
+ // change endpoint
+ // Hub ports < 7
+ //
+ UsbIo = &NewController->UsbIo;
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ NewController->HubEndpointAddress,
+ TRUE,
+ 100,
+ 1,
+ OnHubInterruptComplete,
+ NewController
+ );
- }
}
- } else {
- //
- // Something disconnected from USB root hub
- //
- DEBUG ((gUSBDebugLevel, "Something deteached from Root Hub\n"));
+ }
+ } else {
+ //
+ // Something disconnected from USB root hub
+ //
+ DEBUG ((gUSBDebugLevel, "Something disconnected from Root Hub at Port0x%x\n", Index));
- OldUsbIoDevice = HubController->Children[Index];
+ OldUsbIoDevice = HubController->Children[Index];
- UsbDeviceDeConfiguration (OldUsbIoDevice);
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
- HubController->Children[Index] = NULL;
+ HubController->Children[Index] = NULL;
- UsbHCInterface->ClearRootHubPortFeature (
- UsbHCInterface,
- Index,
- EfiUsbPortEnableChange
- );
+ UsbVirtualHcClearRootHubPortFeature (
+ UsbBusDev,
+ Index,
+ EfiUsbPortEnableChange
+ );
+ }
+ }
- UsbHCInterface->GetRootHubPortStatus (
- UsbHCInterface,
- Index,
- (EFI_USB_PORT_STATUS *) &HubPortStatus
- );
+ return ;
+}
+//
+// USB Root Hub Enumerator
+//
+STATIC
+VOID
+EFIAPI
+HubEnumeration (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
- }
- }
+ Routine Description:
+
+ This is Usb Hub enumerator
- return ;
- } else {
+ Arguments:
+
+ Event - Indicating which event is signaled
+ Context - actually it is a USB_IO_DEVICE
+
+ Returns:
+
+ VOID
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *HubController;
+ EFI_USB_PORT_STATUS HubPortStatus;
+ EFI_STATUS Status;
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
+ EFI_HANDLE HostController;
+ USB_IO_DEVICE *OldUsbIoDevice;
+ USB_IO_DEVICE *NewDevice;
+ USB_IO_CONTROLLER_DEVICE *NewController;
+ UINT8 Index2;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 StatusChangePort;
+ UINT8 Number;
+
+ HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
+ HostController = HubController->HostController;
+ UsbBusDev = HubController->UsbDevice->BusController;
+
+ //
+ // Event from Hub, Get the hub controller handle
+ //
+ //
+ // Get the status change endpoint
+ //
+ StatusChangePort = HubController->StatusChangePort;
+
+ //
+ // Clear HubController Status Change Bit
+ //
+ HubController->StatusChangePort = 0;
+
+ if (StatusChangePort == 0) {
//
- // Event from Hub, Get the hub controller handle
+ // Hub changes, we don't handle here
//
+ return ;
+ }
+ //
+ // Check which event took place at that port
+ //
+ UsbIo = &HubController->UsbIo;
+ Status = HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ //
+ // Clear some change status
+ //
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
//
- // Get the status change endpoint
+ // Clear Hub port enable change
//
- StatusChangePort = HubController->StatusChangePort;
+ DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortEnableChange
+ );
+
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+ }
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
//
- // Clear HubController Status Change Bit
+ // Clear Hub reset change
//
- HubController->StatusChangePort = 0;
+ DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortResetChange
+ );
- if (StatusChangePort == 0) {
- //
- // Hub changes, we don't handle here
- //
- return ;
- }
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+ }
+
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {
//
- // Check which event took place at that port
+ // Clear Hub overcurrent change
//
- UsbIo = &HubController->UsbIo;
- Status = HubGetPortStatus (
- UsbIo,
- StatusChangePort,
- (UINT32 *) &HubPortStatus
- );
+ DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortOverCurrentChange
+ );
- if (EFI_ERROR (Status)) {
- return ;
- }
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+ }
+
+ if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
//
- // Clear some change status
+ // First clear port connection change
//
- if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
- //
- // Clear Hub port enable change
- //
- DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
- HubClearPortFeature (
- UsbIo,
- StatusChangePort,
- EfiUsbPortEnableChange
- );
+ DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortConnectChange
+ );
- HubGetPortStatus (
- UsbIo,
- StatusChangePort,
- (UINT32 *) &HubPortStatus
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+
+ if (IsPortConnect (HubPortStatus.PortStatus)) {
+
+ DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));
+
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
);
- }
- if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
//
- // Clear Hub reset change
+ // if there is something physically detached, but still logically
+ // attached...
//
- DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
- HubClearPortFeature (
- UsbIo,
- StatusChangePort,
- EfiUsbPortResetChange
- );
+ OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
- HubGetPortStatus (
- UsbIo,
- StatusChangePort,
- (UINT32 *) &HubPortStatus
- );
- }
+ if (NULL != OldUsbIoDevice) {
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
+ HubController->Children[StatusChangePort - 1] = NULL;
+ }
- if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {
+ NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
+ if (NewDevice == NULL) {
+ return ;
+ }
//
- // Clear Hub overcurrent change
+ // Initialize some fields
//
- DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));
- HubClearPortFeature (
- UsbIo,
- StatusChangePort,
- EfiUsbPortOverCurrentChange
- );
+ NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;
+ NewDevice->BusController = HubController->UsbDevice->BusController;
- HubGetPortStatus (
- UsbIo,
- StatusChangePort,
- (UINT32 *) &HubPortStatus
- );
- }
-
- if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
//
- // First clear port connection change
+ // There is something connected to this port,
+ // reset that port
+ //
+ // Disable the enable bit in port status
//
- DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));
HubClearPortFeature (
UsbIo,
StatusChangePort,
- EfiUsbPortConnectChange
- );
-
- HubGetPortStatus (
- UsbIo,
- StatusChangePort,
- (UINT32 *) &HubPortStatus
+ EfiUsbPortEnable
);
- if (IsPortConnect (HubPortStatus.PortStatus)) {
-
- DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));
+ gBS->Stall (50 * 1000);
- ReportUsbStatusCode (
- UsbBusDev,
- EFI_PROGRESS_CODE,
- EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
+ //
+ // Wait for bit change
+ //
+ Number = 10;
+ do {
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
);
+ gBS->Stall (10 * 1000);
+ Number -= 1;
+ } while ((HubPortStatus.PortStatus & USB_PORT_STAT_ENABLE) == 1 && Number > 0);
+ if (Number == 0) {
//
- // if there is something physically detached, but still logically
- // attached...
+ // Cannot disable port, return error
//
- OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
-
- if (NULL != OldUsbIoDevice) {
- UsbDeviceDeConfiguration (OldUsbIoDevice);
- HubController->Children[StatusChangePort - 1] = NULL;
- }
+ DEBUG ((gUSBErrorLevel, "Disable Port Failed\n"));
+ gBS->FreePool (NewDevice);
+ return ;
+ }
- NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
- if (NewDevice == NULL) {
- return ;
- }
+ HubSetPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortReset
+ );
- ResetHubPort (HubController, StatusChangePort);
+ gBS->Stall (50 * 1000);
+ //
+ // Wait for port reset complete
+ //
+ Number = 10;
+ do {
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
+ gBS->Stall (10 * 1000);
+ Number -= 1;
+ } while ((HubPortStatus.PortStatus & USB_PORT_STAT_RESET) == 1 && Number > 0);
+ if (Number == 0) {
//
- // Initialize some fields
+ // Cannot reset port, return error
//
- NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);
+ DEBUG ((gUSBErrorLevel, "Reset Port Failed\n"));
+ gBS->FreePool (NewDevice);
+ return ;
+ }
+ //
+ // Check high speed or full speed device
+ //
+ if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {
+ DEBUG ((gUSBDebugLevel, "Low Speed Device Attached to Hub\n"));
+ NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW;
+ } else if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {
+ DEBUG ((gUSBDebugLevel, "High Speed Device Attached to Hub\n"));
+ NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH;
+ } else {
+ DEBUG ((gUSBDebugLevel, "Full Speed Device Attached to Hub\n"));
+ NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL;
+ }
+ //
+ // Configure that device
+ //
+ Status = UsbDeviceConfiguration (
+ HubController,
+ HostController,
+ (UINT8) (StatusChangePort - 1),
+ NewDevice
+ );
- NewDevice->BusController = HubController->UsbDevice->BusController;
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDevice);
+ return ;
+ }
+ //
+ // Add this device to the usb bus tree
+ // StatusChangePort is begin from 1,
+ //
+ HubController->Children[StatusChangePort - 1] = NewDevice;
+ for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
//
- // Configure that device
+ // If this device is hub, add to the hub index
//
- Status = UsbDeviceConfiguration (
- HubController,
- HostController,
- (UINT8) (StatusChangePort - 1),
- NewDevice
- );
+ NewController = NewDevice->UsbController[Index2];
- if (EFI_ERROR (Status)) {
- gBS->FreePool (NewDevice);
- return ;
- }
//
- // Add this device to the usb bus tree
- // StatusChangePort is begin from 1,
+ // Connect the controller to the driver image
//
- HubController->Children[StatusChangePort - 1] = NewDevice;
+ Status = gBS->ConnectController (
+ NewController->Handle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ //
+ // If connect success, we need to disconnect when
+ // stop the controller, otherwise we need not call
+ // gBS->DisconnectController ()
+ // This is used by those usb devices we don't plan
+ // to support. We can allocate
+ // controller handles for them, but we don't have
+ // device drivers to manage them.
+ //
+ NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
- for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
- //
- // If this device is hub, add to the hub index
- //
- NewController = NewDevice->UsbController[Index2];
+ //
+ // If this device is hub, add to the hub index
+ //
+ if (IsHub (NewController)) {
+
+ NewController->IsUsbHub = TRUE;
//
- // Connect the controller to the driver image
+ // Configure Hub
//
- Status = gBS->ConnectController (
- NewController->Handle,
- NULL,
- NULL,
- TRUE
- );
+ Status = DoHubConfig (NewController);
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
//
- // If connect success, we need to disconnect when
- // stop the controller, otherwise we need not call
- // gBS->DisconnectController ()
- // This is used by those usb devices we don't plan
- // to support. We can allocate
- // controller handles for them, but we don't have
- // device drivers to manage them.
+ // Create an event to do hub enumeration
//
- NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
+ gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ HubEnumeration,
+ NewController,
+ &NewController->HubNotify
+ );
//
- // If this device is hub, add to the hub index
+ // Add request to do query hub status
+ // change endpoint
//
- if (IsHub (NewController)) {
-
- NewController->IsUsbHub = TRUE;
-
- //
- // Configure Hub
- //
- Status = DoHubConfig (NewController);
-
- if (EFI_ERROR (Status)) {
- continue;
- }
- //
- // Create an event to do hub enumeration
- //
- gBS->CreateEvent (
- EFI_EVENT_NOTIFY_SIGNAL,
- EFI_TPL_CALLBACK,
- UsbEnumeration,
- NewController,
- &NewController->HubNotify
+ UsbIo = &NewController->UsbIo;
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ NewController->HubEndpointAddress, // Hub endpoint address
+ TRUE,
+ 100,
+ 1, // Hub ports < 7
+ OnHubInterruptComplete,
+ NewController
);
-
- //
- // Add request to do query hub status
- // change endpoint
- //
- UsbIo = &NewController->UsbIo;
- UsbIo->UsbAsyncInterruptTransfer (
- UsbIo,
- NewController->HubEndpointAddress, // Hub endpoint address
- TRUE,
- 100,
- 1, // Hub ports < 7
- OnHubInterruptComplete,
- NewController
- );
- }
}
- } else {
- //
- // Something disconnected from USB hub
- //
- DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));
-
- OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
+ }
+ } else {
+ //
+ // Something disconnected from USB hub
+ //
+ DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));
- UsbDeviceDeConfiguration (OldUsbIoDevice);
+ OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
- HubController->Children[StatusChangePort - 1] = NULL;
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
- }
+ HubController->Children[StatusChangePort - 1] = NULL;
- return ;
}
return ;
}
-}
-//
-// Clear port connection change status over a given root hub port
-//
-EFI_STATUS
-ClearRootPortConnectionChangeStatus (
- UINT8 PortNum,
- EFI_USB_HC_PROTOCOL *UsbHCInterface
- )
-/*++
- Routine Description:
- Clear port connection change status over a given root hub port
-
- Arguments:
- PortNum - The given port.
- UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.
-
- Returns:
- EFI_SUCCESS
-
---*/
-{
- EFI_STATUS Status;
- Status = UsbHCInterface->ClearRootHubPortFeature (
- UsbHCInterface,
- PortNum,
- EfiUsbPortConnectChange
- );
- return Status;
+ return ;
}
STATIC
@@ -1877,6 +2171,7 @@ InitUsbIoController (
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_USB_HC_PROTOCOL *UsbHcProtocol;
+ EFI_USB2_HC_PROTOCOL *Usb2HcProtocol;
//
// Build the child device path for each new USB_IO device
@@ -1908,14 +2203,25 @@ InitUsbIoController (
return Status;
}
- Status = gBS->OpenProtocol (
- UsbIoController->HostController,
- &gEfiUsbHcProtocolGuid,
- (VOID **) &UsbHcProtocol,
- gUsbBusDriverBinding.DriverBindingHandle,
- UsbIoController->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
+ if (UsbIoController->UsbDevice->BusController->Hc2ProtocolSupported) {
+ Status = gBS->OpenProtocol (
+ UsbIoController->HostController,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **)&Usb2HcProtocol,
+ gUsbBusDriverBinding.DriverBindingHandle,
+ UsbIoController->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ Status = gBS->OpenProtocol (
+ UsbIoController->HostController,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **)&UsbHcProtocol,
+ gUsbBusDriverBinding.DriverBindingHandle,
+ UsbIoController->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ }
return Status;
}
@@ -1934,8 +2240,9 @@ ParentPortReset (
Arguments:
UsbIoController - Indicating the Usb Controller Device.
- Reconfigure - Do we need to reconfigure it.
+ ReConfigure - Do we need to reconfigure it.
RetryTimes - Retry Times when failed
+
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
@@ -1960,7 +2267,7 @@ ParentPortReset (
if (ParentIoDev->DeviceAddress == 1) {
DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));
- ResetRootPort (ParentIoDev->BusController->UsbHCInterface, HubPort, RetryTimes);
+ ResetRootPort (ParentIoDev->BusController, HubPort, RetryTimes);
} else {
DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));
ResetHubPort (ParentController, HubPort + 1);
@@ -2036,9 +2343,9 @@ UsbPortReset (
EFI_STATUS
ResetRootPort (
- IN EFI_USB_HC_PROTOCOL *UsbHCInterface,
- IN UINT8 PortNum,
- IN UINT8 RetryTimes
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNum,
+ IN UINT8 RetryTimes
)
/*++
@@ -2046,25 +2353,27 @@ ResetRootPort (
Reset Root Hub port.
Arguments:
- UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.
- PortNum - The given port to be reset.
- RetryTimes - RetryTimes when failed
+ UsbBusDev - Bus controller of the device.
+ PortNum - The given port to be reset.
+ RetryTimes - RetryTimes when failed
+
Returns:
- N/A
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
--*/
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_USB_PORT_STATUS PortStatus;
//
// reset root port
//
- Status = UsbHCInterface->SetRootHubPortFeature (
- UsbHCInterface,
- PortNum,
- EfiUsbPortReset
- );
-
+ Status = UsbVirtualHcSetRootHubPortFeature (
+ UsbBusDev,
+ PortNum,
+ EfiUsbPortReset
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -2074,46 +2383,56 @@ ResetRootPort (
//
// clear reset root port
//
- Status = UsbHCInterface->ClearRootHubPortFeature (
- UsbHCInterface,
- PortNum,
- EfiUsbPortReset
- );
-
+ Status = UsbVirtualHcClearRootHubPortFeature (
+ UsbBusDev,
+ PortNum,
+ EfiUsbPortReset
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
gBS->Stall (1000);
- Status = ClearRootPortConnectionChangeStatus (PortNum, UsbHCInterface);
-
+ Status = UsbVirtualHcClearRootHubPortFeature (
+ UsbBusDev,
+ PortNum,
+ EfiUsbPortConnectChange
+ );
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
- //
- // Set port enable
- //
- Status = UsbHCInterface->SetRootHubPortFeature (
- UsbHCInterface,
- PortNum,
- EfiUsbPortEnable
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
+
+ UsbVirtualHcGetRootHubPortStatus (
+ UsbBusDev,
+ PortNum,
+ &PortStatus
+ );
+ if (PortStatus.PortStatus & USB_PORT_STAT_OWNER) {
+ //
+ // Set port enable
+ //
+ Status = UsbVirtualHcSetRootHubPortFeature (
+ UsbBusDev,
+ PortNum,
+ EfiUsbPortEnable
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = UsbVirtualHcClearRootHubPortFeature (
+ UsbBusDev,
+ PortNum,
+ EfiUsbPortEnableChange
+ );
}
- Status = UsbHCInterface->ClearRootHubPortFeature (
- UsbHCInterface,
- PortNum,
- EfiUsbPortEnableChange
- );
gBS->Stall ((1 + RetryTimes) * 50 * 1000);
return EFI_SUCCESS;
}
-
EFI_STATUS
ResetHubPort (
IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
@@ -2202,10 +2521,6 @@ ResetHubPort (
return EFI_SUCCESS;
}
-
-
-
-
STATIC
EFI_STATUS
ReportUsbStatusCode (
@@ -2236,7 +2551,6 @@ Routine Description:
);
}
-
EFI_STATUS
IsDeviceDisconnected (
IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
@@ -2264,7 +2578,6 @@ IsDeviceDisconnected (
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_PORT_STATUS PortStatus;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
ParentController = UsbIoController->Parent;
ParentIoDev = ParentController->UsbDevice;
@@ -2275,12 +2588,11 @@ IsDeviceDisconnected (
//
// Connected to the root hub
//
- UsbHCInterface = ParentIoDev->BusController->UsbHCInterface;
- Status = UsbHCInterface->GetRootHubPortStatus (
- UsbHCInterface,
- HubPort,
- &PortStatus
- );
+ UsbVirtualHcGetRootHubPortStatus (
+ ParentIoDev->BusController,
+ HubPort,
+ &PortStatus
+ );
} else {
UsbIo = &UsbIoController->UsbIo;
@@ -2303,3 +2615,1135 @@ IsDeviceDisconnected (
return EFI_SUCCESS;
}
+
+STATIC
+EFI_STATUS
+UsbSetTransactionTranslator (
+ IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
+ IN UINT8 ParentPort,
+ IN OUT USB_IO_DEVICE *Device
+ )
+/*++
+
+ Routine Description:
+
+ Set Transaction Translator parameter
+
+ Arguments:
+
+ ParentHubController - Controller structure of the parent Hub device
+ ParentPort - Number of parent port
+ Device - Structure of the device
+
+ Returns:
+
+ EFI_SUCCESS Success
+ EFI_OUT_OF_RESOURCES Cannot allocate resources
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *AncestorHubController;
+
+ AncestorHubController = ParentHubController;
+ Device->Translator = NULL;
+
+ if (EFI_USB_SPEED_HIGH == Device->DeviceSpeed) {
+ return EFI_SUCCESS;
+ }
+
+ do {
+ if (EFI_USB_SPEED_HIGH == AncestorHubController->UsbDevice->DeviceSpeed) {
+ break;
+ }
+
+ if (NULL == AncestorHubController->Parent) {
+ return EFI_SUCCESS;
+ }
+
+ AncestorHubController = AncestorHubController->Parent;
+ } while (1);
+
+ Device->Translator = AllocatePool (sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR));
+ if (NULL == Device->Translator) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Device->Translator->TranslatorHubAddress = AncestorHubController->UsbDevice->DeviceAddress;
+ Device->Translator->TranslatorPortNumber = ParentPort;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+UsbUnsetTransactionTranslator (
+ USB_IO_DEVICE *Device
+ )
+/*++
+
+ Routine Description:
+
+ Unset Transaction Translator parameter
+
+ Arguments:
+
+ Device - Structure of the device
+
+ Returns:
+
+ EFI_SUCCESS Success
+
+--*/
+{
+ if (Device->Translator) {
+ gBS->FreePool (Device->Translator);
+ Device->Translator = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+IdentifyDeviceSpeed (
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ USB_IO_DEVICE *NewDevice,
+ UINT8 Index
+ )
+/*++
+
+ Routine Description:
+
+ Identify speed of USB device
+
+ Arguments:
+
+ UsbBusDev - UsbBus controller structure of the device
+ NewDevice - Devcie controller structure
+ Index - Number of the port
+
+ Returns:
+
+ EFI_SUCCESS Success
+ EFI_NOT_FOUND Device release to CHC or can't be found
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_PORT_STATUS HubPortStatus;
+
+ UsbVirtualHcGetRootHubPortStatus (
+ UsbBusDev,
+ Index,
+ (EFI_USB_PORT_STATUS *) &HubPortStatus
+ );
+
+ //
+ // Check device device
+ //
+ if (!(HubPortStatus.PortStatus & USB_PORT_STAT_OWNER)) {
+ //
+ // EHC Port Owner
+ //
+ if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {
+ DEBUG ((gUSBDebugLevel, "High Speed Device attached to EHC\n"));
+ NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH;
+ } else {
+ Status = ReleasePortToCHC (UsbBusDev, Index);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gUSBErrorLevel, "Fail to release port to CHC\n"));
+ } else {
+ DEBUG ((gUSBDebugLevel, "Success to release port to CHC\n"));
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ //
+ // CHC Port Owner
+ //
+ if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {
+ DEBUG ((gUSBDebugLevel, "Low Speed Device attached to CHC\n"));
+ NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW;
+ } else {
+ DEBUG ((gUSBDebugLevel, "FULL Speed Device attached to CHC\n"));
+ NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+ReleasePortToCHC (
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ UINT8 PortNum
+ )
+/*++
+
+ Routine Description:
+
+ Set bit to release the port owner to CHC
+
+ Arguments:
+
+ UsbBusDev - UsbBus controller structure of the device
+ PortNum - Number of the port
+
+ Returns:
+
+ EFI_SUCCESS Success
+ EFI_DEVICE_ERROR Fail
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = UsbVirtualHcSetRootHubPortFeature (
+ UsbBusDev,
+ PortNum,
+ EfiUsbPortOwner
+ );
+
+ gBS->Stall (100 * 1000);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcGetCapability (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to Retrieves the capablility of root hub ports
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ MaxSpeed - A pointer to the number of the host controller.
+ PortNumber - A pointer to the number of the root hub ports.
+ Is64BitCapable - A pointer to the flag for whether controller supports
+ 64-bit memory addressing.
+
+ Returns:
+
+ EFI_SUCCESS
+ The host controller capability were retrieved successfully.
+ EFI_INVALID_PARAMETER
+ MaxSpeed or PortNumber or Is64BitCapable is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the capabilities.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->GetCapability (
+ UsbBusDev->Usb2HCInterface,
+ MaxSpeed,
+ PortNumber,
+ Is64BitCapable
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->GetRootHubPortNumber (
+ UsbBusDev->UsbHCInterface,
+ PortNumber
+ );
+ *MaxSpeed = EFI_USB_SPEED_FULL;
+ *Is64BitCapable = (UINT8) FALSE;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcReset (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT16 Attributes
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to provides software reset for the USB host controller
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ Attributes - A bit mask of the reset operation to perform.
+ See below for a list of the supported bit mask values.
+
+ #define EFI_USB_HC_RESET_GLOBAL 0x0001 // Hc2 and Hc
+ #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 // Hc2 and Hc
+ #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 // Hc2
+ #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 // Hc2
+
+ EFI_USB_HC_RESET_GLOBAL
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ EFI_USB_HC_RESET_HOST_CONTROLLER
+ If this bit is set, the USB host controller hardware will be reset.
+ No reset signal will be sent to the USB bus.
+ EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ If this is an EHCI controller and the debug port has configured, then
+ this is will still reset the host controller.
+ EFI_USB_HC_RESET_HOST_WITH_DEBUG
+ If this bit is set, the USB host controller hardware will be reset.
+ If this is an EHCI controller and the debug port has been configured,
+ then this will still reset the host controller.
+
+ Returns:
+
+ EFI_SUCCESS
+ The reset operation succeeded.
+ EFI_INVALID_PARAMETER
+ Attributes is not valid.
+ EFI_UNSUPPOURTED
+ The type of reset specified by Attributes is not currently supported by
+ the host controller hardware.
+ EFI_ACCESS_DENIED
+ Reset operation is rejected due to the debug port being configured and
+ active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or
+ EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
+ perform reset operation for this host controller.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to perform
+ the reset operation.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->Reset (
+ UsbBusDev->Usb2HCInterface,
+ EFI_USB_HC_RESET_GLOBAL
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->Reset (
+ UsbBusDev->UsbHCInterface,
+ EFI_USB_HC_RESET_GLOBAL
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcGetState (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ OUT EFI_USB_HC_STATE *State
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to retrieves current state of the USB host controller
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ State - A pointer to the EFI_USB_HC_STATE data structure that
+ indicates current state of the USB host controller.
+ Type EFI_USB_HC_STATE is defined below.
+
+ typedef enum {
+ EfiUsbHcStateHalt,
+ EfiUsbHcStateOperational,
+ EfiUsbHcStateSuspend,
+ EfiUsbHcStateMaximum
+ } EFI_USB_HC_STATE;
+
+ Returns:
+
+ EFI_SUCCESS
+ The state information of the host controller was returned in State.
+ EFI_INVALID_PARAMETER
+ State is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the
+ host controller's current state.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->GetState (
+ UsbBusDev->Usb2HCInterface,
+ State
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->GetState (
+ UsbBusDev->UsbHCInterface,
+ State
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcSetState (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN EFI_USB_HC_STATE State
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to sets the USB host controller to a specific state
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ State - Indicates the state of the host controller that will be set.
+
+ Returns:
+
+ EFI_SUCCESS
+ The USB host controller was successfully placed in the state
+ specified by State.
+ EFI_INVALID_PARAMETER
+ State is invalid.
+ EFI_DEVICE_ERROR
+ Failed to set the state specified by State due to device error.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->SetState (
+ UsbBusDev->Usb2HCInterface,
+ State
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->SetState (
+ UsbBusDev->UsbHCInterface,
+ State
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcGetRootHubPortStatus (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to retrieves the current status of a USB root hub port
+ both for Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ PortNumber - Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+ PortStatus - A pointer to the current port status bits and
+ port status change bits.
+
+ Returns:
+
+ EFI_SUCCESS The status of the USB root hub port specified by PortNumber
+ was returned in PortStatus.
+ EFI_INVALID_PARAMETER PortNumber is invalid.
+ EFI_DEVICE_ERROR Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->GetRootHubPortStatus (
+ UsbBusDev->Usb2HCInterface,
+ PortNumber,
+ PortStatus
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->GetRootHubPortStatus (
+ UsbBusDev->UsbHCInterface,
+ PortNumber,
+ PortStatus
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcSetRootHubPortFeature (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+ Virual interface to sets a feature for the specified root hub port
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ PortNumber - Specifies the root hub port whose feature
+ is requested to be set.
+ PortFeature - Indicates the feature selector associated
+ with the feature set request.
+
+ Returns:
+
+ EFI_SUCCESS
+ The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->SetRootHubPortFeature (
+ UsbBusDev->Usb2HCInterface,
+ PortNumber,
+ PortFeature
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->SetRootHubPortFeature (
+ UsbBusDev->UsbHCInterface,
+ PortNumber,
+ PortFeature
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcClearRootHubPortFeature (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to clears a feature for the specified root hub port
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ PortNumber - Specifies the root hub port whose feature
+ is requested to be cleared.
+ PortFeature - Indicates the feature selector associated with the
+ feature clear request.
+
+ Returns:
+
+ EFI_SUCCESS
+ The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->ClearRootHubPortFeature (
+ UsbBusDev->Usb2HCInterface,
+ PortNumber,
+ PortFeature
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->ClearRootHubPortFeature (
+ UsbBusDev->UsbHCInterface,
+ PortNumber,
+ PortFeature
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcControlTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits control transfer to a target USB device
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ DeviceSpeed - Indicates target device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ Request - A pointer to the USB device request that will be sent
+ to the USB device.
+ TransferDirection - Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ TimeOut - Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The control transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The control transfer could not be completed due to a lack of resources.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The control transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN IsSlowDevice;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->ControlTransfer (
+ UsbBusDev->Usb2HCInterface,
+ DeviceAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ Request,
+ TransferDirection,
+ Data,
+ DataLength,
+ TimeOut,
+ Translator,
+ TransferResult
+ );
+ } else {
+ IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;
+ Status = UsbBusDev->UsbHCInterface->ControlTransfer (
+ UsbBusDev->UsbHCInterface,
+ DeviceAddress,
+ IsSlowDevice,
+ (UINT8) MaximumPacketLength,
+ Request,
+ TransferDirection,
+ Data,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcBulkTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits bulk transfer to a bulk endpoint of a USB device
+ both for Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+ DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
+ and EFI_USB_SPEED_HIGH.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+ DataToggle - A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+ Translator - A pointr to the transaction translator data.
+ TimeOut - Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ TransferResult - A pointer to the detailed result information of the
+ bulk transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The bulk transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The bulk transfer could not be submitted due to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The bulk transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->BulkTransfer (
+ UsbBusDev->Usb2HCInterface,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ DataBuffersNumber,
+ Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ Translator,
+ TransferResult
+ );
+ } else {
+ Status = UsbBusDev->UsbHCInterface->BulkTransfer (
+ UsbBusDev->UsbHCInterface,
+ DeviceAddress,
+ EndPointAddress,
+ (UINT8) MaximumPacketLength,
+ *Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcAsyncInterruptTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE * UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ DataToggle - A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ PollingInterval - Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ DataLength - Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ Translator - A pointr to the transaction translator data.
+ CallBackFunction - The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ Context - The context that is passed to the CallBackFunction.
+ - This is an optional parameter and may be NULL.
+
+ Returns:
+
+ EFI_SUCCESS
+ The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_OUT_OF_RESOURCES
+ The request could not be completed due to a lack of resources.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN IsSlowDevice;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->AsyncInterruptTransfer (
+ UsbBusDev->Usb2HCInterface,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ IsNewTransfer,
+ DataToggle,
+ PollingInterval,
+ DataLength,
+ Translator,
+ CallBackFunction,
+ Context
+ );
+ } else {
+ IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;
+ Status = UsbBusDev->UsbHCInterface->AsyncInterruptTransfer (
+ UsbBusDev->UsbHCInterface,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ (UINT8) MaximumPacketLength,
+ IsNewTransfer,
+ DataToggle,
+ PollingInterval,
+ DataLength,
+ CallBackFunction,
+ Context
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcSyncInterruptTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Vitual interface to submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+ DataToggle - A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+ TimeOut - Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The synchronous interrupt transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The synchronous interrupt transfer could not be submitted due
+ to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The synchronous interrupt transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The synchronous interrupt transfer failed due to host controller
+ or device error. Caller should check TranferResult for detailed
+ error information.
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN IsSlowDevice;
+
+ Status = EFI_SUCCESS;
+
+ if (UsbBusDev->Hc2ProtocolSupported) {
+ Status = UsbBusDev->Usb2HCInterface->SyncInterruptTransfer (
+ UsbBusDev->Usb2HCInterface,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ Translator,
+ TransferResult
+ );
+ } else {
+ IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;
+ Status = UsbBusDev->UsbHCInterface->SyncInterruptTransfer (
+ UsbBusDev->UsbHCInterface,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ (UINT8) MaximumPacketLength,
+ Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcIsochronousTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits isochronous transfer to a target USB device
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be
+ transmitted to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcAsyncIsochronousTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+
+ Vitual interface to submits Async isochronous transfer to a target USB device
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ Translator - A pointr to the transaction translator data.
+ IsochronousCallBack - When the transfer complete, the call back function will be called
+ Context - Pass to the call back function as parameter
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h
index 036f4dfe50..47f0fd804f 100644
--- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h
@@ -30,13 +30,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "hub.h"
#include "usbutil.h"
-//#ifdef EFI_DEBUG
extern UINTN gUSBDebugLevel;
extern UINTN gUSBErrorLevel;
-//#endif
-#define MICROSECOND 10000
-#define ONESECOND (1000 * MICROSECOND)
+#define MICROSECOND 10000
+#define ONESECOND (1000 * MICROSECOND)
#define BUSPOLLING_PERIOD ONESECOND
//
// We define some maximun value here
@@ -120,21 +118,23 @@ typedef struct usb_io_controller_device {
struct _usb_bus_controller_device;
typedef struct usb_io_device {
- UINT8 DeviceAddress;
- BOOLEAN IsConfigured;
- BOOLEAN IsSlowDevice;
- EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
- LIST_ENTRY ConfigDescListHead;
- CONFIG_DESC_LIST_ENTRY *ActiveConfig;
- UINT16 LangID[USB_MAXLANID];
+ UINT8 DeviceAddress;
+ BOOLEAN IsConfigured;
+ BOOLEAN IsSlowDevice;
+ UINT8 DeviceSpeed;
+ EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator;
+ EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+ LIST_ENTRY ConfigDescListHead;
+ CONFIG_DESC_LIST_ENTRY *ActiveConfig;
+ UINT16 LangID[USB_MAXLANID];
- struct _usb_bus_controller_device *BusController;
+ struct _usb_bus_controller_device *BusController;
//
// Track the controller handle
//
- UINT8 NumOfControllers;
- USB_IO_CONTROLLER_DEVICE *UsbController[USB_MAXCONTROLLERS];
+ UINT8 NumOfControllers;
+ USB_IO_CONTROLLER_DEVICE *UsbController[USB_MAXCONTROLLERS];
} USB_IO_DEVICE;
@@ -154,10 +154,12 @@ typedef struct _usb_bus_controller_device {
UINTN Signature;
EFI_USB_BUS_PROTOCOL BusIdentify;
+ EFI_USB2_HC_PROTOCOL *Usb2HCInterface;
EFI_USB_HC_PROTOCOL *UsbHCInterface;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT8 AddressPool[16];
USB_IO_DEVICE *Root;
+ BOOLEAN Hc2ProtocolSupported;
} USB_BUS_CONTROLLER_DEVICE;
#define USB_BUS_CONTROLLER_DEVICE_FROM_THIS(a) \
@@ -177,28 +179,99 @@ extern EFI_GUID gUSBBusDriverGuid;
BOOLEAN
IsHub (
IN USB_IO_CONTROLLER_DEVICE *Dev
- );
+ )
+/*++
+
+ Routine Description:
+ Tell if a usb controller is a hub controller.
+
+ Arguments:
+ Dev - UsbIoController device structure.
+
+ Returns:
+ TRUE/FALSE
+--*/
+;
EFI_STATUS
UsbGetStringtable (
IN USB_IO_DEVICE *UsbIoDevice
- );
+ )
+/*++
+
+ Routine Description:
+ Get the string table stored in a usb device.
+
+ Arguments:
+ Dev - UsbIoController device structure.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_UNSUPPORTED
+ EFI_OUT_OF_RESOURCES
+
+--*/
+;
EFI_STATUS
UsbGetAllConfigurations (
IN USB_IO_DEVICE *UsbIoDevice
- );
+ )
+/*++
+
+ Routine Description:
+ This function is to parse all the configuration descriptor.
+
+ Arguments:
+ UsbIoDevice - USB_IO_DEVICE device structure.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+;
EFI_STATUS
UsbSetConfiguration (
IN USB_IO_DEVICE *Dev,
IN UINTN ConfigurationValue
- );
+ )
+/*++
+
+ Routine Description:
+ Set the device to a configuration value.
+
+ Arguments:
+ UsbIoDev - USB_IO_DEVICE to be set configuration
+ ConfigrationValue - The configuration value to be set to that device
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+;
EFI_STATUS
UsbSetDefaultConfiguration (
IN USB_IO_DEVICE *Dev
- );
+ )
+/*++
+
+ Routine Description:
+ Set the device to a default configuration value.
+
+ Arguments:
+ UsbIoDev - USB_IO_DEVICE to be set configuration
+
+ Returns
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+;
//
// Device Deconfiguration functions
@@ -206,56 +279,834 @@ UsbSetDefaultConfiguration (
VOID
UsbDestroyAllConfiguration (
IN USB_IO_DEVICE *UsbIoDevice
- );
+ )
+/*++
+
+ Routine Description:
+ Delete all configuration data when device is not used.
+
+ Arguments:
+ UsbIoDevice - USB_IO_DEVICE to be set configuration
+
+ Returns:
+ VOID
+
+--*/
+;
EFI_STATUS
DoHubConfig (
IN USB_IO_CONTROLLER_DEVICE *HubIoDevice
- );
+ )
+/*++
+
+ Routine Description:
+ Configure the hub
+
+ Arguments:
+ HubController - Indicating the hub controller device that
+ will be configured
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+
+;
VOID
GetDeviceEndPointMaxPacketLength (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN UINT8 EndpointAddr,
- OUT UINT8 *MaxPacketLength
- );
+ OUT UINTN *MaxPacketLength
+ )
+/*++
+
+ Routine Description:
+ Get the Max Packet Length of the speified Endpoint.
+
+ Arguments:
+ UsbIo - Given Usb Controller device.
+ EndpointAddr - Given Endpoint address.
+ MaxPacketLength - The max packet length of that endpoint
+
+ Returns:
+ N/A
+
+--*/
+;
VOID
GetDataToggleBit (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN UINT8 EndpointAddr,
OUT UINT8 *DataToggle
- );
+ )
+/*++
+
+ Routine Description:
+ Get the datatoggle of a specified endpoint.
+
+ Arguments:
+ UsbIo - Given Usb Controller device.
+ EndpointAddr - Given Endpoint address.
+ DataToggle - The current data toggle of that endpoint
+
+ Returns:
+ VOID
+
+--*/
+;
VOID
SetDataToggleBit (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN UINT8 EndpointAddr,
IN UINT8 DataToggle
- );
+ )
+/*++
+
+ Routine Description:
+ Set the datatoggle of a specified endpoint
+
+ Arguments:
+ UsbIo - Given Usb Controller device.
+ EndpointAddr - Given Endpoint address.
+ DataToggle - The current data toggle of that endpoint to be set
+
+ Returns:
+ VOID
+
+--*/
+;
-INTERFACE_DESC_LIST_ENTRY *
+INTERFACE_DESC_LIST_ENTRY *
FindInterfaceListEntry (
IN EFI_USB_IO_PROTOCOL *This
- );
+ )
+/*++
+
+ Routine Description:
+ Find Interface ListEntry.
-ENDPOINT_DESC_LIST_ENTRY *
+ Arguments:
+ This - EFI_USB_IO_PROTOCOL
+
+ Returns:
+ INTERFACE_DESC_LIST_ENTRY pointer
+
+--*/
+;
+
+ENDPOINT_DESC_LIST_ENTRY *
FindEndPointListEntry (
IN EFI_USB_IO_PROTOCOL *This,
IN UINT8 EndPointAddress
- );
+ )
+/*++
+
+ Routine Description:
+ Find EndPoint ListEntry.
+ Arguments:
+ This - EFI_USB_IO_PROTOCOL
+ EndpointAddr - Endpoint address.
+
+ Returns:
+ ENDPOINT_DESC_LIST_ENTRY pointer
+
+--*/
+;
EFI_STATUS
IsDeviceDisconnected (
IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
IN OUT BOOLEAN *Disconnected
- );
+ )
+/*++
+
+ Routine Description:
+ Reset if the device is disconencted or not
+
+ Arguments:
+ UsbIoController - Indicating the Usb Controller Device.
+ Disconnected - Indicate whether the device is disconencted or not
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+;
EFI_STATUS
UsbDeviceDeConfiguration (
IN USB_IO_DEVICE *UsbIoDevice
- );
+ )
+/*++
+
+ Routine Description:
+ Remove Device, Device Handles, Uninstall Protocols.
+
+ Arguments:
+ UsbIoDevice - The device to be deconfigured.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+;
+EFI_STATUS
+EFIAPI
+UsbVirtualHcGetCapability (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to Retrieves the capablility of root hub ports
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ MaxSpeed - A pointer to the number of the host controller.
+ PortNumber - A pointer to the number of the root hub ports.
+ Is64BitCapable - A pointer to the flag for whether controller supports
+ 64-bit memory addressing.
+
+ Returns:
+
+ EFI_SUCCESS
+ The host controller capability were retrieved successfully.
+ EFI_INVALID_PARAMETER
+ MaxSpeed or PortNumber or Is64BitCapable is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the capabilities.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcReset (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT16 Attributes
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to provides software reset for the USB host controller
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ Attributes - A bit mask of the reset operation to perform.
+ See below for a list of the supported bit mask values.
+
+ #define EFI_USB_HC_RESET_GLOBAL 0x0001 // Hc2 and Hc
+ #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 // Hc2 and Hc
+ #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 // Hc2
+ #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 // Hc2
+
+ EFI_USB_HC_RESET_GLOBAL
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ EFI_USB_HC_RESET_HOST_CONTROLLER
+ If this bit is set, the USB host controller hardware will be reset.
+ No reset signal will be sent to the USB bus.
+ EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ If this is an EHCI controller and the debug port has configured, then
+ this is will still reset the host controller.
+ EFI_USB_HC_RESET_HOST_WITH_DEBUG
+ If this bit is set, the USB host controller hardware will be reset.
+ If this is an EHCI controller and the debug port has been configured,
+ then this will still reset the host controller.
+
+ Returns:
+
+ EFI_SUCCESS
+ The reset operation succeeded.
+ EFI_INVALID_PARAMETER
+ Attributes is not valid.
+ EFI_UNSUPPOURTED
+ The type of reset specified by Attributes is not currently supported by
+ the host controller hardware.
+ EFI_ACCESS_DENIED
+ Reset operation is rejected due to the debug port being configured and
+ active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or
+ EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
+ perform reset operation for this host controller.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to perform
+ the reset operation.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcGetState (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ OUT EFI_USB_HC_STATE *State
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to retrieves current state of the USB host controller
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ State - A pointer to the EFI_USB_HC_STATE data structure that
+ indicates current state of the USB host controller.
+ Type EFI_USB_HC_STATE is defined below.
+
+ typedef enum {
+ EfiUsbHcStateHalt,
+ EfiUsbHcStateOperational,
+ EfiUsbHcStateSuspend,
+ EfiUsbHcStateMaximum
+ } EFI_USB_HC_STATE;
+
+ Returns:
+
+ EFI_SUCCESS
+ The state information of the host controller was returned in State.
+ EFI_INVALID_PARAMETER
+ State is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the
+ host controller's current state.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcSetState (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN EFI_USB_HC_STATE State
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to sets the USB host controller to a specific state
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ State - Indicates the state of the host controller that will be set.
+
+ Returns:
+
+ EFI_SUCCESS
+ The USB host controller was successfully placed in the state
+ specified by State.
+ EFI_INVALID_PARAMETER
+ State is invalid.
+ EFI_DEVICE_ERROR
+ Failed to set the state specified by State due to device error.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcGetRootHubPortStatus (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to retrieves the current status of a USB root hub port
+ both for Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ PortNumber - Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+ PortStatus - A pointer to the current port status bits and
+ port status change bits.
+
+ Returns:
+
+ EFI_SUCCESS The status of the USB root hub port specified by PortNumber
+ was returned in PortStatus.
+ EFI_INVALID_PARAMETER PortNumber is invalid.
+ EFI_DEVICE_ERROR Can't read register
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcSetRootHubPortFeature (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+ Virual interface to sets a feature for the specified root hub port
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ PortNumber - Specifies the root hub port whose feature
+ is requested to be set.
+ PortFeature - Indicates the feature selector associated
+ with the feature set request.
+
+ Returns:
+
+ EFI_SUCCESS
+ The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcClearRootHubPortFeature (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to clears a feature for the specified root hub port
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ PortNumber - Specifies the root hub port whose feature
+ is requested to be cleared.
+ PortFeature - Indicates the feature selector associated with the
+ feature clear request.
+
+ Returns:
+
+ EFI_SUCCESS
+ The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcControlTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits control transfer to a target USB device
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ DeviceSpeed - Indicates target device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ Request - A pointer to the USB device request that will be sent
+ to the USB device.
+ TransferDirection - Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ TimeOut - Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The control transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The control transfer could not be completed due to a lack of resources.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The control transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcBulkTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits bulk transfer to a bulk endpoint of a USB device
+ both for Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+ DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
+ and EFI_USB_SPEED_HIGH.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+ DataToggle - A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+ Translator - A pointr to the transaction translator data.
+ TimeOut - Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ TransferResult - A pointer to the detailed result information of the
+ bulk transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The bulk transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The bulk transfer could not be submitted due to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The bulk transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcAsyncInterruptTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE * UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ DataToggle - A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ PollingInterval - Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ DataLength - Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ Translator - A pointr to the transaction translator data.
+ CallBackFunction - The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ Context - The context that is passed to the CallBackFunction.
+ - This is an optional parameter and may be NULL.
+
+ Returns:
+
+ EFI_SUCCESS
+ The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_OUT_OF_RESOURCES
+ The request could not be completed due to a lack of resources.
+ EFI_DEVICE_ERROR
+ Can't read register
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcSyncInterruptTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Vitual interface to submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+ DataToggle - A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+ TimeOut - Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ Returns:
+
+ EFI_SUCCESS
+ The synchronous interrupt transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The synchronous interrupt transfer could not be submitted due
+ to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The synchronous interrupt transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The synchronous interrupt transfer failed due to host controller
+ or device error. Caller should check TranferResult for detailed
+ error information.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcIsochronousTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+
+ Virtual interface to submits isochronous transfer to a target USB device
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be
+ transmitted to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ Translator - A pointr to the transaction translator data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+UsbVirtualHcAsyncIsochronousTransfer (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+
+ Vitual interface to submits Async isochronous transfer to a target USB device
+ for both Hc2 and Hc protocol.
+
+ Arguments:
+
+ UsbBusDev - A pointer to bus controller of the device.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ DeviceSpeed - Indicates device speed.
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ DataBuffersNumber - Number of data buffers prepared for the transfer.
+ Data - Array of pointers to the buffers of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ Translator - A pointr to the transaction translator data.
+ IsochronousCallBack - When the transfer complete, the call back function will be called
+ Context - Pass to the call back function as parameter
+
+ Returns:
+
+ EFI_UNSUPPORTED
+
+--*/
+;
#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c
index bd87c5ca2e..eb563b8e8b 100644
--- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c
@@ -233,9 +233,9 @@ UsbControlTransfer (
--*/
{
USB_IO_CONTROLLER_DEVICE *UsbIoController;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
+
EFI_STATUS RetStatus;
- USB_IO_DEVICE *UsbIoDevice;
+ USB_IO_DEVICE *UsbIoDev;
UINT8 MaxPacketLength;
UINT32 TransferResult;
BOOLEAN Disconnected;
@@ -251,9 +251,9 @@ UsbControlTransfer (
// to perform other parameters checking
//
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
- UsbIoDevice = UsbIoController->UsbDevice;
- UsbHCInterface = UsbIoDevice->BusController->UsbHCInterface;
- MaxPacketLength = UsbIoDevice->DeviceDescriptor.MaxPacketSize0;
+ UsbIoDev = UsbIoController->UsbDevice;
+
+ MaxPacketLength = UsbIoDev->DeviceDescriptor.MaxPacketSize0;
if (Request->Request == USB_DEV_CLEAR_FEATURE &&
@@ -268,24 +268,23 @@ UsbControlTransfer (
return EFI_DEVICE_ERROR;
}
}
-
-
-
//
// using HostController's ControlTransfer to complete the request
//
- RetStatus = UsbHCInterface->ControlTransfer (
- UsbHCInterface,
- UsbIoDevice->DeviceAddress,
- UsbIoDevice->IsSlowDevice,
- MaxPacketLength,
- Request,
- Direction,
- Data,
- &DataLength,
- (UINTN) Timeout,
- &TransferResult
- );
+ RetStatus = UsbVirtualHcControlTransfer (
+ UsbIoDev->BusController,
+ UsbIoDev->DeviceAddress,
+ UsbIoDev->DeviceSpeed,
+ MaxPacketLength,
+ Request,
+ Direction,
+ Data,
+ &DataLength,
+ (UINTN) Timeout,
+ UsbIoDev->Translator,
+ &TransferResult
+ );
+
*Status = TransferResult;
if (Request->Request == USB_DEV_CLEAR_FEATURE &&
@@ -346,18 +345,19 @@ UsbBulkTransfer (
--*/
{
USB_IO_DEVICE *UsbIoDev;
- UINT8 MaxPacketLength;
+ UINTN MaxPacketLength;
UINT8 DataToggle;
UINT8 OldToggle;
EFI_STATUS RetStatus;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
+
USB_IO_CONTROLLER_DEVICE *UsbIoController;
ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
UINT32 TransferResult;
-
- UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
- UsbIoDev = UsbIoController->UsbDevice;
- UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
+ UINT8 DataBuffersNumber;
+
+ DataBuffersNumber = 1;
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
//
// Parameters Checking
@@ -408,17 +408,20 @@ UsbBulkTransfer (
//
// using HostController's BulkTransfer to complete the request
//
- RetStatus = UsbHCInterface->BulkTransfer (
- UsbHCInterface,
- UsbIoDev->DeviceAddress,
- DeviceEndpoint,
- MaxPacketLength,
- Data,
- DataLength,
- &DataToggle,
- Timeout,
- &TransferResult
- );
+ RetStatus = UsbVirtualHcBulkTransfer (
+ UsbIoDev->BusController,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->DeviceSpeed,
+ MaxPacketLength,
+ DataBuffersNumber,
+ &Data,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ UsbIoDev->Translator,
+ &TransferResult
+ );
if (OldToggle != DataToggle) {
//
@@ -474,14 +477,13 @@ UsbSyncInterruptTransfer (
--*/
{
- USB_IO_DEVICE *UsbIoDev;
- UINT8 MaxPacketLength;
- UINT8 DataToggle;
- UINT8 OldToggle;
- EFI_STATUS RetStatus;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
- USB_IO_CONTROLLER_DEVICE *UsbIoController;
- ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
+ USB_IO_DEVICE *UsbIoDev;
+ UINTN MaxPacketLength;
+ UINT8 DataToggle;
+ UINT8 OldToggle;
+ EFI_STATUS RetStatus;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
//
// Parameters Checking
@@ -517,8 +519,6 @@ UsbSyncInterruptTransfer (
//
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
UsbIoDev = UsbIoController->UsbDevice;
- UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
-
GetDeviceEndPointMaxPacketLength (
This,
DeviceEndpoint,
@@ -535,18 +535,19 @@ UsbSyncInterruptTransfer (
//
// using HostController's SyncInterruptTransfer to complete the request
//
- RetStatus = UsbHCInterface->SyncInterruptTransfer (
- UsbHCInterface,
- UsbIoDev->DeviceAddress,
- DeviceEndpoint,
- UsbIoDev->IsSlowDevice,
- MaxPacketLength,
- Data,
- DataLength,
- &DataToggle,
- Timeout,
- Status
- );
+ RetStatus = UsbVirtualHcSyncInterruptTransfer (
+ UsbIoDev->BusController,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->DeviceSpeed,
+ MaxPacketLength,
+ Data,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ UsbIoDev->Translator,
+ Status
+ );
if (OldToggle != DataToggle) {
//
@@ -590,7 +591,7 @@ UsbAsyncInterruptTransfer (
the transfer is to be executed.
DataLength - Specifies the length, in bytes, of the data to be
received from the USB device.
- InterruptCallback - The Callback function. This function is called if
+ InterruptCallBack - The Callback function. This function is called if
the asynchronous interrupt transfer is completed.
Context - Passed to InterruptCallback
Returns:
@@ -600,13 +601,12 @@ UsbAsyncInterruptTransfer (
--*/
{
- USB_IO_DEVICE *UsbIoDev;
- UINT8 MaxPacketLength;
- UINT8 DataToggle;
- EFI_USB_HC_PROTOCOL *UsbHCInterface;
- EFI_STATUS RetStatus;
- USB_IO_CONTROLLER_DEVICE *UsbIoController;
- ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
+ USB_IO_DEVICE *UsbIoDev;
+ UINTN MaxPacketLength;
+ UINT8 DataToggle;
+ EFI_STATUS RetStatus;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
//
// Check endpoint
@@ -634,25 +634,25 @@ UsbAsyncInterruptTransfer (
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
UsbIoDev = UsbIoController->UsbDevice;
- UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
if (!IsNewTransfer) {
//
// Delete this transfer
//
- UsbHCInterface->AsyncInterruptTransfer (
- UsbHCInterface,
- UsbIoDev->DeviceAddress,
- DeviceEndpoint,
- UsbIoDev->IsSlowDevice,
- 0,
- FALSE,
- &DataToggle,
- PollingInterval,
- DataLength,
- NULL,
- NULL
- );
+ UsbVirtualHcAsyncInterruptTransfer (
+ UsbIoDev->BusController,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->DeviceSpeed,
+ 0,
+ FALSE,
+ &DataToggle,
+ PollingInterval,
+ DataLength,
+ UsbIoDev->Translator,
+ NULL,
+ NULL
+ );
//
// We need to store the toggle value
@@ -678,19 +678,20 @@ UsbAsyncInterruptTransfer (
&DataToggle
);
- RetStatus = UsbHCInterface->AsyncInterruptTransfer (
- UsbHCInterface,
- UsbIoDev->DeviceAddress,
- DeviceEndpoint,
- UsbIoDev->IsSlowDevice,
- MaxPacketLength,
- TRUE,
- &DataToggle,
- PollingInterval,
- DataLength,
- InterruptCallBack,
- Context
- );
+ RetStatus = UsbVirtualHcAsyncInterruptTransfer (
+ UsbIoDev->BusController,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->DeviceSpeed,
+ MaxPacketLength,
+ TRUE,
+ &DataToggle,
+ PollingInterval,
+ DataLength,
+ UsbIoDev->Translator,
+ InterruptCallBack,
+ Context
+ );
return RetStatus;
}
@@ -1070,6 +1071,7 @@ UsbGetStringDescriptor (
EFI_SUCCESS
EFI_NOT_FOUND
EFI_OUT_OF_RESOURCES
+ EFI_UNSUPPORTED
--*/
{
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c
index 07eb5805e9..e3380856bf 100644
--- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c
@@ -35,10 +35,10 @@ IsPortConnect (
Tell if there is a device connected to that port according to
the Port Status.
- Parameters:
+ Arguments:
PortStatus - The status value of that port.
- Return Value:
+ Returns:
TRUE
FALSE
@@ -280,7 +280,6 @@ IsPortResetChange (
}
}
-
BOOLEAN
IsPortSuspendChange (
IN UINT16 PortChangeStatus
@@ -309,8 +308,7 @@ IsPortSuspendChange (
}
}
-
-INTERFACE_DESC_LIST_ENTRY*
+INTERFACE_DESC_LIST_ENTRY *
FindInterfaceListEntry (
IN EFI_USB_IO_PROTOCOL *This
)
@@ -329,7 +327,7 @@ FindInterfaceListEntry (
{
USB_IO_CONTROLLER_DEVICE *UsbIoController;
USB_IO_DEVICE *UsbIoDev;
- LIST_ENTRY *InterfaceListHead;
+ LIST_ENTRY *InterfaceListHead;
INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
@@ -367,8 +365,8 @@ FindEndPointListEntry (
Find EndPoint ListEntry.
Arguments:
- This - EFI_USB_IO_PROTOCOL
- EndpointAddr - Endpoint address.
+ This - EFI_USB_IO_PROTOCOL
+ EndPointAddress - Endpoint address.
Returns:
ENDPOINT_DESC_LIST_ENTRY pointer
@@ -471,7 +469,7 @@ VOID
GetDeviceEndPointMaxPacketLength (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN UINT8 EndpointAddr,
- OUT UINT8 *MaxPacketLength
+ OUT UINTN *MaxPacketLength
)
/*++
@@ -498,7 +496,7 @@ GetDeviceEndPointMaxPacketLength (
return ;
}
- *MaxPacketLength = (UINT8) (EndpointListEntry->EndpointDescriptor.MaxPacketSize);
+ *MaxPacketLength = (UINTN) (EndpointListEntry->EndpointDescriptor.MaxPacketSize);
return ;
}