diff --git a/libefiusb/Android.mk b/libefiusb/Android.mk
index dd197a8a..00e9bd35 100644
--- a/libefiusb/Android.mk
+++ b/libefiusb/Android.mk
@@ -15,6 +15,7 @@ LOCAL_SRC_FILES := \
usb.c
ifeq ($(KERNELFLINGER_SUPPORT_SELF_USB_DEVICE_MODE_PROTOCOL),true)
+LOCAL_CFLAGS += -DSUPPORT_SUPER_SPEED
LOCAL_CFLAGS += -DUSE_SELF_USB_DEVICE_MODE_PROTOCOL
LOCAL_SRC_FILES += \
device_mode/cpuio.c \
diff --git a/libefiusb/device_mode/UsbDeviceDxe.c b/libefiusb/device_mode/UsbDeviceDxe.c
index 0ffce845..322bdd8d 100644
--- a/libefiusb/device_mode/UsbDeviceDxe.c
+++ b/libefiusb/device_mode/UsbDeviceDxe.c
@@ -1,282 +1,360 @@
-/** @file
- Copyright (c) 2006 - 2017, 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.
-
-**/
-#include
-#include
-#include
-#include
-#include "pci.h"
-#include "UsbDeviceDxe.h"
-#include "UsbDeviceMode.h"
-#include "XdciDWC.h"
-
-static EFI_HANDLE xdci = 0;
-PCI_DEVICE_PATH xhci_path = {.Device = -1, .Function = -1};
-
-VOID
-EFIAPI
-PlatformSpecificInit (
- VOID
- )
-{
- UINTN XhciPciMmBase;
- EFI_PHYSICAL_ADDRESS XhciMemBaseAddress;
-
- XhciPciMmBase = MmPciAddress (
- 0,
- 0,
- xhci_path.Device,
- xhci_path.Function,
- 0
- );
-
-
- XhciMemBaseAddress = MmioRead32 ((UINTN) (XhciPciMmBase + R_XHCI_MEM_BASE)) & B_XHCI_MEM_BASE_BA;
- DEBUG ((DEBUG_INFO, "XhciPciMmBase=%x, XhciMemBaseAddress=%x\n", XhciPciMmBase, XhciMemBaseAddress));
-
- MmioWrite32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0), 0x1310800);
-
- return;
-}
-
-static
-VOID
-EFIAPI
-UsbDeviceDxeExitBootService (
- __attribute__((unused))EFI_EVENT Event,
- VOID *Context
- )
-{
- USB_XDCI_DEV_CONTEXT *UsbXdciDevContext;
-
- UsbXdciDevContext = (USB_XDCI_DEV_CONTEXT *) Context;
- DEBUG ((EFI_D_INFO, "UsbDeviceDxeExitBootService enter\n"));
-
- if (UsbXdciDevContext->XdciPollTimer != NULL) {
- uefi_call_wrapper(BS->SetTimer,
- 3,
- UsbXdciDevContext->XdciPollTimer,
- TimerCancel,
- 0);
-
- uefi_call_wrapper(BS->CloseEvent, 1, UsbXdciDevContext->XdciPollTimer);
- UsbXdciDevContext->XdciPollTimer = NULL;
- }
-
- return;
-}
-
-static EFI_STATUS find_usb_device_controller (EFI_HANDLE Controller)
-{
- EFI_STATUS status = EFI_UNSUPPORTED;
- EFI_PCI_IO *pci;
- USB_CLASSC class_reg;
- UINTN seg;
- UINTN bus;
- UINTN dev;
- UINTN fun;
-
- status = uefi_call_wrapper(BS->OpenProtocol,
- 6,
- Controller,
- &PciIoProtocol,
- (VOID **) &pci,
- g_parent_image,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
-
- if (EFI_ERROR (status))
- return status;
-
- status = uefi_call_wrapper(pci->Pci.Read,
- 5,
- pci,
- EfiPciIoWidthUint8,
- PCI_CLASSCODE_OFFSET,
- sizeof (USB_CLASSC) / sizeof (UINT8),
- &class_reg);
-
- if (EFI_ERROR (status))
- return status;
-
- // Test whether the controller belongs to USB device type
- // 0x0C03FE / 0x0C0380
-
- if ((class_reg.BaseCode == PCI_CLASS_SERIAL) &&
- (class_reg.SubClassCode == PCI_CLASS_SERIAL_USB) &&
- ((class_reg.ProgInterface == PCI_IF_USBDEV) ||
- (class_reg.ProgInterface == 0x80))) {
- return EFI_SUCCESS;
- }
-
-
- if ((class_reg.BaseCode == PCI_CLASS_SERIAL) &&
- (class_reg.SubClassCode == PCI_CLASS_SERIAL_USB) &&
- (class_reg.ProgInterface == PCI_IF_XHCI)) {
-
- status = uefi_call_wrapper(pci->GetLocation,
- 5,
- pci,
- &seg,
- &bus,
- &dev,
- &fun);
- xhci_path.Device = (UINT8)dev;
- xhci_path.Function = (UINT8)fun;
- }
-
- return EFI_UNSUPPORTED;
-}
-
-EFI_GUID gEfiEventExitBootServicesGuid = EventExitBootServices;
-
-static EFI_STATUS usb_device_mode_start (EFI_HANDLE Controller, EFI_USB_DEVICE_MODE_PROTOCOL **usb_device)
-{
- EFI_STATUS Status;
- USB_XDCI_DEV_CONTEXT *UsbXdciDevContext = NULL;
- EFI_PCI_IO *PciIo;
- EFI_EVENT ExitBootServicesEvent;
-
- // Provide protocol interface
- // Get the PCI I/O Protocol on PciHandle
- Status = uefi_call_wrapper(BS->OpenProtocol,
- 6,
- Controller,
- &PciIoProtocol,
- (VOID **) &PciIo,
- g_parent_image,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR (Status)) {
- goto ErrorExit;
- }
-
- UsbXdciDevContext = AllocateZeroPool (sizeof (USB_XDCI_DEV_CONTEXT));
- if (UsbXdciDevContext == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ErrorExit;
- }
-
- // Initialize the driver context
- //
- UsbXdciDevContext->StartUpController = FALSE;
- UsbXdciDevContext->XdciHandle = Controller;
- UsbXdciDevContext->Signature = EFI_USB_DEV_SIGNATURE;
-
- Status = uefi_call_wrapper(PciIo->Pci.Read,
- 5,
- PciIo,
- EfiPciIoWidthUint32,
- R_OTG_BAR0,
- 1,
- &UsbXdciDevContext->XdciMmioBarAddr);
- UsbXdciDevContext->XdciMmioBarAddr &= B_OTG_BAR0_BA;
-
- UINT16 command = 0x6;
- Status = uefi_call_wrapper(PciIo->Pci.Write,
- 5,
- PciIo,
- EfiPciIoWidthUint16,
- R_XDCI_CMD_OFF,
- 1,
- &command);
- //read after write to ensure the former write take effect
- command = 0;
- Status = uefi_call_wrapper(PciIo->Pci.Read,
- 5,
- PciIo,
- EfiPciIoWidthUint16,
- R_XDCI_CMD_OFF,
- 1,
- &command);
-
- CopyMem (&(UsbXdciDevContext->UsbDevModeProtocol),
- &mUsbDeviceModeProtocol,
- sizeof (EFI_USB_DEVICE_MODE_PROTOCOL));
-
- Status = uefi_call_wrapper(BS->CreateEventEx,
- 6,
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- UsbDeviceDxeExitBootService,
- UsbXdciDevContext,
- &gEfiEventExitBootServicesGuid,
- &ExitBootServicesEvent);
- if (EFI_ERROR (Status))
- goto ErrorExit;
-
- *usb_device = &(UsbXdciDevContext->UsbDevModeProtocol);
-
- return Status;
-
-ErrorExit:
-
- if (UsbXdciDevContext != NULL) {
- if (UsbXdciDevContext->XdciPollTimer != NULL) {
- uefi_call_wrapper(BS->CloseEvent,
- 1,
- UsbXdciDevContext->XdciPollTimer);
- UsbXdciDevContext->XdciPollTimer = NULL;
- }
- FreePool (UsbXdciDevContext);
- }
-
- efi_perror(Status, L"ERROR - install driver failed - Exit\n");
- return Status;
-}
-
-static BOOLEAN usb_xdci_enabled(void)
-{
- EFI_STATUS ret;
- UINTN NumberHandles, Index;
- EFI_HANDLE *Handles;
-
- ret = LibLocateHandle(ByProtocol,
- &PciIoProtocol,
- NULL,
- &NumberHandles,
- &Handles);
- if (EFI_ERROR(ret)) {
- efi_perror(ret, L"LibLocateProtocol: Handle not found\n");
- return ret;
- }
-
- for (Index=0; Index < NumberHandles; Index++) {
- ret = find_usb_device_controller(Handles[Index]);
- if (!EFI_ERROR(ret)) {
- xdci = Handles[Index];
- break;
- }
- }
-
- if (Handles) {
- FreePool (Handles);
- }
-
- if (!EFI_ERROR(ret))
- return TRUE;
-
- return FALSE;
-}
-
-EFI_STATUS init_usb_device_mode_protocol(EFI_USB_DEVICE_MODE_PROTOCOL **usb_device)
-{
- EFI_STATUS ret = EFI_UNSUPPORTED;
-
- if (usb_xdci_enabled()) {
- ret = usb_device_mode_start(xdci, usb_device);
- } else {
- efi_perror(ret, L"XDCI is disabled, please enable it in BIOS");
- }
-
- return ret;
-}
+/** @file
+ Copyright (c) 2006 - 2017, 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.
+
+**/
+#include
+#include
+#include
+#include
+#include "pci.h"
+#include "UsbDeviceDxe.h"
+#include "UsbDeviceMode.h"
+#include "XdciDWC.h"
+
+static EFI_HANDLE xdci_handle = 0, xhci_handle = 0;
+PCI_DEVICE_PATH xhci_path = {.Device = -1, .Function = -1};
+UINTN XhciMmioBarAddr = 0;
+
+VOID
+EFIAPI
+PlatformSpecificInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 XhciMmioBarHigh = 0;
+ EFI_PCI_IO *PciIo;
+ UINT32 BitValue;
+ UINT32 BitMask;
+ UINT16 DelayTime = 10000;
+ UINT16 LoopTime;
+
+ // Provide protocol interface
+ // Get the PCI I/O Protocol on PciHandle
+ Status = uefi_call_wrapper(BS->OpenProtocol,
+ 6,
+ xhci_handle,
+ &PciIoProtocol,
+ (VOID **) &PciIo,
+ g_parent_image,
+ xhci_handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit1;
+ }
+
+ Status = uefi_call_wrapper(PciIo->Pci.Read,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint32,
+ R_XHCI_BAR0,
+ 1,
+ &XhciMmioBarAddr);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit1;
+ }
+ if ((XhciMmioBarAddr & B_XHCI_BAR0_TYPE) == B_XHCI_BAR0_64_BIT) {
+ Status = uefi_call_wrapper(PciIo->Pci.Read,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint32,
+ R_XHCI_BAR_HIGH,
+ 1,
+ &XhciMmioBarHigh);
+ }
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit1;
+ }
+ XhciMmioBarAddr = ((UINT64) XhciMmioBarHigh << 32) | XhciMmioBarAddr;
+ XhciMmioBarAddr &= B_XHCI_MEM_BASE_BA;
+
+ DEBUG ((DEBUG_INFO, "XhciMmioBarAddr=0x%016lx\n", XhciMmioBarAddr));
+
+ //
+ // Step 1: Enable OTG device Mode
+ //
+ MmioWrite32 ((UINTN)(XhciMmioBarAddr + R_XHCI_MEM_DUAL_ROLE_CFG0), 0x1310800);
+
+ //
+ // Step 2: 0x80DC register, has a status bit to acknowledge the role change in Bit 29
+ //
+ BitMask = (UINT32) (0x20000000);
+ BitValue = (UINT32) (1 << 29);
+
+ for (LoopTime = 0; LoopTime < DelayTime; LoopTime++) {
+ if ((MmioRead32 ((UINTN)(XhciMmioBarAddr + R_XHCI_MEM_DUAL_ROLE_CFG1)) & BitMask) == (BitValue & BitMask)) {
+ break;
+ } else {
+ uefi_call_wrapper(BS->Stall, 1, 100);
+ }
+ }
+
+ErrorExit1:
+
+ return;
+}
+
+static
+VOID
+EFIAPI
+UsbDeviceDxeExitBootService (
+ __attribute__((unused))EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ USB_XDCI_DEV_CONTEXT *UsbXdciDevContext;
+
+ UsbXdciDevContext = (USB_XDCI_DEV_CONTEXT *) Context;
+ DEBUG ((EFI_D_INFO, "UsbDeviceDxeExitBootService enter\n"));
+
+ if (UsbXdciDevContext->XdciPollTimer != NULL) {
+ uefi_call_wrapper(BS->SetTimer,
+ 3,
+ UsbXdciDevContext->XdciPollTimer,
+ TimerCancel,
+ 0);
+
+ uefi_call_wrapper(BS->CloseEvent, 1, UsbXdciDevContext->XdciPollTimer);
+ UsbXdciDevContext->XdciPollTimer = NULL;
+ }
+
+ return;
+}
+
+static EFI_STATUS find_usb_device_controller (EFI_HANDLE Controller)
+{
+ EFI_STATUS status = EFI_UNSUPPORTED;
+ EFI_PCI_IO *pci;
+ USB_CLASSC class_reg;
+ UINTN seg;
+ UINTN bus;
+ UINTN dev;
+ UINTN fun;
+
+ status = uefi_call_wrapper(BS->OpenProtocol,
+ 6,
+ Controller,
+ &PciIoProtocol,
+ (VOID **) &pci,
+ g_parent_image,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR (status))
+ return status;
+
+ status = uefi_call_wrapper(pci->Pci.Read,
+ 5,
+ pci,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &class_reg);
+
+ if (EFI_ERROR (status))
+ return status;
+
+ // Test whether the controller belongs to USB device type
+ // 0x0C03FE / 0x0C0380
+
+ if ((class_reg.BaseCode == PCI_CLASS_SERIAL) &&
+ (class_reg.SubClassCode == PCI_CLASS_SERIAL_USB) &&
+ ((class_reg.ProgInterface == PCI_IF_USBDEV) ||
+ (class_reg.ProgInterface == 0x80))) {
+ return EFI_SUCCESS;
+ }
+
+
+ if ((class_reg.BaseCode == PCI_CLASS_SERIAL) &&
+ (class_reg.SubClassCode == PCI_CLASS_SERIAL_USB) &&
+ (class_reg.ProgInterface == PCI_IF_XHCI)) {
+
+ status = uefi_call_wrapper(pci->GetLocation,
+ 5,
+ pci,
+ &seg,
+ &bus,
+ &dev,
+ &fun);
+ xhci_path.Device = (UINT8)dev;
+ xhci_path.Function = (UINT8)fun;
+ xhci_handle = Controller;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+EFI_GUID gEfiEventExitBootServicesGuid = EventExitBootServices;
+
+static EFI_STATUS usb_device_mode_start (EFI_HANDLE Controller, EFI_USB_DEVICE_MODE_PROTOCOL **usb_device)
+{
+ EFI_STATUS Status;
+ USB_XDCI_DEV_CONTEXT *UsbXdciDevContext = NULL;
+ EFI_PCI_IO *PciIo;
+ EFI_EVENT ExitBootServicesEvent;
+ UINT32 XdciMmioBarHigh = 0;
+
+ // Provide protocol interface
+ // Get the PCI I/O Protocol on PciHandle
+ Status = uefi_call_wrapper(BS->OpenProtocol,
+ 6,
+ Controller,
+ &PciIoProtocol,
+ (VOID **) &PciIo,
+ g_parent_image,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ UsbXdciDevContext = AllocateZeroPool (sizeof (USB_XDCI_DEV_CONTEXT));
+ if (UsbXdciDevContext == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ // Initialize the driver context
+ //
+ UsbXdciDevContext->StartUpController = FALSE;
+ UsbXdciDevContext->XdciHandle = Controller;
+ UsbXdciDevContext->Signature = EFI_USB_DEV_SIGNATURE;
+
+ Status = uefi_call_wrapper(PciIo->Pci.Read,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint32,
+ R_OTG_BAR0,
+ 1,
+ &UsbXdciDevContext->XdciMmioBarAddr);
+
+ if ((UsbXdciDevContext->XdciMmioBarAddr & B_OTG_BAR0_TYPE) == B_OTG_BAR0_64_BIT) {
+ Status = uefi_call_wrapper(PciIo->Pci.Read,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint32,
+ R_OTG_BAR_HIGH,
+ 1,
+ &XdciMmioBarHigh);
+ }
+
+ UsbXdciDevContext->XdciMmioBarAddr = ((UINT64) XdciMmioBarHigh << 32) | (UsbXdciDevContext->XdciMmioBarAddr & B_OTG_BAR0_BA);
+ DEBUG ((EFI_D_INFO, "USB DEV mode IO addr 0x%016lx\n", UsbXdciDevContext->XdciMmioBarAddr));
+
+ UINT8 command8 = 0x6;
+ Status = uefi_call_wrapper(PciIo->Pci.Write,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint8,
+ R_XDCI_CMD_OFF,
+ 1,
+ &command8);
+ //read after write to ensure the former write take effect
+ command8 = 0;
+ Status = uefi_call_wrapper(PciIo->Pci.Read,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint8,
+ R_XDCI_CMD_OFF,
+ 1,
+ &command8);
+
+ UINT32 command32 = 0;
+ Status = uefi_call_wrapper(PciIo->Pci.Write,
+ 5,
+ PciIo,
+ EfiPciIoWidthUint32,
+ R_XDCI_GEN_REGRW1,
+ 1,
+ &command32);
+
+ CopyMem (&(UsbXdciDevContext->UsbDevModeProtocol),
+ &mUsbDeviceModeProtocol,
+ sizeof (EFI_USB_DEVICE_MODE_PROTOCOL));
+
+ Status = uefi_call_wrapper(BS->CreateEventEx,
+ 6,
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ UsbDeviceDxeExitBootService,
+ UsbXdciDevContext,
+ &gEfiEventExitBootServicesGuid,
+ &ExitBootServicesEvent);
+ if (EFI_ERROR (Status))
+ goto ErrorExit;
+
+ *usb_device = &(UsbXdciDevContext->UsbDevModeProtocol);
+
+ return Status;
+
+ErrorExit:
+
+ if (UsbXdciDevContext != NULL) {
+ if (UsbXdciDevContext->XdciPollTimer != NULL) {
+ uefi_call_wrapper(BS->CloseEvent,
+ 1,
+ UsbXdciDevContext->XdciPollTimer);
+ UsbXdciDevContext->XdciPollTimer = NULL;
+ }
+ FreePool (UsbXdciDevContext);
+ }
+
+ efi_perror(Status, L"ERROR - install driver failed - Exit\n");
+ return Status;
+}
+
+static BOOLEAN usb_xdci_enabled(void)
+{
+ EFI_STATUS ret;
+ UINTN NumberHandles, Index;
+ EFI_HANDLE *Handles;
+
+ ret = LibLocateHandle(ByProtocol,
+ &PciIoProtocol,
+ NULL,
+ &NumberHandles,
+ &Handles);
+ if (EFI_ERROR(ret)) {
+ efi_perror(ret, L"LibLocateProtocol: Handle not found\n");
+ return ret;
+ }
+
+ for (Index=0; Index < NumberHandles; Index++) {
+ ret = find_usb_device_controller(Handles[Index]);
+ if (!EFI_ERROR(ret)) {
+ xdci_handle = Handles[Index];
+ break;
+ }
+ }
+
+ if (Handles) {
+ FreePool (Handles);
+ }
+
+ if (!EFI_ERROR(ret))
+ return TRUE;
+
+ return FALSE;
+}
+
+EFI_STATUS init_usb_device_mode_protocol(EFI_USB_DEVICE_MODE_PROTOCOL **usb_device)
+{
+ EFI_STATUS ret = EFI_UNSUPPORTED;
+
+ if (usb_xdci_enabled()) {
+ ret = usb_device_mode_start(xdci_handle, usb_device);
+ } else {
+ efi_perror(ret, L"XDCI is disabled, please enable it in BIOS");
+ }
+
+ return ret;
+}
+
diff --git a/libefiusb/device_mode/UsbDeviceDxe.h b/libefiusb/device_mode/UsbDeviceDxe.h
index b9fb6595..d0242d60 100644
--- a/libefiusb/device_mode/UsbDeviceDxe.h
+++ b/libefiusb/device_mode/UsbDeviceDxe.h
@@ -13,7 +13,6 @@
#ifndef __USB_DEVICE_DXE_H__
#define __USB_DEVICE_DXE_H__
-
#include
#include "XdciDWC.h"
#include "protocol/UsbDeviceLib.h"
@@ -51,6 +50,7 @@ PlatformSpecificInit (
);
extern PCI_DEVICE_PATH xhci_path;
+extern UINTN XhciMmioBarAddr;
#pragma pack(1)
typedef struct {
@@ -61,35 +61,38 @@ typedef struct {
#pragma pack()
#define PCI_CLASSCODE_OFFSET 0x09
-#define PCI_CLASS_SERIAL 0x0C
+#define PCI_CLASS_SERIAL 0x0C
#define PCI_CLASS_SERIAL_USB 0x03
-#define PCI_IF_USBDEV 0xFE
-#define PCI_IF_XHCI 0x30
+#define PCI_IF_USBDEV 0xFE
+#define PCI_IF_XHCI 0x30
#define EventExitBootServices \
{ 0x27ABF055, 0xB1B8, 0x4C26, { 0x80, 0x48, 0x74, 0x8F, 0x37, 0xBA, 0xA2, 0xDF } }
#define R_OTG_BAR0 0x10 ///< BAR 0
-#define B_OTG_BAR0_BA 0xFFE00000 ///< Base Address
-#define R_XHCI_MEM_BASE 0x10
+#define B_OTG_BAR0_BA 0xFFFFF000 ///< Base Address
+#define B_OTG_BAR0_TYPE 0x00000006 // Type
+#define B_OTG_BAR0_64_BIT 0x00000004 // 64 bit
+#define R_OTG_BAR_HIGH 0x14 // BAR High
+#define R_OTG_BAR1 0x18 // BAR 1
+
+
+#define R_XHCI_BAR0 0x10 // BAR 0
+#define R_XHCI_BAR_HIGH 0x14 // BAR High
+#define B_XHCI_BAR0_TYPE 0x00000006 // Type
+#define B_XHCI_BAR0_64_BIT 0x00000004 // 64 bit
#define B_XHCI_MEM_BASE_BA 0xFFFFFFFFFFFF0000
#define R_XHCI_MEM_DUAL_ROLE_CFG0 0x80D8
#define R_XHCI_MEM_DUAL_ROLE_CFG1 0x80DC
-#define R_XDCI_CMD_OFF 0x04
-
-#define MmPciAddress( Segment, Bus, Device, Function, Register ) \
- ( (UINTN)0xE0000000 + \
- (UINTN)(Bus << 20) + \
- (UINTN)(Device << 15) + \
- (UINTN)(Function << 12) + \
- (UINTN)(Register) \
- )
+#define R_XDCI_CMD_OFF 0x04
+#define R_XDCI_GEN_REGRW1 0xB0
UINT32 MmioRead32(UINTN address);
UINT16 MmioRead16(UINTN address);
-UINT8 MmioRead8(UINTN address);
+UINT8 MmioRead8(UINTN address);
+UINT64 MmioWrite64(UINTN address, UINT64 value);
UINT32 MmioWrite32(UINTN address, UINT32 value);
UINT16 MmioWrite16(UINTN address, UINT16 value);
-UINT8 MmioWrite8(UINTN address, UINT8 value);
+UINT8 MmioWrite8(UINTN address, UINT8 value);
EFI_STATUS install_usb_device_mode_protocol(void);
#endif
diff --git a/libefiusb/device_mode/UsbDeviceMode.c b/libefiusb/device_mode/UsbDeviceMode.c
index ac9a6d31..44e209af 100644
--- a/libefiusb/device_mode/UsbDeviceMode.c
+++ b/libefiusb/device_mode/UsbDeviceMode.c
@@ -1,1488 +1,1482 @@
-/** @file
- Copyright (c) 2006 - 2017, 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.
-
-**/
-
-#include
-#include
-#include
-#include "XdciUtility.h"
-#include "UsbDeviceDxe.h"
-#include "UsbDeviceMode.h"
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-//
-// Global USBD driver object. This is the main private driver object
-// that contains all data needed for this driver to operate.
-//
-USB_DEVICE_DRIVER_OBJ mDrvObj;
-
-//
-// Global data IO transaction request object
-//
-USB_DEVICE_IO_REQ mCtrlIoReq = {
- //
- // IO information containing the Buffer and data size
- //
- {
- NULL,
- 0,
- },
- //
- // Note: This object is used for Control Ep transfers only
- // therefore the endpoint info must always be NULL
- //
- {
- NULL,
- NULL,
- }
-};
-
-//
-// global flag to signal device event processing loop to run/stop
-//
-BOOLEAN mXdciRun = FALSE;
-
-VOID
-XhciSwitchSwid(BOOLEAN enable)
-{
- UINTN XhciPciMmBase;
- EFI_PHYSICAL_ADDRESS XhciMemBaseAddress;
- UINT32 DualRoleCfg0;
- UINT32 DualRoleCfg1;
-
- XhciPciMmBase = MmPciAddress (0, 0, xhci_path.Device, xhci_path.Function, 0);
- XhciMemBaseAddress = MmioRead32 ((UINTN) (XhciPciMmBase + R_XHCI_MEM_BASE)) & B_XHCI_MEM_BASE_BA;
- DEBUG ((DEBUG_INFO, "XhciPciMmBase=%x, XhciMemBaseAddress=%x\n", XhciPciMmBase, XhciMemBaseAddress));
-
- DualRoleCfg0 = MmioRead32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0));
- if (enable) {
- DualRoleCfg0 = DualRoleCfg0 | (1 << 24) | (1 << 21) | (1 << 20);
- DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Set SW ID : 0x%x \n", DualRoleCfg0));
- }
- else {
- DualRoleCfg0 = DualRoleCfg0 & ~(1 << 24) & ~(1 << 21) & ~(1 << 20);
- DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Clear SW ID : 0x%x \n", DualRoleCfg0));
- }
- MmioWrite32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0), DualRoleCfg0);
-
- DualRoleCfg1 = MmioRead32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG1));
- DEBUG ((DEBUG_INFO, "DualRoleCfg1 : 0x%x \n", DualRoleCfg1));
-}
-
-VOID
-EFIAPI
-UsbdMonitorEvents (
- IN EFI_EVENT __attribute__((unused))Event,
- IN VOID *Context
- )
-{
- USB_XDCI_DEV_CONTEXT *XdciDevContext;
- UINT32 EventCount;
- UINT32 PreEventCount;
- UINT32 LoopCount;
-
- XdciDevContext = (USB_XDCI_DEV_CONTEXT *) Context;
- EventCount = UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
- if (EventCount == 0) {
- return;
- }
-
- LoopCount = 0;
- PreEventCount = EventCount;
- while (EventCount != 0) {
- if (UsbDeviceIsrRoutineTimerBased (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
- DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
- }
- EventCount = UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
- if (PreEventCount == EventCount) {
- LoopCount++;
- if (LoopCount >= 5) {
- DEBUG ((DEBUG_INFO, "USB is working on a long event...\n"));
- break;
- }
- } else {
- LoopCount = 0;
- }
- }
-
- return;
-}
-
-/**
- Initializes the XDCI core
-
- @param MmioBar Address of MMIO BAR
- @param XdciHndl Double pointer to for XDCI layer to set as an
- opaque handle to the driver to be used in subsequent
- interactions with the XDCI layer.
-
- @return EFI_SUCCESS if successfully initialized XDCI, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdInit (
- IN UINT32 MmioBar,
- IN VOID **XdciHndl
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- USB_DEV_CONFIG_PARAMS ConfigParams;
-
- XhciSwitchSwid(TRUE);
-
- DEBUG ((DEBUG_INFO, "UsbdInit start\n"));
- ConfigParams.ControllerId = USB_ID_DWC_XDCI;
- ConfigParams.BaseAddress = MmioBar;
- ConfigParams.Role = USB_ROLE_DEVICE;
- ConfigParams.Speed = USB_SPEED_SUPER;
-
- Status = UsbDeviceInit (&ConfigParams, XdciHndl);
-
- DEBUG ((DEBUG_INFO, "UsbdInit status is %x\n", Status));
- DEBUG ((DEBUG_INFO, "ConfigParams.BaseAddress 0x%x\n", ConfigParams.BaseAddress));
-
- return Status;
-}
-
-
-/**
- Copies relevant endpoint data from standard USB endpoint descriptors
- to the usbEpInfo structure used by the XDCI
-
- @param EpDest destination structure
- @param EpSrc source structure
-
- @return VOID
-
-**/
-VOID
-UsbdSetEpInfo (
- IN USB_EP_INFO *EpDest,
- IN USB_DEVICE_ENDPOINT_INFO *EpSrc
- )
-{
- EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc = NULL;
- EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc = NULL;
-
- //
- // start by clearing all data in the destination
- //
- SetMem (EpDest, sizeof(USB_EP_INFO), 0);
- EpDesc = EpSrc->EndpointDesc;
- EpCompDesc = EpSrc->EndpointCompDesc;
-
- if (EpDesc != NULL) {
- EpDest->EpNum = EpDesc->EndpointAddress & 0x0F; //Bits 0-3 are ep num
- EpDest->EpDir = ((EpDesc->EndpointAddress & USB_ENDPOINT_DIR_IN) > 0) ? UsbEpDirIn : UsbEpDirOut;
- EpDest->EpType = EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK;
- EpDest->MaxPktSize = EpDesc->MaxPacketSize;
- EpDest->Interval = EpDesc->Interval;
- }
- if (EpCompDesc != NULL) {
- EpDest->MaxStreams = EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MASK;
- EpDest->BurstSize = EpCompDesc->MaxBurst;
- EpDest->Mult = EpCompDesc->BytesPerInterval;
- }
-
- return;
-}
-
-
-/**
- Initializes the given endpoint
-
- @param XdciHndl Pointer (handle) to the XDCI driver object
- @param DevEpInfo Pointer to endpoint info structure
- for the endpoint to initialize
-
- @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdInitEp (
- IN VOID *XdciHndl,
- IN USB_DEVICE_ENDPOINT_INFO *DevEpInfo
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- USB_EP_INFO EpInfo;
-
- UsbdSetEpInfo (&EpInfo, DevEpInfo);
- Status = UsbDeviceInitEp (XdciHndl, &EpInfo);
-
- return Status;
-}
-
-
-/**
- Callback handler used when transfer operations complete. Calls
- upper layer routine to handle the operation.
-
- @param XdciHndl Pointer (handle) to the XDCI driver object
- @param XferReq Pointer to the transfer request structure
-
- @return VOID
-
-**/
-VOID
-EFIAPI
-UsbdXferDoneHndlr (
- IN VOID __attribute((unused))*XdciHndl,
- IN USB_XFER_REQUEST *XferReq
- )
-{
- EFI_USB_DEVICE_XFER_INFO XferInfo;
-
- DEBUG ((DEBUG_INFO, "UsbdXferDoneHndlr\n"));
-
- XferInfo.EndpointNum = (UINT8)XferReq->EpInfo.EpNum;
- XferInfo.EndpointDir = XferReq->EpInfo.EpDir;
- XferInfo.EndpointType = XferReq->EpInfo.EpType;
- XferInfo.Buffer = XferReq->XferBuffer;
- XferInfo.Length = XferReq->ActualXferLen;
-
- //
- // If this is a non-control transfer complete, notify the class driver
- //
- if (XferInfo.EndpointNum > 0) {
- if (mDrvObj.UsbdDevObj->DataCallback != NULL) {
- mDrvObj.UsbdDevObj->DataCallback (&XferInfo);
- }
- }
-
- return;
-}
-
-
-/**
- Queue a request to transmit data
-
- @param XdciHndl Pointer (handle) to the XDCI driver object
- @param IoReq Pointer to IO structure containing details of the
- transfer request
-
- @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdEpTxData (
- IN VOID *XdciHndl,
- IN USB_DEVICE_IO_REQ *IoReq
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- USB_XFER_REQUEST TxReq;
-
- //
- //set endpoint data
- //
- UsbdSetEpInfo (&(TxReq.EpInfo), &(IoReq->EndpointInfo)); // set endpoint data
-
- //
- //if this is a control endpoint, set the number and direction
- //
- if (IoReq->EndpointInfo.EndpointDesc == NULL) {
- TxReq.EpInfo.EpNum = 0;
- TxReq.EpInfo.EpDir = UsbEpDirIn;
- }
-
- //
- // setup the trasfer request
- //
- TxReq.XferBuffer = IoReq->IoInfo.Buffer;
- TxReq.XferLen = IoReq->IoInfo.Length;
- TxReq.XferDone = UsbdXferDoneHndlr;
-
- DEBUG ((DEBUG_INFO, "TX REQUEST: EpNum: 0x%x, epDir: 0x%x, epType: 0x%x, MaxPktSize: 0x%x\n",\
- TxReq.EpInfo.EpNum, TxReq.EpInfo.EpDir, TxReq.EpInfo.EpType, TxReq.EpInfo.MaxPktSize));
-
- Status = UsbXdciDeviceEpTxData (XdciHndl, &TxReq);
-
- return Status;
-}
-
-
-/**
- Queue a request to receive data
-
- @param XdciHndl Pointer (handle) to the XDCI driver object
- @param IoReq Pointer to IO structure containing details of the
- receive request
-
- @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdEpRxData (
- IN VOID *XdciHndl,
- IN USB_DEVICE_IO_REQ *IoReq
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- USB_XFER_REQUEST RxReq;
- UINT32 ReqPacket;
-
- DEBUG ((DEBUG_INFO, "RX REQUEST in: IoReq->IoInfo.Length: 0x%x\n", IoReq->IoInfo.Length));
- DEBUG ((DEBUG_INFO, "RX REQUEST in: MaxPacketSize: 0x%x\n", IoReq->EndpointInfo.EndpointDesc->MaxPacketSize));
-
- if (IoReq->EndpointInfo.EndpointDesc->MaxPacketSize == 0) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // set endpoint data
- //
- UsbdSetEpInfo (&(RxReq.EpInfo), &(IoReq->EndpointInfo));
-
- //
- // setup the trasfer request
- //
- RxReq.XferBuffer = IoReq->IoInfo.Buffer;
-
- //
- // Transfer length should be multiple of USB packet size.
- //
- ReqPacket = IoReq->IoInfo.Length / IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
- ReqPacket = ((IoReq->IoInfo.Length % IoReq->EndpointInfo.EndpointDesc->MaxPacketSize) == 0)? ReqPacket : ReqPacket + 1;
- RxReq.XferLen = ReqPacket * IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
-
- RxReq.XferDone = UsbdXferDoneHndlr;
-
- DEBUG ((DEBUG_INFO, "RX REQUEST: EpNum: 0x%x, epDir: 0x%x, epType: 0x%x\n",\
- RxReq.EpInfo.EpNum, RxReq.EpInfo.EpDir, RxReq.EpInfo.EpType));
- DEBUG ((DEBUG_INFO, "RX REQUEST send: XferLen: 0x%x\n", RxReq.XferLen));
-
- Status = UsbXdciDeviceEpRxData (XdciHndl, &RxReq);
-
- return Status;
-}
-
-
-/**
- Callback used to handle Reset events from the XDCI
-
- @param Param Pointer to a generic callback parameter structure
-
- @return XDCI usb status
-
-**/
-EFI_STATUS
-EFIAPI
-UsbdResetEvtHndlr (
- IN USB_DEVICE_CALLBACK_PARAM __attribute__((unused)) *Param
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbdResetEvtHndlr\n"));
-
- //
- // reset device address to 0
- //
- Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdResetHdlr() - Failed to set address in XDCI\n"));
- }
-
- return Status;
-}
-
-
-/**
- Callback used to handle Connection done events from the XDCI
-
- @param Param Pointer to a generic callback parameter structure
-
- @return XDCI usb status
-
-**/
-EFI_STATUS
-EFIAPI
-UsbdConnDoneEvtHndlr (
- IN USB_DEVICE_CALLBACK_PARAM __attribute__((unused))*Param
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbdConnDoneEvtHndlr\n"));
-
- //
- //reset device address to 0
- //
- Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
- }
-
- //
- // set the device state to attached/connected
- //
- mDrvObj.State = UsbDevStateAttached;
-
- return Status;
-}
-
-
-/**
- Callback used to handle Control Endpoint Setup events from the XDCI
-
- @param Param Pointer to a generic callback parameter structure
-
- @return XDCI usb status
-
-**/
-EFI_STATUS
-EFIAPI
-UsbdSetupEvtHndlr (
- IN USB_DEVICE_CALLBACK_PARAM *Param
- )
-{
- EFI_STATUS Status = EFI_SUCCESS;
- EFI_USB_DEVICE_REQUEST Req;
-
- DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr\n"));
-
- //
- // Fill out request object from the incomming Buffer
- //
- CopyMem (&Req, Param->Buffer, sizeof(EFI_USB_DEVICE_REQUEST));
-
- Status = UsbdSetupHdlr (&Req);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr: EFI_DEVICE_ERROR\n"));
- }
-
- return Status;
-}
-
-
-/**
- * Callback used to handle XferNotReady events from the XDCI
- *
- * @param Param Pointer to a generic callback parameter structure
- *
- * @return XDCI usb status
- */
-EFI_STATUS
-EFIAPI
-UsbdNrdyEvtHndlr (
- IN USB_DEVICE_CALLBACK_PARAM __attribute((unused))*Param
- )
-{
- DEBUG ((DEBUG_INFO, "UsbdNrdyEvtHndlr\n"));
- return EFI_SUCCESS;
-}
-
-
-/**
- Registers callbacks for event handlers with the XDCI layer.
- The functions will be called as the registered events are triggered.
-
- @param XdciHndl to XDCI core driver
- @return EFI_SUCCESS if successful, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdRegisterCallbacks (
- IN VOID *XdciHndl
- )
-{
- if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_RESET_EVENT, UsbdResetEvtHndlr) != EFI_SUCCESS) {
- goto UdciRegCallbackError;
- }
-
- if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_CONNECTION_DONE, UsbdConnDoneEvtHndlr) != EFI_SUCCESS) {
- goto UdciRegCallbackError;
- }
-
- if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_SETUP_PKT_RECEIVED, UsbdSetupEvtHndlr) != EFI_SUCCESS) {
- goto UdciRegCallbackError;
- }
-
- if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_XFER_NRDY, UsbdNrdyEvtHndlr) != EFI_SUCCESS) {
- goto UdciRegCallbackError;
- }
-
- return EFI_SUCCESS;
-
-UdciRegCallbackError:
- return EFI_DEVICE_ERROR;
-}
-
-
-/**
- Returns the configuration descriptor for this device. The data
- Buffer returned will also contain all downstream interface and
- endpoint Buffers.
-
- @param Buffer Pointer to destination Buffer to copy descriptor data to
- @param DescIndex the index of the descriptor to return
- @param ReqLen the length in bytes of the request Buffer
- @param DataLen Pointer whos value is to be filled with the byte count of
- data copied to the output Buffer
-
- @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdGetConfigDesc (
- IN VOID *Buffer,
- IN UINT8 DescIndex,
- IN UINT32 ReqLen,
- IN UINT32 *DataLen
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- UINT8 NumConfigs = 0;
- UINT32 ConfigLen = 0;
- USB_DEVICE_CONFIG_OBJ *ConfigObj = NULL;
- VOID *Descriptor = 0;
- UINT32 Length = 0;
-
- DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc()\n"));
-
- //
- // For a CONFIGURATION request we send back all descriptors branching out
- // from this descriptor including the INTERFACE and ENDPOINT descriptors
- //
- //
- // Verify the requested configuration exists - check valid index
- //
- NumConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
-
- if (DescIndex < NumConfigs) {
- //
- // get the configuration object using the index Offset
- //
- ConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + DescIndex);
- //
- // get the complete configuration Buffer block including Interface and Endpoint data
- //
- Descriptor = ConfigObj->ConfigAll;
- //
- // The config descriptor TotalLength has the full value for all desc Buffers
- //
- ConfigLen = ConfigObj->ConfigDesc->TotalLength;
- //
- // copy the data to the output Buffer
- //
- Length = MIN (ReqLen, ConfigLen);
- CopyMem (Buffer, Descriptor, Length);
- *DataLen = Length;
- Status = EFI_SUCCESS;
- } else {
- DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc() - Invalid Config index: %i\n", DescIndex));
- }
-
- if (Status == EFI_SUCCESS) {
- if (ConfigObj != NULL) {
- PrintConfigDescriptor (ConfigObj->ConfigDesc);
- }
- }
-
- return Status;
-}
-
-
-/**
- Sets the active configuration to the selected configuration index if it exists
-
- @param CfgValue the configuration value to set
-
- @return EFI_SUCCESS if the configuration was set, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdSetConfig (
- UINT8 CfgValue
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- UINT8 numConfigs = 0;
- USB_DEVICE_CONFIG_OBJ *pConfigObj = NULL;
- USB_DEVICE_INTERFACE_OBJ *pIfObj = NULL;
- USB_DEVICE_ENDPOINT_OBJ *pEpObj = NULL;
- UINT8 cfgItr = 0;
- UINT8 ifItr = 0;
- UINT8 epItr = 0;
- USB_DEVICE_ENDPOINT_INFO EpInfo;
- USB_EP_INFO UsbEpInfo;
-
- DEBUG ((DEBUG_INFO, "UsbdSetConfig()\n"));
- //
- // Verify the requested configuration exists - check valid index
- //
- numConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
-
- if (CfgValue != 0) {
- //
- // Search for a matching configuration
- //
- for (cfgItr = 0; cfgItr < numConfigs; cfgItr++) {
- pConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + cfgItr);
- if (pConfigObj->ConfigDesc->ConfigurationValue == CfgValue) {
-
- //
- // Set the active configuration object
- //
- mDrvObj.ActiveConfigObj = pConfigObj;
- //
- // Find all interface objects for this configuration
- //
- for (ifItr = 0; ifItr < pConfigObj->ConfigDesc->NumInterfaces; ifItr++) {
- pIfObj = (pConfigObj->InterfaceObjs + ifItr);
- //
- // Configure the Endpoints in the XDCI
- //
- for (epItr = 0; epItr < pIfObj->InterfaceDesc->NumEndpoints; epItr++) {
- pEpObj = (pIfObj->EndpointObjs + epItr);
-
- EpInfo.EndpointDesc = pEpObj->EndpointDesc;
- EpInfo.EndpointCompDesc = pEpObj->EndpointCompDesc;
-
- if (UsbdInitEp (mDrvObj.XdciDrvObj, &EpInfo) == EFI_SUCCESS) {
- UsbdSetEpInfo(&UsbEpInfo, &EpInfo);
- if (UsbDeviceEpEnable (mDrvObj.XdciDrvObj, &UsbEpInfo) == EFI_SUCCESS) {
- Status = EFI_SUCCESS;
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to enable endpoint\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to initialize endpoint\n"));
- }
- }
- }
- //
- // Let the class driver know it is configured
- //
- if (Status == EFI_SUCCESS) {
- if (mDrvObj.UsbdDevObj->ConfigCallback != NULL) {
- mDrvObj.UsbdDevObj->ConfigCallback (CfgValue);
- }
- }
-
- mDrvObj.State = UsbDevStateConfigured; // we are now configured
-
- break; // break from config search loop
- }
- }
- }
-
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Invalid requested configuration value: %i\n", CfgValue));
- }
-
- return Status;
-}
-
-
-/**
- Returns the currently active configuration value
-
- @param Buffer Pointer to destination Buffer to copy configuration value to
- @param ReqLen the length in bytes of the request Buffer
- @param DataLen Pointer whos value is to be filled with the byte count of
- data copied to the output Buffer
-
- @return EFI_SUCCESS if config value is successfully copied, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdGetConfig (
- VOID *Buffer,
- UINT32 ReqLen,
- UINT32 *DataLen
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbdGetConfig()\n"));
-
- if (ReqLen >= 1) { // length of data expected must be 1
- if (mDrvObj.ActiveConfigObj != NULL) { // assure we have a config active
- *DataLen = 1; // one byte for ConfigurationValue
- *(UINT8*)Buffer = mDrvObj.ActiveConfigObj->ConfigDesc->ConfigurationValue;
-
- Status = EFI_SUCCESS;
- } else {
- DEBUG ((DEBUG_INFO, "UsbdGetConfig() - No active configuration available\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbdGetConfig() - Invalid data length\n"));
- }
-
- return Status;
-}
-
-
-/**
- Returns the requested string descriptor if it exists
-
- @param Buffer Pointer to destination Buffer to copy descriptor data to
- @param DescIndex the index of the descriptor to return
- @param LangId the target language ID
- @param ReqLen the length in bytes of the request Buffer
- @param DataLen Pointer whos value is to be filled with the byte count of
- data copied to the output Buffer
-
- @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdGetStringDesc (
- VOID *Buffer,
- UINT8 DescIndex,
- UINT16 LangId,
- UINT32 ReqLen,
- UINT32 *DataLen
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- UINT32 Length = 0;
- USB_STRING_DESCRIPTOR *StringDesc;
- UINT8 Index = 0;
- UINT8 StrLangEntries = 0;
- BOOLEAN StrLangFound = FALSE;
-
- DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Index: 0x%x, LangId: 0x%x, ReqLen: 0x%x\n", DescIndex, LangId, ReqLen));
-
- //
- // index zero of the string table contains the supported language codes
- //
- if (DescIndex == 0) {
- StringDesc = (mDrvObj.UsbdDevObj->StringTable);
- Length = MIN (ReqLen, StringDesc->Length);
- CopyMem (Buffer, StringDesc, Length);
- *DataLen = Length;
- Status = EFI_SUCCESS;
- } else {
-
- //
- // Verify the requested language ID is supported. String descriptor Zero
- // (First entry in the string table) is expected to contain the language list.
- // The requested language ID is specified in the Index member of the request.
- //
- StringDesc = mDrvObj.UsbdDevObj->StringTable; // get language string descriptor
- StrLangEntries = ((StringDesc->Length - 2) >> 1);
- DEBUG ((DEBUG_INFO, "StrLangEntries=%x\n", StrLangEntries));
-
- DEBUG ((DEBUG_INFO, "Looking LangID: \n"));
-
- for (Index = 0; Index < StrLangEntries; Index++) {
- DEBUG ((DEBUG_INFO, "LangID [%x]= %x\n", Index, StringDesc->LangID [Index]));
-
- if (StringDesc->LangID [Index] == LangId) {
- DEBUG ((DEBUG_INFO, "Found it\n"));
- StrLangFound = TRUE;
- }
- }
-
- //
- // If we found a matching language, attempt to get the string index requested
- //
- if (StrLangFound == TRUE) {
- DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: StrLangFound=Found, DescIndex=%x, StrTblEntries=%x\n", DescIndex, mDrvObj.UsbdDevObj->StrTblEntries));
-
- if (DescIndex < mDrvObj.UsbdDevObj->StrTblEntries) {
- //
- // get the string descriptor for the requested index
- //
- StringDesc = (mDrvObj.UsbdDevObj->StringTable + DescIndex);
-
- Length = MIN (ReqLen, StringDesc->Length);
- DEBUG ((DEBUG_INFO, "ReqLen=%x, StringLength=%x, Length=%x\n", ReqLen, StringDesc->Length, Length));
-
- CopyMem (Buffer, StringDesc, Length);
- *DataLen = Length;
- Status = EFI_SUCCESS;
- } else {
- DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Invalid String index in USB_REQ_GET_DESCRIPTOR request\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Unsupported String Language ID for USB_REQ_GET_DESCRIPTOR request\n"));
- }
- }
-
- if (Status == EFI_SUCCESS) {
- PrintStringDescriptor (StringDesc);
- }
- return Status;
-}
-
-
-#ifdef SUPPORT_SUPER_SPEED
-/**
- Returns the configuration descriptor for this device. The data
- Buffer returned will also contain all downstream interface and
- endpoint Buffers.
-
- @param Buffer Pointer to destination Buffer to copy descriptor data to
- @param ReqLen the length in bytes of the request Buffer
- @param DataLen Pointer whos value is to be filled with the byte count of
- data copied to the output Buffer
-
- @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdGetBOSDesc (
- IN VOID *Buffer,
- IN UINT32 ReqLen,
- IN UINT32 *DataLen
- )
-{
- EFI_USB_BOS_DESCRIPTOR *BosDesc = 0;
- UINT32 Length = 0;
-
- DEBUG ((DEBUG_INFO, "UsbdGetBOSDesc()\n"));
-
- BosDesc = mDrvObj.UsbdDevObj->BosDesc;
- Length = MIN (ReqLen, mDrvObj.UsbdDevObj->BosDesc->TotalLength);
-
- CopyMem(Buffer, BosDesc, Length);
- *DataLen = Length;
-
- PrintBOSDescriptor (BosDesc);
-
- return EFI_SUCCESS;
-}
-#endif
-
-/**
- Returns the current status for Device/Interface/Endpoint
-
- @param Buffer Pointer to destination Buffer to copy descriptor data to
- @param ReqType The type of status to get
- @param ReqLen the length in bytes of the request Buffer
- @param DataLen Pointer whos value is to be filled with the byte count of
- data copied to the output Buffer
-
- @return EFI_SUCCESS if status successfully copied, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdGetStatus (
- VOID *Buffer,
- UINT8 ReqType,
- UINT32 ReqLen,
- UINT32 *DataLen
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbdGetStatus()\n"));
-
- if (ReqLen >= 2) { // length of data must be at least 2 bytes
- switch (ReqType & USB_TARGET_MASK) {
- case USB_TARGET_DEVICE:
- *DataLen = 2; // two byte for status
- *(UINT16*)Buffer = USB_STATUS_SELFPOWERED;
- Status = EFI_SUCCESS;
- break;
-
- case USB_TARGET_INTERFACE:
- //
- // No implementation needed at this time
- //
- break;
-
- case USB_TARGET_ENDPOINT:
- //
- // No implementation needed at this time
- // Should specify if endpoint is halted. Implement as necessary.
- //
- break;
-
- case USB_TARGET_OTHER:
- //
- // No implementation needed at this time
- //
- break;
-
- default:
- break;
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbdGetStatus() - Invalid data length\n"));
- }
-
- return Status;
-}
-
-
-/**
- Sets the address of the device
-
- @param address the address value to set
-
- @return EFI_SUCCESS if address was set, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdSetAddress (
- UINT8 Address
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbdSetAddress: setting address: 0x%x\n", Address));
-
- if (Address <= 0x7F) { // address must not be > 127
- mDrvObj.Address = Address;
-
- //
- // Configure Address in the XDCI
- //
- Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, mDrvObj.Address);
- if (!EFI_ERROR (Status)) {
- mDrvObj.State = UsbDevStateAddress;
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetAddress: Failed to set address in XDCI\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetAddress: Invalid address: 0x%x\n", Address));
- }
-
- return Status;
-}
-
-
-/**
- Handles Setup device requests. Standard requests are immediately
- handled here, and any Class/Vendor specific requests are forwarded
- to the class driver
-
- @param CtrlRequest Pointer to a device request
-
- @return EFI_SUCCESS if request successfully handled, FALSE otherwise
-
-**/
-EFI_STATUS
-UsbdSetupHdlr (
- IN EFI_USB_DEVICE_REQUEST *CtrlRequest
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- UINT8 DescIndex = 0;
- USB_DEVICE_DESCRIPTOR *DevDesc = 0;
-
- //
- // Initialize the IO object
- //
- mCtrlIoReq.IoInfo.Length = 0;
-
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr start\n"));
- PrintDeviceRequest (CtrlRequest);
-
- //
- // Handle Standard Device Requests
- //
- if ((CtrlRequest->RequestType & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) {
- switch (CtrlRequest->Request) {
- case USB_REQ_GET_DESCRIPTOR:
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Host requests get descriptor\n"));
- if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
- DescIndex = (CtrlRequest->Value & 0xff); // low byte is the index requested
- switch (CtrlRequest->Value >> 8) { // high byte contains request type
- case USB_DESC_TYPE_DEVICE:
- DEBUG ((DEBUG_INFO, "Descriptor tyep: Device\n"));
- DevDesc = mDrvObj.UsbdDevObj->DeviceDesc;
- //
- // copy the data to the output Buffer
- //
- mCtrlIoReq.IoInfo.Length = MIN (CtrlRequest->Length, DevDesc->Length);
- CopyMem (mCtrlIoReq.IoInfo.Buffer, DevDesc, mCtrlIoReq.IoInfo.Length);
- PrintDeviceDescriptor (DevDesc);
- break;
-
- case USB_DESC_TYPE_CONFIG:
- DEBUG ((DEBUG_INFO, "Descriptor tyep: Configuration\n"));
- Status = UsbdGetConfigDesc (
- mCtrlIoReq.IoInfo.Buffer,
- DescIndex,
- CtrlRequest->Length,
- &(mCtrlIoReq.IoInfo.Length)
- );
- break;
-
- case USB_DESC_TYPE_STRING:
- DEBUG ((DEBUG_INFO, "Descriptor tyep: String\n"));
- Status = UsbdGetStringDesc (
- mCtrlIoReq.IoInfo.Buffer,
- DescIndex,
- CtrlRequest->Index,
- CtrlRequest->Length,
- &(mCtrlIoReq.IoInfo.Length)
- );
- break;
-
-#ifdef SUPPORT_SUPER_SPEED
- case USB_DESC_TYPE_BOS:
- DEBUG ((DEBUG_INFO, "Descriptor tyep: BOS\n"));
- Status = UsbdGetBOSDesc (
- mCtrlIoReq.IoInfo.Buffer,
- CtrlRequest->Length,
- &(mCtrlIoReq.IoInfo.Length)
- );
- break;
-
- case USB_DESC_TYPE_SS_ENDPOINT_COMPANION:
- DEBUG ((DEBUG_INFO, "Descriptor tyep: Endpoint Companion\n"));
- break;
-#endif
-
- default:
- DEBUG ((DEBUG_INFO, "Descriptor tyep: Unsupported, USB_REQ_GET_DESCRIPTOR request: 0x%x\n", (CtrlRequest->Value >> 8)));
- break;
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr() - Invalid direction for USB_REQ_GET_DESCRIPTOR request\n"));
- }
- break;
-
- case USB_REQ_GET_CONFIG:
- DEBUG ((DEBUG_INFO, "USB_REQ_GET_CONFIG\n"));
- if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
- Status = UsbdGetConfig (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_CONFIG request\n"));
- }
- break;
-
- case USB_REQ_SET_CONFIG:
- DEBUG ((DEBUG_INFO, "USB_REQ_SET_CONFIG\n"));
- if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
- Status = UsbdSetConfig ((UINT8)CtrlRequest->Value);
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_CONFIG request\n"));
- }
- break;
-
- case USB_REQ_SET_ADDRESS:
- DEBUG ((DEBUG_INFO, "USB_REQ_SET_ADDRESS\n"));
- if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
- Status = UsbdSetAddress ((UINT8)CtrlRequest->Value);
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_ADDRESS request\n"));
- }
- break;
-
- case USB_REQ_GET_STATUS:
- DEBUG ((DEBUG_INFO, "USB_REQ_GET_STATUS\n"));
- if (CtrlRequest->RequestType & USB_RT_TX_DIR_D_TO_H) {
- Status = UsbdGetStatus (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->RequestType, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
- } else {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_STATUS request\n"));
- }
- break;
-#ifdef SUPPORT_SUPER_SPEED
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- case USB_REQ_SET_DESCRIPTOR:
- case USB_REQ_GET_INTERFACE:
- case USB_REQ_SET_INTERFACE:
- case USB_REQ_SYNCH_FRAME:
-#endif
- default:
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Unsupported Standard Request: 0x%x\n", CtrlRequest->Request));
- break;
- }
- } else { // This is not a Standard request, it specifies Class/Vendor handling
- //
- // Forward request to class driver
- //
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Class/Vendor Request\n"));
- if (mDrvObj.UsbdDevObj->SetupCallback != NULL) {
- mDrvObj.UsbdDevObj->SetupCallback (CtrlRequest, &(mCtrlIoReq.IoInfo));
- }
- }
-
- DEBUG ((DEBUG_INFO, "dataLen=%x\n", mCtrlIoReq.IoInfo.Length));
- //
- // Transfer data according to request if necessary
- //
- if (mCtrlIoReq.IoInfo.Length> 0) {
- Status = UsbdEpTxData (mDrvObj.XdciDrvObj, &mCtrlIoReq);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to TX data\n"));
- }
- } else {
- //
- // If we are not responding with data, send control status
- //
- Status = UsbDeviceEp0TxStatus (mDrvObj.XdciDrvObj);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to Tx Ep0 Status\n"));
- }
- }
-
- return Status;
-}
-
-
-/**
- Handles Connection done events. Sets the device address to zero.
-
- @return EFI_SUCCESS if able to set the address, EFI_DEVICE_ERROR otherwise
-
-**/
-EFI_STATUS
-UsbdConnDoneHdlr (
- VOID
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr()\n"));
-
- //
- // reset device address to 0
- //
- Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
- }
-
- //
- // set the device state to attached/connected
- //
- mDrvObj.State = UsbDevStateAttached;
-
- return Status;
-}
-
-
-/**
- Handles transmit/receive completion events. Directly handles
- control endpoint events and forwards class/vendor specific events
- to the class drivers.
-
- @param XferInfo Pointer to Xfer structure
-
- @return
-
-**/
-VOID
-UsbdXferDoneHdlr (
- IN EFI_USB_DEVICE_XFER_INFO *XferInfo
- )
-{
- //
- // If this is a non-control transfer complete, notify the class driver
- //
- if (XferInfo->EndpointNum > 0) {
- if (mDrvObj.UsbdDevObj->DataCallback != NULL) {
- mDrvObj.UsbdDevObj->DataCallback (XferInfo);
- }
- }
-
- return;
-}
-
-
-/**
- Binds a USB class driver with this USB device driver core.
- After calling this routine, the driver is ready to begin
- USB processing.
-
- @param UsbdDevObj Pointer to a usbd device object which contains
- all relevant information for the class driver device
-
- @return TRUE if binding was successful, FALSE otherwise
-
-**/
-EFI_STATUS
-EFIAPI
-UsbDeviceBind (
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute__((unused))*This,
- IN USB_DEVICE_OBJ *UsbdDevObj
- )
-{
- EFI_STATUS Status = EFI_SUCCESS;
-
- //
- // allocate Tx Buffer
- //
- mCtrlIoReq.IoInfo.Buffer = AllocateZeroPool (USB_EPO_MAX_PKT_SIZE_ALL);
- if (mCtrlIoReq.IoInfo.Buffer != NULL) {
- mDrvObj.UsbdDevObj = UsbdDevObj;
- mDrvObj.ActiveConfigObj = NULL;
- mDrvObj.Address = 0;
- mDrvObj.State = UsbDevStateInit;
- } else {
- DEBUG ((DEBUG_INFO, "UsbDeviceBind() - Failed to allocate IO Buffer\n"));
- Status = EFI_DEVICE_ERROR;
- }
-
- return Status;
-}
-
-
-/**
- Unbinds the USB class driver from this USB device driver core.
-
- @return TRUE if successful, FALSE otherwise
-
-**/
-EFI_STATUS
-EFIAPI
-UsbDeviceUnbind (
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute__((unused))*This
- )
-{
- mDrvObj.UsbdDevObj = NULL;
- mDrvObj.ActiveConfigObj = NULL;
- mDrvObj.Address = 0;
- mDrvObj.State = UsbDevStateOff;
- mDrvObj.XdciInitialized = FALSE;
-
- //
- // release allocated Buffer data
- //
- if (mCtrlIoReq.IoInfo.Buffer) {
- FreePool (mCtrlIoReq.IoInfo.Buffer);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Performs continual USB device event processing until a cancel
- event occurs
-
- @param TimeoutMs Connection timeout in ms. If 0, waits forever.
- @return TRUE if run executed normally, FALSE if error ocurred
-
-**/
-EFI_STATUS
-EFIAPI
-UsbDeviceRun (
- IN EFI_USB_DEVICE_MODE_PROTOCOL *This,
- IN UINT32 TimeoutMs
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- USB_XDCI_DEV_CONTEXT *XdciDevContext;
-
- XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
-
- //
- // can only run if XDCI is initialized
- //
- if (mDrvObj.XdciInitialized == TRUE) {
-
- if ((mDrvObj.State == UsbDevStateConfigured) && (XdciDevContext->XdciPollTimer == NULL)) {
- Status = uefi_call_wrapper(BS->CreateEvent,
- 5,
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- UsbdMonitorEvents,
- XdciDevContext,
- &XdciDevContext->XdciPollTimer
- );
- if (!EFI_ERROR (Status)) {
- Status = uefi_call_wrapper(BS->SetTimer, 3, XdciDevContext->XdciPollTimer, TimerPeriodic,200000);
- DEBUG ((EFI_D_ERROR, "UsbDeviceRun Create Event\n"));
- }
- }
-
- mXdciRun = TRUE; // set the run flag to active
- Status = EFI_SUCCESS;
-
- //
- // start the Event processing loop
- //
- while (TRUE) {
- if (XdciDevContext->XdciPollTimer == NULL) {
- if (UsbDeviceIsrRoutine (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
- DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
- }
- }
-
- //
- // Check if a run cancel request exists, if so exit processing loop
- //
- if (mXdciRun == FALSE) {
- if (XdciDevContext->XdciPollTimer != NULL) {
- DEBUG ((EFI_D_ERROR, "UsbDeviceRun close Event\n"));
- uefi_call_wrapper(BS->SetTimer, 3, XdciDevContext->XdciPollTimer, TimerCancel, 0);
- uefi_call_wrapper(BS->CloseEvent, 1, XdciDevContext->XdciPollTimer);
- XdciDevContext->XdciPollTimer = NULL;
- }
- Status = EFI_SUCCESS;
- DEBUG ((DEBUG_INFO, "UsbDeviceRun() - processing was cancelled\n"));
- break;
- }
-
- //
- // check for timeout
- //
- if (TimeoutMs == 0)
- return EFI_TIMEOUT;
- uefi_call_wrapper(BS->Stall, 1, 50);
- TimeoutMs--;
- }
- }
-
- return Status;
-}
-
-
-/**
- Sets a flag to stop the running device processing loop
-
- @return TRUE always
-
-**/
-EFI_STATUS
-EFIAPI
-UsbDeviceStop (
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute__((unused))*This
- )
-{
- mXdciRun = FALSE; // set run flag to FALSE to stop processing
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-EFIAPI
-UsbDeviceInitXdci (
- IN EFI_USB_DEVICE_MODE_PROTOCOL *This
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- USB_XDCI_DEV_CONTEXT *XdciDevContext;
-
- XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
-
- PlatformSpecificInit ();
-
- if (mDrvObj.XdciInitialized == FALSE) {
- if (XdciDevContext->XdciMmioBarAddr != 0) {
-
- //
- // Initialize device controller driver
- //
- DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Initializing Controller...\n"));
-
- //
- // Initialize the device controller interface
- //
- if (UsbdInit ((UINT32)XdciDevContext->XdciMmioBarAddr, &mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
-
- //
- // Setup callbacks
- //
- if (UsbdRegisterCallbacks (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
-
- mDrvObj.XdciInitialized = TRUE;
- Status = EFI_SUCCESS;
-
- DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Controller initialization complete\n"));
- } else {
- DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to register UDCI callbacks\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to initialize UDCI\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI MMIO BAR not set\n"));
- }
- } else {
- DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI already initialized\n"));
- Status = EFI_ALREADY_STARTED;
- }
-
- return Status;
-}
-
-
-EFI_STATUS
-EFIAPI
-UsbDeviceConnect(
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbDeviceConnect \n"));
- if (UsbXdciDeviceConnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
- Status = EFI_SUCCESS;
- }
- return Status;
-}
-
-
-EFI_STATUS
-EFIAPI
-UsbDeviceDisConnect (
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
-
- DEBUG ((DEBUG_INFO, "UsbDeviceDisConnect \n"));
- if (UsbDeviceDisconnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
- mDrvObj.State = UsbDevStateInit;
- Status = EFI_SUCCESS;
- }
-
- XhciSwitchSwid(FALSE);
- return Status;
-}
-
-
-EFI_STATUS
-EFIAPI
-UsbDeviceEpTxData(
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This,
- IN USB_DEVICE_IO_REQ *IoRequest
- )
-{
- EFI_STATUS Status;
-
- Status = UsbdEpTxData (mDrvObj.XdciDrvObj, IoRequest);
- return Status;
-}
-
-
-EFI_STATUS
-EFIAPI
-UsbDeviceEpRxData(
- IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This,
- IN USB_DEVICE_IO_REQ *IoRequest
- )
-{
- EFI_STATUS Status;
-
- Status = UsbdEpRxData (mDrvObj.XdciDrvObj, IoRequest);
- return Status;
-}
-
-
-//
-// The Runtime UsbDeviceMode Protocol instance produced by this driver
-//
-EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol = {
- UsbDeviceInitXdci,
- UsbDeviceConnect,
- UsbDeviceDisConnect,
- UsbDeviceEpTxData,
- UsbDeviceEpRxData,
- UsbDeviceBind,
- UsbDeviceUnbind,
- UsbDeviceRun,
- UsbDeviceStop
-};
-
+/** @file
+ Copyright (c) 2006 - 2017, 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.
+
+**/
+
+#include
+#include
+#include
+#include "XdciUtility.h"
+#include "UsbDeviceDxe.h"
+#include "UsbDeviceMode.h"
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+//
+// Global USBD driver object. This is the main private driver object
+// that contains all data needed for this driver to operate.
+//
+USB_DEVICE_DRIVER_OBJ mDrvObj;
+
+//
+// Global data IO transaction request object
+//
+USB_DEVICE_IO_REQ mCtrlIoReq = {
+ //
+ // IO information containing the Buffer and data size
+ //
+ {
+ NULL,
+ 0,
+ },
+ //
+ // Note: This object is used for Control Ep transfers only
+ // therefore the endpoint info must always be NULL
+ //
+ {
+ NULL,
+ NULL,
+ }
+};
+
+//
+// global flag to signal device event processing loop to run/stop
+//
+BOOLEAN mXdciRun = FALSE;
+
+VOID
+XhciSwitchSwid(BOOLEAN enable)
+{
+ UINT32 DualRoleCfg0;
+ UINT32 DualRoleCfg1;
+
+
+ DualRoleCfg0 = MmioRead32 ((UINTN)(XhciMmioBarAddr + R_XHCI_MEM_DUAL_ROLE_CFG0));
+ if (enable) {
+ DualRoleCfg0 = DualRoleCfg0 | (1 << 24) | (1 << 21) | (1 << 20);
+ DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Set SW ID : 0x%x \n", DualRoleCfg0));
+ }
+ else {
+ DualRoleCfg0 = DualRoleCfg0 & ~(1 << 24) & ~(1 << 21) & ~(1 << 20);
+ DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Clear SW ID : 0x%x \n", DualRoleCfg0));
+ }
+ MmioWrite32 ((UINTN)(XhciMmioBarAddr + R_XHCI_MEM_DUAL_ROLE_CFG0), DualRoleCfg0);
+
+ DualRoleCfg1 = MmioRead32 ((UINTN)(XhciMmioBarAddr + R_XHCI_MEM_DUAL_ROLE_CFG1));
+ DEBUG ((DEBUG_INFO, "DualRoleCfg1 : 0x%x \n", DualRoleCfg1));
+}
+
+VOID
+EFIAPI
+UsbdMonitorEvents (
+ IN EFI_EVENT __attribute__((unused))Event,
+ IN VOID *Context
+ )
+{
+ USB_XDCI_DEV_CONTEXT *XdciDevContext;
+ UINT32 EventCount;
+ UINT32 PreEventCount;
+ UINT32 LoopCount;
+
+ XdciDevContext = (USB_XDCI_DEV_CONTEXT *) Context;
+ EventCount = UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ if (EventCount == 0) {
+ return;
+ }
+
+ LoopCount = 0;
+ PreEventCount = EventCount;
+ while (EventCount != 0) {
+ if (UsbDeviceIsrRoutineTimerBased (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
+ }
+ EventCount = UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ if (PreEventCount == EventCount) {
+ LoopCount++;
+ if (LoopCount >= 5) {
+ DEBUG ((DEBUG_INFO, "USB is working on a long event...\n"));
+ break;
+ }
+ } else {
+ LoopCount = 0;
+ }
+ }
+
+ return;
+}
+
+/**
+ Initializes the XDCI core
+
+ @param MmioBar Address of MMIO BAR
+ @param XdciHndl Double pointer to for XDCI layer to set as an
+ opaque handle to the driver to be used in subsequent
+ interactions with the XDCI layer.
+
+ @return EFI_SUCCESS if successfully initialized XDCI, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdInit (
+ IN UINTN MmioBar,
+ IN VOID **XdciHndl
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_DEV_CONFIG_PARAMS ConfigParams;
+
+// XhciSwitchSwid(TRUE);
+
+ DEBUG ((DEBUG_INFO, "UsbdInit start\n"));
+ ConfigParams.ControllerId = USB_ID_DWC_XDCI;
+ ConfigParams.BaseAddress = MmioBar;
+ ConfigParams.Role = USB_ROLE_DEVICE;
+ ConfigParams.Speed = USB_SPEED_SUPER;
+
+ Status = UsbDeviceInit (&ConfigParams, XdciHndl);
+
+ DEBUG ((DEBUG_INFO, "UsbdInit status is %x\n", Status));
+ DEBUG ((DEBUG_INFO, "ConfigParams.BaseAddress 0x%016lx\n", ConfigParams.BaseAddress));
+
+ return Status;
+}
+
+
+/**
+ Copies relevant endpoint data from standard USB endpoint descriptors
+ to the usbEpInfo structure used by the XDCI
+
+ @param EpDest destination structure
+ @param EpSrc source structure
+
+ @return VOID
+
+**/
+VOID
+UsbdSetEpInfo (
+ IN USB_EP_INFO *EpDest,
+ IN USB_DEVICE_ENDPOINT_INFO *EpSrc
+ )
+{
+ EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc = NULL;
+ EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc = NULL;
+
+ //
+ // start by clearing all data in the destination
+ //
+ SetMem (EpDest, sizeof(USB_EP_INFO), 0);
+ EpDesc = EpSrc->EndpointDesc;
+ EpCompDesc = EpSrc->EndpointCompDesc;
+
+ if (EpDesc != NULL) {
+ EpDest->EpNum = EpDesc->EndpointAddress & 0x0F; //Bits 0-3 are ep num
+ EpDest->EpDir = ((EpDesc->EndpointAddress & USB_ENDPOINT_DIR_IN) > 0) ? UsbEpDirIn : UsbEpDirOut;
+ EpDest->EpType = EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK;
+ EpDest->MaxPktSize = EpDesc->MaxPacketSize;
+ EpDest->Interval = EpDesc->Interval;
+ }
+ if (EpCompDesc != NULL) {
+ EpDest->MaxStreams = EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MASK;
+ EpDest->BurstSize = EpCompDesc->MaxBurst;
+ EpDest->Mult = EpCompDesc->BytesPerInterval;
+ }
+
+ return;
+}
+
+
+/**
+ Initializes the given endpoint
+
+ @param XdciHndl Pointer (handle) to the XDCI driver object
+ @param DevEpInfo Pointer to endpoint info structure
+ for the endpoint to initialize
+
+ @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdInitEp (
+ IN VOID *XdciHndl,
+ IN USB_DEVICE_ENDPOINT_INFO *DevEpInfo
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_EP_INFO EpInfo;
+
+ UsbdSetEpInfo (&EpInfo, DevEpInfo);
+ Status = UsbDeviceInitEp (XdciHndl, &EpInfo);
+
+ return Status;
+}
+
+
+/**
+ Callback handler used when transfer operations complete. Calls
+ upper layer routine to handle the operation.
+
+ @param XdciHndl Pointer (handle) to the XDCI driver object
+ @param XferReq Pointer to the transfer request structure
+
+ @return VOID
+
+**/
+VOID
+EFIAPI
+UsbdXferDoneHndlr (
+ IN VOID __attribute((unused))*XdciHndl,
+ IN USB_XFER_REQUEST *XferReq
+ )
+{
+ EFI_USB_DEVICE_XFER_INFO XferInfo;
+
+ DEBUG ((DEBUG_INFO, "UsbdXferDoneHndlr\n"));
+
+ XferInfo.EndpointNum = (UINT8)XferReq->EpInfo.EpNum;
+ XferInfo.EndpointDir = XferReq->EpInfo.EpDir;
+ XferInfo.EndpointType = XferReq->EpInfo.EpType;
+ XferInfo.Buffer = XferReq->XferBuffer;
+ XferInfo.Length = XferReq->ActualXferLen;
+
+ //
+ // If this is a non-control transfer complete, notify the class driver
+ //
+ if (XferInfo.EndpointNum > 0) {
+ if (mDrvObj.UsbdDevObj->DataCallback != NULL) {
+ mDrvObj.UsbdDevObj->DataCallback (&XferInfo);
+ }
+ }
+
+ return;
+}
+
+
+/**
+ Queue a request to transmit data
+
+ @param XdciHndl Pointer (handle) to the XDCI driver object
+ @param IoReq Pointer to IO structure containing details of the
+ transfer request
+
+ @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdEpTxData (
+ IN VOID *XdciHndl,
+ IN USB_DEVICE_IO_REQ *IoReq
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_XFER_REQUEST TxReq;
+
+ //
+ //set endpoint data
+ //
+ UsbdSetEpInfo (&(TxReq.EpInfo), &(IoReq->EndpointInfo)); // set endpoint data
+
+ //
+ //if this is a control endpoint, set the number and direction
+ //
+ if (IoReq->EndpointInfo.EndpointDesc == NULL) {
+ TxReq.EpInfo.EpNum = 0;
+ TxReq.EpInfo.EpDir = UsbEpDirIn;
+ }
+
+ //
+ // setup the trasfer request
+ //
+ TxReq.XferBuffer = IoReq->IoInfo.Buffer;
+ TxReq.XferLen = IoReq->IoInfo.Length;
+ TxReq.XferDone = UsbdXferDoneHndlr;
+
+ DEBUG ((DEBUG_INFO, "TX REQUEST: EpNum: 0x%x, epDir: 0x%x, epType: 0x%x, MaxPktSize: 0x%x\n",\
+ TxReq.EpInfo.EpNum, TxReq.EpInfo.EpDir, TxReq.EpInfo.EpType, TxReq.EpInfo.MaxPktSize));
+
+ Status = UsbXdciDeviceEpTxData (XdciHndl, &TxReq);
+
+ return Status;
+}
+
+
+/**
+ Queue a request to receive data
+
+ @param XdciHndl Pointer (handle) to the XDCI driver object
+ @param IoReq Pointer to IO structure containing details of the
+ receive request
+
+ @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdEpRxData (
+ IN VOID *XdciHndl,
+ IN USB_DEVICE_IO_REQ *IoReq
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_XFER_REQUEST RxReq;
+ UINT32 ReqPacket;
+
+ DEBUG ((DEBUG_INFO, "RX REQUEST in: IoReq->IoInfo.Length: 0x%x\n", IoReq->IoInfo.Length));
+ DEBUG ((DEBUG_INFO, "RX REQUEST in: MaxPacketSize: 0x%x\n", IoReq->EndpointInfo.EndpointDesc->MaxPacketSize));
+
+ if (IoReq->EndpointInfo.EndpointDesc->MaxPacketSize == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // set endpoint data
+ //
+ UsbdSetEpInfo (&(RxReq.EpInfo), &(IoReq->EndpointInfo));
+
+ //
+ // setup the trasfer request
+ //
+ RxReq.XferBuffer = IoReq->IoInfo.Buffer;
+
+ //
+ // Transfer length should be multiple of USB packet size.
+ //
+ ReqPacket = IoReq->IoInfo.Length / IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
+ ReqPacket = ((IoReq->IoInfo.Length % IoReq->EndpointInfo.EndpointDesc->MaxPacketSize) == 0)? ReqPacket : ReqPacket + 1;
+ RxReq.XferLen = ReqPacket * IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
+
+ RxReq.XferDone = UsbdXferDoneHndlr;
+
+ DEBUG ((DEBUG_INFO, "RX REQUEST: EpNum: 0x%x, epDir: 0x%x, epType: 0x%x\n",\
+ RxReq.EpInfo.EpNum, RxReq.EpInfo.EpDir, RxReq.EpInfo.EpType));
+ DEBUG ((DEBUG_INFO, "RX REQUEST send: XferLen: 0x%x\n", RxReq.XferLen));
+
+ Status = UsbXdciDeviceEpRxData (XdciHndl, &RxReq);
+
+ return Status;
+}
+
+
+/**
+ Callback used to handle Reset events from the XDCI
+
+ @param Param Pointer to a generic callback parameter structure
+
+ @return XDCI usb status
+
+**/
+EFI_STATUS
+EFIAPI
+UsbdResetEvtHndlr (
+ IN USB_DEVICE_CALLBACK_PARAM __attribute__((unused)) *Param
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdResetEvtHndlr\n"));
+
+ //
+ // reset device address to 0
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdResetHdlr() - Failed to set address in XDCI\n"));
+ }
+
+ return Status;
+}
+
+
+/**
+ Callback used to handle Connection done events from the XDCI
+
+ @param Param Pointer to a generic callback parameter structure
+
+ @return XDCI usb status
+
+**/
+EFI_STATUS
+EFIAPI
+UsbdConnDoneEvtHndlr (
+ IN USB_DEVICE_CALLBACK_PARAM __attribute__((unused))*Param
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneEvtHndlr\n"));
+ //
+ //reset device address to 0
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
+ }
+
+ //
+ // set the device state to attached/connected
+ //
+ mDrvObj.State = UsbDevStateAttached;
+
+ return Status;
+}
+
+
+/**
+ Callback used to handle Control Endpoint Setup events from the XDCI
+
+ @param Param Pointer to a generic callback parameter structure
+
+ @return XDCI usb status
+
+**/
+EFI_STATUS
+EFIAPI
+UsbdSetupEvtHndlr (
+ IN USB_DEVICE_CALLBACK_PARAM *Param
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_USB_DEVICE_REQUEST Req;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr\n"));
+
+ //
+ // Fill out request object from the incomming Buffer
+ //
+ CopyMem (&Req, Param->Buffer, sizeof(EFI_USB_DEVICE_REQUEST));
+
+ Status = UsbdSetupHdlr (&Req);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr: EFI_DEVICE_ERROR\n"));
+ }
+
+ return Status;
+}
+
+
+/**
+ * Callback used to handle XferNotReady events from the XDCI
+ *
+ * @param Param Pointer to a generic callback parameter structure
+ *
+ * @return XDCI usb status
+ */
+EFI_STATUS
+EFIAPI
+UsbdNrdyEvtHndlr (
+ IN USB_DEVICE_CALLBACK_PARAM __attribute((unused))*Param
+ )
+{
+ DEBUG ((DEBUG_INFO, "UsbdNrdyEvtHndlr\n"));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Registers callbacks for event handlers with the XDCI layer.
+ The functions will be called as the registered events are triggered.
+
+ @param XdciHndl to XDCI core driver
+ @return EFI_SUCCESS if successful, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdRegisterCallbacks (
+ IN VOID *XdciHndl
+ )
+{
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_RESET_EVENT, UsbdResetEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_CONNECTION_DONE, UsbdConnDoneEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_SETUP_PKT_RECEIVED, UsbdSetupEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_XFER_NRDY, UsbdNrdyEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ return EFI_SUCCESS;
+
+UdciRegCallbackError:
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ Returns the configuration descriptor for this device. The data
+ Buffer returned will also contain all downstream interface and
+ endpoint Buffers.
+
+ @param Buffer Pointer to destination Buffer to copy descriptor data to
+ @param DescIndex the index of the descriptor to return
+ @param ReqLen the length in bytes of the request Buffer
+ @param DataLen Pointer whos value is to be filled with the byte count of
+ data copied to the output Buffer
+
+ @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetConfigDesc (
+ IN VOID *Buffer,
+ IN UINT8 DescIndex,
+ IN UINT32 ReqLen,
+ IN UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT8 NumConfigs = 0;
+ UINT32 ConfigLen = 0;
+ USB_DEVICE_CONFIG_OBJ *ConfigObj = NULL;
+ VOID *Descriptor = 0;
+ UINT32 Length = 0;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc()\n"));
+
+ //
+ // For a CONFIGURATION request we send back all descriptors branching out
+ // from this descriptor including the INTERFACE and ENDPOINT descriptors
+ //
+ //
+ // Verify the requested configuration exists - check valid index
+ //
+ NumConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
+
+ if (DescIndex < NumConfigs) {
+ //
+ // get the configuration object using the index Offset
+ //
+ ConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + DescIndex);
+ //
+ // get the complete configuration Buffer block including Interface and Endpoint data
+ //
+ Descriptor = ConfigObj->ConfigAll;
+ //
+ // The config descriptor TotalLength has the full value for all desc Buffers
+ //
+ ConfigLen = ConfigObj->ConfigDesc->TotalLength;
+ //
+ // copy the data to the output Buffer
+ //
+ Length = MIN (ReqLen, ConfigLen);
+ CopyMem (Buffer, Descriptor, Length);
+ *DataLen = Length;
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc() - Invalid Config index: %i\n", DescIndex));
+ }
+
+ if (Status == EFI_SUCCESS) {
+ if (ConfigObj != NULL) {
+ PrintConfigDescriptor (ConfigObj->ConfigDesc);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Sets the active configuration to the selected configuration index if it exists
+
+ @param CfgValue the configuration value to set
+
+ @return EFI_SUCCESS if the configuration was set, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdSetConfig (
+ UINT8 CfgValue
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT8 numConfigs = 0;
+ USB_DEVICE_CONFIG_OBJ *pConfigObj = NULL;
+ USB_DEVICE_INTERFACE_OBJ *pIfObj = NULL;
+ USB_DEVICE_ENDPOINT_OBJ *pEpObj = NULL;
+ UINT8 cfgItr = 0;
+ UINT8 ifItr = 0;
+ UINT8 epItr = 0;
+ USB_DEVICE_ENDPOINT_INFO EpInfo;
+ USB_EP_INFO UsbEpInfo;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig()\n"));
+ //
+ // Verify the requested configuration exists - check valid index
+ //
+ numConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
+
+ if (CfgValue != 0) {
+ //
+ // Search for a matching configuration
+ //
+ for (cfgItr = 0; cfgItr < numConfigs; cfgItr++) {
+ pConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + cfgItr);
+ if (pConfigObj->ConfigDesc->ConfigurationValue == CfgValue) {
+
+ //
+ // Set the active configuration object
+ //
+ mDrvObj.ActiveConfigObj = pConfigObj;
+ //
+ // Find all interface objects for this configuration
+ //
+ for (ifItr = 0; ifItr < pConfigObj->ConfigDesc->NumInterfaces; ifItr++) {
+ pIfObj = (pConfigObj->InterfaceObjs + ifItr);
+ //
+ // Configure the Endpoints in the XDCI
+ //
+ for (epItr = 0; epItr < pIfObj->InterfaceDesc->NumEndpoints; epItr++) {
+ pEpObj = (pIfObj->EndpointObjs + epItr);
+
+ EpInfo.EndpointDesc = pEpObj->EndpointDesc;
+ EpInfo.EndpointCompDesc = pEpObj->EndpointCompDesc;
+
+ if (UsbdInitEp (mDrvObj.XdciDrvObj, &EpInfo) == EFI_SUCCESS) {
+ UsbdSetEpInfo(&UsbEpInfo, &EpInfo);
+ if (UsbDeviceEpEnable (mDrvObj.XdciDrvObj, &UsbEpInfo) == EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to enable endpoint\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to initialize endpoint\n"));
+ }
+ }
+ }
+ //
+ // Let the class driver know it is configured
+ //
+ if (Status == EFI_SUCCESS) {
+ if (mDrvObj.UsbdDevObj->ConfigCallback != NULL) {
+ mDrvObj.UsbdDevObj->ConfigCallback (CfgValue);
+ }
+ }
+
+ mDrvObj.State = UsbDevStateConfigured; // we are now configured
+
+ break; // break from config search loop
+ }
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Invalid requested configuration value: %i\n", CfgValue));
+ }
+
+ return Status;
+}
+
+
+/**
+ Returns the currently active configuration value
+
+ @param Buffer Pointer to destination Buffer to copy configuration value to
+ @param ReqLen the length in bytes of the request Buffer
+ @param DataLen Pointer whos value is to be filled with the byte count of
+ data copied to the output Buffer
+
+ @return EFI_SUCCESS if config value is successfully copied, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetConfig (
+ VOID *Buffer,
+ UINT32 ReqLen,
+ UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetConfig()\n"));
+
+ if (ReqLen >= 1) { // length of data expected must be 1
+ if (mDrvObj.ActiveConfigObj != NULL) { // assure we have a config active
+ *DataLen = 1; // one byte for ConfigurationValue
+ *(UINT8*)Buffer = mDrvObj.ActiveConfigObj->ConfigDesc->ConfigurationValue;
+
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetConfig() - No active configuration available\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetConfig() - Invalid data length\n"));
+ }
+
+ return Status;
+}
+
+
+/**
+ Returns the requested string descriptor if it exists
+
+ @param Buffer Pointer to destination Buffer to copy descriptor data to
+ @param DescIndex the index of the descriptor to return
+ @param LangId the target language ID
+ @param ReqLen the length in bytes of the request Buffer
+ @param DataLen Pointer whos value is to be filled with the byte count of
+ data copied to the output Buffer
+
+ @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetStringDesc (
+ VOID *Buffer,
+ UINT8 DescIndex,
+ UINT16 LangId,
+ UINT32 ReqLen,
+ UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT32 Length = 0;
+ USB_STRING_DESCRIPTOR *StringDesc;
+ UINT8 Index = 0;
+ UINT8 StrLangEntries = 0;
+ BOOLEAN StrLangFound = FALSE;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Index: 0x%x, LangId: 0x%x, ReqLen: 0x%x\n", DescIndex, LangId, ReqLen));
+
+ //
+ // index zero of the string table contains the supported language codes
+ //
+ if (DescIndex == 0) {
+ StringDesc = (mDrvObj.UsbdDevObj->StringTable);
+ Length = MIN (ReqLen, StringDesc->Length);
+ CopyMem (Buffer, StringDesc, Length);
+ *DataLen = Length;
+ Status = EFI_SUCCESS;
+ } else {
+
+ //
+ // Verify the requested language ID is supported. String descriptor Zero
+ // (First entry in the string table) is expected to contain the language list.
+ // The requested language ID is specified in the Index member of the request.
+ //
+ StringDesc = mDrvObj.UsbdDevObj->StringTable; // get language string descriptor
+ StrLangEntries = ((StringDesc->Length - 2) >> 1);
+ DEBUG ((DEBUG_INFO, "StrLangEntries=%x\n", StrLangEntries));
+
+ DEBUG ((DEBUG_INFO, "Looking LangID: \n"));
+
+ for (Index = 0; Index < StrLangEntries; Index++) {
+ DEBUG ((DEBUG_INFO, "LangID [%x]= %x\n", Index, StringDesc->LangID [Index]));
+
+ if (StringDesc->LangID [Index] == LangId) {
+ DEBUG ((DEBUG_INFO, "Found it\n"));
+ StrLangFound = TRUE;
+ }
+ }
+
+ //
+ // If we found a matching language, attempt to get the string index requested
+ //
+ if (StrLangFound == TRUE) {
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: StrLangFound=Found, DescIndex=%x, StrTblEntries=%x\n", DescIndex, mDrvObj.UsbdDevObj->StrTblEntries));
+
+ if (DescIndex < mDrvObj.UsbdDevObj->StrTblEntries) {
+ //
+ // get the string descriptor for the requested index
+ //
+ StringDesc = (mDrvObj.UsbdDevObj->StringTable + DescIndex);
+
+ Length = MIN (ReqLen, StringDesc->Length);
+ DEBUG ((DEBUG_INFO, "ReqLen=%x, StringLength=%x, Length=%x\n", ReqLen, StringDesc->Length, Length));
+
+ CopyMem (Buffer, StringDesc, Length);
+ *DataLen = Length;
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Invalid String index in USB_REQ_GET_DESCRIPTOR request\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Unsupported String Language ID for USB_REQ_GET_DESCRIPTOR request\n"));
+ }
+ }
+
+ if (Status == EFI_SUCCESS) {
+ PrintStringDescriptor (StringDesc);
+ }
+ return Status;
+}
+
+
+#ifdef SUPPORT_SUPER_SPEED
+/**
+ Returns the configuration descriptor for this device. The data
+ Buffer returned will also contain all downstream interface and
+ endpoint Buffers.
+
+ @param Buffer Pointer to destination Buffer to copy descriptor data to
+ @param ReqLen the length in bytes of the request Buffer
+ @param DataLen Pointer whos value is to be filled with the byte count of
+ data copied to the output Buffer
+
+ @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetBOSDesc (
+ IN VOID *Buffer,
+ IN UINT32 ReqLen,
+ IN UINT32 *DataLen
+ )
+{
+ EFI_USB_BOS_DESCRIPTOR *BosDesc = 0;
+ UINT32 Length = 0;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetBOSDesc()\n"));
+
+ BosDesc = mDrvObj.UsbdDevObj->BosDesc;
+ Length = MIN (ReqLen, mDrvObj.UsbdDevObj->BosDesc->TotalLength);
+
+ CopyMem(Buffer, BosDesc, Length);
+ *DataLen = Length;
+
+ PrintBOSDescriptor (BosDesc);
+
+ return EFI_SUCCESS;
+}
+#endif
+
+/**
+ Returns the current status for Device/Interface/Endpoint
+
+ @param Buffer Pointer to destination Buffer to copy descriptor data to
+ @param ReqType The type of status to get
+ @param ReqLen the length in bytes of the request Buffer
+ @param DataLen Pointer whos value is to be filled with the byte count of
+ data copied to the output Buffer
+
+ @return EFI_SUCCESS if status successfully copied, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetStatus (
+ VOID *Buffer,
+ UINT8 ReqType,
+ UINT32 ReqLen,
+ UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetStatus()\n"));
+
+ if (ReqLen >= 2) { // length of data must be at least 2 bytes
+ switch (ReqType & USB_TARGET_MASK) {
+ case USB_TARGET_DEVICE:
+ *DataLen = 2; // two byte for status
+ *(UINT16*)Buffer = USB_STATUS_SELFPOWERED;
+ Status = EFI_SUCCESS;
+ break;
+
+ case USB_TARGET_INTERFACE:
+ //
+ // No implementation needed at this time
+ //
+ break;
+
+ case USB_TARGET_ENDPOINT:
+ //
+ // No implementation needed at this time
+ // Should specify if endpoint is halted. Implement as necessary.
+ //
+ break;
+
+ case USB_TARGET_OTHER:
+ //
+ // No implementation needed at this time
+ //
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetStatus() - Invalid data length\n"));
+ }
+
+ return Status;
+}
+
+
+/**
+ Sets the address of the device
+
+ @param address the address value to set
+
+ @return EFI_SUCCESS if address was set, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdSetAddress (
+ UINT8 Address
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetAddress: setting address: 0x%x\n", Address));
+
+ if (Address <= 0x7F) { // address must not be > 127
+ mDrvObj.Address = Address;
+
+ //
+ // Configure Address in the XDCI
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, mDrvObj.Address);
+ if (!EFI_ERROR (Status)) {
+ mDrvObj.State = UsbDevStateAddress;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetAddress: Failed to set address in XDCI\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetAddress: Invalid address: 0x%x\n", Address));
+ }
+
+ return Status;
+}
+
+
+/**
+ Handles Setup device requests. Standard requests are immediately
+ handled here, and any Class/Vendor specific requests are forwarded
+ to the class driver
+
+ @param CtrlRequest Pointer to a device request
+
+ @return EFI_SUCCESS if request successfully handled, FALSE otherwise
+
+**/
+EFI_STATUS
+UsbdSetupHdlr (
+ IN EFI_USB_DEVICE_REQUEST *CtrlRequest
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT8 DescIndex = 0;
+ USB_DEVICE_DESCRIPTOR *DevDesc = 0;
+
+ //
+ // Initialize the IO object
+ //
+ mCtrlIoReq.IoInfo.Length = 0;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr start\n"));
+ PrintDeviceRequest (CtrlRequest);
+
+ //
+ // Handle Standard Device Requests
+ //
+ if ((CtrlRequest->RequestType & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) {
+ switch (CtrlRequest->Request) {
+ case USB_REQ_GET_DESCRIPTOR:
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Host requests get descriptor\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
+ DescIndex = (CtrlRequest->Value & 0xff); // low byte is the index requested
+ switch (CtrlRequest->Value >> 8) { // high byte contains request type
+ case USB_DESC_TYPE_DEVICE:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: Device\n"));
+ DevDesc = mDrvObj.UsbdDevObj->DeviceDesc;
+ //
+ // copy the data to the output Buffer
+ //
+ mCtrlIoReq.IoInfo.Length = MIN (CtrlRequest->Length, DevDesc->Length);
+ CopyMem (mCtrlIoReq.IoInfo.Buffer, DevDesc, mCtrlIoReq.IoInfo.Length);
+ PrintDeviceDescriptor (DevDesc);
+ break;
+
+ case USB_DESC_TYPE_CONFIG:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: Configuration\n"));
+ Status = UsbdGetConfigDesc (
+ mCtrlIoReq.IoInfo.Buffer,
+ DescIndex,
+ CtrlRequest->Length,
+ &(mCtrlIoReq.IoInfo.Length)
+ );
+ break;
+
+ case USB_DESC_TYPE_STRING:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: String\n"));
+ Status = UsbdGetStringDesc (
+ mCtrlIoReq.IoInfo.Buffer,
+ DescIndex,
+ CtrlRequest->Index,
+ CtrlRequest->Length,
+ &(mCtrlIoReq.IoInfo.Length)
+ );
+ break;
+
+#ifdef SUPPORT_SUPER_SPEED
+ case USB_DESC_TYPE_BOS:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: BOS\n"));
+ Status = UsbdGetBOSDesc (
+ mCtrlIoReq.IoInfo.Buffer,
+ CtrlRequest->Length,
+ &(mCtrlIoReq.IoInfo.Length)
+ );
+ break;
+
+ case USB_DESC_TYPE_SS_ENDPOINT_COMPANION:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: Endpoint Companion\n"));
+ break;
+#endif
+
+ default:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: Unsupported, USB_REQ_GET_DESCRIPTOR request: 0x%x\n", (CtrlRequest->Value >> 8)));
+ break;
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr() - Invalid direction for USB_REQ_GET_DESCRIPTOR request\n"));
+ }
+ break;
+
+ case USB_REQ_GET_CONFIG:
+ DEBUG ((DEBUG_INFO, "USB_REQ_GET_CONFIG\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
+ Status = UsbdGetConfig (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_CONFIG request\n"));
+ }
+ break;
+
+ case USB_REQ_SET_CONFIG:
+ DEBUG ((DEBUG_INFO, "USB_REQ_SET_CONFIG\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
+ Status = UsbdSetConfig ((UINT8)CtrlRequest->Value);
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_CONFIG request\n"));
+ }
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+ DEBUG ((DEBUG_INFO, "USB_REQ_SET_ADDRESS\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
+ Status = UsbdSetAddress ((UINT8)CtrlRequest->Value);
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_ADDRESS request\n"));
+ }
+ break;
+
+ case USB_REQ_GET_STATUS:
+ DEBUG ((DEBUG_INFO, "USB_REQ_GET_STATUS\n"));
+ if (CtrlRequest->RequestType & USB_RT_TX_DIR_D_TO_H) {
+ Status = UsbdGetStatus (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->RequestType, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_STATUS request\n"));
+ }
+ break;
+#ifdef SUPPORT_SUPER_SPEED
+ case USB_REQ_CLEAR_FEATURE:
+ case USB_REQ_SET_FEATURE:
+ case USB_REQ_SET_DESCRIPTOR:
+ case USB_REQ_GET_INTERFACE:
+ case USB_REQ_SET_INTERFACE:
+ case USB_REQ_SYNCH_FRAME:
+#endif
+ default:
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Unsupported Standard Request: 0x%x\n", CtrlRequest->Request));
+ break;
+ }
+ } else { // This is not a Standard request, it specifies Class/Vendor handling
+ //
+ // Forward request to class driver
+ //
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Class/Vendor Request\n"));
+ if (mDrvObj.UsbdDevObj->SetupCallback != NULL) {
+ mDrvObj.UsbdDevObj->SetupCallback (CtrlRequest, &(mCtrlIoReq.IoInfo));
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "dataLen=%x\n", mCtrlIoReq.IoInfo.Length));
+ //
+ // Transfer data according to request if necessary
+ //
+ if (mCtrlIoReq.IoInfo.Length> 0) {
+ Status = UsbdEpTxData (mDrvObj.XdciDrvObj, &mCtrlIoReq);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to TX data\n"));
+ }
+ } else {
+ //
+ // If we are not responding with data, send control status
+ //
+ Status = UsbDeviceEp0TxStatus (mDrvObj.XdciDrvObj);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to Tx Ep0 Status\n"));
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Handles Connection done events. Sets the device address to zero.
+
+ @return EFI_SUCCESS if able to set the address, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdConnDoneHdlr (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr()\n"));
+
+ //
+ // reset device address to 0
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
+ }
+
+ //
+ // set the device state to attached/connected
+ //
+ mDrvObj.State = UsbDevStateAttached;
+
+ return Status;
+}
+
+
+/**
+ Handles transmit/receive completion events. Directly handles
+ control endpoint events and forwards class/vendor specific events
+ to the class drivers.
+
+ @param XferInfo Pointer to Xfer structure
+
+ @return
+
+**/
+VOID
+UsbdXferDoneHdlr (
+ IN EFI_USB_DEVICE_XFER_INFO *XferInfo
+ )
+{
+ //
+ // If this is a non-control transfer complete, notify the class driver
+ //
+ if (XferInfo->EndpointNum > 0) {
+ if (mDrvObj.UsbdDevObj->DataCallback != NULL) {
+ mDrvObj.UsbdDevObj->DataCallback (XferInfo);
+ }
+ }
+
+ return;
+}
+
+
+/**
+ Binds a USB class driver with this USB device driver core.
+ After calling this routine, the driver is ready to begin
+ USB processing.
+
+ @param UsbdDevObj Pointer to a usbd device object which contains
+ all relevant information for the class driver device
+
+ @return TRUE if binding was successful, FALSE otherwise
+
+**/
+EFI_STATUS
+EFIAPI
+UsbDeviceBind (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute__((unused))*This,
+ IN USB_DEVICE_OBJ *UsbdDevObj
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // allocate Tx Buffer
+ //
+ mCtrlIoReq.IoInfo.Buffer = AllocateZeroPool (USB_EPO_MAX_PKT_SIZE_ALL);
+ if (mCtrlIoReq.IoInfo.Buffer != NULL) {
+ mDrvObj.UsbdDevObj = UsbdDevObj;
+ mDrvObj.ActiveConfigObj = NULL;
+ mDrvObj.Address = 0;
+ mDrvObj.State = UsbDevStateInit;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceBind() - Failed to allocate IO Buffer\n"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+
+/**
+ Unbinds the USB class driver from this USB device driver core.
+
+ @return TRUE if successful, FALSE otherwise
+
+**/
+EFI_STATUS
+EFIAPI
+UsbDeviceUnbind (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute__((unused))*This
+ )
+{
+ mDrvObj.UsbdDevObj = NULL;
+ mDrvObj.ActiveConfigObj = NULL;
+ mDrvObj.Address = 0;
+ mDrvObj.State = UsbDevStateOff;
+ mDrvObj.XdciInitialized = FALSE;
+
+ //
+ // release allocated Buffer data
+ //
+ if (mCtrlIoReq.IoInfo.Buffer) {
+ FreePool (mCtrlIoReq.IoInfo.Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Performs continual USB device event processing until a cancel
+ event occurs
+
+ @param TimeoutMs Connection timeout in ms. If 0, waits forever.
+ @return TRUE if run executed normally, FALSE if error ocurred
+
+**/
+EFI_STATUS
+EFIAPI
+UsbDeviceRun (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL *This,
+ IN UINT32 TimeoutMs
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_XDCI_DEV_CONTEXT *XdciDevContext;
+
+ XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
+
+ //
+ // can only run if XDCI is initialized
+ //
+ if (mDrvObj.XdciInitialized == TRUE) {
+
+ if ((mDrvObj.State == UsbDevStateConfigured) && (XdciDevContext->XdciPollTimer == NULL)) {
+ Status = uefi_call_wrapper(BS->CreateEvent,
+ 5,
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ UsbdMonitorEvents,
+ XdciDevContext,
+ &XdciDevContext->XdciPollTimer
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = uefi_call_wrapper(BS->SetTimer, 3, XdciDevContext->XdciPollTimer, TimerPeriodic,200000);
+ DEBUG ((EFI_D_ERROR, "UsbDeviceRun Create Event\n"));
+ }
+ }
+
+ mXdciRun = TRUE; // set the run flag to active
+ Status = EFI_SUCCESS;
+
+ //
+ // start the Event processing loop
+ //
+ while (TRUE) {
+ if (XdciDevContext->XdciPollTimer == NULL) {
+ if (UsbDeviceIsrRoutine (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
+ }
+ }
+
+ //
+ // Check if a run cancel request exists, if so exit processing loop
+ //
+ if (mXdciRun == FALSE) {
+ if (XdciDevContext->XdciPollTimer != NULL) {
+ DEBUG ((EFI_D_ERROR, "UsbDeviceRun close Event\n"));
+ uefi_call_wrapper(BS->SetTimer, 3, XdciDevContext->XdciPollTimer, TimerCancel, 0);
+ uefi_call_wrapper(BS->CloseEvent, 1, XdciDevContext->XdciPollTimer);
+ XdciDevContext->XdciPollTimer = NULL;
+ }
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_INFO, "UsbDeviceRun() - processing was cancelled\n"));
+ break;
+ }
+
+ //
+ // check for timeout
+ //
+ if (TimeoutMs == 0)
+ return EFI_TIMEOUT;
+ uefi_call_wrapper(BS->Stall, 1, 50);
+ TimeoutMs--;
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Sets a flag to stop the running device processing loop
+
+ @return TRUE always
+
+**/
+EFI_STATUS
+EFIAPI
+UsbDeviceStop (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute__((unused))*This
+ )
+{
+ mXdciRun = FALSE; // set run flag to FALSE to stop processing
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceInitXdci (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_XDCI_DEV_CONTEXT *XdciDevContext;
+
+ XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
+
+ PlatformSpecificInit ();
+
+ if (mDrvObj.XdciInitialized == FALSE) {
+ if (XdciDevContext->XdciMmioBarAddr != 0) {
+
+ //
+ // Initialize device controller driver
+ //
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Initializing Controller...\n"));
+
+ //
+ // Initialize the device controller interface
+ //
+ if (UsbdInit (XdciDevContext->XdciMmioBarAddr, &mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+
+ //
+ // Setup callbacks
+ //
+ if (UsbdRegisterCallbacks (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+
+ mDrvObj.XdciInitialized = TRUE;
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Controller initialization complete\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to register UDCI callbacks\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to initialize UDCI\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI MMIO BAR not set\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI already initialized\n"));
+ Status = EFI_ALREADY_STARTED;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceConnect(
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceConnect \n"));
+ if (UsbXdciDeviceConnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceDisConnect (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceDisConnect \n"));
+ if (UsbDeviceDisconnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+ mDrvObj.State = UsbDevStateInit;
+ Status = EFI_SUCCESS;
+ }
+
+ XhciSwitchSwid(FALSE);
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceEpTxData(
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This,
+ IN USB_DEVICE_IO_REQ *IoRequest
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbdEpTxData (mDrvObj.XdciDrvObj, IoRequest);
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceEpRxData(
+ IN EFI_USB_DEVICE_MODE_PROTOCOL __attribute((unused))*This,
+ IN USB_DEVICE_IO_REQ *IoRequest
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbdEpRxData (mDrvObj.XdciDrvObj, IoRequest);
+ return Status;
+}
+
+
+//
+// The Runtime UsbDeviceMode Protocol instance produced by this driver
+//
+EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol = {
+ UsbDeviceInitXdci,
+ UsbDeviceConnect,
+ UsbDeviceDisConnect,
+ UsbDeviceEpTxData,
+ UsbDeviceEpRxData,
+ UsbDeviceBind,
+ UsbDeviceUnbind,
+ UsbDeviceRun,
+ UsbDeviceStop
+};
+
diff --git a/libefiusb/device_mode/UsbDeviceMode.h b/libefiusb/device_mode/UsbDeviceMode.h
index 506a4c8b..a9b19a65 100644
--- a/libefiusb/device_mode/UsbDeviceMode.h
+++ b/libefiusb/device_mode/UsbDeviceMode.h
@@ -17,8 +17,7 @@
#include "protocol/UsbIo.h"
#include "protocol/UsbDeviceModeProtocol.h"
-
-///
+////
/// Function declaration
///
EFI_STATUS
@@ -27,6 +26,5 @@ UsbdSetupHdlr (
);
extern EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol;
-
#endif
diff --git a/libefiusb/device_mode/XdciCommon.h b/libefiusb/device_mode/XdciCommon.h
index 468e8a83..0d5d5d92 100644
--- a/libefiusb/device_mode/XdciCommon.h
+++ b/libefiusb/device_mode/XdciCommon.h
@@ -154,3 +154,6 @@ struct _USB_XFER_REQUEST {
#endif
+#define DEBUG_INFO EFI_SUCCESS
+#define EFI_D_INFO EFI_SUCCESS
+#define EFI_D_ERROR EFI_DEVICE_ERROR
diff --git a/libefiusb/device_mode/XdciDWC.c b/libefiusb/device_mode/XdciDWC.c
index 8b615f6c..52cd34be 100644
--- a/libefiusb/device_mode/XdciDWC.c
+++ b/libefiusb/device_mode/XdciDWC.c
@@ -1,4022 +1,4032 @@
-/** @file
- Copyright (c) 2006 - 2017, 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.
-
-**/
-#include
-#include
-#include
-#include
-
-#include "UsbDeviceDxe.h"
-#include "XdciInterface.h"
-#include "XdciDWC.h"
-
-UINT32
-UsbRegRead (
- IN UINT32 Base,
- IN UINT32 Offset
- )
-{
- volatile UINT32 *addr = (volatile UINT32 *)(UINTN)(Base + Offset);
- return *addr;
-}
-
-VOID
-UsbRegWrite (
- IN UINT32 Base,
- IN UINT32 Offset,
- IN UINT32 val
- )
-{
- volatile UINT32 *addr = (volatile UINT32 *)(UINTN)(Base + Offset);
- *addr = val;
-}
-
-
-/**
- Internal utility function:
- This function is used to obtain physical endpoint number
- xDCI needs physical endpoint number for EP registers
- We also use it to index into our EP array
- Note: Certain data structures/commands use logical EP numbers
- as opposed to physical endpoint numbers so one should be
- careful when interpreting EP numbers
- @EpNum: Logical endpoint number
- @epDir: Direction for the endpoint
-
-**/
-STATIC
-UINT32
-DwcXdciGetPhysicalEpNum (
- IN UINT32 EndpointNum,
- IN USB_EP_DIR EndpointDir
- )
-{
- return EndpointDir? ((EndpointNum << 1) | EndpointDir) : (EndpointNum << 1);
-}
-
-
-/**
- Internal utility function:
- This function is used to obtain the MPS for control transfers
- Based on the Speed. If this is called before bus reset completes
- then it returns MPS Based on desired Speed. If it is after bus
- reset then MPS returned is Based on actual negotiated Speed
- @CoreHandle: xDCI controller handle address
- @mps: address of 32-bit variable to return the MPS
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreGetCtrlMps (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 *mps
- )
-{
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (mps == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID parameter\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- switch (CoreHandle->ActualSpeed) {
- case USB_SPEED_HIGH:
- *mps = DWC_XDCI_HS_CTRL_EP_MPS;
- break;
- case USB_SPEED_FULL:
- *mps = DWC_XDCI_FS_CTRL_EP_MPS;
- break;
- case USB_SPEED_LOW:
- *mps = DWC_XDCI_LS_CTRL_EP_MPS;
- break;
- case USB_SPEED_SUPER:
- *mps = DWC_XDCI_SS_CTRL_EP_MPS;
- break;
- default:
- *mps = 0;
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: UNKNOWN Speed\n"));
- break;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal utility function:
- This function is used to initialize the parameters required
- for executing endpoint command
- @CoreHandle: xDCI controller handle address
- @EpInfo: EP info address
- @ConfigAction: Configuration action specific to EP command
- @EpCmd: xDCI EP command for which parameters are initialized
- @EpCmdParams: address of struct to return EP params
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreInitEpCmdParams (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN USB_EP_INFO *EpInfo,
- IN UINT32 ConfigAction,
- IN DWC_XDCI_ENDPOINT_CMD EpCmd,
- IN DWC_XDCI_ENDPOINT_CMD_PARAMS *EpCmdParams
- )
-{
- EFI_STATUS status = EFI_SUCCESS;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitEpCmdParams: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Reset params
- //
- EpCmdParams->Param0 = EpCmdParams->Param1 = EpCmdParams->Param2 = 0;
-
- switch (EpCmd) {
- case EPCMD_SET_EP_CONFIG:
- //
- // Issue DEPCFG command for EP
- // Issue a DEPCFG (Command 1) command for endpoint
- //
- if (EpInfo->MaxStreams) {
- EpCmdParams->Param1 = DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK;
- }
-
- if (EpInfo->Interval) {
- EpCmdParams->Param1 |= ((EpInfo->Interval-1) << DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS);
- }
-
- //
- // Set EP num
- //
- EpCmdParams->Param1 |= (EpInfo->EpNum << DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_BIT_POS);
- //
- // Set EP direction
- //
- EpCmdParams->Param1 |= (EpInfo->EpDir << DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_BIT_POS);
- //
- // Set EP-specific Event enable for not ready and
- // complete events
- //
- EpCmdParams->Param1 &= ~DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK;
- //
- // Setup the events we want enabled for this EP
- //
- EpCmdParams->Param1 |= (DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK |
- DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK |
- DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK);
-
- //
- // We only have one interrupt line for this core.
- // Set interrupt number to 0
- //
- EpCmdParams->Param1 &= ~DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK;
-
- //
- // Set FIFOnum = 0 for control EP0
- //
- EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK;
-
- //
- // Program FIFOnum for non-EP0 EPs
- //
- if (EpInfo->EpNum && EpInfo->EpDir) {
- EpCmdParams->Param0 |= (EpInfo->EpNum << DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_BIT_POS);
- }
-
- //
- // Program max packet size
- //
- EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK;
- EpCmdParams->Param0 |= (EpInfo->MaxPktSize << DWC_XDCI_PARAM0_SET_EP_CFG_MPS_BIT_POS);
-
- //
- // Set Burst size. 0 means burst size of 1
- //
- EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK;
- EpCmdParams->Param0 |= (EpInfo->BurstSize << DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_BIT_POS);
-
- //
- // Set EP type
- //
- EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK;
- EpCmdParams->Param0 |= (EpInfo->EpType << DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_BIT_POS);
-
- //
- // Set config action
- //
- EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK;
- EpCmdParams->Param0 |= (ConfigAction << DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_BIT_POS);
- break;
-
- case EPCMD_SET_EP_XFER_RES_CONFIG:
- // Set Param0 to 1. Same for all EPs when resource
- // configuration is done
- //
- EpCmdParams->Param0 = 1;
- break;
-
- case EPCMD_END_XFER:
- //
- // Nothing to set. Already reset params for all cmds
- //
- break;
-
- case EPCMD_START_NEW_CONFIG:
- //
- // Nothing to set. Already reset params for all cmds
- //
- break;
-
- default:
- status = EFI_INVALID_PARAMETER;
- DEBUG ((DEBUG_INFO, "\nDwcXdciCoreInitEpCmdParams: INVALID Parameter"));
- break;
- }
-
- return status;
-}
-
-
-/**
- Internal utility function:
- This function is used to issue the xDCI endpoint command
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical EP num
- @EpCmd: xDCI EP command
- @EpCmdParams: EP command parameters address
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreIssueEpCmd (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 EpNum,
- IN UINT32 EpCmd,
- IN DWC_XDCI_ENDPOINT_CMD_PARAMS *EpCmdParams
- )
-{
- UINT32 BaseAddr;
- UINT32 MaxDelayIter = 5000;//DWC_XDCI_MAX_DELAY_ITERATIONS;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIssueEpCmd: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = CoreHandle->BaseAddress;
-
- //
- // Set EP command parameter values
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EPCMD_PARAM2_REG(EpNum),
- EpCmdParams->Param2
- );
-
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EPCMD_PARAM1_REG(EpNum),
- EpCmdParams->Param1
- );
-
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EPCMD_PARAM0_REG(EpNum),
- EpCmdParams->Param0
- );
-
- //
- // Set the command code and activate it
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EPCMD_REG(EpNum),
- EpCmd | DWC_XDCI_EPCMD_CMD_ACTIVE_MASK
- );
-
- //
- // Wait until command completes
- //
- do {
- if (!(UsbRegRead (BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_CMD_ACTIVE_MASK))
- break;
- else
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreIssueEpCmd. ERROR: Failed to issue Command\n"));
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal utility function:
- This function is used to flush all FIFOs
- @CoreHandle: xDCI controller handle address
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreFlushAllFifos (
- IN XDCI_CORE_HANDLE *CoreHandle
- )
-{
- UINT32 BaseAddr;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushAllFifos: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = CoreHandle->BaseAddress;
-
- //
- // Write the command to flush all FIFOs
- //
- UsbRegWrite(
- BaseAddr,
- DWC_XDCI_DGCMD_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_ALL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
- );
-
- //
- // Wait until command completes
- //
- do {
- if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
- break;
- else
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal utility function:
- This function is used to flush Tx FIFO specific to an endpoint
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical EP num
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreFlushEpTxFifo (
- XDCI_CORE_HANDLE *CoreHandle,
- __attribute__((unused)) UINT32 EpNum
- )
-{
- UINT32 BaseAddr;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = CoreHandle->BaseAddress;
- //
- // TODO: Currently we are only using TxFIFO 0. Later map these
- // Write the FIFO num/dir param for the generic command.
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DGCMD_PARAM_REG,
- ((UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG) & ~DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK) | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK)
- );
-
- //
- // Write the command to flush all FIFOs
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DGCMD_REG,
- (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
- );
-
-
- //
- // Wait until command completes
- //
- do {
- if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
- break;
- else
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-
-
-STATIC
-EFI_STATUS
-DwcXdciCorePrepareOneTrb (
- IN DWC_XDCI_TRB *Trb,
- IN DWC_XDCI_TRB_CONTROL TrbCtrl,
- IN UINT32 LastBit,
- IN UINT32 ChainBit,
- IN UINT8 *BufferPtr,
- IN UINT32 size
- )
-{
- DEBUG ((DEBUG_INFO, "Trb is 0x%x, BufferPtr is 0x%x, size is 0x%x\n", Trb, BufferPtr, size));
-
- Trb->BuffPtrLow = (UINT32)(UINTN)BufferPtr;
- Trb->BuffPtrHigh = 0;
- Trb->LenXferParams = size;
- Trb->TrbCtrl = TrbCtrl << DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
-
- if (ChainBit)
- Trb->TrbCtrl |= ChainBit << DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS;
-
- if (LastBit)
- Trb->TrbCtrl |= LastBit << DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS;
-
- Trb->TrbCtrl |= DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK| DWC_XDCI_TRB_CTRL_HWO_MASK;
-
- DEBUG ((DEBUG_INFO, "(DwcXdciCorePrepareOneTrb) Trb->BuffPtrLow = 0x%x, Trb->LenXferParams is 0x%x, Trb->TrbCtrl is 0x%x\n",
- Trb->BuffPtrLow, Trb->LenXferParams, Trb->TrbCtrl));
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal utility function:
- This function is used to initialize transfer request block
- @CoreHandle: xDCI controller handle address
- @Trb: Address of TRB to initialize
- @TrbCtrl: TRB control value
- @buffPtr: Transfer Buffer address
- @size: Size of the transfer
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreInitTrb (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN DWC_XDCI_TRB *Trb,
- IN DWC_XDCI_TRB_CONTROL TrbCtrl,
- IN UINT8 *BufferPtr,
- IN UINT32 size
- )
-{
-#define ONE_TRB_SIZE (DWC_XDCI_TRB_BUFF_SIZE_MASK & 0x00F00000)
- UINT8 *TrbBuffer;
- UINT32 TrbCtrlLast;
- UINT32 TrbCtrlChain;
- UINT32 TrbIndex;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (Trb == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Init TRB fields
- // NOTE: Assuming we are only using 32-bit addresses
- // TODO: update for 64-bit addresses
- //
- if (size <= DWC_XDCI_TRB_BUFF_SIZE_MASK) {
- //
- // Can transfer in one TRB
- //
- TrbCtrlChain = 0;
- TrbCtrlLast = 1;
- DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, BufferPtr, size);
- return EFI_SUCCESS;
- }
-
- //
- // Can't transfer in one TRB.
- // Seperate it in every ONE_TRB_SIZE of TRB
- //
- TrbBuffer = BufferPtr;
- TrbIndex = 0;
- while (size > ONE_TRB_SIZE) {
- TrbCtrlChain = 1;
- TrbCtrlLast = 0;
- DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBuffer, ONE_TRB_SIZE);
- TrbBuffer += ONE_TRB_SIZE;
- size -= ONE_TRB_SIZE;
- Trb++;
- TrbIndex++;
- if (TrbIndex >= DWC_XDCI_TRB_NUM)
- return EFI_OUT_OF_RESOURCES;
- }
- TrbCtrlChain = 0;
- TrbCtrlLast = 1;
- DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBuffer, size);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to start a SETUP phase on control endpoint
- @CoreHandle: xDCI controller handle address
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciCoreStartEp0SetupXfer (
- IN XDCI_CORE_HANDLE *CoreHandle
- )
-{
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS status = EFI_DEVICE_ERROR;
- DWC_XDCI_TRB *Trb;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreStartEp0SetupXfer: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (CoreHandle->EpHandles[0].State == USB_EP_STATE_SETUP) {
- DEBUG ((DEBUG_INFO, "EP0 was already in SETUP phase\n"));
- return EFI_SUCCESS;
- }
-
- CoreHandle->EpHandles[0].State = USB_EP_STATE_SETUP;
- Trb = CoreHandle->Trbs;
- DEBUG ((DEBUG_INFO, "(DwcXdciCoreStartEp0SetupXfer)\n"));
-
- status = DwcXdciCoreInitTrb (
- CoreHandle,
- Trb,
- TRBCTL_SETUP,
- CoreHandle->AlignedSetupBuffer,
- 8
- );
-
- if (status)
- return status;
-
- //
- // Issue a DEPSTRTXFER for EP0
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Init the lower re-bits for TRB address
- //
- EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
-
- //
- // Issue the command to start transfer on physical
- // endpoint 0
- //
- status = DwcXdciCoreIssueEpCmd (
- CoreHandle,
- 0,
- EPCMD_START_XFER,
- &EpCmdParams
- );
-
- //
- // Save new resource index for this transfer
- //
- CoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead (
- CoreHandle->BaseAddress,
- DWC_XDCI_EPCMD_REG(0)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS
- );
-
- return status;
-}
-
-
-/**
- Internal function:
- This function is used to process the state change event
- @CoreHandle: xDCI controller handle address
- @event: device event dword
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessDeviceStateChangeEvent (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 Event
- )
-{
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceStateChangeEvent: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- CoreHandle->HirdVal = (Event & DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK) >> DWC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS;
-
- CoreHandle->LinkState = ((Event & DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_MASK) >> DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS);
-
- if (CoreHandle->EventCallbacks.DevLinkStateCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.LinkState = CoreHandle->LinkState;
- CoreHandle->EventCallbacks.CbEventParams.Hird = CoreHandle->HirdVal;
- CoreHandle->EventCallbacks.CbEventParams.SsEvent = (Event & DWC_XDCI_EVENT_BUFF_DEV_SS_EVENT_MASK) ? 1 : 0;
- CoreHandle->EventCallbacks.DevLinkStateCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to issue a command to end transfer
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical EP num for which transfer is to be ended
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciEndXfer (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 EpNum
- )
-{
- EFI_STATUS status;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- UINT32 cmdParams;
- DWC_XDCI_TRB *TrbPtr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciEndXfer: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- CoreHandle->EpHandles[EpNum].CheckFlag = FALSE;
-
- //
- // Issue a DEPENDXFER for EP
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- cmdParams = ((CoreHandle->EpHandles[EpNum].CurrentXferRscIdx << DWC_XDCI_EPCMD_RES_IDX_BIT_POS) | DWC_XDCI_EPCMD_FORCE_RM_MASK);
-
- if (CoreHandle->EpHandles[EpNum].CurrentXferRscIdx == 0) {
- return EFI_SUCCESS;
- }
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd(
- CoreHandle,
- EpNum,
- cmdParams | DWC_XDCI_EPCMD_END_XFER,
- &EpCmdParams
- );
-
- if (!status) {
- CoreHandle->EpHandles[EpNum].CurrentXferRscIdx = 0;
- TrbPtr = CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM);
- ZeroMem (TrbPtr, DWC_XDCI_TRB_NUM * sizeof (DWC_XDCI_TRB));
- }
-
- return status;
-}
-
-
-/**
- Internal function:
- This function is used to process bus reset detection event
- @CoreHandle: xDCI controller handle address
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessDeviceResetDet (
- IN XDCI_CORE_HANDLE *CoreHandle
- )
-{
- EFI_STATUS status = EFI_SUCCESS;
-
- if (CoreHandle == NULL) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Flush all FIFOs
- //
- status = DwcXdciCoreFlushAllFifos(CoreHandle);
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to flush FIFOs\n"));
- }
-
- //
- // Start SETUP phase on EP0
- //
- status = DwcXdciCoreStartEp0SetupXfer(CoreHandle);
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to start SETUP phase for EP0\n"));
- return status;
- }
-
- //
- // Notify upper layer if a callback is registerd for
- // this event
- //
- if (CoreHandle->EventCallbacks.DevBusResetCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- status = CoreHandle->EventCallbacks.DevBusResetCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- return status;
-}
-
-
-/**
- Internal function:
- This function is used to process connection done (means reset
- complete) event
- @CoreHandle: xDCI controller handle address
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessDeviceResetDone (
- IN XDCI_CORE_HANDLE *CoreHandle
- )
-{
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- UINT32 BaseAddr;
- EFI_STATUS status = EFI_SUCCESS;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceResetDone: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = CoreHandle->BaseAddress;
- CoreHandle->ActualSpeed = (UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_CONN_SPEED_MASK);
- DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDone CoreHandle->ActualSpeed is %x\n", CoreHandle->ActualSpeed));
-
- //
- // Program MPS Based on the negotiated Speed
- //
- DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[0].EpInfo.MaxPktSize);
- DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[1].EpInfo.MaxPktSize);
-
- //
- // Init DEPCFG cmd params for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- CoreHandle,
- &CoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- CoreHandle,
- 0,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- return status;
- }
-
- //
- // Init DEPCFG cmd params for EP1
- //
- status = DwcXdciCoreInitEpCmdParams (
- CoreHandle,
- &CoreHandle->EpHandles[1].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- CoreHandle,
- 1,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- //
- // Put the other PHY into suspend
- //
- if (CoreHandle->ActualSpeed == USB_SPEED_SUPER) {
- //
- // Put HS PHY to suspend
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB2PHYCFG_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) | DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
- );
-
- //
- // Clear SS PHY's suspend mask
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB3PIPECTL_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
- );
-
- } else {
- //
- // Put SS PHY to suspend
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB3PIPECTL_REG(0),
- (UsbRegRead(BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) | DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
- );
-
- //
- // Clear HS PHY's suspend mask
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB2PHYCFG_REG(0),
- (UsbRegRead(BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
- );
- }
-
- //
- // Notify upper layer if callback is registered
- //
- if (CoreHandle->EventCallbacks.DevResetDoneCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.Speed = CoreHandle->ActualSpeed;
- CoreHandle->EventCallbacks.DevResetDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- return status;
-}
-
-
-/**
- Internal function:
- This function is used to process device event
- @CoreHandle: xDCI controller handle address
- @IntLineEventBuffer: event Buffer pointing to device event
- @ProcessedEventSize: address of variable to save the size of
- the event that was Processed
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessDeviceEvent (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN DWC_XDCI_EVENT_BUFFER *IntLineEventBuffer,
- IN UINT32 *ProcessedEventSize
- )
-{
- UINT32 event;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceEvent: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Extract device event
- //
- event = (IntLineEventBuffer->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK);
- event >>= DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS;
-
- //
- // Assume default event size. Change it in switch case if
- // different
- //
- *ProcessedEventSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
-
- switch (event) {
- case DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT\n"));
- DwcXdciProcessDeviceResetDet (CoreHandle);
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT\n"));
- DwcXdciProcessDeviceResetDone (CoreHandle);
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT\n"));
- DwcXdciProcessDeviceStateChangeEvent (CoreHandle, IntLineEventBuffer->Event);
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT:
- DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT\n"));
- *ProcessedEventSize = DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES;
- break;
-
- default:
- DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceEvent: UNHANDLED device event: %x\n", event));
- break;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to process EP not ready for
- non-control endpoints
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical endpoint number
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessEpXferNotReady (
- __attribute__((unused)) XDCI_CORE_HANDLE *CoreHandle,
- __attribute__((unused)) UINT32 EpNum
- )
-{
- //
- // TODO: Not doing on-demand transfers
- // Revisit if required for later use
- //
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to process EP not ready for
- control endpoints
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical endpoint number
- @dataStage: EP not ready when data stage token was received
- @statusStage: EP not ready when status stage token was received
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessEp0XferNotReady (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 EpNum,
- IN UINT32 epEventStatus
- )
-{
- USB_EP_STATE epState = USB_EP_STATE_SETUP;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferNotReady: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
- //
- // Is it data stage or status stage
- //
- if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK) {
- epState = USB_EP_STATE_DATA;
- } else if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK) {
- epState = USB_EP_STATE_STATUS;
- }
-
- if ((EpNum == 0) && (epState == USB_EP_STATE_STATUS)) {
- if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_XFER_ACTIVE_MASK) {
- DEBUG ((DEBUG_INFO, "XFER_ACTIVE\n"));
- } else {
- DEBUG ((DEBUG_INFO, "XFER_NOT_ACTIVE\n"));
- }
- DwcXdciEp0ReceiveStatusPkt (CoreHandle);
- }
-
- //
- // Notify upper layer if a callback is registered for
- // this event
- //
- if (CoreHandle->EventCallbacks.DevXferNrdyCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.EpState = epState;
- CoreHandle->EventCallbacks.DevXferNrdyCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to process transfer phone done for EP0
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical endpoint number (0 for OUT and 1 for IN)
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessEp0XferPhaseDone (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 EpNum
- )
-{
- DWC_XDCI_ENDPOINT *epHandle;
- DWC_XDCI_TRB *Trb;
- EFI_STATUS status = EFI_SUCCESS;
- UINT32 TrbSts;
- UINT32 TrbCtrl;
- UINT32 TrbBufsize;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferPhaseDone: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- epHandle = &CoreHandle->EpHandles[EpNum];
- Trb = CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM);
- DEBUG ((DEBUG_INFO, "(DwcXdciProcessEp0XferPhaseDone)EpNum is %d\n", EpNum));
-
- if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
- DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone. HW owns TRB: %x!!!\n", (UINT32)(UINTN)Trb));
- }
-
- epHandle->CurrentXferRscIdx = 0;
- epHandle->State = USB_EP_STATE_ENABLED;
- TrbCtrl = (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
- TrbSts = (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_TRB_STATUS_BIT_POS;
- TrbBufsize = Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK;
-
- switch (TrbCtrl) {
- case DWC_XDCI_TRB_CTRL_TYPE_SETUP:
- DEBUG ((DEBUG_INFO, "SETUP\n"));
- if (CoreHandle->EventCallbacks.DevSetupPktReceivedCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.Buffer = CoreHandle->AlignedSetupBuffer;
- status = CoreHandle->EventCallbacks.DevSetupPktReceivedCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- if (!(CoreHandle->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIRECTION_MASK)) {
- //
- // Keep a Buffer ready for setup phase
- //
- DwcXdciCoreStartEp0SetupXfer (CoreHandle);
- }
-
- break;
-
- case DWC_XDCI_TRB_CTRL_TYPE_STATUS2:
- DEBUG ((DEBUG_INFO, "STATUS2\n"));
- break;
-
- case DWC_XDCI_TRB_CTRL_TYPE_STATUS3:
- DEBUG ((DEBUG_INFO, "STATUS3\n"));
- //
- // Notify upper layer of control transfer completion
- // if a callback function was registerd
- //
- if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
- CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
- CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(Trb->BuffPtrLow);
- CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- //
- // Status phase done. Queue next SETUP packet
- //
- status = DwcXdciCoreStartEp0SetupXfer(CoreHandle);
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to queue SETUP\n"));
- }
- break;
-
- case DWC_XDCI_TRB_CTRL_TYPE_DATA:
- DEBUG ((DEBUG_INFO, "DATA\n"));
- if (TrbSts == DWC_XDCI_TRB_STATUS_SETUP_PENDING || TrbBufsize != 0) {
- DEBUG ((DEBUG_INFO, "ERROR: Control transfert aborted by host: Setup pending\n"));
- DwcXdciCoreStartEp0SetupXfer (CoreHandle);
- }
-
- if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
- CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
- CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(Trb->BuffPtrLow);
- CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
- break;
-
- default:
- DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: UNHANDLED STATE in TRB\n"));
- break;
- }
-
- return status;
-}
-
-
-/**
- Internal function:
- This function is used to process transfer done for
- non-control endpoints
- @CoreHandle: xDCI controller handle address
- @EpNum: Physical endpoint number
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessEpXferDone (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 EpNum
- )
-{
- DWC_XDCI_ENDPOINT *epHandle;
- DWC_XDCI_TRB *Trb;
- USB_XFER_REQUEST *XferReq;
- UINT32 remainingLen;
-
- if (EpNum > DWC_XDCI_MAX_ENDPOINTS) {
- EpNum = DWC_XDCI_MAX_ENDPOINTS;
- }
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- epHandle = &CoreHandle->EpHandles[EpNum];
- epHandle->CurrentXferRscIdx = 0;
- Trb = epHandle->Trb;
- XferReq = &epHandle->XferHandle;
-
- //
- // if transfer done, set CheckFlag to FALSE for allow next transfer request.
- //
- epHandle->CheckFlag = FALSE;
-
- if ((Trb == NULL) || (XferReq == NULL)) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID parameter\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Compute the actual transfer length
- //
- XferReq->ActualXferLen = XferReq->XferLen;
- remainingLen = (Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK);
-
- if (remainingLen > XferReq->XferLen) {
- //
- // Buffer overrun? This should never happen
- //
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: Possible Buffer overrun\n"));
- } else {
- XferReq->ActualXferLen -= remainingLen;
- }
-
- //
- // Notify upper layer of request-specific transfer completion
- // if there is a callback specifically for this request
- //
- if (XferReq->XferDone) {
- XferReq->XferDone(CoreHandle->ParentHandle, XferReq);
- }
-
- //
- // Notify upper layer if a callback was registered
- //
- if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
- CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
- CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
- CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
- CoreHandle->EventCallbacks.CbEventParams.EpType = epHandle->EpInfo.EpType;
- CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(epHandle->Trb->BuffPtrLow);
- CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to process endpoint events
- @CoreHandle: xDCI controller handle address
- @IntLineEventBuffer: address of Buffer containing event
- to process
- @ProcessedEventSize: address to save the size of event
- Processed
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessEpEvent (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN DWC_XDCI_EVENT_BUFFER *IntLineEventBuffer,
- IN UINT32 *ProcessedEventSize
- )
-{
- UINT32 EpNum;
- UINT32 epEvent;
- UINT32 epEventStatus;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpEvent: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- epEvent = IntLineEventBuffer->Event;
-
- *ProcessedEventSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
-
- //
- // Get EP num
- //
- EpNum = ((epEvent & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS);
- epEventStatus = (epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK);
-
- //
- // Interpret event and handle transfer completion here
- //
- epEvent = ((epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_EVENT_BUFF_EP_EVENT_BIT_POS);
-
- switch (epEvent) {
- case DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT:
- DEBUG ((DEBUG_INFO, "XFER_CMPLT ep %d\n", EpNum));
- if (EpNum > 1) {
- DwcXdciProcessEpXferDone (CoreHandle, EpNum);
- } else {
- DwcXdciProcessEp0XferPhaseDone (CoreHandle, EpNum);
- }
- break;
-
- case DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS:
- DEBUG ((DEBUG_INFO, "IN_PROGRESS\n"));
- break;
-
- case DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY:
- DEBUG ((DEBUG_INFO, "NOT_READY ep %d\n", EpNum));
- if (EpNum > 1) {
- //
- // Endpoint transfer is not ready
- //
- DwcXdciProcessEpXferNotReady (CoreHandle, EpNum);
- } else {
- DwcXdciProcessEp0XferNotReady (CoreHandle, EpNum, epEventStatus);
- }
- break;
-
- default:
- DEBUG ((DEBUG_INFO, "DwcXdciProcessEpEvent: UNKNOWN EP event\n"));
- break;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Internal function:
- This function is used to process events on single interrupt line
- @CoreHandle: xDCI controller handle address
- @eventCount: event bytes to process
- @ProcessedEventCount: address to save the size
- (in bytes) of event Processed
- Processed
-
-**/
-STATIC
-EFI_STATUS
-DwcXdciProcessInterruptLineEvents (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 eventCount,
- IN UINT32 *ProcessedEventCount
- )
-{
- UINT32 ProcessedEventSize = 0;
- UINT32 currentEventAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (CoreHandle->CurrentEventBuffer == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID event Buffer\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- currentEventAddr = (UINT32)(UINTN)(CoreHandle->CurrentEventBuffer);
-
- //
- // Process eventCount/eventSize number of events
- // in this run
- //
- while (eventCount) {
- if (CoreHandle->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) {
- DwcXdciProcessDeviceEvent (
- CoreHandle,
- CoreHandle->CurrentEventBuffer,
- &ProcessedEventSize
- );
- } else {
- DwcXdciProcessEpEvent (
- CoreHandle,
- CoreHandle->CurrentEventBuffer,
- &ProcessedEventSize);
- }
-
- eventCount -= ProcessedEventSize;
- *ProcessedEventCount += ProcessedEventSize;
- if ((currentEventAddr + ProcessedEventSize) >=
- ((UINT32)(UINTN)(CoreHandle->AlignedEventBuffers) + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))
- ) {
- currentEventAddr = (UINT32)(UINTN)(CoreHandle->AlignedEventBuffers);
- DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer bound reached\n"));
- } else {
- currentEventAddr += ProcessedEventSize;
- }
-
- CoreHandle->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER *)(UINTN)currentEventAddr;
- }
-
- return EFI_SUCCESS;
-}
-
-//
-// DWC XDCI APIs
-//
-
-/**
- Interface:
-
- This function is used to initialize the xDCI core
- @configParams: Parameters from app to configure the core
- @deviceCorePtr: HW-independent APIs handle for device core
- @CoreHandle: xDCI controller handle retured
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreInit (
- IN USB_DEV_CONFIG_PARAMS *ConfigParams,
- IN VOID *deviceCorePtr,
- IN VOID **CoreHandle
- )
-{
- EFI_STATUS status = EFI_DEVICE_ERROR;
- UINT32 BaseAddr;
- XDCI_CORE_HANDLE *LocalCoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
- UINT8 i;
-
- LocalCoreHandle = (XDCI_CORE_HANDLE *)AllocateZeroPool (sizeof(XDCI_CORE_HANDLE));
-
- if (CoreHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (LocalCoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xDCI\n"));
- return EFI_OUT_OF_RESOURCES;
- }
-
- ZeroMem (LocalCoreHandle, sizeof(XDCI_CORE_HANDLE));
-
- LocalCoreHandle->ParentHandle = deviceCorePtr;
-
- *CoreHandle = (VOID *)LocalCoreHandle;
-
- LocalCoreHandle->Id = ConfigParams->ControllerId;
- LocalCoreHandle->BaseAddress = BaseAddr = ConfigParams->BaseAddress;
- LocalCoreHandle->Flags = ConfigParams->Flags;
- LocalCoreHandle->DesiredSpeed = LocalCoreHandle->ActualSpeed = ConfigParams->Speed;
- LocalCoreHandle->Role = ConfigParams->Role;
-
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_CSFTRST_MASK);
-
- // Wait until core soft reset completes
- do {
- if (!(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & DWC_XDCI_DCTL_CSFTRST_MASK)) {
- break;
- } else {
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- }
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- efi_perror (status, L"Failed to reset device controller 0x%x",(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG)));
- return EFI_DEVICE_ERROR;
- }
-
- DEBUG ((DEBUG_INFO, "USB core has been reset\n"));
-
- //
- // All FIFOs are flushed at this point
- //
- //
- // Ensure we have EP0 Rx/Tx handles initialized
- //
- LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
- LocalCoreHandle->EpHandles[0].EpInfo.EpDir = UsbEpDirOut;
- LocalCoreHandle->EpHandles[0].EpInfo.EpType = USB_ENDPOINT_CONTROL;
- LocalCoreHandle->EpHandles[0].EpInfo.MaxPktSize = DWC_XDCI_SS_CTRL_EP_MPS;
- //
- // 0 means burst size of 1
- //
- LocalCoreHandle->EpHandles[0].EpInfo.BurstSize = 0;
-
- LocalCoreHandle->EpHandles[1].EpInfo.EpNum = 0;
- LocalCoreHandle->EpHandles[1].EpInfo.EpDir = UsbEpDirIn;
- LocalCoreHandle->EpHandles[1].EpInfo.EpType = USB_ENDPOINT_CONTROL;
- LocalCoreHandle->EpHandles[1].EpInfo.MaxPktSize = DWC_XDCI_SS_CTRL_EP_MPS;
- //
- // 0 means burst size of 1
- //
- LocalCoreHandle->EpHandles[1].EpInfo.BurstSize = 0;
-
- LocalCoreHandle->DevState = UsbDevStateDefault;
-
- //
- // Clear KeepConnect bit so we can allow disconnect and
- // re-connect. Stay in RX_DETECT state
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) &
- (~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) &
- ((~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK) | (DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS))
- );
-
- DEBUG ((DEBUG_INFO, "Device controller Synopsys ID: %x\n", UsbRegRead (BaseAddr, DWC_XDCI_GSNPSID_REG)));
- DEBUG ((DEBUG_INFO, "Default value of xDCI GSBUSCFG0 and GSBUSCFG1: %x, %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG0_REG),
- UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG1_REG)));
-
- DEBUG ((DEBUG_INFO, "Default value of xDCI GTXTHRCFG and GRXTHRCFG: %x, %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GTXTHRCFG_REG),
- UsbRegRead (BaseAddr, DWC_XDCI_GRXTHRCFG_REG)));
-
- //
- // Clear ULPI auto-resume bit
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB2PHYCFG_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)) & ~DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK)
- );
-
- DEBUG ((DEBUG_INFO, "Default value of xDCI GUSB2PHYCFG and GUSB3PIPECTL: %x, %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)),
- UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG (0))));
- //
- // Only one RxFIFO
- //
- DEBUG ((DEBUG_INFO, "Default value of DWC_XDCI_GRXFIFOSIZ: %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GRXFIFOSIZ_REG (0))));
-
- for (i = 0; i < DWC_XDCI_MAX_ENDPOINTS; i++) {
- DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_GTXFIFOSIZ %d: %x\n",
- i, UsbRegRead (BaseAddr, DWC_XDCI_GTXFIFOSIZ_REG (i))));
- }
-
- //
- // TODO: Need to check if TxFIFO should start where RxFIFO ends
- // or default is correct i.e. TxFIFO starts at 0 just like RxFIFO
- //
-
- //
- // Allocate and Initialize Event Buffers
- //
- LocalCoreHandle->MaxDevIntLines = ((UsbRegRead (BaseAddr, DWC_XDCI_GHWPARAMS1_REG) &
- DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
- DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS);
-
- DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIntLines));
- //
- // One event Buffer per interrupt line.
- // Need to align it to size of event Buffer
- // Buffer needs to be big enough. Otherwise the core
- // won't operate
- //
- LocalCoreHandle->AlignedEventBuffers = (DWC_XDCI_EVENT_BUFFER *)
- ((UINT32)(UINTN)(LocalCoreHandle->EventBuffers) +
- ((sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) -
- (((UINT32)(UINTN)(LocalCoreHandle->EventBuffers)) %
- (sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))));
-
- for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GEVNTADR_REG (i),
- (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)
- );
-
- //
- // Clear High 32bit address register, GEVNTADR register is 64-bit register
- // default is 0xffffffffffffffff
- //
- UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000);
-
- LocalCoreHandle->CurrentEventBuffer = LocalCoreHandle->AlignedEventBuffers;
- //
- // Write size and clear the mask
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EVNTSIZ_REG (i),
- sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER
- );
-
- //
- // Write 0 to the event count register as the last step
- //
- // for event configuration
- //
- UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), 0);
-
- DEBUG ((DEBUG_INFO, "Value of xDCI Event Buffer %d: %x, Size: %x, Count: %x\n",
- i,
- UsbRegRead (BaseAddr, DWC_XDCI_GEVNTADR_REG (i)),
- UsbRegRead (BaseAddr, DWC_XDCI_EVNTSIZ_REG (i)),
- UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i))));
- }
-
- //
- // Program Global Control Register to disable scaledown,
- // disable clock gating
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GCTL_REG,
- ((UsbRegRead(BaseAddr, DWC_XDCI_GCTL_REG) &
- ~(DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK + DWC_XDCI_GCTL_RAMCLKSEL_MASK + DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK)) |
- DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK |
- (DWC_XDCI_GCTL_PRT_CAP_DEVICE << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)));
-
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
-
- //
- // TODO: Program desired Speed and set LPM capable
- // We will do this when SuperSpeed works. For now,
- // force into High-Speed mode to aVOID anyone trying this
- // on Super Speed port
- //
-
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCFG_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | LocalCoreHandle->DesiredSpeed
- );
-#if 0
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCFG_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | DWC_XDCI_DCFG_DESIRED_HS_SPEED
- );
-#endif
-
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG)));
-
- //
- // Enable Device Interrupt Events
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DEVTEN_REG,
- DWC_XDCI_DEVTEN_DEVICE_INTS
- );
- //
- // Program the desired role
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GCTL_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG) & ~DWC_XDCI_GCTL_PRT_CAP_DIR_MASK) | (LocalCoreHandle->Role << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)
- );
- //
- // Clear USB2 suspend for start new config command
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB2PHYCFG_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
- );
-
- //
- // Clear USB3 suspend for start new config command
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB3PIPECTL_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
- );
-
- //
- // Issue DEPSTARTCFG command for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_START_NEW_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to init params for START_NEW_CONFIG EP command on xDCI");
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_START_NEW_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to issue START_NEW_CONFIG EP command on xDCI");
- return status;
- }
-
- //
- // Issue DEPCFG command for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP0");
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams);
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP0");
- return status;
- }
-
- //
- // Issue DEPCFG command for EP1
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[1].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP1");
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 1,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP1");
- return status;
- }
-
- //
- // Issue DEPXFERCFG command for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0");
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0");
- return status;
- }
-
- //
- // Issue DEPXFERCFG command for EP1
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[1].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1");
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 1,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- efi_perror (status, L"DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1");
- return status;
- }
-
- //
- // Prepare a Buffer for SETUP packet
- //
- LocalCoreHandle->Trbs = (DWC_XDCI_TRB *)(UINTN)((UINT32)(UINTN)
- LocalCoreHandle->UnalignedTrbs +
- (DWC_XDCI_TRB_BYTE_ALIGNMENT -
- ((UINT32)(UINTN)LocalCoreHandle->UnalignedTrbs %
- DWC_XDCI_TRB_BYTE_ALIGNMENT)));
-
- DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ unalignedTrbs address is 0x%x\n", LocalCoreHandle->UnalignedTrbs));
- DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ TRB address is 0x%x\n", LocalCoreHandle->Trbs));
- //
- // Allocate Setup Buffer that is 8-byte aligned
- //
- LocalCoreHandle->AlignedSetupBuffer = LocalCoreHandle->DefaultSetupBuffer +
- (DWC_XDCI_SETUP_BUFF_SIZE -
- ((UINT32)(UINTN)(LocalCoreHandle->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
-
- //
- // Aligned Buffer for status phase
- //
- LocalCoreHandle->AlignedMiscBuffer = LocalCoreHandle->MiscBuffer +
- (DWC_XDCI_SETUP_BUFF_SIZE -
- ((UINT32)(UINTN)(LocalCoreHandle->AlignedMiscBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
-
-
- //
- // Enable Physical Endpoints 0
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EP_DALEPENA_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 0)
- );
- //
- // Enable Physical Endpoints 1
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EP_DALEPENA_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 1)
- );
-
- DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
- return status;
-}
-
-
-/**
- Interface:
- This function is used to de-initialize the xDCI core
- @CoreHandle: xDCI controller handle
- @flags: Special flags for de-initializing the core in
- particular way
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreDeinit (
- VOID *CoreHandle,
- __attribute__((unused)) UINT32 flags
- )
-{
- FreePool (CoreHandle);
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to register event callback function
- @CoreHandle: xDCI controller handle
- @event: Event for which callback is to be registered
- @callbackFn: Callback function to invoke after event occurs
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreRegisterCallback (
- IN VOID *CoreHandle,
- IN USB_DEVICE_EVENT_ID Event,
- IN USB_DEVICE_CALLBACK_FUNC CallbackFunc
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
-
- if (LocalCoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreRegisterCallback: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- DEBUG ((DEBUG_INFO, "DwcXdciCoreRegisterCallback: event is %d\n", Event));
- switch (Event) {
- case USB_DEVICE_DISCONNECT_EVENT:
- LocalCoreHandle->EventCallbacks.DevDisconnectCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_RESET_EVENT:
- LocalCoreHandle->EventCallbacks.DevBusResetCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_CONNECTION_DONE:
- LocalCoreHandle->EventCallbacks.DevResetDoneCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_STATE_CHANGE_EVENT:
- LocalCoreHandle->EventCallbacks.DevLinkStateCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_WAKEUP_EVENT:
- LocalCoreHandle->EventCallbacks.DevWakeupCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_HIBERNATION_REQ_EVENT:
- LocalCoreHandle->EventCallbacks.DevHibernationCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_SOF_EVENT:
- LocalCoreHandle->EventCallbacks.DevSofCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_ERRATIC_ERR_EVENT:
- LocalCoreHandle->EventCallbacks.DevErraticErrCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_CMD_CMPLT_EVENT:
- LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_BUFF_OVERFLOW_EVENT:
- LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_TEST_LMP_RX_EVENT:
- LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_SETUP_PKT_RECEIVED:
- LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_XFER_NRDY:
- LocalCoreHandle->EventCallbacks.DevXferNrdyCallback = CallbackFunc;
- break;
-
- case USB_DEVICE_XFER_DONE:
- LocalCoreHandle->EventCallbacks.DevXferDoneCallback = CallbackFunc;
- break;
-
- default:
- break;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to unregister event callback function
- @CoreHandle: xDCI controller handle
- @event: Event for which callback function is to be unregistered
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreUnregisterCallback (
- IN VOID *CoreHandle,
- IN USB_DEVICE_EVENT_ID event
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
-
- if (LocalCoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreUnregisterCallback: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- switch (event) {
- case USB_DEVICE_DISCONNECT_EVENT:
- LocalCoreHandle->EventCallbacks.DevDisconnectCallback = NULL;
- break;
-
- case USB_DEVICE_RESET_EVENT:
- LocalCoreHandle->EventCallbacks.DevBusResetCallback = NULL;
- break;
-
- case USB_DEVICE_CONNECTION_DONE:
- LocalCoreHandle->EventCallbacks.DevResetDoneCallback = NULL;
- break;
-
- case USB_DEVICE_STATE_CHANGE_EVENT:
- LocalCoreHandle->EventCallbacks.DevLinkStateCallback = NULL;
- break;
-
- case USB_DEVICE_WAKEUP_EVENT:
- LocalCoreHandle->EventCallbacks.DevWakeupCallback = NULL;
- break;
-
- case USB_DEVICE_HIBERNATION_REQ_EVENT:
- LocalCoreHandle->EventCallbacks.DevHibernationCallback = NULL;
- break;
-
- case USB_DEVICE_SOF_EVENT:
- LocalCoreHandle->EventCallbacks.DevSofCallback = NULL;
- break;
-
- case USB_DEVICE_ERRATIC_ERR_EVENT:
- LocalCoreHandle->EventCallbacks.DevErraticErrCallback = NULL;
- break;
-
- case USB_DEVICE_CMD_CMPLT_EVENT:
- LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback = NULL;
- break;
-
- case USB_DEVICE_BUFF_OVERFLOW_EVENT:
- LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback = NULL;
- break;
-
- case USB_DEVICE_TEST_LMP_RX_EVENT:
- LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback = NULL;
- break;
-
- case USB_DEVICE_SETUP_PKT_RECEIVED:
- LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback = NULL;
- break;
-
- case USB_DEVICE_XFER_NRDY:
- LocalCoreHandle->EventCallbacks.DevXferNrdyCallback = NULL;
- break;
-
- case USB_DEVICE_XFER_DONE:
- LocalCoreHandle->EventCallbacks.DevXferDoneCallback = NULL;
- break;
-
- default:
- break;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used as an interrupt service routine
- @CoreHandle: xDCI controller handle
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreIsrRoutine (
- IN VOID *CoreHandle
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 BaseAddr;
- UINT32 eventCount;
- UINT32 ProcessedEventCount;
- UINT32 i;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutine: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (LocalCoreHandle->InterrupProcessing == TRUE) {
- DEBUG ((DEBUG_INFO, "interrupProcessing.........\n"));
- return EFI_SUCCESS;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
- //
- // Event Buffer corresponding to each interrupt line needs
- // to be Processed
- //
- LocalCoreHandle->InterrupProcessing = TRUE;
- for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
- //
- // Get the number of events HW has written for this
- // interrupt line
- //
- eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i));
- eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
- ProcessedEventCount = 0;
-
- //
- // Process interrupt line Buffer only if count is non-zero
- //
- if (eventCount) {
- //
- // Process events in this Buffer
- //
- DwcXdciProcessInterruptLineEvents (LocalCoreHandle, eventCount, &ProcessedEventCount);
- //
- // Write back the Processed number of events so HW decrements it from current
- // event count
- //
- UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), ProcessedEventCount);
- }
- }
- LocalCoreHandle->InterrupProcessing = FALSE;
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used as an interrupt service routine and it processes only one event at a time.
- @CoreHandle: xDCI controller handle
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreIsrRoutineTimerBased (
- IN VOID *CoreHandle
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 BaseAddr;
- UINT32 eventCount;
- UINT32 ProcessedEventCount;
- UINT32 currentEventAddr;
- UINT32 ProcessedEventSize = 0;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutineTimerBased: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (LocalCoreHandle->CurrentEventBuffer == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIsrRoutineTimerBased: INVALID event Buffer\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0)) & DWC_XDCI_EVNTCOUNT_MASK;
-
- if (LocalCoreHandle->InterrupProcessing == TRUE) {
- DEBUG ((DEBUG_INFO, "interrupProcessing.........\n"));
- return EFI_SUCCESS;
- }
-
- LocalCoreHandle->InterrupProcessing = TRUE;
-
- ProcessedEventCount = 0;
- currentEventAddr = (UINT32)(UINTN)(LocalCoreHandle->CurrentEventBuffer);
-
- if (LocalCoreHandle->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) {
- DwcXdciProcessDeviceEvent (
- LocalCoreHandle,
- LocalCoreHandle->CurrentEventBuffer,
- &ProcessedEventSize
- );
- } else {
- DwcXdciProcessEpEvent (
- LocalCoreHandle,
- LocalCoreHandle->CurrentEventBuffer,
- &ProcessedEventSize);
- }
-
- eventCount -= ProcessedEventSize;
- ProcessedEventCount += ProcessedEventSize;
- if ((currentEventAddr + ProcessedEventSize) >=
- ((UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers) + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))
- ) {
- currentEventAddr = (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers);
- DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer bound reached\n"));
- } else {
- currentEventAddr += ProcessedEventSize;
- }
-
- LocalCoreHandle->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER *)(UINTN)currentEventAddr;
- UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0), ProcessedEventCount);
- LocalCoreHandle->InterrupProcessing = FALSE;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to enable xDCI to connect to the host
- @CoreHandle: xDCI controller handle
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreConnect (
- IN VOID *CoreHandle
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
- UINT32 BaseAddr;
-
- EFI_STATUS ret = EFI_DEVICE_ERROR;
- if (CoreHandle == NULL) {
- efi_perror (ret, L"DwcXdciCoreConnect: INVALID handle\n");
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- // Clear KeepConnect bit so we can allow disconnect and re-connect
- // Also issue No action on state change to aVOID any link change
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- (UsbRegRead(BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) & ~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK
- );
-
- //
- // Set Run bit to connect to the host
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_RUN_STOP_MASK
- );
-
- // Wait until core starts running
- do {
- if (!(UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK)) {
- break;
- } else {
- efi_perror (ret, L"Stall for core run");
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- }
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to disconnect xDCI from the host
- @CoreHandle: xDCI controller handle
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreDisconnect (
- IN VOID *CoreHandle
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
- UINT32 BaseAddr;
- UINT32 eventCount;
- UINT32 dsts;
- UINT32 i;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0));
- eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
-
- DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=%d\n", eventCount));
- while (eventCount) {
- DwcXdciCoreIsrRoutine(LocalCoreHandle);
- eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0));
- eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
- DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=%d\n", eventCount));
- }
-
- //
- // Issue DEPENDXFER for active transfers
- //
- for (i = 0; i < DWC_XDCI_MAX_ENDPOINTS; i++){
- if (LocalCoreHandle->EpHandles[i].CurrentXferRscIdx){
- DwcXdciEndXfer(LocalCoreHandle, i);
- }
- }
- //
- // Clear Run bit to disconnect from host
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead(BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_RUN_STOP_MASK);
-
- //
- // Wait until core is halted
- //
- do {
- dsts = UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG);
- DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: waiting halt: DSTS=0x%x\n", dsts));
- if ((dsts & DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK) != 0){
- break;
- } else {
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- }
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: Failed to halt the device controller\n"));
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to obtain current USB bus Speed
- @CoreHandle: xDCI controller handle
- @Speed: Address of variable to save the Speed
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreGetSpeed (
- IN VOID *CoreHandle,
- IN USB_SPEED *Speed
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (Speed == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID parameter\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- *Speed = UsbRegRead (LocalCoreHandle->BaseAddress, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_CONN_SPEED_MASK;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to obtain current USB bus Speed
- @CoreHandle: xDCI controller handle
- @address: USB address to set (assigned by USB host)
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreSetAddress (
- IN VOID *CoreHandle,
- IN UINT32 address
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress is 0x%x \n", address));
- //
- // Program USB device address
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCFG_REG,
- (UsbRegRead(BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DEV_ADDRESS_MASK) | (address << DWC_XDCI_DCFG_DEV_ADDRESS_BIT_POS)
- );
-
- LocalCoreHandle->DevState = UsbDevStateAddress;
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG)));
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to set configuration
- @CoreHandle: xDCI controller handle
- @ConfigNum: config num to set (assigned by USB host)
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciCoreSetConfig (
- VOID *CoreHandle,
- __attribute__((unused)) UINT32 ConfigNum
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS status;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Issue DEPSTARTCFG command on EP0 (new config for
- // non-control EPs)
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_START_NEW_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: Failed to init params for EPCMD_START_NEW_CONFIG command\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- (EPCMD_START_NEW_CONFIG | (2 << DWC_XDCI_EPCMD_RES_IDX_BIT_POS)),
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: Failed to issue EPCMD_START_NEW_CONFIG command\n"));
- return status;
- }
-
- return status;
-}
-
-
-/**
- Interface:
- This function is used to set link state
- @CoreHandle: xDCI controller handle
- @state: Desired link state
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciSetLinkState (
- IN VOID *CoreHandle,
- IN USB_DEVICE_SS_LINK_STATE state
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciSetLinkState: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // Clear old mask
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK
- );
-
- //
- // Request new state
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | (state << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS)
- );
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to initialize endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- to be initialized
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciInitEp (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS status;
- UINT32 EpNum;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciInitEp: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
-
- //
- // Save EP properties
- //
- CopyMem (&(LocalCoreHandle->EpHandles[EpNum].EpInfo), EpInfo, sizeof (USB_EP_INFO));
-
- //
- // Init CheckFlag
- //
- LocalCoreHandle->EpHandles[EpNum].CheckFlag = FALSE;
-
- //
- // Init DEPCFG cmd params for EP
- //
- status = DwcXdciCoreInitEpCmdParams (
- CoreHandle,
- &LocalCoreHandle->EpHandles[EpNum].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to init params for EPCMD_SET_EP_CONFIG command\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- CoreHandle,
- EpNum,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_CONFIG command\n"));
- return status;
- }
-
- //
- // Issue a DEPXFERCFG command for endpoint
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[EpNum].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- EpNum,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command\n"));
- }
-
- return status;
-}
-
-
-/**
- Interface:
- This function is used to enable non-Ep0 endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- to be enabled
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpEnable (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 EpNum;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpEnable: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
-
- //
- // Enable Physical Endpoint EpNum
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EP_DALEPENA_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << EpNum)
- );
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to disable non-Ep0 endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- to be enabled
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpDisable (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 EpNum;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpDisable: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
-
- //
- // Disable Physical Endpoint EpNum
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EP_DALEPENA_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) & ~(1 << EpNum)
- );
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to STALL and endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- to be enabled
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpStall (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS status;
- UINT32 EpNum;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpStall: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
-
- //
- // Set Ep State Info
- //
- if (LocalCoreHandle->EpHandles[EpNum].State != USB_EP_STATE_STALLED) {
- LocalCoreHandle->EpHandles[EpNum].OrgState = LocalCoreHandle->EpHandles[EpNum].State;
- LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_STALLED;
- }
- //
- // Issue a DWC_XDCI_EPCMD_SET_STALL for EP
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- EpNum,
- DWC_XDCI_EPCMD_SET_STALL,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP stall command\n"));
- }
-
- return status;
-}
-
-
-/**
- Interface:
- This function is used to clear endpoint STALL
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- to be enabled
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpClearStall (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS status;
- UINT32 EpNum;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpClearStall: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
-
- //
- // Set Ep State Info
- //
- LocalCoreHandle->EpHandles[EpNum].State = LocalCoreHandle->EpHandles[EpNum].OrgState;
-
- //
- // Issue a DWC_XDCI_EPCMD_CLEAR_STALL for EP
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- EpNum,
- DWC_XDCI_EPCMD_CLEAR_STALL,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP clea stall command\n"));
- }
-
- return status;
-}
-
-
-/**
- Interface:
- This function is used to set endpoint in NOT READY state
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- to be enabled
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpSetNrdy (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- UINT32 EpNum;
- UINT32 BaseAddr;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpSetNrdy: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
-
- //
- // Program the EP number in command's param reg
- //
- UsbRegWrite (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG, EpNum);
-
- //
- // Issue EP not ready generic device command
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DGCMD_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SET_EP_NRDY)
- );
-
- //
- // Activate the command
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DGCMD_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
- );
-
- //
- // Wait until command completes
- //
- do {
- if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
- break;
- else
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Interface:
- This function is used to queue receive SETUP packet request
- @CoreHandle: xDCI controller handle
- @Buffer: Address of Buffer to receive SETUP packet
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEp0ReceiveSetupPkt (
- IN VOID *CoreHandle,
- IN UINT8 *Buffer
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- DWC_XDCI_TRB *Trb;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
- LocalCoreHandle->EpHandles[0].EpInfo.EpDir = 0;
- LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_SETUP;
- Trb = LocalCoreHandle->Trbs;
- DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveSetupPkt)\n"));
-
- Status = DwcXdciCoreInitTrb (
- LocalCoreHandle,
- Trb,
- TRBCTL_SETUP,
- Buffer,
- 8
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: Init TRB Failed \n"));
- return Status;
- }
-
- //
- // Issue a DEPSTRTXFER for EP0
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Init the lower re-bits for TRB address
- //
- EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
-
- //
- // Issue the command
- //
- Status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_START_XFER,
- &EpCmdParams
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "\nDwcXdciEp0ReceiveSetupPkt: Failed to issue Start Transfer command"));
- }
-
- //
- // Save new resource index for this transfer
- //
- LocalCoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead(LocalCoreHandle->BaseAddress, DWC_XDCI_EPCMD_REG(0)) &
- DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS
- );
-
- return Status;
-}
-
-
-/**
- Interface:
- This function is used to queue receive status packet on EP0
- @CoreHandle: xDCI controller handle
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEp0ReceiveStatusPkt (
- IN VOID *CoreHandle
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_TRB *Trb;
- DWC_XDCI_TRB_CONTROL TrbCtrl;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS Status;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // We are receiving on EP0 so physical EP is 0
- //
- Trb = LocalCoreHandle->Trbs;
- DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveStatusPkt)\n"));
- if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
- DEBUG ((DEBUG_INFO, "statusPkt still not transferred.\n"));
- return EFI_SUCCESS;
- }
-
- LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
- LocalCoreHandle->EpHandles[0].EpInfo.EpDir = 0;
-
- //
- // OUT data phase for 3-phased control transfer
- //
- TrbCtrl = TRBCTL_3_PHASE;
-
- //
- // Init TRB for the transfer
- //
- Status = DwcXdciCoreInitTrb (
- LocalCoreHandle,
- Trb,
- TrbCtrl,
- LocalCoreHandle->AlignedSetupBuffer,
- 0
- );
-
- if (!Status) {
- //
- // Issue a DEPSTRTXFER for EP0
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Init the lower bits for TRB address
- //
- EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
-
- //
- // Issue the command
- //
- Status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_START_XFER,
- &EpCmdParams
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: Failed to issue Start Transfer command for EP0\n"));
- }
- //
- // Save new resource index for this transfer
- //
- LocalCoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(0)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
-
- //
- // TODO: We are not using the EP state for control transfers
- // right now simply because we're only supporting IN
- // data phase. For the current use case, we don't
- // need OUT data phase. We can add that later and we will
- // add some of the state and SETUP packet awareness code
- //
- LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
- }
-
- return Status;
-}
-
-
-/**
- Interface:
- This function is used to send status packet on EP0
- @CoreHandle: xDCI controller handle
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEp0SendStatusPkt (
- IN VOID *CoreHandle
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_TRB *Trb;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- EFI_STATUS Status;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // We are sending on EP0 so physical EP is 1
- //
- Trb = (LocalCoreHandle->Trbs + (1 * DWC_XDCI_TRB_NUM));
- DEBUG ((DEBUG_INFO, "(DwcXdciEp0SendStatusPkt)\n"));
-
- LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
- Status = DwcXdciCoreInitTrb (
- LocalCoreHandle,
- Trb,
- TRBCTL_2_PHASE,
- LocalCoreHandle->AlignedMiscBuffer,
- 0
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: TRB failed during status phase\n"));
- return Status;
- }
-
- //
- // Issue a DEPSTRTXFER for EP1
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Init the lower re-bits for TRB address
- //
- EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
-
- //
- // Issue the command
- //
- Status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 1,
- EPCMD_START_XFER,
- &EpCmdParams
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: Failed to issue Start Transfer on EP0\n"));
- }
-
- //
- // Save new resource index for this transfer
- //
- LocalCoreHandle->EpHandles[1].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(1)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
- LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
-
- return Status;
-}
-
-
-/**
- Interface:
- This function is used to send data on non-EP0 endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- @Buffer: Buffer containing data to transmit
- @size: Size of transfer (in bytes)
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpTxData (
- IN VOID *CoreHandle,
- IN USB_XFER_REQUEST *XferReq
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- DWC_XDCI_TRB *Trb;
- DWC_XDCI_TRB_CONTROL TrbCtrl;
- EFI_STATUS Status;
- UINT32 EpNum;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (XferReq == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID transfer request\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (
- XferReq->EpInfo.EpNum,
- XferReq->EpInfo.EpDir
- );
-
- Trb = (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM));
- DEBUG ((DEBUG_INFO, "(DwcXdciEpTxData)EpNum is %d\n", EpNum));
-
-
- if (EpNum > 1)
- TrbCtrl = TRBCTL_NORMAL;
- else
- TrbCtrl = TRBCTL_CTRL_DATA_PHASE;
-
- if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
- Status = DwcXdciEndXfer (LocalCoreHandle, EpNum);
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfer\n"));
- }
-
- Status = DwcXdciCoreFlushEpTxFifo (LocalCoreHandle, EpNum);
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfer\n"));
- }
- }
-
- //
- // Data phase
- //
- CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeof (USB_XFER_REQUEST));
- LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_DATA;
-
- LocalCoreHandle->EpHandles[EpNum].Trb = Trb;
-
- Status = DwcXdciCoreInitTrb (
- LocalCoreHandle,
- Trb,
- TrbCtrl,
- XferReq->XferBuffer,
- XferReq->XferLen
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: TRB failed\n"));
- return Status;
- }
-
- //
- // Issue a DEPSTRTXFER for EP
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Init the lower re-bits for TRB address
- //
- EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
-
- //
- // Issue the command
- //
- Status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- EpNum,
- EPCMD_START_XFER,
- &EpCmdParams
- );
-
- //
- // Save new resource index for this transfer
- //
- LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx = ((UsbRegRead (BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
-
- return Status;
-}
-
-
-/**
- Interface:
- This function is used to receive data on non-EP0 endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
- @Buffer: Buffer containing data to transmit
- @size: Size of transfer (in bytes)
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpRxData (
- IN VOID *CoreHandle,
- IN USB_XFER_REQUEST *XferReq
- )
-{
- XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- DWC_XDCI_TRB *Trb;
- DWC_XDCI_TRB_CONTROL TrbCtrl;
- EFI_STATUS Status;
- UINT32 EpNum;
- UINT32 BaseAddr;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- if (XferReq == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID transfer request\n"));
- return EFI_INVALID_PARAMETER;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- //
- // Convert to physical endpoint
- //
- EpNum = DwcXdciGetPhysicalEpNum (XferReq->EpInfo.EpNum, XferReq->EpInfo.EpDir);
-
- Trb = (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM));
- DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)EpNum is %d\n", EpNum));
-
- if (EpNum > 1)
- TrbCtrl = TRBCTL_NORMAL;
- else
- TrbCtrl = TRBCTL_CTRL_DATA_PHASE;
-
- //
- // If CheckFlag didn't set to FALSE, means the previous transfer request didn't complete,
- // need to wait the previous request done.
- //
- if (LocalCoreHandle->EpHandles[EpNum].CheckFlag == TRUE) {
- return EFI_NOT_READY;
- }
-
- LocalCoreHandle->EpHandles[EpNum].CheckFlag = TRUE;
-
- //
- // Data phase
- //
- CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeof (USB_XFER_REQUEST));
-
- LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_DATA;
-
- LocalCoreHandle->EpHandles[EpNum].Trb = Trb;
-
- DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)XferReq->XferLen is 0x%x\n", XferReq->XferLen));
-
- Status = DwcXdciCoreInitTrb (
- LocalCoreHandle,
- Trb,
- TrbCtrl,
- XferReq->XferBuffer,
- XferReq->XferLen
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: TRB failed\n"));
- return Status;
- }
- //
- // Issue a DEPSTRTXFER for EP
- // Reset params
- //
- EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
-
- //
- // Init the lower re-bits for TRB address
- //
- EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
-
- //
- // Issue the command
- //
- Status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- EpNum,
- EPCMD_START_XFER,
- &EpCmdParams
- );
-
- if (Status) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: Failed to start transfer\n"));
- }
-
- //
- // Save new resource index for this transfer
- //
- LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
-
- return Status;
-}
-
-
-
-STATIC
-EFI_STATUS
-DwcXdciCoreFlushEpFifo (
- IN XDCI_CORE_HANDLE *CoreHandle,
- IN UINT32 EpNum
- )
-{
- UINT32 BaseAddr;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
- UINT32 fifoNum;
- UINT32 Param;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- BaseAddr = CoreHandle->BaseAddress;
-
- //
- // Translate to FIFOnum
- // NOTE: Assuming this is a Tx EP
- //
- fifoNum = (EpNum >> 1);
-
- //
- // TODO: Currently we are only using TxFIFO 0. Later map these
- // Write the FIFO num/dir param for the generic command.
- //
-
- Param = UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG);
- Param &= ~(DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK);
-
- if ((EpNum & 0x01) != 0) {
- Param |= (fifoNum | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK);
- } else {
- Param |= fifoNum;
- }
-
- DEBUG ((DEBUG_INFO, "USB FU Flash: CMD 0x%08x :: Param 0x%08x\n",
- (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK),
- Param));
-
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DGCMD_PARAM_REG,
- Param
- );
-
- //
- // Write the command to flush all FIFOs
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DGCMD_REG,
- (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
- );
-
-
- //
- // Wait until command completes
- //
- do {
- if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
- break;
- else
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Interface:
- This function is used to cancel a transfer on non-EP0 endpoint
- @CoreHandle: xDCI controller handle
- @EpInfo: Address of structure describing properties of EP
-
-**/
-EFI_STATUS
-EFIAPI
-DwcXdciEpCancelTransfer (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- UINT32 EpNum;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Get physical EP num
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
- Status = DwcXdciEndXfer(CoreHandle, EpNum);
- DwcXdciCoreFlushEpFifo(CoreHandle, EpNum);
-
- return Status;
-}
-
-
-EFI_STATUS
-usbProcessDeviceResetDet (
- IN XDCI_CORE_HANDLE *CoreHandle
- )
-{
- return DwcXdciProcessDeviceResetDet (CoreHandle);
-}
-
-EFI_STATUS
-usbProcessDeviceResetDone (
- IN XDCI_CORE_HANDLE *CoreHandle
- )
-{
- return DwcXdciProcessDeviceResetDone (CoreHandle);
-}
-
-UINT32
-UsbGetPhysicalEpNum (
- IN UINT32 EndpointNum,
- IN USB_EP_DIR EndpointDir
- )
-{
- return DwcXdciGetPhysicalEpNum(
- EndpointNum,
- EndpointDir
- );
-}
-
-
-EFI_STATUS
-EFIAPI
-UsbXdciCoreReinit (
- IN VOID *CoreHandle
- )
-{
- EFI_STATUS status = EFI_DEVICE_ERROR;
- UINT32 BaseAddr;
- XDCI_CORE_HANDLE *LocalCoreHandle;
- DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
- UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
- UINT8 i;
-
- LocalCoreHandle = CoreHandle;
-
- if (CoreHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (LocalCoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xDCI\n"));
- return EFI_OUT_OF_RESOURCES;
- }
-
- BaseAddr = LocalCoreHandle->BaseAddress;
-
- DEBUG ((DEBUG_INFO, "Resetting the USB core\n"));
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_CSFTRST_MASK
- );
-
- //
- // Wait until core soft reset completes
- //
- do {
- if (!(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & DWC_XDCI_DCTL_CSFTRST_MASK)) {
- break;
- } else {
- uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
- }
- } while (--MaxDelayIter);
-
- if (!MaxDelayIter) {
- DEBUG ((DEBUG_INFO, "Failed to reset device controller\n"));
- return EFI_DEVICE_ERROR;
- }
-
- DEBUG ((DEBUG_INFO, "USB core has been reset\n"));
-
- LocalCoreHandle->DevState = UsbDevStateDefault;
-
- //
- // Clear KeepConnect bit so we can allow disconnect and
- // re-connect. Stay in RX_DETECT state
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCTL_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) &
- (~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) &
- ((~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK) |
- (DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS))
- );
-
- DEBUG ((DEBUG_INFO, "Device controller Synopsys ID: %x\n", UsbRegRead (BaseAddr, DWC_XDCI_GSNPSID_REG)));
- DEBUG ((DEBUG_INFO, "Default value of xDCI GSBUSCFG0 and GSBUSCFG1: %x, %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG0_REG),
- UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG1_REG)));
-
- DEBUG ((DEBUG_INFO, "Default value of xDCI GTXTHRCFG and GRXTHRCFG: %x, %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GTXTHRCFG_REG),
- UsbRegRead (BaseAddr, DWC_XDCI_GRXTHRCFG_REG)));
-
- //
- // Clear ULPI auto-resume bit
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB2PHYCFG_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)) & ~DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK)
- );
-
- DEBUG ((DEBUG_INFO, "Default value of xDCI GUSB2PHYCFG and GUSB3PIPECTL: %x, %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)),
- UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG (0))));
-
- //
- // Only one RxFIFO
- //
- DEBUG ((DEBUG_INFO, "Default value of DWC_XDCI_GRXFIFOSIZ: %x\n",
- UsbRegRead (BaseAddr, DWC_XDCI_GRXFIFOSIZ_REG (0))));
-
- for (i = 0; i < DWC_XDCI_MAX_ENDPOINTS; i++) {
- DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_GTXFIFOSIZ %d: %x\n",
- i, UsbRegRead (BaseAddr, DWC_XDCI_GTXFIFOSIZ_REG (i))));
- }
-
- //
- // TODO: Need to check if TxFIFO should start where RxFIFO ends
- // or default is correct i.e. TxFIFO starts at 0 just like RxFIFO
- //
-
- //
- // Allocate and Initialize Event Buffers
- //
- LocalCoreHandle->MaxDevIntLines = ((UsbRegRead (BaseAddr, DWC_XDCI_GHWPARAMS1_REG) &
- DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
- DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS);
-
- DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIntLines));
- //
- // One event Buffer per interrupt line.
- // Need to align it to size of event Buffer
- // Buffer needs to be big enough. Otherwise the core
- // won't operate
- //
- LocalCoreHandle->AlignedEventBuffers = (DWC_XDCI_EVENT_BUFFER *)
- ((UINT32)(UINTN)(LocalCoreHandle->EventBuffers) +
- ((sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) -
- (((UINT32)(UINTN)(LocalCoreHandle->EventBuffers)) %
- (sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))));
-
- for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GEVNTADR_REG (i),
- (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)
- );
-
- //
- // Clear High 32bit address register, GEVNTADR register is 64-bit register
- // default is 0xffffffffffffffff
- //
- UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000);
-
- LocalCoreHandle->CurrentEventBuffer = LocalCoreHandle->AlignedEventBuffers;
- //
- // Write size and clear the mask
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EVNTSIZ_REG (i),
- sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER
- );
-
- //
- // Write 0 to the event count register as the last step
- // for event configuration
- //
- UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), 0);
-
- DEBUG ((DEBUG_INFO, "Value of xDCI Event Buffer %d: %x, Size: %x, Count: %x\n",
- i,
- UsbRegRead (BaseAddr, DWC_XDCI_GEVNTADR_REG (i)),
- UsbRegRead (BaseAddr, DWC_XDCI_EVNTSIZ_REG (i)),
- UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i))));
- }
-
- //
- // Program Global Control Register to disable scaledown,
- // disable clock gating
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GCTL_REG,
- ((UsbRegRead(BaseAddr, DWC_XDCI_GCTL_REG) &
- ~(DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK + DWC_XDCI_GCTL_RAMCLKSEL_MASK + DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK)) |
- DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK |
- (DWC_XDCI_GCTL_PRT_CAP_DEVICE << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)));
-
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
-
-
- //
- // TODO: Program desired Speed and set LPM capable
- // We will do this when SuperSpeed works. For now,
- // force into High-Speed mode to aVOID anyone trying this
- // on Super Speed port
- //
-#if 1
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCFG_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | LocalCoreHandle->DesiredSpeed
- );
-#else
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DCFG_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | DWC_XDCI_DCFG_DESIRED_HS_SPEED
- );
-#endif
-
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
- DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG)));
-
- //
- // Enable Device Interrupt Events
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_DEVTEN_REG,
- DWC_XDCI_DEVTEN_DEVICE_INTS
- );
-
- //
- // Program the desired role
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GCTL_REG,
- (UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG) & ~DWC_XDCI_GCTL_PRT_CAP_DIR_MASK) | (LocalCoreHandle->Role << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)
- );
-
- //
- // Clear USB2 suspend for start new config command
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB2PHYCFG_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
- );
- //
- // Clear USB3 suspend for start new config command
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_GUSB3PIPECTL_REG (0),
- (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
- );
- //
- // Issue DEPSTARTCFG command for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_START_NEW_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for START_NEW_CONFIG EP command on xDCI\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_START_NEW_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue START_NEW_CONFIG EP command on xDCI\n"));
- return status;
- }
-
- //
- // Issue DEPCFG command for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP0\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams);
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP0\n"));
- return status;
- }
-
- //
- // Issue DEPCFG command for EP1
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[1].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP1\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 1,
- EPCMD_SET_EP_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP1\n"));
- return status;
- }
-
- //
- // Issue DEPXFERCFG command for EP0
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[0].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 0,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n"));
- return status;
- }
-
- //
- // Issue DEPXFERCFG command for EP1
- //
- status = DwcXdciCoreInitEpCmdParams (
- LocalCoreHandle,
- &LocalCoreHandle->EpHandles[1].EpInfo,
- DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n"));
- return status;
- }
-
- //
- // Issue the command
- //
- status = DwcXdciCoreIssueEpCmd (
- LocalCoreHandle,
- 1,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- &EpCmdParams
- );
-
- if (status) {
- DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n"));
- return status;
- }
-
- //
- // Prepare a Buffer for SETUP packet
- //
- LocalCoreHandle->Trbs = (DWC_XDCI_TRB *)(UINTN)((UINT32)(UINTN)
- LocalCoreHandle->UnalignedTrbs +
- (DWC_XDCI_TRB_BYTE_ALIGNMENT -
- ((UINT32)(UINTN)LocalCoreHandle->UnalignedTrbs %
- DWC_XDCI_TRB_BYTE_ALIGNMENT)));
-
- DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ unalignedTrbs address is 0x%x\n", LocalCoreHandle->UnalignedTrbs));
- DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ TRB address is 0x%x\n", LocalCoreHandle->Trbs));
-
- //
- // Allocate Setup Buffer that is 8-byte aligned
- //
- LocalCoreHandle->AlignedSetupBuffer = LocalCoreHandle->DefaultSetupBuffer +
- (DWC_XDCI_SETUP_BUFF_SIZE -
- ((UINT32)(UINTN)(LocalCoreHandle->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
-
- //
- // Aligned Buffer for status phase
- //
- LocalCoreHandle->AlignedMiscBuffer = LocalCoreHandle->MiscBuffer +
- (DWC_XDCI_SETUP_BUFF_SIZE -
- ((UINT32)(UINTN)(LocalCoreHandle->AlignedMiscBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
-
- //
- // We will queue SETUP request when we see bus reset
- //
-
- //
- // Enable Physical Endpoints 0
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EP_DALEPENA_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 0)
- );
-
- //
- // Enable Physical Endpoints 1
- //
- UsbRegWrite (
- BaseAddr,
- DWC_XDCI_EP_DALEPENA_REG,
- UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 1)
- );
-
- DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
- return status;
-
-
-}
-
-
-EFI_STATUS
-UsbXdciCoreFlushEpFifo (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- )
-{
- EFI_STATUS Status = EFI_DEVICE_ERROR;
- UINT32 EpNum;
-
- if (CoreHandle == NULL) {
- DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n"));
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Get physical EP num
- //
- EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
- DwcXdciCoreFlushEpFifo(CoreHandle, EpNum);
-
- return Status;
-}
+/** @file
+ Copyright (c) 2006 - 2017, 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.
+
+**/
+#include
+#include
+#include
+#include
+
+#include "UsbDeviceDxe.h"
+#include "XdciInterface.h"
+#include "XdciDWC.h"
+
+UINT32
+UsbRegRead (
+ IN UINTN Base,
+ IN UINT32 Offset
+ )
+{
+ volatile UINT32 *addr = (volatile UINT32 *)(UINTN)(Base + Offset);
+ return *addr;
+}
+
+VOID
+UsbRegWrite (
+ IN UINTN Base,
+ IN UINT32 Offset,
+ IN UINT32 val
+ )
+{
+ volatile UINT32 *addr = (volatile UINT32 *)(UINTN)(Base + Offset);
+ *addr = val;
+}
+
+
+/**
+ Internal utility function:
+ This function is used to obtain physical endpoint number
+ xDCI needs physical endpoint number for EP registers
+ We also use it to index into our EP array
+ Note: Certain data structures/commands use logical EP numbers
+ as opposed to physical endpoint numbers so one should be
+ careful when interpreting EP numbers
+ @EpNum: Logical endpoint number
+ @epDir: Direction for the endpoint
+
+**/
+STATIC
+UINT32
+DwcXdciGetPhysicalEpNum (
+ IN UINT32 EndpointNum,
+ IN USB_EP_DIR EndpointDir
+ )
+{
+ return EndpointDir? ((EndpointNum << 1) | EndpointDir) : (EndpointNum << 1);
+}
+
+
+/**
+ Internal utility function:
+ This function is used to obtain the MPS for control transfers
+ Based on the Speed. If this is called before bus reset completes
+ then it returns MPS Based on desired Speed. If it is after bus
+ reset then MPS returned is Based on actual negotiated Speed
+ @CoreHandle: xDCI controller handle address
+ @mps: address of 32-bit variable to return the MPS
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreGetCtrlMps (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 *mps
+ )
+{
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (mps == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (CoreHandle->ActualSpeed) {
+ case USB_SPEED_HIGH:
+ *mps = DWC_XDCI_HS_CTRL_EP_MPS;
+ break;
+ case USB_SPEED_FULL:
+ *mps = DWC_XDCI_FS_CTRL_EP_MPS;
+ break;
+ case USB_SPEED_LOW:
+ *mps = DWC_XDCI_LS_CTRL_EP_MPS;
+ break;
+ case USB_SPEED_SUPER:
+ *mps = DWC_XDCI_SS_CTRL_EP_MPS;
+ break;
+ default:
+ *mps = 0;
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: UNKNOWN Speed\n"));
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal utility function:
+ This function is used to initialize the parameters required
+ for executing endpoint command
+ @CoreHandle: xDCI controller handle address
+ @EpInfo: EP info address
+ @ConfigAction: Configuration action specific to EP command
+ @EpCmd: xDCI EP command for which parameters are initialized
+ @EpCmdParams: address of struct to return EP params
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreInitEpCmdParams (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN USB_EP_INFO *EpInfo,
+ IN UINT32 ConfigAction,
+ IN DWC_XDCI_ENDPOINT_CMD EpCmd,
+ IN DWC_XDCI_ENDPOINT_CMD_PARAMS *EpCmdParams
+ )
+{
+ EFI_STATUS status = EFI_SUCCESS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitEpCmdParams: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Reset params
+ //
+ EpCmdParams->Param0 = EpCmdParams->Param1 = EpCmdParams->Param2 = 0;
+
+ switch (EpCmd) {
+ case EPCMD_SET_EP_CONFIG:
+ //
+ // Issue DEPCFG command for EP
+ // Issue a DEPCFG (Command 1) command for endpoint
+ //
+ if (EpInfo->MaxStreams) {
+ EpCmdParams->Param1 = DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK;
+ }
+
+ if (EpInfo->Interval) {
+ EpCmdParams->Param1 |= ((EpInfo->Interval-1) << DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS);
+ }
+
+ //
+ // Set EP num
+ //
+ EpCmdParams->Param1 |= (EpInfo->EpNum << DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_BIT_POS);
+ //
+ // Set EP direction
+ //
+ EpCmdParams->Param1 |= (EpInfo->EpDir << DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_BIT_POS);
+ //
+ // Set EP-specific Event enable for not ready and
+ // complete events
+ //
+ EpCmdParams->Param1 &= ~DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK;
+ //
+ // Setup the events we want enabled for this EP
+ //
+ EpCmdParams->Param1 |= (DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK |
+ DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK |
+ DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK);
+
+ //
+ // We only have one interrupt line for this core.
+ // Set interrupt number to 0
+ //
+ EpCmdParams->Param1 &= ~DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK;
+
+ //
+ // Set FIFOnum = 0 for control EP0
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK;
+
+ //
+ // Program FIFOnum for non-EP0 EPs
+ //
+ if (EpInfo->EpNum && EpInfo->EpDir) {
+ EpCmdParams->Param0 |= (EpInfo->EpNum << DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_BIT_POS);
+ }
+
+ //
+ // Program max packet size
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK;
+ EpCmdParams->Param0 |= (EpInfo->MaxPktSize << DWC_XDCI_PARAM0_SET_EP_CFG_MPS_BIT_POS);
+
+ //
+ // Set Burst size. 0 means burst size of 1
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK;
+ EpCmdParams->Param0 |= (EpInfo->BurstSize << DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_BIT_POS);
+
+ //
+ // Set EP type
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK;
+ EpCmdParams->Param0 |= (EpInfo->EpType << DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_BIT_POS);
+
+ //
+ // Set config action
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK;
+ EpCmdParams->Param0 |= (ConfigAction << DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_BIT_POS);
+ break;
+
+ case EPCMD_SET_EP_XFER_RES_CONFIG:
+ // Set Param0 to 1. Same for all EPs when resource
+ // configuration is done
+ //
+ EpCmdParams->Param0 = 1;
+ break;
+
+ case EPCMD_END_XFER:
+ //
+ // Nothing to set. Already reset params for all cmds
+ //
+ break;
+
+ case EPCMD_START_NEW_CONFIG:
+ //
+ // Nothing to set. Already reset params for all cmds
+ //
+ break;
+
+ default:
+ status = EFI_INVALID_PARAMETER;
+ DEBUG ((DEBUG_INFO, "\nDwcXdciCoreInitEpCmdParams: INVALID Parameter"));
+ break;
+ }
+
+ return status;
+}
+
+
+/**
+ Internal utility function:
+ This function is used to issue the xDCI endpoint command
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical EP num
+ @EpCmd: xDCI EP command
+ @EpCmdParams: EP command parameters address
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreIssueEpCmd (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum,
+ IN UINT32 EpCmd,
+ IN DWC_XDCI_ENDPOINT_CMD_PARAMS *EpCmdParams
+ )
+{
+ UINTN BaseAddr;
+ UINT32 MaxDelayIter = 5000;//DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIssueEpCmd: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+
+ //
+ // Set EP command parameter values
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EPCMD_PARAM2_REG(EpNum),
+ EpCmdParams->Param2
+ );
+
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EPCMD_PARAM1_REG(EpNum),
+ EpCmdParams->Param1
+ );
+
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EPCMD_PARAM0_REG(EpNum),
+ EpCmdParams->Param0
+ );
+
+ //
+ // Set the command code and activate it
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EPCMD_REG(EpNum),
+ EpCmd | DWC_XDCI_EPCMD_CMD_ACTIVE_MASK
+ );
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_CMD_ACTIVE_MASK))
+ break;
+ else
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreIssueEpCmd. ERROR: Failed to issue Command\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal utility function:
+ This function is used to flush all FIFOs
+ @CoreHandle: xDCI controller handle address
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreFlushAllFifos (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ )
+{
+ UINTN BaseAddr;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushAllFifos: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+
+ //
+ // Write the command to flush all FIFOs
+ //
+ UsbRegWrite(
+ BaseAddr,
+ DWC_XDCI_DGCMD_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_ALL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
+ break;
+ else
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal utility function:
+ This function is used to flush Tx FIFO specific to an endpoint
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical EP num
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreFlushEpTxFifo (
+ XDCI_CORE_HANDLE *CoreHandle,
+ __attribute__((unused)) UINT32 EpNum
+ )
+{
+ UINTN BaseAddr;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+ //
+ // TODO: Currently we are only using TxFIFO 0. Later map these
+ // Write the FIFO num/dir param for the generic command.
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DGCMD_PARAM_REG,
+ ((UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG) & ~DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK) | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK)
+ );
+
+ //
+ // Write the command to flush all FIFOs
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DGCMD_REG,
+ (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
+ break;
+ else
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+STATIC
+EFI_STATUS
+DwcXdciCorePrepareOneTrb (
+ IN DWC_XDCI_TRB *Trb,
+ IN DWC_XDCI_TRB_CONTROL TrbCtrl,
+ IN UINT32 LastBit,
+ IN UINT32 ChainBit,
+ IN UINT8 *BufferPtr,
+ IN UINT32 size
+ )
+{
+ DEBUG ((DEBUG_INFO, "Trb is 0x%x, BufferPtr is 0x%x, size is 0x%x\n", Trb, BufferPtr, size));
+
+ Trb->BuffPtrLow = (UINT32)(UINTN)BufferPtr;
+ Trb->BuffPtrHigh = 0;
+ Trb->LenXferParams = size;
+ Trb->TrbCtrl = TrbCtrl << DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
+
+ if (ChainBit)
+ Trb->TrbCtrl |= ChainBit << DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS;
+
+ if (LastBit)
+ Trb->TrbCtrl |= LastBit << DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS;
+
+ Trb->TrbCtrl |= DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK| DWC_XDCI_TRB_CTRL_HWO_MASK;
+
+ DEBUG ((DEBUG_INFO, "(DwcXdciCorePrepareOneTrb) Trb->BuffPtrLow = 0x%x, Trb->LenXferParams is 0x%x, Trb->TrbCtrl is 0x%x\n",
+ Trb->BuffPtrLow, Trb->LenXferParams, Trb->TrbCtrl));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal utility function:
+ This function is used to initialize transfer request block
+ @CoreHandle: xDCI controller handle address
+ @Trb: Address of TRB to initialize
+ @TrbCtrl: TRB control value
+ @buffPtr: Transfer Buffer address
+ @size: Size of the transfer
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreInitTrb (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN DWC_XDCI_TRB *Trb,
+ IN DWC_XDCI_TRB_CONTROL TrbCtrl,
+ IN UINT8 *BufferPtr,
+ IN UINT32 size
+ )
+{
+#define ONE_TRB_SIZE (DWC_XDCI_TRB_BUFF_SIZE_MASK & 0x00F00000)
+ UINT8 *TrbBuffer;
+ UINT32 TrbCtrlLast;
+ UINT32 TrbCtrlChain;
+ UINT32 TrbIndex;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Trb == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Init TRB fields
+ // NOTE: Assuming we are only using 32-bit addresses
+ // TODO: update for 64-bit addresses
+ //
+ if (size <= DWC_XDCI_TRB_BUFF_SIZE_MASK) {
+ //
+ // Can transfer in one TRB
+ //
+ TrbCtrlChain = 0;
+ TrbCtrlLast = 1;
+ DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, BufferPtr, size);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Can't transfer in one TRB.
+ // Seperate it in every ONE_TRB_SIZE of TRB
+ //
+ TrbBuffer = BufferPtr;
+ TrbIndex = 0;
+ while (size > ONE_TRB_SIZE) {
+ TrbCtrlChain = 1;
+ TrbCtrlLast = 0;
+ DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBuffer, ONE_TRB_SIZE);
+ TrbBuffer += ONE_TRB_SIZE;
+ size -= ONE_TRB_SIZE;
+ Trb++;
+ TrbIndex++;
+ if (TrbIndex >= DWC_XDCI_TRB_NUM)
+ return EFI_OUT_OF_RESOURCES;
+ }
+ TrbCtrlChain = 0;
+ TrbCtrlLast = 1;
+ DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBuffer, size);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to start a SETUP phase on control endpoint
+ @CoreHandle: xDCI controller handle address
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciCoreStartEp0SetupXfer (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ )
+{
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status = EFI_DEVICE_ERROR;
+ DWC_XDCI_TRB *Trb;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreStartEp0SetupXfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CoreHandle->EpHandles[0].State == USB_EP_STATE_SETUP) {
+ DEBUG ((DEBUG_INFO, "EP0 was already in SETUP phase\n"));
+ return EFI_SUCCESS;
+ }
+
+ CoreHandle->EpHandles[0].State = USB_EP_STATE_SETUP;
+ Trb = CoreHandle->Trbs;
+ DEBUG ((DEBUG_INFO, "(DwcXdciCoreStartEp0SetupXfer)\n"));
+
+ status = DwcXdciCoreInitTrb (
+ CoreHandle,
+ Trb,
+ TRBCTL_SETUP,
+ CoreHandle->AlignedSetupBuffer,
+ 8
+ );
+
+ if (status)
+ return status;
+
+ //
+ // Issue a DEPSTRTXFER for EP0
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command to start transfer on physical
+ // endpoint 0
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ 0,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ //
+ // Save new resource index for this transfer
+ //
+ CoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead (
+ CoreHandle->BaseAddress,
+ DWC_XDCI_EPCMD_REG(0)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS
+ );
+
+ return status;
+}
+
+
+/**
+ Internal function:
+ This function is used to process the state change event
+ @CoreHandle: xDCI controller handle address
+ @event: device event dword
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessDeviceStateChangeEvent (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 Event
+ )
+{
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceStateChangeEvent: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CoreHandle->HirdVal = (Event & DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK) >> DWC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS;
+
+ CoreHandle->LinkState = ((Event & DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_MASK) >> DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS);
+
+ if (CoreHandle->EventCallbacks.DevLinkStateCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.LinkState = CoreHandle->LinkState;
+ CoreHandle->EventCallbacks.CbEventParams.Hird = CoreHandle->HirdVal;
+ CoreHandle->EventCallbacks.CbEventParams.SsEvent = (Event & DWC_XDCI_EVENT_BUFF_DEV_SS_EVENT_MASK) ? 1 : 0;
+ CoreHandle->EventCallbacks.DevLinkStateCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to issue a command to end transfer
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical EP num for which transfer is to be ended
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciEndXfer (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum
+ )
+{
+ EFI_STATUS status;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ UINT32 cmdParams;
+ DWC_XDCI_TRB *TrbPtr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciEndXfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CoreHandle->EpHandles[EpNum].CheckFlag = FALSE;
+
+ //
+ // Issue a DEPENDXFER for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ cmdParams = ((CoreHandle->EpHandles[EpNum].CurrentXferRscIdx << DWC_XDCI_EPCMD_RES_IDX_BIT_POS) | DWC_XDCI_EPCMD_FORCE_RM_MASK);
+
+ if (CoreHandle->EpHandles[EpNum].CurrentXferRscIdx == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd(
+ CoreHandle,
+ EpNum,
+ cmdParams | DWC_XDCI_EPCMD_END_XFER,
+ &EpCmdParams
+ );
+
+ if (!status) {
+ CoreHandle->EpHandles[EpNum].CurrentXferRscIdx = 0;
+ TrbPtr = CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM);
+ ZeroMem (TrbPtr, DWC_XDCI_TRB_NUM * sizeof (DWC_XDCI_TRB));
+ }
+
+ return status;
+}
+
+
+/**
+ Internal function:
+ This function is used to process bus reset detection event
+ @CoreHandle: xDCI controller handle address
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessDeviceResetDet (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ )
+{
+ EFI_STATUS status = EFI_SUCCESS;
+
+ if (CoreHandle == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Flush all FIFOs
+ //
+ status = DwcXdciCoreFlushAllFifos(CoreHandle);
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to flush FIFOs\n"));
+ }
+
+ //
+ // Start SETUP phase on EP0
+ //
+ status = DwcXdciCoreStartEp0SetupXfer(CoreHandle);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to start SETUP phase for EP0\n"));
+ return status;
+ }
+
+ //
+ // Notify upper layer if a callback is registerd for
+ // this event
+ //
+ if (CoreHandle->EventCallbacks.DevBusResetCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ status = CoreHandle->EventCallbacks.DevBusResetCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ return status;
+}
+
+
+/**
+ Internal function:
+ This function is used to process connection done (means reset
+ complete) event
+ @CoreHandle: xDCI controller handle address
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessDeviceResetDone (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ )
+{
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ UINTN BaseAddr;
+ EFI_STATUS status = EFI_SUCCESS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceResetDone: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+ CoreHandle->ActualSpeed = (UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_CONN_SPEED_MASK);
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDone CoreHandle->ActualSpeed is %x\n", CoreHandle->ActualSpeed));
+
+ //
+ // Program MPS Based on the negotiated Speed
+ //
+ DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[0].EpInfo.MaxPktSize);
+ DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[1].EpInfo.MaxPktSize);
+
+ //
+ // Init DEPCFG cmd params for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ CoreHandle,
+ &CoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ 0,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ return status;
+ }
+
+ //
+ // Init DEPCFG cmd params for EP1
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ CoreHandle,
+ &CoreHandle->EpHandles[1].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ 1,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ //
+ // Put the other PHY into suspend
+ //
+ if (CoreHandle->ActualSpeed == USB_SPEED_SUPER) {
+ //
+ // Put HS PHY to suspend
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) | DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
+ );
+
+ //
+ // Clear SS PHY's suspend mask
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB3PIPECTL_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
+ );
+
+ } else {
+ //
+ // Put SS PHY to suspend
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB3PIPECTL_REG(0),
+ (UsbRegRead(BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) | DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
+ );
+
+ //
+ // Clear HS PHY's suspend mask
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG(0),
+ (UsbRegRead(BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
+ );
+ }
+
+ //
+ // Notify upper layer if callback is registered
+ //
+ if (CoreHandle->EventCallbacks.DevResetDoneCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.Speed = CoreHandle->ActualSpeed;
+ CoreHandle->EventCallbacks.DevResetDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ return status;
+}
+
+
+/**
+ Internal function:
+ This function is used to process device event
+ @CoreHandle: xDCI controller handle address
+ @IntLineEventBuffer: event Buffer pointing to device event
+ @ProcessedEventSize: address of variable to save the size of
+ the event that was Processed
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessDeviceEvent (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN DWC_XDCI_EVENT_BUFFER *IntLineEventBuffer,
+ IN UINT32 *ProcessedEventSize
+ )
+{
+ UINT32 event;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceEvent: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Extract device event
+ //
+ event = (IntLineEventBuffer->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK);
+ event >>= DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS;
+
+ //
+ // Assume default event size. Change it in switch case if
+ // different
+ //
+ *ProcessedEventSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
+
+ switch (event) {
+ case DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT\n"));
+ DwcXdciProcessDeviceResetDet (CoreHandle);
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT\n"));
+ DwcXdciProcessDeviceResetDone (CoreHandle);
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT\n"));
+ DwcXdciProcessDeviceStateChangeEvent (CoreHandle, IntLineEventBuffer->Event);
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT:
+ DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT\n"));
+ *ProcessedEventSize = DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES;
+ break;
+
+ default:
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceEvent: UNHANDLED device event: %x\n", event));
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to process EP not ready for
+ non-control endpoints
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical endpoint number
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessEpXferNotReady (
+ __attribute__((unused)) XDCI_CORE_HANDLE *CoreHandle,
+ __attribute__((unused)) UINT32 EpNum
+ )
+{
+ //
+ // TODO: Not doing on-demand transfers
+ // Revisit if required for later use
+ //
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to process EP not ready for
+ control endpoints
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical endpoint number
+ @dataStage: EP not ready when data stage token was received
+ @statusStage: EP not ready when status stage token was received
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessEp0XferNotReady (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum,
+ IN UINT32 epEventStatus
+ )
+{
+ USB_EP_STATE epState = USB_EP_STATE_SETUP;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferNotReady: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Is it data stage or status stage
+ //
+ if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK) {
+ epState = USB_EP_STATE_DATA;
+ } else if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK) {
+ epState = USB_EP_STATE_STATUS;
+ }
+
+ if ((EpNum == 0) && (epState == USB_EP_STATE_STATUS)) {
+ if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_XFER_ACTIVE_MASK) {
+ DEBUG ((DEBUG_INFO, "XFER_ACTIVE\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "XFER_NOT_ACTIVE\n"));
+ }
+ DwcXdciEp0ReceiveStatusPkt (CoreHandle);
+ }
+
+ //
+ // Notify upper layer if a callback is registered for
+ // this event
+ //
+ if (CoreHandle->EventCallbacks.DevXferNrdyCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpState = epState;
+ CoreHandle->EventCallbacks.DevXferNrdyCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to process transfer phone done for EP0
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical endpoint number (0 for OUT and 1 for IN)
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessEp0XferPhaseDone (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum
+ )
+{
+ DWC_XDCI_ENDPOINT *epHandle;
+ DWC_XDCI_TRB *Trb;
+ EFI_STATUS status = EFI_SUCCESS;
+ UINT32 TrbSts;
+ UINT32 TrbCtrl;
+ UINT32 TrbBufsize;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferPhaseDone: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ epHandle = &CoreHandle->EpHandles[EpNum];
+ Trb = CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM);
+ DEBUG ((DEBUG_INFO, "(DwcXdciProcessEp0XferPhaseDone)EpNum is %d\n", EpNum));
+
+ if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone. HW owns TRB: %x!!!\n", (UINT32)(UINTN)Trb));
+ }
+
+ epHandle->CurrentXferRscIdx = 0;
+ epHandle->State = USB_EP_STATE_ENABLED;
+ TrbCtrl = (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
+ TrbSts = (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_TRB_STATUS_BIT_POS;
+ TrbBufsize = Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK;
+
+ switch (TrbCtrl) {
+ case DWC_XDCI_TRB_CTRL_TYPE_SETUP:
+ DEBUG ((DEBUG_INFO, "SETUP\n"));
+ if (CoreHandle->EventCallbacks.DevSetupPktReceivedCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = CoreHandle->AlignedSetupBuffer;
+ status = CoreHandle->EventCallbacks.DevSetupPktReceivedCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ if (!(CoreHandle->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIRECTION_MASK)) {
+ //
+ // Keep a Buffer ready for setup phase
+ //
+ DwcXdciCoreStartEp0SetupXfer (CoreHandle);
+ }
+
+ break;
+
+ case DWC_XDCI_TRB_CTRL_TYPE_STATUS2:
+ DEBUG ((DEBUG_INFO, "STATUS2\n"));
+ break;
+
+ case DWC_XDCI_TRB_CTRL_TYPE_STATUS3:
+ DEBUG ((DEBUG_INFO, "STATUS3\n"));
+ //
+ // Notify upper layer of control transfer completion
+ // if a callback function was registerd
+ //
+ if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(Trb->BuffPtrLow);
+ CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ //
+ // Status phase done. Queue next SETUP packet
+ //
+ status = DwcXdciCoreStartEp0SetupXfer(CoreHandle);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to queue SETUP\n"));
+ }
+ break;
+
+ case DWC_XDCI_TRB_CTRL_TYPE_DATA:
+ DEBUG ((DEBUG_INFO, "DATA\n"));
+ if (TrbSts == DWC_XDCI_TRB_STATUS_SETUP_PENDING || TrbBufsize != 0) {
+ DEBUG ((DEBUG_INFO, "ERROR: Control transfert aborted by host: Setup pending\n"));
+ DwcXdciCoreStartEp0SetupXfer (CoreHandle);
+ } else {
+ DwcXdciEp0ReceiveStatusPkt (CoreHandle);
+ }
+
+ if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(Trb->BuffPtrLow);
+ CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+ break;
+
+ default:
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: UNHANDLED STATE in TRB\n"));
+ break;
+ }
+
+ return status;
+}
+
+
+/**
+ Internal function:
+ This function is used to process transfer done for
+ non-control endpoints
+ @CoreHandle: xDCI controller handle address
+ @EpNum: Physical endpoint number
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessEpXferDone (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum
+ )
+{
+ DWC_XDCI_ENDPOINT *epHandle;
+ DWC_XDCI_TRB *Trb;
+ USB_XFER_REQUEST *XferReq;
+ UINT32 remainingLen;
+
+ if (EpNum > DWC_XDCI_MAX_ENDPOINTS) {
+ EpNum = DWC_XDCI_MAX_ENDPOINTS;
+ }
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ epHandle = &CoreHandle->EpHandles[EpNum];
+ epHandle->CurrentXferRscIdx = 0;
+ Trb = epHandle->Trb;
+ XferReq = &epHandle->XferHandle;
+
+ //
+ // if transfer done, set CheckFlag to FALSE for allow next transfer request.
+ //
+ epHandle->CheckFlag = FALSE;
+
+ if ((Trb == NULL) || (XferReq == NULL)) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute the actual transfer length
+ //
+ XferReq->ActualXferLen = XferReq->XferLen;
+ remainingLen = (Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK);
+
+ if (remainingLen > XferReq->XferLen) {
+ //
+ // Buffer overrun? This should never happen
+ //
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: Possible Buffer overrun\n"));
+ } else {
+ XferReq->ActualXferLen -= remainingLen;
+ }
+
+ //
+ // Notify upper layer of request-specific transfer completion
+ // if there is a callback specifically for this request
+ //
+ if (XferReq->XferDone) {
+ XferReq->XferDone(CoreHandle->ParentHandle, XferReq);
+ }
+
+ //
+ // Notify upper layer if a callback was registered
+ //
+ if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpType = epHandle->EpInfo.EpType;
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(epHandle->Trb->BuffPtrLow);
+ CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to process endpoint events
+ @CoreHandle: xDCI controller handle address
+ @IntLineEventBuffer: address of Buffer containing event
+ to process
+ @ProcessedEventSize: address to save the size of event
+ Processed
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessEpEvent (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN DWC_XDCI_EVENT_BUFFER *IntLineEventBuffer,
+ IN UINT32 *ProcessedEventSize
+ )
+{
+ UINT32 EpNum;
+ UINT32 epEvent;
+ UINT32 epEventStatus;
+ USB_EP_STATE epState = USB_EP_STATE_DATA;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpEvent: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ epEvent = IntLineEventBuffer->Event;
+
+ *ProcessedEventSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
+
+ //
+ // Get EP num
+ //
+ EpNum = ((epEvent & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS);
+ epEventStatus = (epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK);
+
+ //
+ // Interpret event and handle transfer completion here
+ //
+ epEvent = ((epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_EVENT_BUFF_EP_EVENT_BIT_POS);
+
+ switch (epEvent) {
+ case DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT:
+ DEBUG ((DEBUG_INFO, "XFER_CMPLT ep %d\n", EpNum));
+ if (EpNum > 1) {
+ DwcXdciProcessEpXferDone (CoreHandle, EpNum);
+ } else {
+ DwcXdciProcessEp0XferPhaseDone (CoreHandle, EpNum);
+ }
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS:
+ DEBUG ((DEBUG_INFO, "IN_PROGRESS\n"));
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY:
+ DEBUG ((DEBUG_INFO, "NOT_READY ep %d\n", EpNum));
+ if (EpNum > 1) {
+ //
+ // Endpoint transfer is not ready
+ //
+ DwcXdciProcessEpXferNotReady (CoreHandle, EpNum);
+ } else {
+ /* Is it data stage or status stage */
+ if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK) {
+ epState = USB_EP_STATE_DATA;
+ } else if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK) {
+ epState = USB_EP_STATE_STATUS;
+ }
+ /* Process transfer not ready case */
+ DwcXdciProcessEp0XferNotReady (CoreHandle, EpNum, epState);
+ }
+ break;
+
+ default:
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEpEvent: UNKNOWN EP event\n"));
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal function:
+ This function is used to process events on single interrupt line
+ @CoreHandle: xDCI controller handle address
+ @eventCount: event bytes to process
+ @ProcessedEventCount: address to save the size
+ (in bytes) of event Processed
+ Processed
+
+**/
+STATIC
+EFI_STATUS
+DwcXdciProcessInterruptLineEvents (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 eventCount,
+ IN UINT32 *ProcessedEventCount
+ )
+{
+ UINT32 ProcessedEventSize = 0;
+ UINT32 currentEventAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CoreHandle->CurrentEventBuffer == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID event Buffer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ currentEventAddr = (UINT32)(UINTN)(CoreHandle->CurrentEventBuffer);
+
+ //
+ // Process eventCount/eventSize number of events
+ // in this run
+ //
+ while (eventCount) {
+ if (CoreHandle->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) {
+ DwcXdciProcessDeviceEvent (
+ CoreHandle,
+ CoreHandle->CurrentEventBuffer,
+ &ProcessedEventSize
+ );
+ } else {
+ DwcXdciProcessEpEvent (
+ CoreHandle,
+ CoreHandle->CurrentEventBuffer,
+ &ProcessedEventSize);
+ }
+
+ eventCount -= ProcessedEventSize;
+ *ProcessedEventCount += ProcessedEventSize;
+ if ((currentEventAddr + ProcessedEventSize) >=
+ ((UINT32)(UINTN)(CoreHandle->AlignedEventBuffers) + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))
+ ) {
+ currentEventAddr = (UINT32)(UINTN)(CoreHandle->AlignedEventBuffers);
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer bound reached\n"));
+ } else {
+ currentEventAddr += ProcessedEventSize;
+ }
+
+ CoreHandle->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER *)(UINTN)currentEventAddr;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// DWC XDCI APIs
+//
+
+/**
+ Interface:
+
+ This function is used to initialize the xDCI core
+ @configParams: Parameters from app to configure the core
+ @deviceCorePtr: HW-independent APIs handle for device core
+ @CoreHandle: xDCI controller handle retured
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreInit (
+ IN USB_DEV_CONFIG_PARAMS *ConfigParams,
+ IN VOID *deviceCorePtr,
+ IN VOID **CoreHandle
+ )
+{
+ EFI_STATUS status = EFI_DEVICE_ERROR;
+ UINTN BaseAddr;
+ XDCI_CORE_HANDLE *LocalCoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT8 i;
+
+ LocalCoreHandle = (XDCI_CORE_HANDLE *)AllocateZeroPool (sizeof(XDCI_CORE_HANDLE));
+
+ if (CoreHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xDCI\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (LocalCoreHandle, sizeof(XDCI_CORE_HANDLE));
+
+ LocalCoreHandle->ParentHandle = deviceCorePtr;
+
+ *CoreHandle = (VOID *)LocalCoreHandle;
+
+ LocalCoreHandle->Id = ConfigParams->ControllerId;
+ LocalCoreHandle->BaseAddress = BaseAddr = ConfigParams->BaseAddress;
+ LocalCoreHandle->Flags = ConfigParams->Flags;
+ LocalCoreHandle->DesiredSpeed = LocalCoreHandle->ActualSpeed = ConfigParams->Speed;
+ LocalCoreHandle->Role = ConfigParams->Role;
+
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_CSFTRST_MASK);
+
+ // Wait until core soft reset completes
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & DWC_XDCI_DCTL_CSFTRST_MASK)) {
+ break;
+ } else {
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ }
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ efi_perror (status, L"Failed to reset device controller 0x%x",(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_INFO, "USB core has been reset\n"));
+
+ //
+ // All FIFOs are flushed at this point
+ //
+ //
+ // Ensure we have EP0 Rx/Tx handles initialized
+ //
+ LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpDir = UsbEpDirOut;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpType = USB_ENDPOINT_CONTROL;
+ LocalCoreHandle->EpHandles[0].EpInfo.MaxPktSize = DWC_XDCI_SS_CTRL_EP_MPS;
+ //
+ // 0 means burst size of 1
+ //
+ LocalCoreHandle->EpHandles[0].EpInfo.BurstSize = 0;
+
+ LocalCoreHandle->EpHandles[1].EpInfo.EpNum = 0;
+ LocalCoreHandle->EpHandles[1].EpInfo.EpDir = UsbEpDirIn;
+ LocalCoreHandle->EpHandles[1].EpInfo.EpType = USB_ENDPOINT_CONTROL;
+ LocalCoreHandle->EpHandles[1].EpInfo.MaxPktSize = DWC_XDCI_SS_CTRL_EP_MPS;
+ //
+ // 0 means burst size of 1
+ //
+ LocalCoreHandle->EpHandles[1].EpInfo.BurstSize = 0;
+
+ LocalCoreHandle->DevState = UsbDevStateDefault;
+
+ //
+ // Clear KeepConnect bit so we can allow disconnect and
+ // re-connect. Stay in RX_DETECT state
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) &
+ (~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) &
+ ((~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK) | (DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS))
+ );
+
+ DEBUG ((DEBUG_INFO, "Device controller Synopsys ID: %x\n", UsbRegRead (BaseAddr, DWC_XDCI_GSNPSID_REG)));
+ DEBUG ((DEBUG_INFO, "Default value of xDCI GSBUSCFG0 and GSBUSCFG1: %x, %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG0_REG),
+ UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG1_REG)));
+
+ DEBUG ((DEBUG_INFO, "Default value of xDCI GTXTHRCFG and GRXTHRCFG: %x, %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GTXTHRCFG_REG),
+ UsbRegRead (BaseAddr, DWC_XDCI_GRXTHRCFG_REG)));
+
+ //
+ // Clear ULPI auto-resume bit
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)) & ~DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK)
+ );
+
+ DEBUG ((DEBUG_INFO, "Default value of xDCI GUSB2PHYCFG and GUSB3PIPECTL: %x, %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)),
+ UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG (0))));
+ //
+ // Only one RxFIFO
+ //
+ DEBUG ((DEBUG_INFO, "Default value of DWC_XDCI_GRXFIFOSIZ: %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GRXFIFOSIZ_REG (0))));
+
+ for (i = 0; i < DWC_XDCI_MAX_ENDPOINTS; i++) {
+ DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_GTXFIFOSIZ %d: %x\n",
+ i, UsbRegRead (BaseAddr, DWC_XDCI_GTXFIFOSIZ_REG (i))));
+ }
+
+ //
+ // TODO: Need to check if TxFIFO should start where RxFIFO ends
+ // or default is correct i.e. TxFIFO starts at 0 just like RxFIFO
+ //
+
+ //
+ // Allocate and Initialize Event Buffers
+ //
+ LocalCoreHandle->MaxDevIntLines = ((UsbRegRead (BaseAddr, DWC_XDCI_GHWPARAMS1_REG) &
+ DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
+ DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS);
+
+ DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIntLines));
+ //
+ // One event Buffer per interrupt line.
+ // Need to align it to size of event Buffer
+ // Buffer needs to be big enough. Otherwise the core
+ // won't operate
+ //
+ LocalCoreHandle->AlignedEventBuffers = (DWC_XDCI_EVENT_BUFFER *)
+ ((UINT32)(UINTN)(LocalCoreHandle->EventBuffers) +
+ ((sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) -
+ (((UINT32)(UINTN)(LocalCoreHandle->EventBuffers)) %
+ (sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))));
+
+ for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GEVNTADR_REG (i),
+ (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)
+ );
+
+ //
+ // Clear High 32bit address register, GEVNTADR register is 64-bit register
+ // default is 0xffffffffffffffff
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000);
+
+ LocalCoreHandle->CurrentEventBuffer = LocalCoreHandle->AlignedEventBuffers;
+ //
+ // Write size and clear the mask
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EVNTSIZ_REG (i),
+ sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER
+ );
+
+ //
+ // Write 0 to the event count register as the last step
+ //
+ // for event configuration
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), 0);
+
+ DEBUG ((DEBUG_INFO, "Value of xDCI Event Buffer %d: %x, Size: %x, Count: %x\n",
+ i,
+ UsbRegRead (BaseAddr, DWC_XDCI_GEVNTADR_REG (i)),
+ UsbRegRead (BaseAddr, DWC_XDCI_EVNTSIZ_REG (i)),
+ UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i))));
+ }
+
+ //
+ // Program Global Control Register to disable scaledown,
+ // disable clock gating
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GCTL_REG,
+ ((UsbRegRead(BaseAddr, DWC_XDCI_GCTL_REG) &
+ ~(DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK + DWC_XDCI_GCTL_RAMCLKSEL_MASK + DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK)) |
+ DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK |
+ (DWC_XDCI_GCTL_PRT_CAP_DEVICE << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)));
+
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
+
+ //
+ // TODO: Program desired Speed and set LPM capable
+ // We will do this when SuperSpeed works. For now,
+ // force into High-Speed mode to aVOID anyone trying this
+ // on Super Speed port
+ //
+#ifdef SUPPORT_SUPER_SPEED
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCFG_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | LocalCoreHandle->DesiredSpeed
+ );
+#else
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCFG_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | DWC_XDCI_DCFG_DESIRED_HS_SPEED
+ );
+#endif
+
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG)));
+
+ //
+ // Enable Device Interrupt Events
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DEVTEN_REG,
+ DWC_XDCI_DEVTEN_DEVICE_INTS
+ );
+ //
+ // Program the desired role
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GCTL_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG) & ~DWC_XDCI_GCTL_PRT_CAP_DIR_MASK) | (LocalCoreHandle->Role << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)
+ );
+ //
+ // Clear USB2 suspend for start new config command
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
+ );
+
+ //
+ // Clear USB3 suspend for start new config command
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB3PIPECTL_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
+ );
+
+ //
+ // Issue DEPSTARTCFG command for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_START_NEW_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to init params for START_NEW_CONFIG EP command on xDCI");
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_START_NEW_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to issue START_NEW_CONFIG EP command on xDCI");
+ return status;
+ }
+
+ //
+ // Issue DEPCFG command for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP0");
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams);
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP0");
+ return status;
+ }
+
+ //
+ // Issue DEPCFG command for EP1
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[1].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP1");
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP1");
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0");
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0");
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP1
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[1].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1");
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ efi_perror (status, L"DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1");
+ return status;
+ }
+
+ //
+ // Prepare a Buffer for SETUP packet
+ //
+ LocalCoreHandle->Trbs = (DWC_XDCI_TRB *)(UINTN)((UINT32)(UINTN)
+ LocalCoreHandle->UnalignedTrbs +
+ (DWC_XDCI_TRB_BYTE_ALIGNMENT -
+ ((UINT32)(UINTN)LocalCoreHandle->UnalignedTrbs %
+ DWC_XDCI_TRB_BYTE_ALIGNMENT)));
+
+ DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ unalignedTrbs address is 0x%x\n", LocalCoreHandle->UnalignedTrbs));
+ DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ TRB address is 0x%x\n", LocalCoreHandle->Trbs));
+ //
+ // Allocate Setup Buffer that is 8-byte aligned
+ //
+ LocalCoreHandle->AlignedSetupBuffer = LocalCoreHandle->DefaultSetupBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
+
+ //
+ // Aligned Buffer for status phase
+ //
+ LocalCoreHandle->AlignedMiscBuffer = LocalCoreHandle->MiscBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->AlignedMiscBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
+
+
+ //
+ // Enable Physical Endpoints 0
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EP_DALEPENA_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 0)
+ );
+ //
+ // Enable Physical Endpoints 1
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EP_DALEPENA_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 1)
+ );
+
+ DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
+ return status;
+}
+
+
+/**
+ Interface:
+ This function is used to de-initialize the xDCI core
+ @CoreHandle: xDCI controller handle
+ @flags: Special flags for de-initializing the core in
+ particular way
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreDeinit (
+ VOID *CoreHandle,
+ __attribute__((unused)) UINT32 flags
+ )
+{
+ FreePool (CoreHandle);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to register event callback function
+ @CoreHandle: xDCI controller handle
+ @event: Event for which callback is to be registered
+ @callbackFn: Callback function to invoke after event occurs
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreRegisterCallback (
+ IN VOID *CoreHandle,
+ IN USB_DEVICE_EVENT_ID Event,
+ IN USB_DEVICE_CALLBACK_FUNC CallbackFunc
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreRegisterCallback: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreRegisterCallback: event is %d\n", Event));
+ switch (Event) {
+ case USB_DEVICE_DISCONNECT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevDisconnectCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_RESET_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBusResetCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_CONNECTION_DONE:
+ LocalCoreHandle->EventCallbacks.DevResetDoneCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_STATE_CHANGE_EVENT:
+ LocalCoreHandle->EventCallbacks.DevLinkStateCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_WAKEUP_EVENT:
+ LocalCoreHandle->EventCallbacks.DevWakeupCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_HIBERNATION_REQ_EVENT:
+ LocalCoreHandle->EventCallbacks.DevHibernationCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_SOF_EVENT:
+ LocalCoreHandle->EventCallbacks.DevSofCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_ERRATIC_ERR_EVENT:
+ LocalCoreHandle->EventCallbacks.DevErraticErrCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_CMD_CMPLT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_BUFF_OVERFLOW_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_TEST_LMP_RX_EVENT:
+ LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_SETUP_PKT_RECEIVED:
+ LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_XFER_NRDY:
+ LocalCoreHandle->EventCallbacks.DevXferNrdyCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_XFER_DONE:
+ LocalCoreHandle->EventCallbacks.DevXferDoneCallback = CallbackFunc;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to unregister event callback function
+ @CoreHandle: xDCI controller handle
+ @event: Event for which callback function is to be unregistered
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreUnregisterCallback (
+ IN VOID *CoreHandle,
+ IN USB_DEVICE_EVENT_ID event
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreUnregisterCallback: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (event) {
+ case USB_DEVICE_DISCONNECT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevDisconnectCallback = NULL;
+ break;
+
+ case USB_DEVICE_RESET_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBusResetCallback = NULL;
+ break;
+
+ case USB_DEVICE_CONNECTION_DONE:
+ LocalCoreHandle->EventCallbacks.DevResetDoneCallback = NULL;
+ break;
+
+ case USB_DEVICE_STATE_CHANGE_EVENT:
+ LocalCoreHandle->EventCallbacks.DevLinkStateCallback = NULL;
+ break;
+
+ case USB_DEVICE_WAKEUP_EVENT:
+ LocalCoreHandle->EventCallbacks.DevWakeupCallback = NULL;
+ break;
+
+ case USB_DEVICE_HIBERNATION_REQ_EVENT:
+ LocalCoreHandle->EventCallbacks.DevHibernationCallback = NULL;
+ break;
+
+ case USB_DEVICE_SOF_EVENT:
+ LocalCoreHandle->EventCallbacks.DevSofCallback = NULL;
+ break;
+
+ case USB_DEVICE_ERRATIC_ERR_EVENT:
+ LocalCoreHandle->EventCallbacks.DevErraticErrCallback = NULL;
+ break;
+
+ case USB_DEVICE_CMD_CMPLT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback = NULL;
+ break;
+
+ case USB_DEVICE_BUFF_OVERFLOW_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback = NULL;
+ break;
+
+ case USB_DEVICE_TEST_LMP_RX_EVENT:
+ LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback = NULL;
+ break;
+
+ case USB_DEVICE_SETUP_PKT_RECEIVED:
+ LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback = NULL;
+ break;
+
+ case USB_DEVICE_XFER_NRDY:
+ LocalCoreHandle->EventCallbacks.DevXferNrdyCallback = NULL;
+ break;
+
+ case USB_DEVICE_XFER_DONE:
+ LocalCoreHandle->EventCallbacks.DevXferDoneCallback = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used as an interrupt service routine
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreIsrRoutine (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINTN BaseAddr;
+ UINT32 eventCount;
+ UINT32 ProcessedEventCount;
+ UINT32 i;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutine: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (LocalCoreHandle->InterrupProcessing == TRUE) {
+ DEBUG ((DEBUG_INFO, "interrupProcessing.........\n"));
+ return EFI_SUCCESS;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+ //
+ // Event Buffer corresponding to each interrupt line needs
+ // to be Processed
+ //
+ LocalCoreHandle->InterrupProcessing = TRUE;
+ for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
+ //
+ // Get the number of events HW has written for this
+ // interrupt line
+ //
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i));
+ eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+ ProcessedEventCount = 0;
+
+ //
+ // Process interrupt line Buffer only if count is non-zero
+ //
+ if (eventCount) {
+ //
+ // Process events in this Buffer
+ //
+ DwcXdciProcessInterruptLineEvents (LocalCoreHandle, eventCount, &ProcessedEventCount);
+ //
+ // Write back the Processed number of events so HW decrements it from current
+ // event count
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), ProcessedEventCount);
+ }
+ }
+ LocalCoreHandle->InterrupProcessing = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used as an interrupt service routine and it processes only one event at a time.
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreIsrRoutineTimerBased (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINTN BaseAddr;
+ UINT32 eventCount;
+ UINT32 ProcessedEventCount;
+ UINT32 currentEventAddr;
+ UINT32 ProcessedEventSize = 0;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutineTimerBased: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (LocalCoreHandle->CurrentEventBuffer == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIsrRoutineTimerBased: INVALID event Buffer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0)) & DWC_XDCI_EVNTCOUNT_MASK;
+
+ if (LocalCoreHandle->InterrupProcessing == TRUE) {
+ DEBUG ((DEBUG_INFO, "interrupProcessing.........\n"));
+ return EFI_SUCCESS;
+ }
+
+ LocalCoreHandle->InterrupProcessing = TRUE;
+
+ ProcessedEventCount = 0;
+ currentEventAddr = (UINT32)(UINTN)(LocalCoreHandle->CurrentEventBuffer);
+
+ if (LocalCoreHandle->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) {
+ DwcXdciProcessDeviceEvent (
+ LocalCoreHandle,
+ LocalCoreHandle->CurrentEventBuffer,
+ &ProcessedEventSize
+ );
+ } else {
+ DwcXdciProcessEpEvent (
+ LocalCoreHandle,
+ LocalCoreHandle->CurrentEventBuffer,
+ &ProcessedEventSize);
+ }
+
+ eventCount -= ProcessedEventSize;
+ ProcessedEventCount += ProcessedEventSize;
+ if ((currentEventAddr + ProcessedEventSize) >=
+ ((UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers) + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))
+ ) {
+ currentEventAddr = (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers);
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer bound reached\n"));
+ } else {
+ currentEventAddr += ProcessedEventSize;
+ }
+
+ LocalCoreHandle->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER *)(UINTN)currentEventAddr;
+ UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0), ProcessedEventCount);
+ LocalCoreHandle->InterrupProcessing = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to enable xDCI to connect to the host
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreConnect (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINTN BaseAddr;
+
+ EFI_STATUS ret = EFI_DEVICE_ERROR;
+ if (CoreHandle == NULL) {
+ efi_perror (ret, L"DwcXdciCoreConnect: INVALID handle\n");
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ // Clear KeepConnect bit so we can allow disconnect and re-connect
+ // Also issue No action on state change to aVOID any link change
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ (UsbRegRead(BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) & ~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK
+ );
+
+ //
+ // Set Run bit to connect to the host
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_RUN_STOP_MASK
+ );
+
+ // Wait until core starts running
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK)) {
+ break;
+ } else {
+ efi_perror (ret, L"Stall for core run");
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ }
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to disconnect xDCI from the host
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreDisconnect (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINTN BaseAddr;
+ UINT32 eventCount;
+ UINT32 dsts;
+ UINT32 i;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=%d\n", eventCount));
+ while (eventCount) {
+ DwcXdciCoreIsrRoutine(LocalCoreHandle);
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=%d\n", eventCount));
+ }
+
+ //
+ // Issue DEPENDXFER for active transfers
+ //
+ for (i = 0; i < DWC_XDCI_MAX_ENDPOINTS; i++){
+ if (LocalCoreHandle->EpHandles[i].CurrentXferRscIdx){
+ DwcXdciEndXfer(LocalCoreHandle, i);
+ }
+ }
+ //
+ // Clear Run bit to disconnect from host
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead(BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_RUN_STOP_MASK);
+
+ //
+ // Wait until core is halted
+ //
+ do {
+ dsts = UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG);
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: waiting halt: DSTS=0x%x\n", dsts));
+ if ((dsts & DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK) != 0){
+ break;
+ } else {
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ }
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: Failed to halt the device controller\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to obtain current USB bus Speed
+ @CoreHandle: xDCI controller handle
+ @Speed: Address of variable to save the Speed
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreGetSpeed (
+ IN VOID *CoreHandle,
+ IN USB_SPEED *Speed
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Speed == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Speed = UsbRegRead (LocalCoreHandle->BaseAddress, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_CONN_SPEED_MASK;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to obtain current USB bus Speed
+ @CoreHandle: xDCI controller handle
+ @address: USB address to set (assigned by USB host)
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreSetAddress (
+ IN VOID *CoreHandle,
+ IN UINT32 address
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress is 0x%x \n", address));
+ //
+ // Program USB device address
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCFG_REG,
+ (UsbRegRead(BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DEV_ADDRESS_MASK) | (address << DWC_XDCI_DCFG_DEV_ADDRESS_BIT_POS)
+ );
+
+ LocalCoreHandle->DevState = UsbDevStateAddress;
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG)));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to set configuration
+ @CoreHandle: xDCI controller handle
+ @ConfigNum: config num to set (assigned by USB host)
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreSetConfig (
+ VOID *CoreHandle,
+ __attribute__((unused)) UINT32 ConfigNum
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Issue DEPSTARTCFG command on EP0 (new config for
+ // non-control EPs)
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_START_NEW_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: Failed to init params for EPCMD_START_NEW_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ (EPCMD_START_NEW_CONFIG | (2 << DWC_XDCI_EPCMD_RES_IDX_BIT_POS)),
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: Failed to issue EPCMD_START_NEW_CONFIG command\n"));
+ return status;
+ }
+
+ return status;
+}
+
+
+/**
+ Interface:
+ This function is used to set link state
+ @CoreHandle: xDCI controller handle
+ @state: Desired link state
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciSetLinkState (
+ IN VOID *CoreHandle,
+ IN USB_DEVICE_SS_LINK_STATE state
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciSetLinkState: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Clear old mask
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK
+ );
+
+ //
+ // Request new state
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | (state << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to initialize endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ to be initialized
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciInitEp (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Save EP properties
+ //
+ CopyMem (&(LocalCoreHandle->EpHandles[EpNum].EpInfo), EpInfo, sizeof (USB_EP_INFO));
+
+ //
+ // Init CheckFlag
+ //
+ LocalCoreHandle->EpHandles[EpNum].CheckFlag = FALSE;
+
+ //
+ // Init DEPCFG cmd params for EP
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ CoreHandle,
+ &LocalCoreHandle->EpHandles[EpNum].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to init params for EPCMD_SET_EP_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ EpNum,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue a DEPXFERCFG command for endpoint
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[EpNum].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command\n"));
+ }
+
+ return status;
+}
+
+
+/**
+ Interface:
+ This function is used to enable non-Ep0 endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ to be enabled
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpEnable (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 EpNum;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpEnable: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Enable Physical Endpoint EpNum
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EP_DALEPENA_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << EpNum)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to disable non-Ep0 endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ to be enabled
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpDisable (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 EpNum;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpDisable: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Disable Physical Endpoint EpNum
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EP_DALEPENA_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) & ~(1 << EpNum)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to STALL and endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ to be enabled
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpStall (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpStall: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Set Ep State Info
+ //
+ if (LocalCoreHandle->EpHandles[EpNum].State != USB_EP_STATE_STALLED) {
+ LocalCoreHandle->EpHandles[EpNum].OrgState = LocalCoreHandle->EpHandles[EpNum].State;
+ LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_STALLED;
+ }
+ //
+ // Issue a DWC_XDCI_EPCMD_SET_STALL for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ DWC_XDCI_EPCMD_SET_STALL,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP stall command\n"));
+ }
+
+ return status;
+}
+
+
+/**
+ Interface:
+ This function is used to clear endpoint STALL
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ to be enabled
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpClearStall (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpClearStall: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Set Ep State Info
+ //
+ LocalCoreHandle->EpHandles[EpNum].State = LocalCoreHandle->EpHandles[EpNum].OrgState;
+
+ //
+ // Issue a DWC_XDCI_EPCMD_CLEAR_STALL for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ DWC_XDCI_EPCMD_CLEAR_STALL,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP clea stall command\n"));
+ }
+
+ return status;
+}
+
+
+/**
+ Interface:
+ This function is used to set endpoint in NOT READY state
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ to be enabled
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpSetNrdy (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 EpNum;
+ UINTN BaseAddr;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpSetNrdy: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Program the EP number in command's param reg
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG, EpNum);
+
+ //
+ // Issue EP not ready generic device command
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DGCMD_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SET_EP_NRDY)
+ );
+
+ //
+ // Activate the command
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DGCMD_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
+ break;
+ else
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used to queue receive SETUP packet request
+ @CoreHandle: xDCI controller handle
+ @Buffer: Address of Buffer to receive SETUP packet
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEp0ReceiveSetupPkt (
+ IN VOID *CoreHandle,
+ IN UINT8 *Buffer
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ DWC_XDCI_TRB *Trb;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpDir = 0;
+ LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_SETUP;
+ Trb = LocalCoreHandle->Trbs;
+ DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveSetupPkt)\n"));
+
+ Status = DwcXdciCoreInitTrb (
+ LocalCoreHandle,
+ Trb,
+ TRBCTL_SETUP,
+ Buffer,
+ 8
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: Init TRB Failed \n"));
+ return Status;
+ }
+
+ //
+ // Issue a DEPSTRTXFER for EP0
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "\nDwcXdciEp0ReceiveSetupPkt: Failed to issue Start Transfer command"));
+ }
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead(LocalCoreHandle->BaseAddress, DWC_XDCI_EPCMD_REG(0)) &
+ DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS
+ );
+
+ return Status;
+}
+
+
+/**
+ Interface:
+ This function is used to queue receive status packet on EP0
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEp0ReceiveStatusPkt (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_TRB_CONTROL TrbCtrl;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS Status;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // We are receiving on EP0 so physical EP is 0
+ //
+ Trb = LocalCoreHandle->Trbs;
+ DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveStatusPkt)\n"));
+ if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
+ DEBUG ((DEBUG_INFO, "statusPkt still not transferred.\n"));
+ return EFI_SUCCESS;
+ }
+
+ LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpDir = 0;
+
+ //
+ // OUT data phase for 3-phased control transfer
+ //
+ TrbCtrl = TRBCTL_3_PHASE;
+
+ //
+ // Init TRB for the transfer
+ //
+ Status = DwcXdciCoreInitTrb (
+ LocalCoreHandle,
+ Trb,
+ TrbCtrl,
+ LocalCoreHandle->AlignedSetupBuffer,
+ 0
+ );
+
+ if (!Status) {
+ //
+ // Issue a DEPSTRTXFER for EP0
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: Failed to issue Start Transfer command for EP0\n"));
+ }
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(0)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
+
+ //
+ // TODO: We are not using the EP state for control transfers
+ // right now simply because we're only supporting IN
+ // data phase. For the current use case, we don't
+ // need OUT data phase. We can add that later and we will
+ // add some of the state and SETUP packet awareness code
+ //
+ LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Interface:
+ This function is used to send status packet on EP0
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEp0SendStatusPkt (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS Status;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // We are sending on EP0 so physical EP is 1
+ //
+ Trb = (LocalCoreHandle->Trbs + (1 * DWC_XDCI_TRB_NUM));
+ DEBUG ((DEBUG_INFO, "(DwcXdciEp0SendStatusPkt)\n"));
+
+ LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
+ Status = DwcXdciCoreInitTrb (
+ LocalCoreHandle,
+ Trb,
+ TRBCTL_2_PHASE,
+ LocalCoreHandle->AlignedMiscBuffer,
+ 0
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: TRB failed during status phase\n"));
+ return Status;
+ }
+
+ //
+ // Issue a DEPSTRTXFER for EP1
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: Failed to issue Start Transfer on EP0\n"));
+ }
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[1].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(1)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
+ LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
+
+ return Status;
+}
+
+
+/**
+ Interface:
+ This function is used to send data on non-EP0 endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ @Buffer: Buffer containing data to transmit
+ @size: Size of transfer (in bytes)
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpTxData (
+ IN VOID *CoreHandle,
+ IN USB_XFER_REQUEST *XferReq
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_TRB_CONTROL TrbCtrl;
+ EFI_STATUS Status;
+ UINT32 EpNum;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (XferReq == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID transfer request\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (
+ XferReq->EpInfo.EpNum,
+ XferReq->EpInfo.EpDir
+ );
+
+ Trb = (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM));
+ DEBUG ((DEBUG_INFO, "(DwcXdciEpTxData)EpNum is %d\n", EpNum));
+
+
+ if (EpNum > 1)
+ TrbCtrl = TRBCTL_NORMAL;
+ else
+ TrbCtrl = TRBCTL_CTRL_DATA_PHASE;
+
+ if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
+ Status = DwcXdciEndXfer (LocalCoreHandle, EpNum);
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfer\n"));
+ }
+
+ Status = DwcXdciCoreFlushEpTxFifo (LocalCoreHandle, EpNum);
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfer\n"));
+ }
+ }
+
+ //
+ // Data phase
+ //
+ CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeof (USB_XFER_REQUEST));
+ LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_DATA;
+
+ LocalCoreHandle->EpHandles[EpNum].Trb = Trb;
+
+ Status = DwcXdciCoreInitTrb (
+ LocalCoreHandle,
+ Trb,
+ TrbCtrl,
+ XferReq->XferBuffer,
+ XferReq->XferLen
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: TRB failed\n"));
+ return Status;
+ }
+
+ //
+ // Issue a DEPSTRTXFER for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx = ((UsbRegRead (BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
+
+ return Status;
+}
+
+
+/**
+ Interface:
+ This function is used to receive data on non-EP0 endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+ @Buffer: Buffer containing data to transmit
+ @size: Size of transfer (in bytes)
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpRxData (
+ IN VOID *CoreHandle,
+ IN USB_XFER_REQUEST *XferReq
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_TRB_CONTROL TrbCtrl;
+ EFI_STATUS Status;
+ UINT32 EpNum;
+ UINTN BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (XferReq == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID transfer request\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (XferReq->EpInfo.EpNum, XferReq->EpInfo.EpDir);
+
+ Trb = (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM));
+ DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)EpNum is %d\n", EpNum));
+
+ if (EpNum > 1)
+ TrbCtrl = TRBCTL_NORMAL;
+ else
+ TrbCtrl = TRBCTL_CTRL_DATA_PHASE;
+
+ //
+ // If CheckFlag didn't set to FALSE, means the previous transfer request didn't complete,
+ // need to wait the previous request done.
+ //
+ if (LocalCoreHandle->EpHandles[EpNum].CheckFlag == TRUE) {
+ return EFI_NOT_READY;
+ }
+
+ LocalCoreHandle->EpHandles[EpNum].CheckFlag = TRUE;
+
+ //
+ // Data phase
+ //
+ CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeof (USB_XFER_REQUEST));
+
+ LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_DATA;
+
+ LocalCoreHandle->EpHandles[EpNum].Trb = Trb;
+
+ DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)XferReq->XferLen is 0x%x\n", XferReq->XferLen));
+
+ Status = DwcXdciCoreInitTrb (
+ LocalCoreHandle,
+ Trb,
+ TrbCtrl,
+ XferReq->XferBuffer,
+ XferReq->XferLen
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: TRB failed\n"));
+ return Status;
+ }
+ //
+ // Issue a DEPSTRTXFER for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: Failed to start transfer\n"));
+ }
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
+
+ return Status;
+}
+
+
+
+STATIC
+EFI_STATUS
+DwcXdciCoreFlushEpFifo (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum
+ )
+{
+ UINTN BaseAddr;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT32 fifoNum;
+ UINT32 Param;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+
+ //
+ // Translate to FIFOnum
+ // NOTE: Assuming this is a Tx EP
+ //
+ fifoNum = (EpNum >> 1);
+
+ //
+ // TODO: Currently we are only using TxFIFO 0. Later map these
+ // Write the FIFO num/dir param for the generic command.
+ //
+
+ Param = UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG);
+ Param &= ~(DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK);
+
+ if ((EpNum & 0x01) != 0) {
+ Param |= (fifoNum | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK);
+ } else {
+ Param |= fifoNum;
+ }
+
+ DEBUG ((DEBUG_INFO, "USB FU Flash: CMD 0x%08x :: Param 0x%08x\n",
+ (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK),
+ Param));
+
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DGCMD_PARAM_REG,
+ Param
+ );
+
+ //
+ // Write the command to flush all FIFOs
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DGCMD_REG,
+ (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_MASK))
+ break;
+ else
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "Failed to issue Command\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Interface:
+ This function is used to cancel a transfer on non-EP0 endpoint
+ @CoreHandle: xDCI controller handle
+ @EpInfo: Address of structure describing properties of EP
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciEpCancelTransfer (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get physical EP num
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+ Status = DwcXdciEndXfer(CoreHandle, EpNum);
+ DwcXdciCoreFlushEpFifo(CoreHandle, EpNum);
+
+ return Status;
+}
+
+
+EFI_STATUS
+usbProcessDeviceResetDet (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ )
+{
+ return DwcXdciProcessDeviceResetDet (CoreHandle);
+}
+
+EFI_STATUS
+usbProcessDeviceResetDone (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ )
+{
+ return DwcXdciProcessDeviceResetDone (CoreHandle);
+}
+
+UINT32
+UsbGetPhysicalEpNum (
+ IN UINT32 EndpointNum,
+ IN USB_EP_DIR EndpointDir
+ )
+{
+ return DwcXdciGetPhysicalEpNum(
+ EndpointNum,
+ EndpointDir
+ );
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbXdciCoreReinit (
+ IN VOID *CoreHandle
+ )
+{
+ EFI_STATUS status = EFI_DEVICE_ERROR;
+ UINTN BaseAddr;
+ XDCI_CORE_HANDLE *LocalCoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT8 i;
+
+ LocalCoreHandle = CoreHandle;
+
+ if (CoreHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xDCI\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ DEBUG ((DEBUG_INFO, "Resetting the USB core\n"));
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_CSFTRST_MASK
+ );
+
+ //
+ // Wait until core soft reset completes
+ //
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & DWC_XDCI_DCTL_CSFTRST_MASK)) {
+ break;
+ } else {
+ uefi_call_wrapper(BS->Stall, 1, DWC_XDCI_MAX_DELAY_ITERATIONS);
+ }
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "Failed to reset device controller\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_INFO, "USB core has been reset\n"));
+
+ LocalCoreHandle->DevState = UsbDevStateDefault;
+
+ //
+ // Clear KeepConnect bit so we can allow disconnect and
+ // re-connect. Stay in RX_DETECT state
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCTL_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) &
+ (~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) &
+ ((~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK) |
+ (DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS))
+ );
+
+ DEBUG ((DEBUG_INFO, "Device controller Synopsys ID: %x\n", UsbRegRead (BaseAddr, DWC_XDCI_GSNPSID_REG)));
+ DEBUG ((DEBUG_INFO, "Default value of xDCI GSBUSCFG0 and GSBUSCFG1: %x, %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG0_REG),
+ UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG1_REG)));
+
+ DEBUG ((DEBUG_INFO, "Default value of xDCI GTXTHRCFG and GRXTHRCFG: %x, %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GTXTHRCFG_REG),
+ UsbRegRead (BaseAddr, DWC_XDCI_GRXTHRCFG_REG)));
+
+ //
+ // Clear ULPI auto-resume bit
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)) & ~DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK)
+ );
+
+ DEBUG ((DEBUG_INFO, "Default value of xDCI GUSB2PHYCFG and GUSB3PIPECTL: %x, %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)),
+ UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG (0))));
+
+ //
+ // Only one RxFIFO
+ //
+ DEBUG ((DEBUG_INFO, "Default value of DWC_XDCI_GRXFIFOSIZ: %x\n",
+ UsbRegRead (BaseAddr, DWC_XDCI_GRXFIFOSIZ_REG (0))));
+
+ for (i = 0; i < DWC_XDCI_MAX_ENDPOINTS; i++) {
+ DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_GTXFIFOSIZ %d: %x\n",
+ i, UsbRegRead (BaseAddr, DWC_XDCI_GTXFIFOSIZ_REG (i))));
+ }
+
+ //
+ // TODO: Need to check if TxFIFO should start where RxFIFO ends
+ // or default is correct i.e. TxFIFO starts at 0 just like RxFIFO
+ //
+
+ //
+ // Allocate and Initialize Event Buffers
+ //
+ LocalCoreHandle->MaxDevIntLines = ((UsbRegRead (BaseAddr, DWC_XDCI_GHWPARAMS1_REG) &
+ DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
+ DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS);
+
+ DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIntLines));
+ //
+ // One event Buffer per interrupt line.
+ // Need to align it to size of event Buffer
+ // Buffer needs to be big enough. Otherwise the core
+ // won't operate
+ //
+ LocalCoreHandle->AlignedEventBuffers = (DWC_XDCI_EVENT_BUFFER *)
+ ((UINT32)(UINTN)(LocalCoreHandle->EventBuffers) +
+ ((sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) -
+ (((UINT32)(UINTN)(LocalCoreHandle->EventBuffers)) %
+ (sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))));
+
+ for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GEVNTADR_REG (i),
+ (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)
+ );
+
+ //
+ // Clear High 32bit address register, GEVNTADR register is 64-bit register
+ // default is 0xffffffffffffffff
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000);
+
+ LocalCoreHandle->CurrentEventBuffer = LocalCoreHandle->AlignedEventBuffers;
+ //
+ // Write size and clear the mask
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EVNTSIZ_REG (i),
+ sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER
+ );
+
+ //
+ // Write 0 to the event count register as the last step
+ // for event configuration
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), 0);
+
+ DEBUG ((DEBUG_INFO, "Value of xDCI Event Buffer %d: %x, Size: %x, Count: %x\n",
+ i,
+ UsbRegRead (BaseAddr, DWC_XDCI_GEVNTADR_REG (i)),
+ UsbRegRead (BaseAddr, DWC_XDCI_EVNTSIZ_REG (i)),
+ UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i))));
+ }
+
+ //
+ // Program Global Control Register to disable scaledown,
+ // disable clock gating
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GCTL_REG,
+ ((UsbRegRead(BaseAddr, DWC_XDCI_GCTL_REG) &
+ ~(DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK + DWC_XDCI_GCTL_RAMCLKSEL_MASK + DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK)) |
+ DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK |
+ (DWC_XDCI_GCTL_PRT_CAP_DEVICE << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)));
+
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
+
+
+ //
+ // TODO: Program desired Speed and set LPM capable
+ // We will do this when SuperSpeed works. For now,
+ // force into High-Speed mode to aVOID anyone trying this
+ // on Super Speed port
+ //
+#ifdef SUPPORT_SUPER_SPEED
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCFG_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | LocalCoreHandle->DesiredSpeed
+ );
+#else
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DCFG_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK) | DWC_XDCI_DCFG_DESIRED_HS_SPEED
+ );
+#endif
+
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG)));
+
+ //
+ // Enable Device Interrupt Events
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_DEVTEN_REG,
+ DWC_XDCI_DEVTEN_DEVICE_INTS
+ );
+
+ //
+ // Program the desired role
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GCTL_REG,
+ (UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG) & ~DWC_XDCI_GCTL_PRT_CAP_DIR_MASK) | (LocalCoreHandle->Role << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS)
+ );
+
+ //
+ // Clear USB2 suspend for start new config command
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK)
+ );
+ //
+ // Clear USB3 suspend for start new config command
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB3PIPECTL_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK)
+ );
+ //
+ // Issue DEPSTARTCFG command for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_START_NEW_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for START_NEW_CONFIG EP command on xDCI\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_START_NEW_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue START_NEW_CONFIG EP command on xDCI\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPCFG command for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPCFG command for EP1
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[1].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP0
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[0].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP1
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ LocalCoreHandle,
+ &LocalCoreHandle->EpHandles[1].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Prepare a Buffer for SETUP packet
+ //
+ LocalCoreHandle->Trbs = (DWC_XDCI_TRB *)(UINTN)((UINT32)(UINTN)
+ LocalCoreHandle->UnalignedTrbs +
+ (DWC_XDCI_TRB_BYTE_ALIGNMENT -
+ ((UINT32)(UINTN)LocalCoreHandle->UnalignedTrbs %
+ DWC_XDCI_TRB_BYTE_ALIGNMENT)));
+
+ DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ unalignedTrbs address is 0x%x\n", LocalCoreHandle->UnalignedTrbs));
+ DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ TRB address is 0x%x\n", LocalCoreHandle->Trbs));
+
+ //
+ // Allocate Setup Buffer that is 8-byte aligned
+ //
+ LocalCoreHandle->AlignedSetupBuffer = LocalCoreHandle->DefaultSetupBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
+
+ //
+ // Aligned Buffer for status phase
+ //
+ LocalCoreHandle->AlignedMiscBuffer = LocalCoreHandle->MiscBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->AlignedMiscBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
+
+ //
+ // We will queue SETUP request when we see bus reset
+ //
+
+ //
+ // Enable Physical Endpoints 0
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EP_DALEPENA_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 0)
+ );
+
+ //
+ // Enable Physical Endpoints 1
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_EP_DALEPENA_REG,
+ UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 1)
+ );
+
+ DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
+ return status;
+
+
+}
+
+
+EFI_STATUS
+UsbXdciCoreFlushEpFifo (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get physical EP num
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+ DwcXdciCoreFlushEpFifo(CoreHandle, EpNum);
+
+ return Status;
+}
diff --git a/libefiusb/device_mode/XdciDWC.h b/libefiusb/device_mode/XdciDWC.h
index c756899c..f4178f02 100644
--- a/libefiusb/device_mode/XdciDWC.h
+++ b/libefiusb/device_mode/XdciDWC.h
@@ -1,742 +1,751 @@
-/** @file
- Copyright (c) 2006 - 2017, 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.
-
-**/
-
-#ifndef _XDCI_DWC_H_
-#define _XDCI_DWC_H_
-
-#include "XdciCommon.h"
-#include "XdciDevice.h"
-#include "protocol/UsbDeviceLib.h"
-
-#define DWC_XDCI_MAX_ENDPOINTS (16)
-#define DWC_XDCI_SS_CTRL_EP_MPS (512)
-#define DWC_XDCI_HS_CTRL_EP_MPS (64)
-#define DWC_XDCI_FS_CTRL_EP_MPS (64)
-#define DWC_XDCI_LS_CTRL_EP_MPS (8)
-#define DWC_XDCI_SS_CTRL_BUF_SIZE (512)
-#define DWC_XDCI_SETUP_BUFF_SIZE (8)
-#define DWC_XDCI_MAX_EVENTS_PER_BUFFER (16)
-#define DWC_XDCI_TRB_BYTE_ALIGNMENT (16)
-#define DWC_XDCI_DEFAULT_TX_FIFO_SIZE (1024)
-#define DWC_XDCI_TRB_NUM (32)
-#define DWC_XDCI_MASK (DWC_XDCI_TRB_NUM - 1)
-
-#define DWC_XDCI_MAX_DELAY_ITERATIONS (1000)
-
-#define DWC_XDCI_GSBUSCFG0_REG (0xC100)
-#define DWC_XDCI_GSBUSCFG1_REG (0xC104)
-#define DWC_XDCI_GTXTHRCFG_REG (0xC108)
-#define DWC_XDCI_GRXTHRCFG_REG (0xC10C)
-
-//
-// Global Control Register and bit definitions
-//
-#define DWC_XDCI_GCTL_REG (0xC110)
-#define DWC_XDCI_GCTL_PWRDNSCALE_MASK (0xFFF80000)
-#define DWC_XDCI_GCTL_PWRDNSCALE_VAL (0x13880000)
-#define DWC_XDCI_GCTL_U2RSTECN_MASK (0x00010000)
-#define DWC_XDCI_GCTL_PRT_CAP_DIR_MASK (0x00003000)
-#define DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS (12)
-#define DWC_XDCI_GCTL_PRT_CAP_HOST (1)
-#define DWC_XDCI_GCTL_PRT_CAP_DEVICE (2)
-#define DWC_XDCI_GCTL_PRT_CAP_OTG (3)
-#define DWC_XDCI_GCTL_RAMCLKSEL_MASK (0x000000C0)
-#define DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK (0x00000030)
-#define DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK (0x00000001)
-#define DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK (0x00000008)
-
-#define DWC_XDCI_GSTS_REG (0xC118)
-#define DWC_XDCI_GSNPSID_REG (0xC120)
-#define DWC_XDCI_GGPIO_REG (0xC124)
-#define DWC_XDCI_GUID_REG (0xC128)
-#define DWC_XDCI_GUCTL_REG (0xC12C)
-#define DWC_XDCI_GBUSERRADDR (0xC130)
-
-//
-// Global Hardware Parameters Registers
-//
-#define DWC_XDCI_GHWPARAMS0_REG (0xC140)
-#define DWC_XDCI_GHWPARAMS1_REG (0xC144)
-#define DWC_XDCI_GHWPARAMS1_NUM_INT_MASK (0x1F8000)
-#define DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS (15)
-
-#define DWC_XDCI_GHWPARAMS2_REG (0xC148)
-#define DWC_XDCI_GHWPARAMS3_REG (0xC14C)
-#define DWC_XDCI_GHWPARAMS4_REG (0xC150)
-#define DWC_XDCI_GHWPARAMS4_CACHE_TRBS_PER_XFER_MASK (0x0000003F)
-#define DWC_XDCI_GHWPARAMS5_REG (0xC154)
-#define DWC_XDCI_GHWPARAMS6_REG (0xC158)
-#define DWC_XDCI_GHWPARAMS7_REG (0xC15C)
-#define DWC_XDCI_GHWPARAMS8_REG (0xC600)
-
-#define DWC_XDCI_GDBGFIFOSPACE_REG (0xC160)
-
-#define DWC_XDCI_GUSB2PHYCFG_REG(n) (0xC200 + (n << 2))
-#define DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK (0x00008000)
-#define DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK (0x00000040)
-
-#define DWC_XDCI_GUSB3PIPECTL_REG(n) (0xC2C0 + (n << 2))
-#define DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK (0x00020000)
-
-#define DWC_XDCI_GTXFIFOSIZ_REG(n) (0xC300 + (n << 2))
-#define DWC_XDCI_GTXFIFOSIZ_START_ADDRESS_MASK (0xFFFF0000)
-#define DWC_XDCI_GTXFIFOSIZ_START_ADDRESS_BIT_POS (16)
-#define DWC_XDCI_GRXFIFOSIZ_REG(n) (0xC380 + (n << 2))
-
-//
-// Global Event Buffer Registers
-//
-#define DWC_XDCI_GEVNTADR_REG(n) (0xC400 + (n << 4))
-#define DWC_XDCI_EVNTSIZ_REG(n) (0xC408 + (n << 4))
-#define DWC_XDCI_EVNTSIZ_MASK (0x0000FFFF)
-#define DWC_XDCI_EVNT_INTR_MASK (0x80000000)
-#define DWC_XDCI_EVNTCOUNT_REG(n) (0xC40C + (n << 4))
-#define DWC_XDCI_EVNTCOUNT_MASK (0x0000FFFF)
-
-//
-// Device Configuration Register and Bit Definitions
-//
-#define DWC_XDCI_DCFG_REG (0xC700)
-#define DWC_XDCI_DCFG_LPM_CAPABLE_MASK (0x00400000)
-#define DWC_XDCI_DCFG_DEV_ADDRESS_MASK (0x000003F8)
-#define DWC_XDCI_DCFG_DEV_ADDRESS_BIT_POS (3)
-#define DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK (0x00000007)
-#define DWC_XDCI_DCFG_DESIRED_SS_SPEED (0x00000004)
-#define DWC_XDCI_DCFG_DESIRED_FS_SPEED (0x00000001)
-#define DWC_XDCI_DCFG_DESIRED_HS_SPEED (0x00000000)
-
-//
-// Device Control Register
-//
-#define DWC_XDCI_DCTL_REG (0xC704)
-#define DWC_XDCI_DCTL_RUN_STOP_MASK (0x80000000)
-#define DWC_XDCI_DCTL_RUN_STOP_BIT_POS (31)
-#define DWC_XDCI_DCTL_CSFTRST_MASK (0x40000000)
-#define DWC_XDCI_DCTL_CSFTRST_BIT_POS (30)
-#define DWC_XDCI_DCTL_KEEP_CONNECT_MASK (0x00080000)
-#define DWC_XDCI_DCTL_KEEP_CONNECT_BIT_POS (19)
-#define DWC_XDCI_DCTL_CSFTRST_BIT_POS (30)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK (0x000001E0)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS (5)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_NO_ACTION (1)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_SS_DISABLED (4)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT (5)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_SS_INACTIVE (6)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_RECOVERY (8)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_COMPLIANCE (10)
-#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_REMOTE_WAKEUP (8)
-
-//
-// Device Event Enable Register
-//
-#define DWC_XDCI_DEVTEN_REG (0xC708)
-#define DWC_XDCI_DEVTEN_DISCONN_DET_EN_MASK (0x00000001)
-#define DWC_XDCI_DEVTEN_RESET_DET_EN_MASK (0x00000002)
-#define DWC_XDCI_DEVTEN_CONN_DONE_DET_EN_MASK (0x00000004)
-#define DWC_XDCI_DEVTEN_LINK_STATE_CHANGE_DET_EN_MASK (0x00000008)
-#define DWC_XDCI_DEVTEN_RESUME_WAKEUP_DET_EN_MASK (0x00000010)
-#define DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK (0x00000020)
-#define DWC_XDCI_DEVTEN_U3L2L1_DET_EN_MASK (0x00000040)
-#define DWC_XDCI_DEVTEN_SOF_DET_EN_MASK (0x00000080)
-#define DWC_XDCI_DEVTEN_ERRATIC_ERR_DET_EN_MASK (0x00000200)
-#define DWC_XDCI_DEVTEN_VNDR_DEV_TST_RX_DET_EN_MASK (0x00001000)
-
-#define DWC_XDCI_DEVTEN_DEVICE_INTS (DWC_XDCI_DEVTEN_DISCONN_DET_EN_MASK | \
- DWC_XDCI_DEVTEN_RESET_DET_EN_MASK | DWC_XDCI_DEVTEN_CONN_DONE_DET_EN_MASK | \
- DWC_XDCI_DEVTEN_LINK_STATE_CHANGE_DET_EN_MASK | DWC_XDCI_DEVTEN_RESUME_WAKEUP_DET_EN_MASK | \
- DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK | DWC_XDCI_DEVTEN_U3L2L1_DET_EN_MASK | \
- DWC_XDCI_DEVTEN_ERRATIC_ERR_DET_EN_MASK)
-
-#define DWC_XDCI_EVENT_BUFF_BULK_STREAM_ID_MASK (0xFFFF0000)
-#define DWC_XDCI_EVENT_BUFF_ISOCH_UFRAME_NUM_MASK (0xFFFF0000)
-#define DWC_XDCI_EVENT_BUFF_EP_CMD_TYPE_MASK (0x0F000000)
-#define DWC_XDCI_EVENT_BUFF_EP_XFER_RES_INDEX_MASK (0x007F0000)
-#define DWC_XDCI_EVENT_BUFF_EP_XFER_ACTIVE_MASK (0x00008000)
-#define DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK (0x00001000)
-#define DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK (0x00002000)
-#define DWC_XDCI_EVENT_BUFF_EP_LST_MASK (0x00008000)
-#define DWC_XDCI_EVENT_BUFF_EP_MISSED_ISOCH_MASK (0x00008000)
-#define DWC_XDCI_EVENT_BUFF_EP_IOC_MASK (0x00004000)
-#define DWC_XDCI_EVENT_BUFF_EP_LAST_PKT_MASK (0x00002000)
-#define DWC_XDCI_EVENT_BUFF_EP_STREAM_NOT_FND_MASK (0x00002000)
-#define DWC_XDCI_EVENT_BUFF_EP_STREAM_FND_MASK (0x00001000)
-#define DWC_XDCI_EVENT_BUFF_EP_ERR_NO_RES_MASK (0x00001000)
-#define DWC_XDCI_EVENT_BUFF_EP_INVALID_RES_MASK (0x00001000)
-
-#define DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK (0x000003C0)
-#define DWC_XDCI_EVENT_BUFF_EP_EVENT_BIT_POS (6)
-#define DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT (1)
-#define DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS (2)
-#define DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY (3)
-#define DWC_XDCI_EVENT_BUFF_EP_STREAM_EVENT (6)
-#define DWC_XDCI_EVENT_BUFF_EP_CMD_CMPLT (7)
-
-#define DWC_XDCI_EVENT_BUFF_EP_NUM_MASK (0x0000003E)
-#define DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS (1)
-
-#define DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK (0x0000F000)
-
-
-#define DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK (0x01E00000)
-#define DWC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS (21)
-#define DWC_XDCI_EVENT_BUFF_DEV_SS_EVENT_MASK (0x00100000)
-#define DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_MASK (0x000F0000)
-#define DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS (16)
-
-#define DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK (0x00000F00)
-#define DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS (8)
-#define DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT (12)
-#define DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT (11)
-#define DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT (10)
-#define DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT (9)
-#define DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT (7)
-#define DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT (5)
-#define DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT (4)
-#define DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT (3)
-#define DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT (2)
-#define DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT (1)
-#define DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT (0)
-
-#define DWC_XDCI_EVENT_DEV_MASK (0x00000001)
-
-//
-// Device Status Register and Bit Definitions
-//
-#define DWC_XDCI_DSTS_REG (0xC70C)
-#define DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK (0x00400000)
-#define DWC_XDCI_DSTS_DEV_CTRL_HALTED_BIT_POS (22)
-#define DWC_XDCI_DSTS_CORE_IDLE (1 << 23)
-#define DWC_XDCI_DSTS_CONN_SPEED_MASK (0x00000007)
-#define DWC_XDCI_DSTS_LINK_STATE_MASK (0x003C0000)
-#define DWC_XDCI_DSTS_LINK_STATE_DISCONNECT (0x00100000)
-
-//
-// Device Generic Command Parameter Register
-//
-#define DWC_XDCI_DGCMD_PARAM_REG (0xC710)
-#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK (0x0000001F)
-#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK (0x00000020)
-#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_BIT_POS (5)
-
-//
-// Device Generic Command Register
-//
-#define DWC_XDCI_DGCMD_REG (0xC714)
-#define DWC_XDCI_DGCMD_CMD_STATUS_MASK (0x00008000)
-#define DWC_XDCI_DGCMD_CMD_ACTIVE_MASK (0x00000400)
-#define DWC_XDCI_DGCMD_CMD_IOC_MASK (0x00000100)
-#define DWC_XDCI_DGCMD_CMD_TYPE_MASK (0x000000FF)
-#define DWC_XDCI_DGCMD_CMD_SET_PERIODIC_PARAMS (0x2)
-#define DWC_XDCI_DGCMD_CMD_SET_SCRATCH_PAD_BUFF_ARR_LO (0x4)
-#define DWC_XDCI_DGCMD_CMD_SET_SCRATCH_PAD_BUFF_ARR_HI (0x5)
-#define DWC_XDCI_DGCMD_CMD_XMIT_DEVICE_NOTIFICATION (0x7)
-#define DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH (0x9)
-#define DWC_XDCI_DGCMD_CMD_ALL_FIFO_FLUSH (0xA)
-#define DWC_XDCI_DGCMD_CMD_SET_EP_NRDY (0xC)
-#define DWC_XDCI_DGCMD_CMD_RUN_SOC_BUS_LPBK (0x10)
-
-//
-// Device Active USB EP Enable Register
-//
-#define DWC_XDCI_EP_DALEPENA_REG (0xC720)
-
-//
-// Device Physical EP CMD Param 2 Register. Value is 32-bit
-//
-#define DWC_XDCI_EPCMD_PARAM2_REG(n) (0xC800 + (n << 4))
-
-//
-// Device Physical EP CMD Param 1 Register. Value is 32-bit
-//
-#define DWC_XDCI_EPCMD_PARAM1_REG(n) (0xC804 + (n << 4))
-
-//
-// Device Physical EP CMD Param 0 Register. Value is 32-bit
-//
-#define DWC_XDCI_EPCMD_PARAM0_REG(n) (0xC808 + (n << 4))
-
-//
-// Device Physical EP Command Registers and Bit Definitions
-//
-#define DWC_XDCI_EPCMD_REG(n) (0xC80C + (n << 4))
-#define DWC_XDCI_EPCMD_RES_IDX_MASK (0x007F0000)
-#define DWC_XDCI_EPCMD_RES_IDX_BIT_POS (16)
-#define DWC_XDCI_EPCMD_CMDTYPE_MASK (0x0000000F)
-#define DWC_XDCI_EPCMD_SET_EP_CONFIG (0x1)
-#define DWC_XDCI_EPCMD_SET_EP_XFER_RES_CONFIG (0x2)
-#define DWC_XDCI_EPCMD_GET_EP_STATE (0x3)
-#define DWC_XDCI_EPCMD_SET_STALL (0x4)
-#define DWC_XDCI_EPCMD_CLEAR_STALL (0x5)
-#define DWC_XDCI_EPCMD_START_XFER (0x6)
-#define DWC_XDCI_EPCMD_UPDATE_XFER (0x7)
-#define DWC_XDCI_EPCMD_END_XFER (0x8)
-#define DWC_XDCI_EPCMD_START_NEW_CONFIG (0x9)
-
-#define DWC_XDCI_EPCMD_CMD_IOC_MASK (0x00000100)
-#define DWC_XDCI_EPCMD_CMD_ACTIVE_MASK (0x00000400)
-#define DWC_XDCI_EPCMD_HIGH_PRIO_MASK (0x00000800)
-#define DWC_XDCI_EPCMD_FORCE_RM_MASK (0x00000800)
-
-//
-// Command status and parameter values same as event status and parameters values
-//
-#define DWC_XDCI_EPCMD_CMD_STATUS_MASK (0x0000F000)
-
-//
-// Command Params bit masks
-//
-#define DWC_XDCI_PARAM1_SET_EP_CFG_FIFO_BASED_MASK (0x80000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_BULK_BASED_MASK (0x40000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_MASK (0x3C000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_MASK (0x02000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK (0x01000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_MASK (0x00FF0000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS (16)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EBC_MASK (0x00008000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK (0x00003F00)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_BIT_POS (8)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_STRM_MASK (0x00002000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK (0x00000400)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK (0x00000200)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK (0x00000100)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK (0x0000001F)
-
-//
-// CMD 1 param 0
-//
-#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK (0xC0000000)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_BIT_POS (30)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE (0)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_RESTORE_ST (1)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE (2)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE (3)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK (0x03C00000)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_BIT_POS (22)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK (0x003E0000)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_BIT_POS (17)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK (0x00003FF8)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_MPS_BIT_POS (3)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK (0x00000006)
-#define DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_BIT_POS (1)
-#define DWC_XDCI_PARAM0_EP_TYPE_CTRL (0)
-#define DWC_XDCI_PARAM0_EP_TYPE_ISOCH (1)
-#define DWC_XDCI_PARAM0_EP_TYPE_BULK (2)
-#define DWC_XDCI_PARAM0_EP_TYPE_INTR (3)
-
-//
-// CMD 1 param 1
-//
-#define DWC_XDCI_PARAM1_SET_EP_CFG_BULK_BASED_MASK (0x40000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_MASK (0x3C000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_BIT_POS (26)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_MASK (0x02000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_BIT_POS (25)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK (0x01000000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_MASK (0x00FF0000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS (16)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EBC_MASK (0x00008000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK (0x00003F00)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_BIT_POS (8)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_STRM_MASK (0x00002000)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK (0x00000400)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK (0x00000200)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK (0x00000100)
-#define DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK (0x0000001F)
-
-//
-// CMD 2 param 0
-//
-#define DWC_XDCI_PARAM0_SET_EP_XFER_RES_NUM_MASK (0x0000FFFF)
-
-//
-// CMD 3 param 2
-//
-#define DWC_XDCI_PARAM2_GET_EP_STATE_MASK (0xFFFFFFFF)
-
-//
-// CMD 6 param 1
-//
-#define DWC_XDCI_PARAM1_STRT_XFER_TD_ADDR_LO_MASK (0xFFFFFFFF)
-
-//
-// CMD 6 param 0
-//
-#define DWC_XDCI_PARAM0_STRT_XFER_TD_ADDR_HI_MASK (0xFFFFFFFF)
-
-//
-// Transfer Request Block Fields' Bit Definitions
-//
-#define DWC_XDCI_TRB_BUFF_SIZE_MASK (0x00FFFFFF)
-#define DWC_XDCI_TRB_PCM1_MASK (0x03000000)
-#define DWC_XDCI_TRB_PCM1_BIT_POS (24)
-#define DWC_XDCI_TRB_STATUS_MASK (0xF0000000)
-#define DWC_XDCI_TRB_STATUS_BIT_POS (28)
-#define DWC_XDCI_TRB_STATUS_OK (0)
-#define DWC_XDCI_TRB_STATUS_MISSED_ISOCH (1)
-#define DWC_XDCI_TRB_STATUS_SETUP_PENDING (2)
-
-#define DWC_XDCI_TRB_CTRL_HWO_MASK (0x00000001)
-#define DWC_XDCI_TRB_CTRL_LST_TRB_MASK (0x00000002)
-#define DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS (1)
-#define DWC_XDCI_TRB_CTRL_CHAIN_BUFF_MASK (0x00000004)
-#define DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS (2)
-#define DWC_XDCI_TRB_CTRL_CSP_MASK (0x00000008)
-#define DWC_XDCI_TRB_CTRL_CSP_BIT_POS (3)
-#define DWC_XDCI_TRB_CTRL_TYPE_MASK (0x000003F0)
-#define DWC_XDCI_TRB_CTRL_TYPE_BIT_POS (4)
-#define DWC_XDCI_TRB_CTRL_TYPE_NORMAL (1)
-#define DWC_XDCI_TRB_CTRL_TYPE_SETUP (2)
-#define DWC_XDCI_TRB_CTRL_TYPE_STATUS2 (3)
-#define DWC_XDCI_TRB_CTRL_TYPE_STATUS3 (4)
-#define DWC_XDCI_TRB_CTRL_TYPE_DATA (5)
-#define DWC_XDCI_TRB_CTRL_TYPE_ISOCH_FIRST (6)
-#define DWC_XDCI_TRB_CTRL_TYPE_ISOCH (7)
-#define DWC_XDCI_TRB_CTRL_TYPE_LINK_TRB (8)
-#define DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK (0x00000400)
-#define DWC_XDCI_TRB_CTRL_IOSP_MISOCH_BIT_POS (10)
-#define DWC_XDCI_TRB_CTRL_IOC_MASK (0x00000800)
-#define DWC_XDCI_TRB_CTRL_IOC_BIT_POS (11)
-#define DWC_XDCI_TRB_CTRL_STRM_ID_SOF_NUM_MASK (0x3FFFC000)
-#define DWC_XDCI_TRB_CTRL_STRM_ID_SOF_BIT_POS (14)
-
-#define DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES (4)
-#define DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES (12)
-
-typedef enum {
- EPCMD_SET_EP_CONFIG = 1,
- EPCMD_SET_EP_XFER_RES_CONFIG,
- EPCMD_GET_EP_STATE,
- EPCMD_SET_STALL,
- EPCMD_CLEAR_STALL,
- EPCMD_START_XFER,
- EPCMD_UPDATE_XFER,
- EPCMD_END_XFER,
- EPCMD_START_NEW_CONFIG = 9
-} DWC_XDCI_ENDPOINT_CMD;
-
-typedef enum {
- ON = 0,
- SLEEP = 2,
- SUSPEND,
- DISCONNECTED,
- EARLY_SUSPEND,
- RESET = 14,
- RESUME = 15
-} DWC_XDCI_HS_LINK_STATE;
-
-typedef enum {
- TRBCTL_NORMAL = 1,
- TRBCTL_SETUP,
- TRBCTL_2_PHASE,
- TRBCTL_3_PHASE,
- TRBCTL_CTRL_DATA_PHASE,
- TRBCTL_ISOCH_FIRST,
- TRBCTL_ISOCH,
- TRBCTL_LINK
-} DWC_XDCI_TRB_CONTROL;
-
-//
-// DWC XDCI Endpoint Commands Parameters struct
-//
-typedef struct {
- UINT32 Param2;
- UINT32 Param1;
- UINT32 Param0;
-} DWC_XDCI_ENDPOINT_CMD_PARAMS;
-
-//
-// Event Buffer Struct
-//
-typedef struct {
- UINT32 Event;
- UINT32 DevTstLmp1;
- UINT32 DevTstLmp2;
- UINT32 Reserved;
-} DWC_XDCI_EVENT_BUFFER;
-
-//
-// Transfer Request Block
-//
-typedef struct {
- UINT32 BuffPtrLow;
- UINT32 BuffPtrHigh;
- UINT32 LenXferParams;
- UINT32 TrbCtrl;
-} DWC_XDCI_TRB;
-
-typedef struct {
- USB_EP_INFO EpInfo;
- DWC_XDCI_TRB *Trb;
- USB_XFER_REQUEST XferHandle;
- UINT32 CurrentXferRscIdx;
- VOID *CoreHandle;
- USB_EP_STATE State;
- USB_EP_STATE OrgState;
- BOOLEAN CheckFlag;
-} DWC_XDCI_ENDPOINT;
-
-typedef struct {
- //
- // CbEventParams must be copied over by upper layer if
- // it defers event processing
- //
- USB_DEVICE_CALLBACK_PARAM CbEventParams;
-
- //
- // Callback function list
- //
- USB_DEVICE_CALLBACK_FUNC DevDisconnectCallback;
- USB_DEVICE_CALLBACK_FUNC DevBusResetCallback;
- USB_DEVICE_CALLBACK_FUNC DevResetDoneCallback;
- USB_DEVICE_CALLBACK_FUNC DevLinkStateCallback;
- USB_DEVICE_CALLBACK_FUNC DevWakeupCallback;
- USB_DEVICE_CALLBACK_FUNC DevHibernationCallback;
- USB_DEVICE_CALLBACK_FUNC DevSofCallback;
- USB_DEVICE_CALLBACK_FUNC DevErraticErrCallback;
- USB_DEVICE_CALLBACK_FUNC DevCmdCmpltCallback;
- USB_DEVICE_CALLBACK_FUNC DevBuffOvflwCallback;
- USB_DEVICE_CALLBACK_FUNC DevTestLmpRxCallback;
- USB_DEVICE_CALLBACK_FUNC DevSetupPktReceivedCallback;
- USB_DEVICE_CALLBACK_FUNC DevXferNrdyCallback;
- USB_DEVICE_CALLBACK_FUNC DevXferDoneCallback;
-} USB_DEV_CALLBACK_LIST;
-
-typedef struct {
- VOID *ParentHandle; // Pointer to the parent this driver is associated
- USB_CONTROLLER_ID Id; // ID of the controllers supported in our DCD
- USB_SPEED DesiredSpeed; // Desired SS, HS, FS or LS Speeds for the core
- USB_ROLE Role; // Desired role i.e. host, Device or OTG
- USB_SPEED ActualSpeed; // Actual Speed
- USB_DEVICE_STATE DevState; // Device state
- UINT32 BaseAddress; // Register Base address
- UINT32 Flags; // Init flags
- UINT32 MaxDevIntLines; // One event Buffer per interrupt line
- DWC_XDCI_EVENT_BUFFER EventBuffers [DWC_XDCI_MAX_EVENTS_PER_BUFFER * 2]; // Event Buffer pool
- DWC_XDCI_EVENT_BUFFER *AlignedEventBuffers; // Aligned event Buffer pool
- DWC_XDCI_EVENT_BUFFER *CurrentEventBuffer; // Current event Buffer address
- DWC_XDCI_TRB UnalignedTrbs [(DWC_XDCI_MAX_ENDPOINTS + 1) * DWC_XDCI_TRB_NUM]; // TRBs.
- DWC_XDCI_TRB *Trbs; // 16-bytes aligned TRBs.
- DWC_XDCI_ENDPOINT EpHandles [DWC_XDCI_MAX_ENDPOINTS * 2]; // EPs, diretion in and out for each EP
- UINT8 DefaultSetupBuffer [DWC_XDCI_SETUP_BUFF_SIZE * 2]; // Unaligned setup Buffer
- UINT8 *AlignedSetupBuffer; // Aligned setup Buffer. Aligned to 8-byte boundary
- UINT8 MiscBuffer [528]; // Unaligned misc Buffer
- UINT8 *AlignedMiscBuffer; // Aligned misc Buffer
- UINT32 LinkState; // Link state
- UINT32 HirdVal; // HIRD value
- USB_DEV_CALLBACK_LIST EventCallbacks;
- volatile BOOLEAN InterrupProcessing;
-} XDCI_CORE_HANDLE;
-
-//
-// DWC XDCI API prototypes
-//
-EFI_STATUS
-EFIAPI
-DwcXdciCoreInit (
- IN USB_DEV_CONFIG_PARAMS *ConfigParams,
- IN VOID *ParentHandle,
- IN VOID **CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreDeinit (
- IN VOID *CoreHandle,
- IN UINT32 flags
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreRegisterCallback (
- IN VOID *CoreHandle,
- IN USB_DEVICE_EVENT_ID Event,
- IN USB_DEVICE_CALLBACK_FUNC CallbackFunc
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreUnregisterCallback (
- IN VOID *CoreHandle,
- IN USB_DEVICE_EVENT_ID Event
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreIsrRoutine (
- IN VOID *CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreIsrRoutineTimerBased (
- IN VOID *CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreConnect (
- IN VOID *CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreDisconnect (
- IN VOID *CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreGetSpeed (
- IN VOID *CoreHandle,
- IN USB_SPEED *Speed
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreSetAddress (
- IN VOID *CoreHandle,
- IN UINT32 Address
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciCoreSetConfig (
- IN VOID *CoreHandle,
- IN UINT32 ConfigNum
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciSetLinkState (
- IN VOID *CoreHandle,
- IN USB_DEVICE_SS_LINK_STATE State
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciInitEp (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpEnable (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpDisable (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpStall (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpClearStall (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpSetNrdy (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEp0ReceiveSetupPkt (
- IN VOID *CoreHandle,
- IN UINT8 *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEp0ReceiveStatusPkt (
- IN VOID *CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEp0SendStatusPkt (
- IN VOID *CoreHandle
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpTxData (
- IN VOID *CoreHandle,
- IN USB_XFER_REQUEST *XferReq
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpRxData(
- IN VOID *CoreHandle,
- IN USB_XFER_REQUEST *XferReq
- );
-
-EFI_STATUS
-EFIAPI
-DwcXdciEpCancelTransfer (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-usbProcessDeviceResetDet (
- IN XDCI_CORE_HANDLE *CoreHandle
- );
-
-EFI_STATUS
-usbProcessDeviceResetDone (
- IN XDCI_CORE_HANDLE *CoreHandle
- );
-
-UINT32
-UsbGetPhysicalEpNum (
- IN UINT32 EndpointNum,
- IN USB_EP_DIR EndpointDir
- );
-
-UINT32
-UsbRegRead (
- IN UINT32 Base,
- IN UINT32 Offset
- );
-
-VOID
-UsbRegWrite (
- IN UINT32 Base,
- IN UINT32 Offset,
- IN UINT32 val
- );
-
-EFI_STATUS
-UsbXdciCoreFlushEpFifo (
- IN VOID *CoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-#endif
-
+/** @file
+ Copyright (c) 2006 - 2017, 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.
+
+**/
+
+#ifndef _XDCI_DWC_H_
+#define _XDCI_DWC_H_
+
+#include "XdciCommon.h"
+#include "XdciDevice.h"
+#include "protocol/UsbDeviceLib.h"
+
+#define DWC_XDCI_MAX_ENDPOINTS (16)
+#define DWC_XDCI_SS_CTRL_EP_MPS (512)
+#define DWC_XDCI_HS_CTRL_EP_MPS (64)
+#define DWC_XDCI_FS_CTRL_EP_MPS (64)
+#define DWC_XDCI_LS_CTRL_EP_MPS (8)
+#define DWC_XDCI_SS_CTRL_BUF_SIZE (512)
+#define DWC_XDCI_SETUP_BUFF_SIZE (8)
+#define DWC_XDCI_MAX_EVENTS_PER_BUFFER (16)
+#define DWC_XDCI_TRB_BYTE_ALIGNMENT (16)
+#define DWC_XDCI_DEFAULT_TX_FIFO_SIZE (1024)
+#define DWC_XDCI_TRB_NUM (32)
+#define DWC_XDCI_MASK (DWC_XDCI_TRB_NUM - 1)
+
+/* TODO: Platform-specific define. Later move it to platform-specific
+ * header file
+ * */
+#define DWC_XDCI_MAX_DELAY_ITERATIONS (1000)
+
+/* Top-level register offsets from base address */
+#define DWC_XDCI_GLOBAL_REG_OFFSET (0xC100)
+#define DWC_XDCI_DEVICE_REG_OFFSET (0xC700)
+#define DWC_XDCI_OTG_BC_REG_OFFSET (0xCC00)
+#define DWC_XDCI_GSBUSCFG0_REG (0xC100)
+#define DWC_XDCI_GSBUSCFG1_REG (0xC104)
+#define DWC_XDCI_GTXTHRCFG_REG (0xC108)
+#define DWC_XDCI_GRXTHRCFG_REG (0xC10C)
+
+//
+// Global Control Register and bit definitions
+//
+#define DWC_XDCI_GCTL_REG (0xC110)
+#define DWC_XDCI_GCTL_PWRDNSCALE_MASK (0xFFF80000)
+#define DWC_XDCI_GCTL_PWRDNSCALE_VAL (0x13880000)
+#define DWC_XDCI_GCTL_U2RSTECN_MASK (0x00010000)
+#define DWC_XDCI_GCTL_PRT_CAP_DIR_MASK (0x00003000)
+#define DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS (12)
+#define DWC_XDCI_GCTL_PRT_CAP_HOST (1)
+#define DWC_XDCI_GCTL_PRT_CAP_DEVICE (2)
+#define DWC_XDCI_GCTL_PRT_CAP_OTG (3)
+#define DWC_XDCI_GCTL_RAMCLKSEL_MASK (0x000000C0)
+#define DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK (0x00000030)
+#define DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK (0x00000001)
+#define DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK (0x00000008)
+
+#define DWC_XDCI_GSTS_REG (0xC118)
+#define DWC_XDCI_GSNPSID_REG (0xC120)
+#define DWC_XDCI_GGPIO_REG (0xC124)
+#define DWC_XDCI_GUID_REG (0xC128)
+#define DWC_XDCI_GUCTL_REG (0xC12C)
+#define DWC_XDCI_GBUSERRADDR (0xC130)
+
+//
+// Global Hardware Parameters Registers
+//
+#define DWC_XDCI_GHWPARAMS0_REG (0xC140)
+#define DWC_XDCI_GHWPARAMS1_REG (0xC144)
+#define DWC_XDCI_GHWPARAMS1_NUM_INT_MASK (0x1F8000)
+#define DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS (15)
+
+#define DWC_XDCI_GHWPARAMS2_REG (0xC148)
+#define DWC_XDCI_GHWPARAMS3_REG (0xC14C)
+#define DWC_XDCI_GHWPARAMS4_REG (0xC150)
+#define DWC_XDCI_GHWPARAMS4_CACHE_TRBS_PER_XFER_MASK (0x0000003F)
+#define DWC_XDCI_GHWPARAMS5_REG (0xC154)
+#define DWC_XDCI_GHWPARAMS6_REG (0xC158)
+#define DWC_XDCI_GHWPARAMS7_REG (0xC15C)
+#define DWC_XDCI_GHWPARAMS8_REG (0xC600)
+
+#define DWC_XDCI_GDBGFIFOSPACE_REG (0xC160)
+
+#define DWC_XDCI_GUSB2PHYCFG_REG(n) (0xC200 + (n << 2))
+#define DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK (0x00008000)
+#define DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK (0x00000040)
+
+#define DWC_XDCI_GUSB3PIPECTL_REG(n) (0xC2C0 + (n << 2))
+#define DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK (0x00020000)
+
+#define DWC_XDCI_GTXFIFOSIZ_REG(n) (0xC300 + (n << 2))
+#define DWC_XDCI_GTXFIFOSIZ_START_ADDRESS_MASK (0xFFFF0000)
+#define DWC_XDCI_GTXFIFOSIZ_START_ADDRESS_BIT_POS (16)
+#define DWC_XDCI_GRXFIFOSIZ_REG(n) (0xC380 + (n << 2))
+
+//
+// Global Event Buffer Registers
+//
+#define DWC_XDCI_GEVNTADR_REG(n) (0xC400 + (n << 4))
+#define DWC_XDCI_EVNTSIZ_REG(n) (0xC408 + (n << 4))
+#define DWC_XDCI_EVNTSIZ_MASK (0x0000FFFF)
+#define DWC_XDCI_EVNT_INTR_MASK (0x80000000)
+#define DWC_XDCI_EVNTCOUNT_REG(n) (0xC40C + (n << 4))
+#define DWC_XDCI_EVNTCOUNT_MASK (0x0000FFFF)
+
+//
+// Device Configuration Register and Bit Definitions
+//
+#define DWC_XDCI_DCFG_REG (0xC700)
+#define DWC_XDCI_DCFG_LPM_CAPABLE_MASK (0x00400000)
+#define DWC_XDCI_DCFG_DEV_ADDRESS_MASK (0x000003F8)
+#define DWC_XDCI_DCFG_DEV_ADDRESS_BIT_POS (3)
+#define DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK (0x00000007)
+#define DWC_XDCI_DCFG_DESIRED_SS_SPEED (0x00000004)
+#define DWC_XDCI_DCFG_DESIRED_FS_SPEED (0x00000001)
+#define DWC_XDCI_DCFG_DESIRED_HS_SPEED (0x00000000)
+
+//
+// Device Control Register
+//
+#define DWC_XDCI_DCTL_REG (0xC704)
+#define DWC_XDCI_DCTL_RUN_STOP_MASK (0x80000000)
+#define DWC_XDCI_DCTL_RUN_STOP_BIT_POS (31)
+#define DWC_XDCI_DCTL_CSFTRST_MASK (0x40000000)
+#define DWC_XDCI_DCTL_CSFTRST_BIT_POS (30)
+#define DWC_XDCI_DCTL_KEEP_CONNECT_MASK (0x00080000)
+#define DWC_XDCI_DCTL_KEEP_CONNECT_BIT_POS (19)
+#define DWC_XDCI_DCTL_CSFTRST_BIT_POS (30)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK (0x000001E0)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS (5)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_NO_ACTION (1)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_SS_DISABLED (4)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT (5)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_SS_INACTIVE (6)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_RECOVERY (8)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_COMPLIANCE (10)
+#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_REMOTE_WAKEUP (8)
+
+//
+// Device Event Enable Register
+//
+#define DWC_XDCI_DEVTEN_REG (0xC708)
+#define DWC_XDCI_DEVTEN_DISCONN_DET_EN_MASK (0x00000001)
+#define DWC_XDCI_DEVTEN_RESET_DET_EN_MASK (0x00000002)
+#define DWC_XDCI_DEVTEN_CONN_DONE_DET_EN_MASK (0x00000004)
+#define DWC_XDCI_DEVTEN_LINK_STATE_CHANGE_DET_EN_MASK (0x00000008)
+#define DWC_XDCI_DEVTEN_RESUME_WAKEUP_DET_EN_MASK (0x00000010)
+#define DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK (0x00000020)
+#define DWC_XDCI_DEVTEN_U3L2L1_DET_EN_MASK (0x00000040)
+#define DWC_XDCI_DEVTEN_SOF_DET_EN_MASK (0x00000080)
+#define DWC_XDCI_DEVTEN_ERRATIC_ERR_DET_EN_MASK (0x00000200)
+#define DWC_XDCI_DEVTEN_VNDR_DEV_TST_RX_DET_EN_MASK (0x00001000)
+
+#define DWC_XDCI_DEVTEN_DEVICE_INTS (DWC_XDCI_DEVTEN_DISCONN_DET_EN_MASK | \
+ DWC_XDCI_DEVTEN_RESET_DET_EN_MASK | DWC_XDCI_DEVTEN_CONN_DONE_DET_EN_MASK | \
+ DWC_XDCI_DEVTEN_LINK_STATE_CHANGE_DET_EN_MASK | DWC_XDCI_DEVTEN_RESUME_WAKEUP_DET_EN_MASK | \
+ DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK | DWC_XDCI_DEVTEN_U3L2L1_DET_EN_MASK | \
+ DWC_XDCI_DEVTEN_ERRATIC_ERR_DET_EN_MASK)
+
+#define DWC_XDCI_EVENT_BUFF_BULK_STREAM_ID_MASK (0xFFFF0000)
+#define DWC_XDCI_EVENT_BUFF_ISOCH_UFRAME_NUM_MASK (0xFFFF0000)
+#define DWC_XDCI_EVENT_BUFF_EP_CMD_TYPE_MASK (0x0F000000)
+#define DWC_XDCI_EVENT_BUFF_EP_XFER_RES_INDEX_MASK (0x007F0000)
+#define DWC_XDCI_EVENT_BUFF_EP_XFER_ACTIVE_MASK (0x00008000)
+#define DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK (0x00001000)
+#define DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK (0x00002000)
+#define DWC_XDCI_EVENT_BUFF_EP_LST_MASK (0x00008000)
+#define DWC_XDCI_EVENT_BUFF_EP_MISSED_ISOCH_MASK (0x00008000)
+#define DWC_XDCI_EVENT_BUFF_EP_IOC_MASK (0x00004000)
+#define DWC_XDCI_EVENT_BUFF_EP_LAST_PKT_MASK (0x00002000)
+#define DWC_XDCI_EVENT_BUFF_EP_STREAM_NOT_FND_MASK (0x00002000)
+#define DWC_XDCI_EVENT_BUFF_EP_STREAM_FND_MASK (0x00001000)
+#define DWC_XDCI_EVENT_BUFF_EP_ERR_NO_RES_MASK (0x00001000)
+#define DWC_XDCI_EVENT_BUFF_EP_INVALID_RES_MASK (0x00001000)
+
+#define DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK (0x000003C0)
+#define DWC_XDCI_EVENT_BUFF_EP_EVENT_BIT_POS (6)
+#define DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT (1)
+#define DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS (2)
+#define DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY (3)
+#define DWC_XDCI_EVENT_BUFF_EP_STREAM_EVENT (6)
+#define DWC_XDCI_EVENT_BUFF_EP_CMD_CMPLT (7)
+
+#define DWC_XDCI_EVENT_BUFF_EP_NUM_MASK (0x0000003E)
+#define DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS (1)
+
+#define DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK (0x0000F000)
+
+
+#define DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK (0x01E00000)
+#define DWC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS (21)
+#define DWC_XDCI_EVENT_BUFF_DEV_SS_EVENT_MASK (0x00100000)
+#define DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_MASK (0x000F0000)
+#define DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS (16)
+
+#define DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK (0x00000F00)
+#define DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS (8)
+#define DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT (12)
+#define DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT (11)
+#define DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT (10)
+#define DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT (9)
+#define DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT (7)
+#define DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT (5)
+#define DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT (4)
+#define DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT (3)
+#define DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT (2)
+#define DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT (1)
+#define DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT (0)
+
+#define DWC_XDCI_EVENT_DEV_MASK (0x00000001)
+
+//
+// Device Status Register and Bit Definitions
+//
+#define DWC_XDCI_DSTS_REG (0xC70C)
+#define DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK (0x00400000)
+#define DWC_XDCI_DSTS_DEV_CTRL_HALTED_BIT_POS (22)
+#define DWC_XDCI_DSTS_CORE_IDLE (1 << 23)
+#define DWC_XDCI_DSTS_CONN_SPEED_MASK (0x00000007)
+#define DWC_XDCI_DSTS_LINK_STATE_MASK (0x003C0000)
+#define DWC_XDCI_DSTS_LINK_STATE_DISCONNECT (0x00100000)
+
+//
+// Device Generic Command Parameter Register
+//
+#define DWC_XDCI_DGCMD_PARAM_REG (0xC710)
+#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK (0x0000001F)
+#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK (0x00000020)
+#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_BIT_POS (5)
+
+//
+// Device Generic Command Register
+//
+#define DWC_XDCI_DGCMD_REG (0xC714)
+#define DWC_XDCI_DGCMD_CMD_STATUS_MASK (0x00008000)
+#define DWC_XDCI_DGCMD_CMD_ACTIVE_MASK (0x00000400)
+#define DWC_XDCI_DGCMD_CMD_IOC_MASK (0x00000100)
+#define DWC_XDCI_DGCMD_CMD_TYPE_MASK (0x000000FF)
+#define DWC_XDCI_DGCMD_CMD_SET_PERIODIC_PARAMS (0x2)
+#define DWC_XDCI_DGCMD_CMD_SET_SCRATCH_PAD_BUFF_ARR_LO (0x4)
+#define DWC_XDCI_DGCMD_CMD_SET_SCRATCH_PAD_BUFF_ARR_HI (0x5)
+#define DWC_XDCI_DGCMD_CMD_XMIT_DEVICE_NOTIFICATION (0x7)
+#define DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH (0x9)
+#define DWC_XDCI_DGCMD_CMD_ALL_FIFO_FLUSH (0xA)
+#define DWC_XDCI_DGCMD_CMD_SET_EP_NRDY (0xC)
+#define DWC_XDCI_DGCMD_CMD_RUN_SOC_BUS_LPBK (0x10)
+
+//
+// Device Active USB EP Enable Register
+//
+#define DWC_XDCI_EP_DALEPENA_REG (0xC720)
+
+//
+// Device Physical EP CMD Param 2 Register. Value is 32-bit
+//
+#define DWC_XDCI_EPCMD_PARAM2_REG(n) (0xC800 + (n << 4))
+
+//
+// Device Physical EP CMD Param 1 Register. Value is 32-bit
+//
+#define DWC_XDCI_EPCMD_PARAM1_REG(n) (0xC804 + (n << 4))
+
+//
+// Device Physical EP CMD Param 0 Register. Value is 32-bit
+//
+#define DWC_XDCI_EPCMD_PARAM0_REG(n) (0xC808 + (n << 4))
+
+//
+// Device Physical EP Command Registers and Bit Definitions
+//
+#define DWC_XDCI_EPCMD_REG(n) (0xC80C + (n << 4))
+#define DWC_XDCI_EPCMD_RES_IDX_MASK (0x007F0000)
+#define DWC_XDCI_EPCMD_RES_IDX_BIT_POS (16)
+#define DWC_XDCI_EPCMD_CMDTYPE_MASK (0x0000000F)
+#define DWC_XDCI_EPCMD_SET_EP_CONFIG (0x1)
+#define DWC_XDCI_EPCMD_SET_EP_XFER_RES_CONFIG (0x2)
+#define DWC_XDCI_EPCMD_GET_EP_STATE (0x3)
+#define DWC_XDCI_EPCMD_SET_STALL (0x4)
+#define DWC_XDCI_EPCMD_CLEAR_STALL (0x5)
+#define DWC_XDCI_EPCMD_START_XFER (0x6)
+#define DWC_XDCI_EPCMD_UPDATE_XFER (0x7)
+#define DWC_XDCI_EPCMD_END_XFER (0x8)
+#define DWC_XDCI_EPCMD_START_NEW_CONFIG (0x9)
+
+#define DWC_XDCI_EPCMD_CMD_IOC_MASK (0x00000100)
+#define DWC_XDCI_EPCMD_CMD_ACTIVE_MASK (0x00000400)
+#define DWC_XDCI_EPCMD_HIGH_PRIO_MASK (0x00000800)
+#define DWC_XDCI_EPCMD_FORCE_RM_MASK (0x00000800)
+
+//
+// Command status and parameter values same as event status and parameters values
+//
+#define DWC_XDCI_EPCMD_CMD_STATUS_MASK (0x0000F000)
+
+//
+// Command Params bit masks
+//
+#define DWC_XDCI_PARAM1_SET_EP_CFG_FIFO_BASED_MASK (0x80000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_BULK_BASED_MASK (0x40000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_MASK (0x3C000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_MASK (0x02000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK (0x01000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_MASK (0x00FF0000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS (16)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EBC_MASK (0x00008000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK (0x00003F00)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_BIT_POS (8)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_STRM_MASK (0x00002000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK (0x00000400)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK (0x00000200)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK (0x00000100)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK (0x0000001F)
+
+//
+// CMD 1 param 0
+//
+#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK (0xC0000000)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_BIT_POS (30)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE (0)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_RESTORE_ST (1)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE (2)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE (3)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK (0x03C00000)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_BIT_POS (22)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK (0x003E0000)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_BIT_POS (17)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK (0x00003FF8)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_MPS_BIT_POS (3)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK (0x00000006)
+#define DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_BIT_POS (1)
+#define DWC_XDCI_PARAM0_EP_TYPE_CTRL (0)
+#define DWC_XDCI_PARAM0_EP_TYPE_ISOCH (1)
+#define DWC_XDCI_PARAM0_EP_TYPE_BULK (2)
+#define DWC_XDCI_PARAM0_EP_TYPE_INTR (3)
+
+//
+// CMD 1 param 1
+//
+#define DWC_XDCI_PARAM1_SET_EP_CFG_BULK_BASED_MASK (0x40000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_MASK (0x3C000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_BIT_POS (26)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_MASK (0x02000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_BIT_POS (25)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK (0x01000000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_MASK (0x00FF0000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS (16)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EBC_MASK (0x00008000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK (0x00003F00)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_BIT_POS (8)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_STRM_MASK (0x00002000)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK (0x00000400)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK (0x00000200)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK (0x00000100)
+#define DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK (0x0000001F)
+
+//
+// CMD 2 param 0
+//
+#define DWC_XDCI_PARAM0_SET_EP_XFER_RES_NUM_MASK (0x0000FFFF)
+
+//
+// CMD 3 param 2
+//
+#define DWC_XDCI_PARAM2_GET_EP_STATE_MASK (0xFFFFFFFF)
+
+//
+// CMD 6 param 1
+//
+#define DWC_XDCI_PARAM1_STRT_XFER_TD_ADDR_LO_MASK (0xFFFFFFFF)
+
+//
+// CMD 6 param 0
+//
+#define DWC_XDCI_PARAM0_STRT_XFER_TD_ADDR_HI_MASK (0xFFFFFFFF)
+
+//
+// Transfer Request Block Fields' Bit Definitions
+//
+#define DWC_XDCI_TRB_BUFF_SIZE_MASK (0x00FFFFFF)
+#define DWC_XDCI_TRB_PCM1_MASK (0x03000000)
+#define DWC_XDCI_TRB_PCM1_BIT_POS (24)
+#define DWC_XDCI_TRB_STATUS_MASK (0xF0000000)
+#define DWC_XDCI_TRB_STATUS_BIT_POS (28)
+#define DWC_XDCI_TRB_STATUS_OK (0)
+#define DWC_XDCI_TRB_STATUS_MISSED_ISOCH (1)
+#define DWC_XDCI_TRB_STATUS_SETUP_PENDING (2)
+
+#define DWC_XDCI_TRB_CTRL_HWO_MASK (0x00000001)
+#define DWC_XDCI_TRB_CTRL_LST_TRB_MASK (0x00000002)
+#define DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS (1)
+#define DWC_XDCI_TRB_CTRL_CHAIN_BUFF_MASK (0x00000004)
+#define DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS (2)
+#define DWC_XDCI_TRB_CTRL_CSP_MASK (0x00000008)
+#define DWC_XDCI_TRB_CTRL_CSP_BIT_POS (3)
+#define DWC_XDCI_TRB_CTRL_TYPE_MASK (0x000003F0)
+#define DWC_XDCI_TRB_CTRL_TYPE_BIT_POS (4)
+#define DWC_XDCI_TRB_CTRL_TYPE_NORMAL (1)
+#define DWC_XDCI_TRB_CTRL_TYPE_SETUP (2)
+#define DWC_XDCI_TRB_CTRL_TYPE_STATUS2 (3)
+#define DWC_XDCI_TRB_CTRL_TYPE_STATUS3 (4)
+#define DWC_XDCI_TRB_CTRL_TYPE_DATA (5)
+#define DWC_XDCI_TRB_CTRL_TYPE_ISOCH_FIRST (6)
+#define DWC_XDCI_TRB_CTRL_TYPE_ISOCH (7)
+#define DWC_XDCI_TRB_CTRL_TYPE_LINK_TRB (8)
+#define DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK (0x00000400)
+#define DWC_XDCI_TRB_CTRL_IOSP_MISOCH_BIT_POS (10)
+#define DWC_XDCI_TRB_CTRL_IOC_MASK (0x00000800)
+#define DWC_XDCI_TRB_CTRL_IOC_BIT_POS (11)
+#define DWC_XDCI_TRB_CTRL_STRM_ID_SOF_NUM_MASK (0x3FFFC000)
+#define DWC_XDCI_TRB_CTRL_STRM_ID_SOF_BIT_POS (14)
+
+#define DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES (4)
+#define DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES (12)
+
+typedef enum {
+ EPCMD_SET_EP_CONFIG = 1,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ EPCMD_GET_EP_STATE,
+ EPCMD_SET_STALL,
+ EPCMD_CLEAR_STALL,
+ EPCMD_START_XFER,
+ EPCMD_UPDATE_XFER,
+ EPCMD_END_XFER,
+ EPCMD_START_NEW_CONFIG = 9
+} DWC_XDCI_ENDPOINT_CMD;
+
+typedef enum {
+ ON = 0,
+ SLEEP = 2,
+ SUSPEND,
+ DISCONNECTED,
+ EARLY_SUSPEND,
+ RESET = 14,
+ RESUME = 15
+} DWC_XDCI_HS_LINK_STATE;
+
+typedef enum {
+ TRBCTL_NORMAL = 1,
+ TRBCTL_SETUP,
+ TRBCTL_2_PHASE,
+ TRBCTL_3_PHASE,
+ TRBCTL_CTRL_DATA_PHASE,
+ TRBCTL_ISOCH_FIRST,
+ TRBCTL_ISOCH,
+ TRBCTL_LINK
+} DWC_XDCI_TRB_CONTROL;
+
+//
+#pragma pack (1)
+// DWC XDCI Endpoint Commands Parameters struct
+//
+typedef struct {
+ UINT32 Param2;
+ UINT32 Param1;
+ UINT32 Param0;
+} DWC_XDCI_ENDPOINT_CMD_PARAMS;
+
+//
+// Event Buffer Struct
+//
+typedef struct {
+ UINT32 Event;
+ UINT32 DevTstLmp1;
+ UINT32 DevTstLmp2;
+ UINT32 Reserved;
+} DWC_XDCI_EVENT_BUFFER;
+
+//
+// Transfer Request Block
+//
+typedef struct {
+ UINT32 BuffPtrLow;
+ UINT32 BuffPtrHigh;
+ UINT32 LenXferParams;
+ UINT32 TrbCtrl;
+} DWC_XDCI_TRB;
+
+typedef struct {
+ USB_EP_INFO EpInfo;
+ DWC_XDCI_TRB *Trb;
+ USB_XFER_REQUEST XferHandle;
+ UINT32 CurrentXferRscIdx;
+ VOID *CoreHandle;
+ USB_EP_STATE State;
+ USB_EP_STATE OrgState;
+ BOOLEAN CheckFlag;
+} DWC_XDCI_ENDPOINT;
+#pragma pack ()
+
+typedef struct {
+ //
+ // CbEventParams must be copied over by upper layer if
+ // it defers event processing
+ //
+ USB_DEVICE_CALLBACK_PARAM CbEventParams;
+
+ //
+ // Callback function list
+ //
+ USB_DEVICE_CALLBACK_FUNC DevDisconnectCallback;
+ USB_DEVICE_CALLBACK_FUNC DevBusResetCallback;
+ USB_DEVICE_CALLBACK_FUNC DevResetDoneCallback;
+ USB_DEVICE_CALLBACK_FUNC DevLinkStateCallback;
+ USB_DEVICE_CALLBACK_FUNC DevWakeupCallback;
+ USB_DEVICE_CALLBACK_FUNC DevHibernationCallback;
+ USB_DEVICE_CALLBACK_FUNC DevSofCallback;
+ USB_DEVICE_CALLBACK_FUNC DevErraticErrCallback;
+ USB_DEVICE_CALLBACK_FUNC DevCmdCmpltCallback;
+ USB_DEVICE_CALLBACK_FUNC DevBuffOvflwCallback;
+ USB_DEVICE_CALLBACK_FUNC DevTestLmpRxCallback;
+ USB_DEVICE_CALLBACK_FUNC DevSetupPktReceivedCallback;
+ USB_DEVICE_CALLBACK_FUNC DevXferNrdyCallback;
+ USB_DEVICE_CALLBACK_FUNC DevXferDoneCallback;
+} USB_DEV_CALLBACK_LIST;
+
+typedef struct {
+ VOID *ParentHandle; // Pointer to the parent this driver is associated
+ USB_CONTROLLER_ID Id; // ID of the controllers supported in our DCD
+ USB_SPEED DesiredSpeed; // Desired SS, HS, FS or LS Speeds for the core
+ USB_ROLE Role; // Desired role i.e. host, Device or OTG
+ USB_SPEED ActualSpeed; // Actual Speed
+ USB_DEVICE_STATE DevState; // Device state
+ UINTN BaseAddress; // Register Base address
+ UINT32 Flags; // Init flags
+ UINT32 MaxDevIntLines; // One event Buffer per interrupt line
+ DWC_XDCI_EVENT_BUFFER EventBuffers [DWC_XDCI_MAX_EVENTS_PER_BUFFER * 2]; // Event Buffer pool
+ DWC_XDCI_EVENT_BUFFER *AlignedEventBuffers; // Aligned event Buffer pool
+ DWC_XDCI_EVENT_BUFFER *CurrentEventBuffer; // Current event Buffer address
+ DWC_XDCI_TRB UnalignedTrbs [(DWC_XDCI_MAX_ENDPOINTS + 1) * DWC_XDCI_TRB_NUM]; // TRBs.
+ DWC_XDCI_TRB *Trbs; // 16-bytes aligned TRBs.
+ DWC_XDCI_ENDPOINT EpHandles [DWC_XDCI_MAX_ENDPOINTS * 2]; // EPs, diretion in and out for each EP
+ UINT8 DefaultSetupBuffer [DWC_XDCI_SETUP_BUFF_SIZE * 2]; // Unaligned setup Buffer
+ UINT8 *AlignedSetupBuffer; // Aligned setup Buffer. Aligned to 8-byte boundary
+ UINT8 MiscBuffer [528]; // Unaligned misc Buffer
+ UINT8 *AlignedMiscBuffer; // Aligned misc Buffer
+ UINT32 LinkState; // Link state
+ UINT32 HirdVal; // HIRD value
+ USB_DEV_CALLBACK_LIST EventCallbacks;
+ volatile BOOLEAN InterrupProcessing;
+} XDCI_CORE_HANDLE;
+
+//
+// DWC XDCI API prototypes
+//
+EFI_STATUS
+EFIAPI
+DwcXdciCoreInit (
+ IN USB_DEV_CONFIG_PARAMS *ConfigParams,
+ IN VOID *ParentHandle,
+ IN VOID **CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreDeinit (
+ IN VOID *CoreHandle,
+ IN UINT32 flags
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreRegisterCallback (
+ IN VOID *CoreHandle,
+ IN USB_DEVICE_EVENT_ID Event,
+ IN USB_DEVICE_CALLBACK_FUNC CallbackFunc
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreUnregisterCallback (
+ IN VOID *CoreHandle,
+ IN USB_DEVICE_EVENT_ID Event
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreIsrRoutine (
+ IN VOID *CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreIsrRoutineTimerBased (
+ IN VOID *CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreConnect (
+ IN VOID *CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreDisconnect (
+ IN VOID *CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreGetSpeed (
+ IN VOID *CoreHandle,
+ IN USB_SPEED *Speed
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreSetAddress (
+ IN VOID *CoreHandle,
+ IN UINT32 Address
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciCoreSetConfig (
+ IN VOID *CoreHandle,
+ IN UINT32 ConfigNum
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciSetLinkState (
+ IN VOID *CoreHandle,
+ IN USB_DEVICE_SS_LINK_STATE State
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciInitEp (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpEnable (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpDisable (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpStall (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpClearStall (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpSetNrdy (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEp0ReceiveSetupPkt (
+ IN VOID *CoreHandle,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEp0ReceiveStatusPkt (
+ IN VOID *CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEp0SendStatusPkt (
+ IN VOID *CoreHandle
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpTxData (
+ IN VOID *CoreHandle,
+ IN USB_XFER_REQUEST *XferReq
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpRxData(
+ IN VOID *CoreHandle,
+ IN USB_XFER_REQUEST *XferReq
+ );
+
+EFI_STATUS
+EFIAPI
+DwcXdciEpCancelTransfer (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+usbProcessDeviceResetDet (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ );
+
+EFI_STATUS
+usbProcessDeviceResetDone (
+ IN XDCI_CORE_HANDLE *CoreHandle
+ );
+
+UINT32
+UsbGetPhysicalEpNum (
+ IN UINT32 EndpointNum,
+ IN USB_EP_DIR EndpointDir
+ );
+
+UINT32
+UsbRegRead (
+ IN UINTN Base,
+ IN UINT32 Offset
+ );
+
+VOID
+UsbRegWrite (
+ IN UINTN Base,
+ IN UINT32 Offset,
+ IN UINT32 val
+ );
+
+EFI_STATUS
+UsbXdciCoreFlushEpFifo (
+ IN VOID *CoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+#endif
+
diff --git a/libefiusb/device_mode/XdciDevice.h b/libefiusb/device_mode/XdciDevice.h
index aee6bdef..3ea139ba 100644
--- a/libefiusb/device_mode/XdciDevice.h
+++ b/libefiusb/device_mode/XdciDevice.h
@@ -1,184 +1,184 @@
-/** @file
- Copyright (c) 2006 - 2017, 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.
-
-**/
-
-#ifndef _USB_DEVICE_H_
-#define _USB_DEVICE_H_
-
-//
-// @USB_DEV_CONFIG_PARAMS: Struct to be filled in with configuration
-// parameters and passed to the init routine for device controller
-//
-typedef struct {
- USB_CONTROLLER_ID ControllerId; // Controller ID of the core
- UINT32 BaseAddress; // Base address of the controller registers and on-chip memory
- UINT32 Flags; // Initialization flags
- USB_SPEED Speed; // Desired USB bus Speed
- USB_ROLE Role; // Default USB role
-} USB_DEV_CONFIG_PARAMS;
-
-//
-// @USB_DEV_CORE: Struct used as a handle for all
-// hardware-independent APIs
-//
-typedef struct {
- const struct UsbDeviceCoreDriver *CoreDriver;
- VOID *ControllerHandle;
-} USB_DEV_CORE;
-
-typedef
-EFI_STATUS
-(EFIAPI *USB_DEVICE_CALLBACK_FUNC) (
- IN USB_DEVICE_CALLBACK_PARAM *Param
- );
-
-EFI_STATUS
-UsbDeviceInit (
- IN USB_DEV_CONFIG_PARAMS *ConfigParams,
- IN OUT VOID **DevCoreHandle
- );
-
-EFI_STATUS
-UsbDeviceDeinit (
- IN VOID *DevCoreHandle,
- IN UINT32 Flags
- );
-
-EFI_STATUS
-UsbDeviceRegisterCallback (
- IN VOID *DevCoreHandle,
- IN USB_DEVICE_EVENT_ID EventId,
- IN USB_DEVICE_CALLBACK_FUNC CallbackFunc
- );
-
-EFI_STATUS
-UsbDeviceUnregisterCallback (
- IN VOID *DevCoreHandle,
- IN USB_DEVICE_EVENT_ID EventId
- );
-
-EFI_STATUS
-UsbDeviceIsrRoutine (
- IN VOID *DevCoreHandle
- );
-
-EFI_STATUS
-UsbDeviceIsrRoutineTimerBased (
- IN VOID *DevCoreHandle
- );
-
-EFI_STATUS
-UsbXdciDeviceConnect (
- IN VOID *DevCoreHandle
- );
-
-EFI_STATUS
-UsbDeviceDisconnect (
- IN VOID *DevCoreHandle
- );
-
-EFI_STATUS
-UsbDeviceGetSpeed (
- IN VOID *DevCoreHandle,
- IN USB_SPEED *Speed
- );
-
-EFI_STATUS
-UsbDeviceSetLinkState (
- IN VOID *DevCoreHandle,
- IN USB_DEVICE_SS_LINK_STATE State
- );
-
-EFI_STATUS
-UsbDeviceSetAddress (
- IN VOID *DevCoreHandle,
- IN UINT32 Address
- );
-
-EFI_STATUS
-UsbDeviceSetConfiguration (
- IN VOID *DevCoreHandle,
- IN UINT32 ConfigNum
- );
-
-EFI_STATUS
-UsbDeviceInitEp (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-UsbDeviceEpEnable (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-UsbDeviceEpDisable (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-UsbDeviceEpStall (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-UsbDeviceEpClearStall (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-UsbDeviceEpSetNrdy (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-EFI_STATUS
-UsbDeviceEp0RxSetup (
- IN VOID *DevCoreHandle,
- IN UINT8 *Buffer
- );
-
-EFI_STATUS
-UsbDeviceEp0RxStatus (
- IN VOID *DevCoreHandle
- );
-
-EFI_STATUS
-UsbDeviceEp0TxStatus (
- IN VOID *DevCoreHandle
- );
-
-EFI_STATUS
-UsbXdciDeviceEpTxData (
- IN VOID *DevCoreHandle,
- IN USB_XFER_REQUEST *XferReq
- );
-
-EFI_STATUS
-UsbXdciDeviceEpRxData (
- IN VOID *DevCoreHandle,
- IN USB_XFER_REQUEST *XferReq
- );
-
-EFI_STATUS
-UsbDeviceEpCancelTransfer (
- IN VOID *DevCoreHandle,
- IN USB_EP_INFO *EpInfo
- );
-
-#endif
-
+/** @file
+ Copyright (c) 2006 - 2017, 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.
+
+**/
+
+#ifndef _USB_DEVICE_H_
+#define _USB_DEVICE_H_
+
+//
+// @USB_DEV_CONFIG_PARAMS: Struct to be filled in with configuration
+// parameters and passed to the init routine for device controller
+//
+typedef struct {
+ USB_CONTROLLER_ID ControllerId; // Controller ID of the core
+ UINT64 BaseAddress; // Base address of the controller registers and on-chip memory
+ UINT32 Flags; // Initialization flags
+ USB_SPEED Speed; // Desired USB bus Speed
+ USB_ROLE Role; // Default USB role
+} USB_DEV_CONFIG_PARAMS;
+
+//
+// @USB_DEV_CORE: Struct used as a handle for all
+// hardware-independent APIs
+//
+typedef struct {
+ const struct UsbDeviceCoreDriver *CoreDriver;
+ VOID *ControllerHandle;
+} USB_DEV_CORE;
+
+typedef
+EFI_STATUS
+(EFIAPI *USB_DEVICE_CALLBACK_FUNC) (
+ IN USB_DEVICE_CALLBACK_PARAM *Param
+ );
+
+EFI_STATUS
+UsbDeviceInit (
+ IN USB_DEV_CONFIG_PARAMS *ConfigParams,
+ IN OUT VOID **DevCoreHandle
+ );
+
+EFI_STATUS
+UsbDeviceDeinit (
+ IN VOID *DevCoreHandle,
+ IN UINT32 Flags
+ );
+
+EFI_STATUS
+UsbDeviceRegisterCallback (
+ IN VOID *DevCoreHandle,
+ IN USB_DEVICE_EVENT_ID EventId,
+ IN USB_DEVICE_CALLBACK_FUNC CallbackFunc
+ );
+
+EFI_STATUS
+UsbDeviceUnregisterCallback (
+ IN VOID *DevCoreHandle,
+ IN USB_DEVICE_EVENT_ID EventId
+ );
+
+EFI_STATUS
+UsbDeviceIsrRoutine (
+ IN VOID *DevCoreHandle
+ );
+
+EFI_STATUS
+UsbDeviceIsrRoutineTimerBased (
+ IN VOID *DevCoreHandle
+ );
+
+EFI_STATUS
+UsbXdciDeviceConnect (
+ IN VOID *DevCoreHandle
+ );
+
+EFI_STATUS
+UsbDeviceDisconnect (
+ IN VOID *DevCoreHandle
+ );
+
+EFI_STATUS
+UsbDeviceGetSpeed (
+ IN VOID *DevCoreHandle,
+ IN USB_SPEED *Speed
+ );
+
+EFI_STATUS
+UsbDeviceSetLinkState (
+ IN VOID *DevCoreHandle,
+ IN USB_DEVICE_SS_LINK_STATE State
+ );
+
+EFI_STATUS
+UsbDeviceSetAddress (
+ IN VOID *DevCoreHandle,
+ IN UINT32 Address
+ );
+
+EFI_STATUS
+UsbDeviceSetConfiguration (
+ IN VOID *DevCoreHandle,
+ IN UINT32 ConfigNum
+ );
+
+EFI_STATUS
+UsbDeviceInitEp (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+UsbDeviceEpEnable (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+UsbDeviceEpDisable (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+UsbDeviceEpStall (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+UsbDeviceEpClearStall (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+UsbDeviceEpSetNrdy (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+EFI_STATUS
+UsbDeviceEp0RxSetup (
+ IN VOID *DevCoreHandle,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+UsbDeviceEp0RxStatus (
+ IN VOID *DevCoreHandle
+ );
+
+EFI_STATUS
+UsbDeviceEp0TxStatus (
+ IN VOID *DevCoreHandle
+ );
+
+EFI_STATUS
+UsbXdciDeviceEpTxData (
+ IN VOID *DevCoreHandle,
+ IN USB_XFER_REQUEST *XferReq
+ );
+
+EFI_STATUS
+UsbXdciDeviceEpRxData (
+ IN VOID *DevCoreHandle,
+ IN USB_XFER_REQUEST *XferReq
+ );
+
+EFI_STATUS
+UsbDeviceEpCancelTransfer (
+ IN VOID *DevCoreHandle,
+ IN USB_EP_INFO *EpInfo
+ );
+
+#endif
+
diff --git a/libefiusb/device_mode/XdciUtility.c b/libefiusb/device_mode/XdciUtility.c
index 4fbe1d51..c0aece8d 100644
--- a/libefiusb/device_mode/XdciUtility.c
+++ b/libefiusb/device_mode/XdciUtility.c
@@ -16,6 +16,7 @@
#include
#include "XdciUtility.h"
+#include "UsbDeviceMode.h"
VOID
PrintDeviceDescriptor (
@@ -131,7 +132,7 @@ PrintDeviceRequest (
DEBUG ((DEBUG_INFO, "Length : 0x%x\n", DevReq->Length));
DEBUG ((DEBUG_INFO, "\n"));
}
-
+#ifdef SUPPORT_SUPER_SPEED
VOID
PrintBOSDescriptor (
IN __attribute__((unused)) EFI_USB_BOS_DESCRIPTOR *BosDesc
@@ -144,4 +145,4 @@ PrintBOSDescriptor (
DEBUG ((DEBUG_INFO, "NumDeviceCaps : 0x%x\n", BosDesc->NumDeviceCaps));
DEBUG ((DEBUG_INFO, "\n"));
}
-
+#endif
diff --git a/libefiusb/device_mode/XdciUtility.h b/libefiusb/device_mode/XdciUtility.h
index 4650f48e..2e7ac374 100644
--- a/libefiusb/device_mode/XdciUtility.h
+++ b/libefiusb/device_mode/XdciUtility.h
@@ -14,6 +14,7 @@
#ifndef _XDCI_UTILITY_H_
#define _XDCI_UTILITY_H_
+#include "XdciCommon.h"
#include "protocol/UsbDeviceLib.h"
VOID
@@ -51,10 +52,11 @@ PrintDeviceRequest (
IN EFI_USB_DEVICE_REQUEST *DevReq
);
+#ifdef SUPPORT_SUPER_SPEED
VOID
PrintBOSDescriptor (
IN EFI_USB_BOS_DESCRIPTOR *BosDesc
);
-
+#endif
#endif
diff --git a/libefiusb/device_mode/cpuio.c b/libefiusb/device_mode/cpuio.c
index 6a21fff1..971fd0ce 100644
--- a/libefiusb/device_mode/cpuio.c
+++ b/libefiusb/device_mode/cpuio.c
@@ -152,6 +152,7 @@ UINT32 MmioWrite32(UINTN add, UINT32 data)
efi_perror(ret, L"Fail to write data to 0x%x", add);
return 0xFFFFFFFF;
}
+ efi_perror(EFI_SUCCESS, L"write data 0x%x to 0x%016lx", data, add);
return data;
}
diff --git a/libefiusb/protocol/Usb.h b/libefiusb/protocol/Usb.h
old mode 100644
new mode 100755
index 299fb4cd..d25490b8
--- a/libefiusb/protocol/Usb.h
+++ b/libefiusb/protocol/Usb.h
@@ -139,6 +139,7 @@ typedef struct {
UINT8 Attributes;
UINT16 MaxPacketSize;
UINT8 Interval;
+/* for super speed, a companion descriptor follows */
} USB_ENDPOINT_DESCRIPTOR;
///
diff --git a/libefiusb/protocol/UsbDeviceLib.h b/libefiusb/protocol/UsbDeviceLib.h
old mode 100644
new mode 100755
index 83647b7c..9dbdffd8
--- a/libefiusb/protocol/UsbDeviceLib.h
+++ b/libefiusb/protocol/UsbDeviceLib.h
@@ -55,7 +55,7 @@
//
#define USB_BCD_VERSION_LS 0x0110
#define USB_BCD_VERSION_HS 0x0200
-#define USB_BCD_VERSION_SS 0x0300
+#define USB_BCD_VERSION_SS 0x0320
//
// Device RequestType Flags
@@ -89,8 +89,24 @@
//
// USB Descriptor types
//
-#define USB_DESC_TYPE_SS_ENDPOINT_COMPANION 0x30
#define USB_DESC_TYPE_BOS 0x0F
+#define USB_DESC_TYPE_DEVICE_CAPABILITY 0x10
+#define USB_DESC_TYPE_SS_ENDPOINT_COMPANION 0x30
+#pragma pack(1)
+
+#ifdef SUPPORT_SUPER_SPEED
+//
+// USB device capability Type Codes
+// USB3 Table 9-13
+//
+typedef enum {
+ WirelessUSB = 0x01,
+ USB2Extension,
+ SuperSpeedUSB,
+ ContainerID,
+ SuperSpeedPlusUSB = 0x0A
+} USB_DEVICE_CAP_TYPE_CODE;
+#endif
//
@@ -125,6 +141,7 @@ typedef struct {
//
// SuperSpeed Endpoint companion descriptor
+// USB3 table 9-22
//
typedef struct {
UINT8 Length;
@@ -174,7 +191,85 @@ typedef struct {
VOID *ConfigAll;
USB_DEVICE_INTERFACE_OBJ *InterfaceObjs;
} USB_DEVICE_CONFIG_OBJ;
-#pragma pack()
+
+#ifdef SUPPORT_SUPER_SPEED
+//
+// SuperSpeed Binary Device Object Store(BOS) descriptor
+// USB3 9.6.2
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT16 TotalLength;
+ UINT8 NumDeviceCaps;
+} EFI_USB_BOS_DESCRIPTOR;
+
+//
+// Generic Header of Device Capability descriptor
+// USB3 9.6.2.2
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 DevCapabilityType;
+ UINT8 CapDependent;
+} EFI_USB_SS_DEVICE_CAP_DESCRIPTOR;
+
+//
+// USB2.0 Extension descriptor
+// USB3 Table 9-14
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 DeviceCapabilityType;
+ UINT32 Attributes;
+} EFI_USB_USB2_EXT_CAP_DESCRIPTOR;
+
+
+//
+// SuperSpeed USB Device Capability descriptor
+// USB3 Table 9-15
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 DeviceCapabilityType;
+ UINT8 Attributes;
+ UINT16 SpeedSupported;
+ UINT8 FunctionalitySupport;
+ UINT8 U1DevExitLat;
+ UINT16 U2DevExitLat;
+} EFI_USB_SS_USB_DEV_CAP_DESCRIPTOR;
+
+//
+// Container ID descriptor
+// USB3 Table 9-16
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 DeviceCapabilityType;
+ UINT8 Reserved;
+ UINT8 UUID[16];
+} EFI_USB_CONTAINER_ID_DESCRIPTOR;
+
+//
+// Container ID descriptor
+// USB3 Table 9-16
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 DeviceCapabilityType;
+ UINT8 ReservedByte;
+ UINT32 Attributes;
+ UINT16 FunctionalitySupport;
+ UINT16 ReservedWord;
+ UINT32 SublinkSpeedAttr[2];
+} EFI_USB_SS_PLUS_USB_DEV_CAP_DESCRIPTOR;
+
+#endif
typedef
EFI_STATUS
@@ -192,16 +287,8 @@ EFI_STATUS
typedef
EFI_STATUS
(EFIAPI *EFI_USB_DATA_CALLBACK) (
- IN EFI_USB_DEVICE_XFER_INFO *XferInfo
- );
-
-#pragma pack(1)
-typedef struct {
- UINT8 Length;
- UINT8 DescriptorType;
- UINT16 TotalLength;
- UINT8 NumDeviceCaps;
-} EFI_USB_BOS_DESCRIPTOR;
+ IN EFI_USB_DEVICE_XFER_INFO *XferInfo
+ );
typedef struct {
USB_DEVICE_DESCRIPTOR *DeviceDesc;
diff --git a/libefiusb/usb.c b/libefiusb/usb.c
old mode 100644
new mode 100755
index 69d9b261..7ac37ec0
--- a/libefiusb/usb.c
+++ b/libefiusb/usb.c
@@ -44,17 +44,17 @@
#define CONFIG_COUNT 1
#define INTERFACE_COUNT 1
#define ENDPOINT_COUNT 2
-#define CFG_MAX_POWER 0x00 /* Max power consumption of
+#define CFG_MAX_POWER 100 /* Max power consumption of
the USB device from the bus
for this config */
-#define IF_SUBCLASS 0x00 /* Default subclass */
-#define IF_PROTOCOL 0x00 /* Default protocol */
+#define IF_SUBCLASS 66 /* Default subclass */
+#define IF_PROTOCOL 1 /* Default protocol */
#define IN_ENDPOINT_NUM 1
#define OUT_ENDPOINT_NUM 2
#define BULK_EP_PKT_SIZE USB_BULK_EP_PKT_SIZE_HS /* default to using high speed */
#define VENDOR_ID 0x8087 /* Intel Inc. */
#define PRODUCT_ID 0x09EF
-#define BCD_DEVICE 0x0100
+#define BCD_DEVICE 0
static data_callback_t rx_callback = NULL;
static data_callback_t tx_callback = NULL;
@@ -96,6 +96,7 @@ static USB_STRING_DESCRIPTOR string_table[] = {
};
/* Complete Configuration structure */
+#ifndef SUPPORT_SUPER_SPEED
struct config_descriptor {
EFI_USB_CONFIG_DESCRIPTOR config;
EFI_USB_INTERFACE_DESCRIPTOR interface;
@@ -131,7 +132,7 @@ static struct config_descriptor config_descriptor = {
IN_ENDPOINT_NUM | USB_ENDPOINT_DIR_IN,
USB_ENDPOINT_BULK,
BULK_EP_PKT_SIZE,
- 0x00 /* Not specified for bulk endpoint */
+ 0x00, /* Not specified for bulk endpoint */
},
.ep_out = {
sizeof(EFI_USB_ENDPOINT_DESCRIPTOR),
@@ -139,9 +140,10 @@ static struct config_descriptor config_descriptor = {
OUT_ENDPOINT_NUM | USB_ENDPOINT_DIR_OUT,
USB_ENDPOINT_BULK,
BULK_EP_PKT_SIZE,
- 0x00 /* Not specified for bulk endpoint */
- }
+ 0x00, /* Not specified for bulk endpoint */
+ },
};
+#endif
static USB_DEVICE_DESCRIPTOR device_descriptor = {
sizeof(USB_DEVICE_DESCRIPTOR),
@@ -160,6 +162,98 @@ static USB_DEVICE_DESCRIPTOR device_descriptor = {
CONFIG_COUNT
};
+#ifdef SUPPORT_SUPER_SPEED
+/* usb 3.0 root hub device descriptor */
+
+struct config_descriptor {
+ EFI_USB_CONFIG_DESCRIPTOR config;
+ EFI_USB_INTERFACE_DESCRIPTOR interface;
+ EFI_USB_ENDPOINT_DESCRIPTOR ep_in;
+ EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR ep_comp_in;
+ EFI_USB_ENDPOINT_DESCRIPTOR ep_out;
+ EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR ep_comp_out;
+} __attribute__((packed));
+
+static struct config_descriptor config_descriptor = {
+ .config = {
+ sizeof(EFI_USB_CONFIG_DESCRIPTOR),
+ USB_DESC_TYPE_CONFIG,
+ sizeof(struct config_descriptor),
+ INTERFACE_COUNT,
+ 1,
+ STR_TBL_CONFIG,
+ USB_BM_ATTR_RESERVED,
+ CFG_MAX_POWER
+ },
+ .interface = {
+ sizeof(EFI_USB_INTERFACE_DESCRIPTOR),
+ USB_DESC_TYPE_INTERFACE,
+ 0x0,
+ 0x0,
+ ENDPOINT_COUNT,
+ USB_DEVICE_VENDOR_CLASS,
+ IF_SUBCLASS,
+ IF_PROTOCOL,
+ STR_TBL_INTERFACE
+ },
+ .ep_in = {
+ sizeof(EFI_USB_ENDPOINT_DESCRIPTOR),
+ USB_DESC_TYPE_ENDPOINT,
+ IN_ENDPOINT_NUM | USB_ENDPOINT_DIR_IN,
+ USB_ENDPOINT_BULK,
+ USB_BULK_EP_PKT_SIZE_SS,
+ 0x00, /* Not specified for bulk endpoint */
+ },
+ .ep_comp_in = {
+ sizeof(EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR),
+ USB_DESC_TYPE_SS_ENDPOINT_COMPANION,
+ 0x04,
+ 0x00,
+ 0x00
+ },
+ .ep_out = {
+ sizeof(EFI_USB_ENDPOINT_DESCRIPTOR),
+ USB_DESC_TYPE_ENDPOINT,
+ OUT_ENDPOINT_NUM | USB_ENDPOINT_DIR_OUT,
+ USB_ENDPOINT_BULK,
+ USB_BULK_EP_PKT_SIZE_SS,
+ 0x00, /* Not specified for bulk endpoint */
+ },
+ .ep_comp_out = {
+ sizeof(EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR),
+ USB_DESC_TYPE_SS_ENDPOINT_COMPANION,
+ 0x04,
+ 0x00,
+ 0x00
+ }
+};
+
+struct usb_bos_descriptor {
+ EFI_USB_BOS_DESCRIPTOR bos;
+ EFI_USB_SS_USB_DEV_CAP_DESCRIPTOR ss_cap;
+} __attribute__((packed));
+
+static struct usb_bos_descriptor bos_descriptor = {
+
+ .bos = {
+ .Length = sizeof(EFI_USB_BOS_DESCRIPTOR),
+ .DescriptorType = USB_DESC_TYPE_BOS,
+ .TotalLength = sizeof(struct usb_bos_descriptor),
+ .NumDeviceCaps = 1,
+ },
+ .ss_cap = {
+ .Length = sizeof(EFI_USB_SS_USB_DEV_CAP_DESCRIPTOR),
+ .DescriptorType = USB_DESC_TYPE_DEVICE_CAPABILITY,
+ .DeviceCapabilityType = SuperSpeedUSB,
+ .Attributes = 0,
+ .SpeedSupported = 0x000f,
+ .FunctionalitySupport = 1,
+ .U1DevExitLat = 1,
+ .U2DevExitLat =500,
+ },
+};
+#endif
+
EFI_STATUS usb_write(void *buf, UINT32 size)
{
EFI_STATUS ret;
@@ -204,9 +298,21 @@ EFI_STATUS usb_read(void *buf, UINT32 size)
static EFIAPI EFI_STATUS setup_handler(__attribute__((__unused__)) EFI_USB_DEVICE_REQUEST *CtrlRequest,
__attribute__((__unused__)) USB_DEVICE_IO_INFO *IoInfo)
{
+ short version;
- /* Does not handle any Class/Vendor specific setup requests */
+ if (IoInfo == NULL || CtrlRequest == NULL)
+ return EFI_UNSUPPORTED;
+ switch (CtrlRequest->Request) {
+ case 0x33: // Android Open Accessory (AOA) protocol
+ version = 0x02;
+ IoInfo->Length = sizeof(version);
+ CopyMem (IoInfo->Buffer, &version, IoInfo->Length);
+ break;
+ default:
+ error(L"Unknown Class/Vendor setup 0x%x", CtrlRequest->Request);
+ break;
+ }
return EFI_SUCCESS;
}
@@ -347,9 +453,16 @@ static void init_driver_objs(UINT8 subclass,
/* Endpoint Data In/Out objects */
gEndpointObjs[0].EndpointDesc = &config_descriptor.ep_in;
gEndpointObjs[0].EndpointCompDesc = NULL;
-
gEndpointObjs[1].EndpointDesc = &config_descriptor.ep_out;
gEndpointObjs[1].EndpointCompDesc = NULL;
+
+#ifdef SUPPORT_SUPER_SPEED
+ device_descriptor.BcdUSB = USB_BCD_VERSION_SS;
+ gDevObj.BosDesc = &bos_descriptor.bos;
+ gEndpointObjs[0].EndpointCompDesc = &config_descriptor.ep_comp_in;
+ gEndpointObjs[1].EndpointCompDesc = &config_descriptor.ep_comp_out;
+#endif
+
}
EFI_STATUS usb_start(UINT8 subclass, UINT8 protocol,
@@ -357,7 +470,7 @@ EFI_STATUS usb_start(UINT8 subclass, UINT8 protocol,
start_callback_t start_cb, data_callback_t rx_cb,
data_callback_t tx_cb)
{
- EFI_STATUS ret;
+ EFI_STATUS ret = EFI_UNSUPPORTED;
if (!str_configuration || !str_interface || !start_cb || !rx_cb || !tx_cb)
return EFI_INVALID_PARAMETER;
@@ -366,6 +479,7 @@ EFI_STATUS usb_start(UINT8 subclass, UINT8 protocol,
rx_callback = rx_cb;
tx_callback = tx_cb;
+#ifndef USE_SELF_USB_DEVICE_MODE_PROTOCOL
ret = LibLocateProtocol(&gEfiUsbDeviceModeProtocolGuid, (void **)&usb_device);
if (EFI_ERROR(ret) || !usb_device) {
efi_perror(ret, L"Can't locate USB device mode protocol in BIOS");
@@ -374,7 +488,7 @@ EFI_STATUS usb_start(UINT8 subclass, UINT8 protocol,
if (EFI_ERROR(ret))
efi_perror(ret, L"Init USB xDCI failed");
}
-
+#endif
if (EFI_ERROR(ret)) {
#ifdef USE_SELF_USB_DEVICE_MODE_PROTOCOL
debug(L"Trying self implemented USB device mode protocol");
diff --git a/libkernelflinger/nvme.c b/libkernelflinger/nvme.c
index c3e9c8d3..857b0b7c 100644
--- a/libkernelflinger/nvme.c
+++ b/libkernelflinger/nvme.c
@@ -194,7 +194,7 @@ static EFI_STATUS nvme_erase_blocks(
* this work to the following fill_zero
*/
if (is_UEFI())
- return EFI_UNSUPPORTED;
+ return EFI_SUCCESS;
debug(L"nvme_erase_blocks: 0x%X blocks", end - start + 1);
dp = DevicePathFromHandle(handle);