public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Leif Lindholm" <leif@nuviainc.com>
To: Vin Xue <vinxue@outlook.com>
Cc: devel@edk2.groups.io, Ard Biesheuvel <ard.biesheuvel@arm.com>,
	Meenakshi Aggarwal <meenakshi.aggarwal@oss.nxp.com>
Subject: Re: [edk2-platforms PATCH 1/5] Silicon/Synopsys/DesignWare: Import DesignWare USB3 peripheral driver
Date: Mon, 20 Jul 2020 18:43:24 +0100	[thread overview]
Message-ID: <20200720174324.GR12303@vanye> (raw)
In-Reply-To: <SL2PR03MB4442ED3E414E5FCB952E88E9C57C0@SL2PR03MB4442.apcprd03.prod.outlook.com>

Hi Vin, +Meenakshi

Can you clarify the exact origin of this source code please?
We can only accept bsd+patent code contributions, and these days we
use only SPDX tags rather than full license statements at top of
files.

Meenakshi - I would certainly prefer to have a single (and
Arm-functional) driver for DWC3 rather than init-only drivers per
platform. Can you have a look at this code plese and see if it looks
feasible to integrate in the NXP platforms?

Regards,

Leif

On Fri, Jul 17, 2020 at 18:01:59 +0800, Vin Xue wrote:
> Incorporate the driver for the DesignWare USB3 DRD controller device
> mode (peripheral) that is defined in
> edk2-platforms/devel-IntelAtomProcessorE3900 branch.
> 
> The driver is supported by Intel Atom series (Merrifield/BayTrail/
> CherryTrail/Broxton/ApoloLake/GeminiLake etc.) and Core series
> (6th Generation and newer).
> 
> The driver verified on AAEON UP Squared developer board (Intel
> ApoloLake platform).
> 
> The driver supports Synopsys DesignWare DWC_usb3 and DWC_usb31 IP.
> 
> It is better if the driver can be ported to ARM silicon.
> 
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> Signed-off-by: Vin Xue <vinxue@outlook.com>
> ---
>  .../Drivers/UsbDeviceDxe/ComponentName.c      |  305 ++
>  .../Drivers/UsbDeviceDxe/UsbDeviceDxe.c       |  395 ++
>  .../Drivers/UsbDeviceDxe/UsbDeviceDxe.h       |  159 +
>  .../Drivers/UsbDeviceDxe/UsbDeviceDxe.inf     |   74 +
>  .../Drivers/UsbDeviceDxe/UsbDeviceMode.c      | 1489 ++++++
>  .../Drivers/UsbDeviceDxe/UsbDeviceMode.h      |   39 +
>  .../Drivers/UsbDeviceDxe/UsbFuncIo.c          | 2221 +++++++++
>  .../Drivers/UsbDeviceDxe/UsbFuncIo.h          |  234 +
>  .../Drivers/UsbDeviceDxe/UsbIoNode.c          |  177 +
>  .../Drivers/UsbDeviceDxe/UsbIoNode.h          |   90 +
>  .../Drivers/UsbDeviceDxe/XdciCommon.h         |  156 +
>  .../DesignWare/Drivers/UsbDeviceDxe/XdciDWC.c | 4030 +++++++++++++++++
>  .../DesignWare/Drivers/UsbDeviceDxe/XdciDWC.h |  741 +++
>  .../Drivers/UsbDeviceDxe/XdciDevice.c         |  695 +++
>  .../Drivers/UsbDeviceDxe/XdciDevice.h         |  184 +
>  .../Drivers/UsbDeviceDxe/XdciInterface.h      |  241 +
>  .../Drivers/UsbDeviceDxe/XdciTable.c          |   55 +
>  .../Drivers/UsbDeviceDxe/XdciUtility.c        |  148 +
>  .../Drivers/UsbDeviceDxe/XdciUtility.h        |   62 +
>  .../DesignWare/Include/Library/UsbDeviceLib.h |  323 ++
>  .../DesignWare/Include/Protocol/EfiUsbFnIo.h  |  430 ++
>  .../Include/Protocol/UsbDeviceModeProtocol.h  |  104 +
>  22 files changed, 12352 insertions(+)
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/ComponentName.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.inf
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciCommon.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciInterface.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciTable.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.c
>  create mode 100644 Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Include/Library/UsbDeviceLib.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Include/Protocol/EfiUsbFnIo.h
>  create mode 100644 Silicon/Synopsys/DesignWare/Include/Protocol/UsbDeviceModeProtocol.h
> 
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/ComponentName.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/ComponentName.c
> new file mode 100644
> index 0000000000..acb4b6a23d
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/ComponentName.c
> @@ -0,0 +1,305 @@
> +/** @file
> +  Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 <Uefi.h>
> +#include <Library/UefiLib.h>
> +
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language. This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
> +                                This and the language specified by Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  );
> +
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This handle
> +                                specifies the controller whose name is to be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to retrieve
> +                                the name of.  This is an optional parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified in
> +                                RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in
> +                                the language specified by Language for the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHandle,
> +  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT CHAR16                                          **ControllerName
> +  );
> +
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  mUsbDeviceDxeComponentName = {
> +  UsbDeviceDxeGetDriverName,
> +  UsbDeviceDxeGetControllerName,
> +  "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mUsbDeviceDxeComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UsbDeviceDxeGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UsbDeviceDxeGetControllerName,
> +  "en"
> +};
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUsbDeviceDxeDriverNameTable[] = {
> +  { "eng;en", L"Usb Device Driver" },
> +  { NULL , NULL }
> +};
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language. This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
> +                                This and the language specified by Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mUsbDeviceDxeDriverNameTable,
> +           DriverName,
> +           (BOOLEAN)(This == &mUsbDeviceDxeComponentName)
> +           );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This handle
> +                                specifies the controller whose name is to be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to retrieve
> +                                the name of.  This is an optional parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified in
> +                                RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in
> +                                the language specified by Language for the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHandle,
> +  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT CHAR16                                          **ControllerName
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.c
> new file mode 100644
> index 0000000000..2732cc2e31
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.c
> @@ -0,0 +1,395 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 "UsbDeviceDxe.h"
> +#include <Guid/EventGroup.h>
> +
> +EFI_DRIVER_BINDING_PROTOCOL mUsbDeviceDxeDriverBinding = {
> +  UsbDeviceDxeDriverSupported,
> +  UsbDeviceDxeDriverStart,
> +  UsbDeviceDxeDriverStop,
> +  0x1,
> +  NULL,
> +  NULL
> +};
> +
> +
> +
> +VOID
> +EFIAPI
> +PlatformSpecificInit (
> +  VOID
> +  )
> +{
> +  UINTN                 XhciPciMmBase;
> +  EFI_PHYSICAL_ADDRESS  XhciMemBaseAddress;
> +
> +  XhciPciMmBase   = MmPciAddress (
> +                      0,
> +                      0,
> +                      PCI_DEVICE_NUMBER_XHCI,
> +                      PCI_FUNCTION_NUMBER_XHCI,
> +                      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);
> +
> +  PmicUSBSwitchControl (TRUE);//conduction USB switch.
> +  return;
> +}
> +
> +
> +VOID
> +EFIAPI
> +UsbDeviceDxeExitBootService (
> +  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) {
> +    gBS->SetTimer (UsbXdciDevContext->XdciPollTimer, TimerCancel, 0);
> +    gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer);
> +    UsbXdciDevContext->XdciPollTimer = NULL;
> +    }
> +
> +  return;
> +}
> +
> +/**
> +  The USB bus driver entry pointer.
> +
> +  @param ImageHandle       The driver image handle.
> +  @param SystemTable       The system table.
> +
> +  @return EFI_SUCCESS      The component name protocol is installed.
> +  @return Others           Failed to init the usb driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeEntryPoint (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  return EfiLibInstallDriverBindingComponentName2 (
> +           ImageHandle,
> +           SystemTable,
> +           &mUsbDeviceDxeDriverBinding,
> +           ImageHandle,
> +           &mUsbDeviceDxeComponentName,
> +           &mUsbDeviceDxeComponentName2
> +           );
> +}
> +
> +/**
> +  Check whether USB bus driver support this device.
> +
> +  @param  This                   The USB bus driver binding protocol.
> +  @param  Controller             The controller handle to check.
> +  @param  RemainingDevicePath    The remaining device path.
> +
> +  @retval EFI_SUCCESS            The bus supports this controller.
> +  @retval EFI_UNSUPPORTED        This device isn't supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeDriverSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_PCI_IO_PROTOCOL       *PciIo;
> +  USB_CLASSC                UsbClassCReg;
> +
> +
> +  Status = gBS->OpenProtocol (
> +                  Controller,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **) &PciIo,
> +                  This->DriverBindingHandle,
> +                  Controller,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint8,
> +                        PCI_CLASSCODE_OFFSET,
> +                        sizeof (USB_CLASSC) / sizeof (UINT8),
> +                        &UsbClassCReg
> +                        );
> +
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_UNSUPPORTED;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Test whether the controller belongs to USB device type
> +  //
> +  // 0x0C03FE / 0x0C0380
> +  //
> +  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
> +      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
> +      ((UsbClassCReg.ProgInterface != PCI_IF_USBDEV) && (UsbClassCReg.ProgInterface != 0x80))) {
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +ON_EXIT:
> +  gBS->CloseProtocol (
> +         Controller,
> +         &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle,
> +         Controller
> +         );
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Start to process the controller.
> +
> +  @param  This                   The USB bus driver binding instance.
> +  @param  Controller             The controller to check.
> +  @param  RemainingDevicePath    The remaining device patch.
> +
> +  @retval EFI_SUCCESS            The controller is controlled by the usb bus.
> +  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb
> +                                 bus.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeDriverStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS            Status;
> +  USB_XDCI_DEV_CONTEXT  *UsbXdciDevContext;
> +  EFI_PCI_IO_PROTOCOL   *PciIo;
> +  EFI_EVENT             ExitBootServicesEvent;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFunIoEntryPoint - Entry\n"));
> +
> +  UsbXdciDevContext = NULL;
> +
> +  //
> +  // Provide protocol interface
> +  //
> +  //
> +  // Get the PCI I/O Protocol on PciHandle
> +  //
> +  Status = gBS->OpenProtocol (
> +                  Controller,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **) &PciIo,
> +                  This->DriverBindingHandle,
> +                  Controller,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> +                  );
> +
> +  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->FirstNodePtr = NULL;
> +  UsbXdciDevContext->Signature = EFI_USB_DEV_SIGNATURE;
> +
> +  PciIo->Pci.Read (
> +               PciIo,
> +               EfiPciIoWidthUint32,
> +               R_OTG_BAR0,
> +               1,
> +               &UsbXdciDevContext->XdciMmioBarAddr
> +               );
> +
> +  UsbXdciDevContext->XdciMmioBarAddr &= B_OTG_BAR0_BA;
> +  DEBUG ((USB_FUIO_DEBUG_INFO, "USB DEV mode IO addr 0x%08x\n", UsbXdciDevContext->XdciMmioBarAddr));
> +
> +  CopyMem (
> +    &(UsbXdciDevContext->UsbFunIoProtocol),
> +    &mUsbFunIoProtocol,
> +    sizeof (EFI_USBFN_IO_PROTOCOL)
> +    );
> +
> +  CopyMem (
> +    &(UsbXdciDevContext->UsbDevModeProtocol),
> +    &mUsbDeviceModeProtocol,
> +    sizeof (EFI_USB_DEVICE_MODE_PROTOCOL)
> +    );
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_NOTIFY,
> +                  UsbDeviceDxeExitBootService,
> +                  UsbXdciDevContext,
> +                  &gEfiEventExitBootServicesGuid,
> +                  &ExitBootServicesEvent
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ErrorExit;
> +  }
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &UsbXdciDevContext->XdciHandle,
> +                  &gEfiUsbFnIoProtocolGuid,
> +                  &UsbXdciDevContext->UsbFunIoProtocol,
> +                  &gEfiUsbDeviceModeProtocolGuid,
> +                  &UsbXdciDevContext->UsbDevModeProtocol,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((USB_FUIO_DEBUG_ERROR, "ERROR - Failed to install upper protocol, Status: %r\n", Status));
> +    goto ErrorExit;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "Done - install upper protocol complete\n"));
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFunIoEntryPoint - Exit\n"));
> +  return Status;
> +
> +ErrorExit:
> +  gBS->CloseProtocol (
> +         Controller,
> +         &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle,
> +         Controller
> +         );
> +
> +  if (UsbXdciDevContext != NULL) {
> +    if (UsbXdciDevContext->XdciPollTimer != NULL) {
> +      gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer);
> +      UsbXdciDevContext->XdciPollTimer = NULL;
> +    }
> +    FreePool (UsbXdciDevContext);
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_ERROR, "ERROR - UsbFunIoEntryPoint - Exit\n"));
> +  return Status;
> +}
> +
> +/**
> +  Stop handle the controller by this USB bus driver.
> +
> +  @param  This                   The USB bus driver binding protocol.
> +  @param  Controller             The controller to release.
> +  @param  NumberOfChildren       The child of USB bus that opened controller
> +                                 BY_CHILD.
> +  @param  ChildHandleBuffer      The array of child handle.
> +
> +  @retval EFI_SUCCESS            The controller or children are stopped.
> +  @retval EFI_DEVICE_ERROR       Failed to stop the driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeDriverStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN UINTN                        NumberOfChildren,
> +  IN EFI_HANDLE                   *ChildHandleBuffer
> +  )
> +{
> +  EFI_USBFN_IO_PROTOCOL           *UsbFunIoProtocol;
> +  EFI_STATUS                      Status;
> +  USB_XDCI_DEV_CONTEXT            *UsbXdciDevContext;
> +
> +
> +  //
> +  // Locate USB_BUS for the current host controller
> +  //
> +  Status = gBS->OpenProtocol (
> +                  Controller,
> +                  &gEfiUsbFnIoProtocolGuid,
> +                  (VOID **)&UsbFunIoProtocol,
> +                  This->DriverBindingHandle,
> +                  Controller,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  UsbXdciDevContext = USBFUIO_CONTEXT_FROM_PROTOCOL (UsbFunIoProtocol);
> +
> +  //
> +  // free pool
> +  //
> +  while (UsbXdciDevContext->FirstNodePtr != NULL) {
> +    RemoveNode (UsbFunIoProtocol, UsbXdciDevContext->FirstNodePtr);
> +  }
> +
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> +                  UsbXdciDevContext->XdciHandle,
> +                  &gEfiUsbFnIoProtocolGuid,
> +                  &UsbXdciDevContext->UsbFunIoProtocol,
> +                  &gEfiUsbDeviceModeProtocolGuid,
> +                  &UsbXdciDevContext->UsbDevModeProtocol,
> +                  NULL
> +                  );
> +
> +  if (UsbXdciDevContext->StartUpController == TRUE) {
> +    Status = StopController (UsbFunIoProtocol);
> +    DEBUG ((USB_FUIO_DEBUG_INFO, "USB DEV mode STOP UsbFnDeInitDevice %r\n", Status));
> +  }
> +
> +  if (UsbXdciDevContext->XdciPollTimer != NULL) {
> +    gBS->SetTimer (UsbXdciDevContext->XdciPollTimer, TimerCancel, 0);
> +    gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer);
> +    UsbXdciDevContext->XdciPollTimer = NULL;
> +  }
> +
> +  gBS->CloseProtocol (
> +         Controller,
> +         &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle,
> +         Controller
> +         );
> +
> +  FreePool (UsbXdciDevContext);
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.h
> new file mode 100644
> index 0000000000..36620f9b12
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.h
> @@ -0,0 +1,159 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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_DXE_H__
> +#define __USB_DEVICE_DXE_H__
> +
> +#include <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/DriverLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/IoLib.h>
> +#include <Protocol/EfiUsbFnIo.h>
> +#include <Protocol/UsbDeviceModeProtocol.h>
> +#include <PlatformBaseAddresses.h>
> +#include <ScAccess.h>
> +#include "UsbFuncIo.h"
> +#include "UsbDeviceMode.h"
> +
> +
> +#define PCI_IF_USBDEV                      0xFE
> +
> +#define EFI_USB_DEV_SIGNATURE              0x55534244 //"USBD"
> +#define USBFUIO_CONTEXT_FROM_PROTOCOL(a)   CR (a, USB_XDCI_DEV_CONTEXT, UsbFunIoProtocol, EFI_USB_DEV_SIGNATURE)
> +#define USBUSBD_CONTEXT_FROM_PROTOCOL(a)   CR (a, USB_XDCI_DEV_CONTEXT, UsbDevModeProtocol, EFI_USB_DEV_SIGNATURE)
> +
> +
> +typedef struct _USB_FUIO_EVENT_NODE   USB_FUIO_EVENT_NODE;
> +
> +#pragma pack(1)
> +struct _USB_FUIO_EVENT_NODE{
> +  EFI_USBFN_MESSAGE            Message;
> +  UINTN                        PayloadSize;
> +  EFI_USBFN_MESSAGE_PAYLOAD    Payload;
> +  USB_FUIO_EVENT_NODE          *Nextptr;
> +};
> +
> +typedef struct {
> +  UINTN                         Signature;
> +  UINTN                         XdciMmioBarAddr;
> +  EFI_HANDLE                    XdciHandle;
> +  //
> +  // Timer to handle EndPoint event periodically.
> +  //
> +  EFI_EVENT                     XdciPollTimer;
> +  EFI_USB_DEVICE_MODE_PROTOCOL  UsbDevModeProtocol;
> +  EFI_USBFN_IO_PROTOCOL         UsbFunIoProtocol;
> +
> +  //
> +  // Structure members used by UsbFunIoProtocol.
> +  //
> +  USB_MEM_NODE                  *FirstNodePtr;
> +  EFI_USB_DEVICE_INFO           *DevInfoPtr;
> +  EFI_USB_CONFIG_INFO           IndexPtrConfig;
> +  EFI_USB_INTERFACE_INFO        IndexPtrInteface;
> +  USB_DEVICE_ENDPOINT_INFO      IndexPtrInEp;
> +  USB_DEVICE_ENDPOINT_INFO      IndexPtrOutEp;
> +  XDCI_CORE_HANDLE              *XdciDrvIfHandle;
> +  USB_DEV_CORE                  *DrvCore;
> +  UINT16                        VendorId;
> +  UINT16                        DeviceId;
> +  USBD_EP_XFER_REC              EndPointXferRec[DWC_XDCI_MAX_ENDPOINTS];
> +  BOOLEAN                       StartUpController;
> +  BOOLEAN                       DevReConnect;
> +  BOOLEAN                       DevResetFlag;
> +  EFI_EVENT                     TimerEvent;
> +  USB_FUIO_EVENT_NODE           *EventNodePtr;
> +  //
> +  // Following structure members are used by UsbDevModeProtocol.
> +  //
> +
> +} USB_XDCI_DEV_CONTEXT;
> +#pragma pack()
> +
> +
> +
> +/**
> +  Check whether USB bus driver support this device.
> +
> +  @param  This                   The USB bus driver binding protocol.
> +  @param  Controller             The controller handle to check.
> +  @param  RemainingDevicePath    The remaining device path.
> +
> +  @retval EFI_SUCCESS            The bus supports this controller.
> +  @retval EFI_UNSUPPORTED        This device isn't supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeDriverSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> +  );
> +
> +/**
> +  Start to process the controller.
> +
> +  @param  This                   The USB bus driver binding instance.
> +  @param  Controller             The controller to check.
> +  @param  RemainingDevicePath    The remaining device patch.
> +
> +  @retval EFI_SUCCESS            The controller is controlled by the usb bus.
> +  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb
> +                                 bus.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeDriverStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> +  );
> +
> +/**
> +  Stop handle the controller by this USB bus driver.
> +
> +  @param  This                   The USB bus driver binding protocol.
> +  @param  Controller             The controller to release.
> +  @param  NumberOfChildren       The child of USB bus that opened controller
> +                                 BY_CHILD.
> +  @param  ChildHandleBuffer      The array of child handle.
> +
> +  @retval EFI_SUCCESS            The controller or children are stopped.
> +  @retval EFI_DEVICE_ERROR       Failed to stop the driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UsbDeviceDxeDriverStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN UINTN                        NumberOfChildren,
> +  IN EFI_HANDLE                   *ChildHandleBuffer
> +  );
> +
> +VOID
> +EFIAPI
> +PlatformSpecificInit (
> +  VOID
> +  );
> +
> +extern EFI_COMPONENT_NAME_PROTOCOL    mUsbDeviceDxeComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL   mUsbDeviceDxeComponentName2;
> +
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.inf b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.inf
> new file mode 100644
> index 0000000000..acf5021327
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceDxe.inf
> @@ -0,0 +1,74 @@
> +## @file
> +#
> +#  Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>
> +#
> +#  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.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = UsbDeviceDxe
> +  FILE_GUID                      = 42CF2D4A-78B4-4B80-80F9-96A83A630D70
> +  MODULE_TYPE                    = UEFI_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UsbDeviceDxeEntryPoint
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources.common]
> +  UsbDeviceDxe.c
> +  UsbFuncIo.c
> +  UsbIoNode.c
> +  ComponentName.c
> +  UsbDeviceMode.c
> +  XdciDevice.c
> +  XdciDWC.c
> +  XdciTable.c
> +  XdciUtility.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  BroxtonSiPkg/BroxtonSiPkg.dec
> +  BroxtonPlatformPkg/PlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  TimerLib
> +  PcdLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  PmicLib
> +
> +[Protocols]
> +  gEfiUsbDeviceModeProtocolGuid
> +  gEfiUsbFnIoProtocolGuid
> +  gEfiPciIoProtocolGuid
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +
> +[Guids]
> +  gEfiEventExitBootServicesGuid
> +
> +#[BuildOptions]
> +#  MSFT:*_*_*_CC_FLAGS = /D SUPPORT_SUPER_SPEED
> +#  GCC:*_*_*_CC_FLAGS = -DSUPPORT_SUPER_SPEED
> +
> +[Depex]
> +  TRUE
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.c
> new file mode 100644
> index 0000000000..48a37a37fb
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.c
> @@ -0,0 +1,1489 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 <Base.h>
> +#include <Library/BaseLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/IoLib.h>
> +#include <PlatformBaseAddresses.h>
> +#include <ScAccess.h>
> +#include "XdciUtility.h"
> +#include "UsbDeviceMode.h"
> +#include "UsbDeviceDxe.h"
> +
> +//
> +// 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;
> +
> +STATIC VOID
> +XhciSwitchSwid(BOOLEAN enable)
> +{
> +  UINTN                             XhciPciMmBase;
> +  EFI_PHYSICAL_ADDRESS              XhciMemBaseAddress;
> +  UINT32                            DualRoleCfg0;
> +  UINT32                            DualRoleCfg1;
> +
> +  XhciPciMmBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_XHCI, PCI_FUNCTION_NUMBER_XHCI, 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            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                    *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  *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 *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 *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               *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               *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 = gBS->CreateEvent (
> +                      EVT_TIMER | EVT_NOTIFY_SIGNAL,
> +                      TPL_NOTIFY,
> +                      UsbdMonitorEvents,
> +                      XdciDevContext,
> +                      &XdciDevContext->XdciPollTimer
> +                      );
> +      if (!EFI_ERROR (Status)) {
> +        Status = gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerPeriodic, EFI_TIMER_PERIOD_MILLISECONDS (20));
> +        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"));
> +          gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerCancel, 0);
> +          gBS->CloseEvent (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;
> +      gBS->Stall (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               *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               *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               *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               *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               *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/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.h
> new file mode 100644
> index 0000000000..ac9c89b2f1
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbDeviceMode.h
> @@ -0,0 +1,39 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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_MODE_DXE_H_
> +#define _USB_DEVICE_MODE_DXE_H_
> +
> +#include <Uefi.h>
> +#include <PiDxe.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UsbDeviceLib.h>
> +#include <Protocol/UsbDeviceModeProtocol.h>
> +#include "XdciCommon.h"
> +#include "XdciDevice.h"
> +
> +
> +///
> +/// Function declaration
> +///
> +EFI_STATUS
> +UsbdSetupHdlr (
> +  IN EFI_USB_DEVICE_REQUEST    *CtrlRequest
> +  );
> +
> +extern EFI_USB_DEVICE_MODE_PROTOCOL  mUsbDeviceModeProtocol;
> +
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.c
> new file mode 100644
> index 0000000000..a4138328fd
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.c
> @@ -0,0 +1,2221 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 "UsbDeviceDxe.h"
> +
> +//
> +// 16 bytes in a guid x 2 characters per byte, 4 chars for dashes and a NUL
> +//
> +#define CHARS_IN_GUID (sizeof(GUID) * 2 + 4 + 1)
> +
> +//
> +// Strings that get sent with the USB Connection
> +//
> +static CHAR16 mUsbFnDxeMfgString[] = L"Intel Corporation";
> +static CHAR16 mUsbFnDxeProductString[] = L"Broxton";
> +static CHAR16 mUsbFnDxeSerialNumber[] = L"INT123456";
> +
> +//
> +// Duplicated from MiscSystemManufacturerData.c Some parts of it will
> +// replaced with device-specific unique values.
> +//
> +static GUID mSmBiosUniqueGuid = {
> +        0x5e24fe9c, 0xc8d0, 0x45bd, 0xa7, 0x9f, 0x54, 0xea, 0x5f, 0xbd, 0x3d, 0x97
> +    };
> +
> +EFI_USBFN_IO_PROTOCOL         mUsbFunIoProtocol = {
> +  EFI_USBFN_IO_PROTOCOL_REVISION,
> +  DetectPort,
> +  ConfigureEnableEndpoints,
> +  GetEndpointMaxPacketSize,
> +  GetDeviceInfo,
> +  GetVendorIdProductId,
> +  AbortTransfer,
> +  GetEndpointStallState,
> +  SetEndpointStallState,
> +  EventHandler,
> +  Transfer,
> +  GetMaxTransferSize,
> +  AllocateTransferBuffer,
> +  FreeTransferBuffer,
> +  StartController,
> +  StopController,
> +  SetEndpointPolicy,
> +  GetEndpointPolicy
> +};
> +
> +
> +EFI_STATUS
> +PrintEventBuffer(
> +  IN  EFI_USBFN_IO_PROTOCOL  *This
> +  )
> +{
> +  UINT32                          EventCount;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  UINT32                          Index;
> +  UINT32                          *DbBufPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +
> +  EventCount = UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(0));
> +
> +  DbBufPtr = (UINT32*)(UINTN)XdciCorePtr->CurrentEventBuffer;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: XdciCorePtr->AlignedEventBuffers 0x%08x\n", (UINTN)XdciCorePtr->AlignedEventBuffers));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: DUMP BUF_S\n"));
> +  for (Index = 0; Index < ((EventCount / 4) + 1); Index++) {
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, "0x%08x\n", DbBufPtr[Index]));
> +  }
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: DUMP BUF_E\n"));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +Debug End
> +**/
> +
> +/**
> +  Returns information about what type of device was attached.
> +
> +  @param[in]  This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[out] PortType           Returns the USB port type.
> +
> +
> +  @retval EFI_SUCCESS            The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER  A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR       The physical device reported an error.
> +  @retval EFI_NOT_READY          The physical device is busy or not ready to
> +                                 process this request or the device is not
> +                                 attached to the host.
> +
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DetectPort (
> +  IN  EFI_USBFN_IO_PROTOCOL  *This,
> +  OUT EFI_USBFN_PORT_TYPE    *PortType
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT  *UsbFuncIoDevPtr;
> +  EFI_STATUS            Status;
> +  UINT8                 Value8;
> +
> +  DEBUG ((USB_FUIO_DEBUG_INFO, "DetectPort - Entry\n"));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  //
> +  // USBSRCDETRSLT Bit[5:2]
> +  // Result of USB HW Source Detection algorithm
> +  // Power-Domain: VRTC
> +  // Result of USB HW Source Detection algorithm :
> +  // 0000 = Not determined
> +  // 0001 = SDP Attached
> +  // 0010 = DCP Attached
> +  // 0011 = CDP Attached
> +  // 0100 = ACA Attached
> +  // 0101 = SE1 Attached
> +  // 0110 = MHL Attached
> +  // 0111 = Floating D+/D- Attached
> +  // 1000 = Other Attached
> +  // 1001 = DCP detected by ext. USB PHY
> +  // 1010-1111 = Rsvd
> +  // Reset: 0000B
> +  //
> +
> +  Value8 =PmicRead8 (0x5E, 0X29);
> +  if ((Value8 & 0x03) != 0x02) {
> +    *PortType = EfiUsbUnknownPort;
> +    Status = EFI_NOT_READY;
> +    goto out;
> +  }
> +
> +  Value8 = Value8 >> 2 & 0x0f;
> +  Status = EFI_SUCCESS;
> +  switch (Value8) {
> +    case 1:
> +      *PortType = EfiUsbStandardDownstreamPort;
> +      break;
> +    case 2:
> +      *PortType = EfiUsbDedicatedChargingPort;
> +      break;
> +    case 3:
> +      *PortType = EfiUsbChargingDownstreamPort;
> +      break;
> +
> +    case 4:
> +    case 5:
> +    case 6:
> +    case 7:
> +    case 8:
> +    case 9:
> +      *PortType = EfiUsbUnknownPort;
> +      break;
> +    case 0:
> +    case 10:
> +    case 11:
> +    case 12:
> +    case 13:
> +    case 14:
> +    case 15:
> +      *PortType = EfiUsbUnknownPort;
> +      Status = EFI_NOT_READY;
> +     break;
> +  }
> +
> +out:
> +  DEBUG ((USB_FUIO_DEBUG_INFO, "DetectPort - Exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  The AllocateTransferBuffer function allocates a memory region of Size bytes
> +  and returns the address of the allocated memory that satisfies underlying
> +  controller requirements in the location referenced by Buffer.
> +
> +  @param[in] This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in] Size               The number of bytes to allocate for the transfer
> +                                Buffer.
> +  @param[in] Buffer             A pointer to a pointer to the allocated Buffer
> +                                if the call succeeds; undefined otherwise.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval The requested transfer Buffer could not be allocated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AllocateTransferBuffer (
> +  IN EFI_USBFN_IO_PROTOCOL    *This,
> +  IN UINTN                    Size,
> +  OUT VOID                    **Buffer
> +  )
> +{
> +  EFI_STATUS            Status;
> +  USB_XDCI_DEV_CONTEXT  *UsbFuncIoDevPtr;
> +  VOID                  *AllocateBufferPtr;
> +  USB_MEM_NODE          *NodePtr;
> +
> +  DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer - Entry\n"));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  if (Size == 0) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto ErrorExit;
> +  }
> +
> +  AllocateBufferPtr = AllocateZeroPool (Size);
> +
> +  if (AllocateBufferPtr == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ErrorExit;
> +  }
> +
> +  //
> +  // Create new node
> +  //
> +  Status = InsertNewNodeToHead (This, &NodePtr);
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ErrorExit;
> +  }
> +
> +  NodePtr->Size = Size;
> +  NodePtr->AllocatePtr = AllocateBufferPtr;
> +
> +  *Buffer = AllocateBufferPtr;
> +
> +  DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer addr 0x%08x\n", AllocateBufferPtr));
> +  DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer - Exit\n"));
> +  return EFI_SUCCESS;
> +
> +ErrorExit:
> +
> +  DEBUG ((USB_FUIO_DEBUG_ERROR, "AllocateTransferBuffer - ERRROR %r\n",Status));
> +  return Status;
> +}
> +
> +
> +/**
> +  Deallocates the memory allocated for the transfer Buffer by
> +  AllocateTransferBuffer function.
> +
> +  @param[in] This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in] Buffer             Buffer Pointer to the transfer Buffer
> +                                to deallocate.
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +FreeTransferBuffer (
> +  IN EFI_USBFN_IO_PROTOCOL    *This,
> +  IN VOID                     *Buffer
> +  )
> +{
> +  EFI_STATUS            Status;
> +  USB_XDCI_DEV_CONTEXT  *UsbFuncIoDevPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - Entry\n"));
> +
> +  Status = RemoveNode (This, Buffer);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - ERROR\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - Exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Configure endpoints Based on supplied device and configuration descriptors.
> +
> +  @param[in] This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in] DeviceInfo         A pointer to EFI_USBFN_DEVICE_INFO instance.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to
> +                                lack of resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ConfigureEnableEndpoints (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN EFI_USB_DEVICE_INFO           *DeviceInfo
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  Status = EFI_SUCCESS;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "ConfigureEnableEndpoints - Entry\n"));
> +  //
> +  //Assuming that the hardware has already been initialized,
> +  //this function configures the endpoints using supplied
> +  //DeviceInfo, activates the port, and starts receiving USB events
> +  //
> +  Status = EFI_SUCCESS;
> +  if (DeviceInfo == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto FUNC_EXIT;
> +  }
> +
> +  UsbFuncIoDevPtr->DevInfoPtr->DeviceDescriptor = DeviceInfo->DeviceDescriptor;
> +
> +  //
> +  // Set Configure table
> +  //
> +  if (DeviceInfo->DeviceDescriptor->NumConfigurations > 1) {
> +    DEBUG ((EFI_D_ERROR, "!!!Error ConfigNum over '1' %d\n", DeviceInfo->DeviceDescriptor->NumConfigurations));
> +  }
> +  UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor = DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor;
> +  UsbFuncIoDevPtr->IndexPtrConfig.InterfaceInfoTable[0] = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0];
> +
> +  //
> +  // Set Interface
> +  //
> +  if (DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor->NumInterfaces > 1) {
> +    DEBUG ((EFI_D_ERROR, "!!!Error NumInterfaces[0] over '1' %d\n", DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor->NumInterfaces));
> +  }
> +  UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->InterfaceDescriptor;
> +
> +  //
> +  // Set Endpoint
> +  //
> +  if (UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor->NumEndpoints > 2) {
> +    DEBUG ((EFI_D_ERROR, "!!!Error NumEndPoint[0] over '2' %d\n", UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor->NumEndpoints));
> +  }
> +
> +  UsbFuncIoDevPtr->IndexPtrInEp.EndpointCompDesc = NULL;
> +  UsbFuncIoDevPtr->IndexPtrOutEp.EndpointCompDesc = NULL;
> +
> +  if ((DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0]->EndpointAddress & USB_ENDPOINT_DIR_IN) != 0) {
> +    UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0];
> +    UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[1];
> +  } else {
> +    UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[1];
> +    UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0];
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, " In Ep Num 0x%02x\n", UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc->EndpointAddress));
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, " Out Ep Num 0x%02x\n", UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc->EndpointAddress));
> +
> +FUNC_EXIT:
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "ConfigureEnableEndpoints - exit %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  Returns the maximum packet size of the specified endpoint type for
> +  the supplied bus Speed.
> +
> +  @param[in] This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in] EndpointType       Endpoint type as defined as EFI_USB_ENDPOINT_TYPE.
> +  @param[in] BusSpeed           Bus Speed as defined as EFI_USB_BUS_SPEED.
> +  @param[in] MaxPacketSize      The maximum packet size, in bytes,
> +                                of the specified endpoint type.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetEndpointMaxPacketSize (
> +  IN EFI_USBFN_IO_PROTOCOL      *This,
> +  IN EFI_USB_ENDPOINT_TYPE      EndpointType,
> +  IN EFI_USB_BUS_SPEED          BusSpeed,
> +  OUT UINT16                    *MaxPacketSize
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +  USB_DEV_CORE                      *DevCorePtr;
> +  XDCI_CORE_HANDLE                  *XdciCorePtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  DevCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = DevCorePtr->ControllerHandle;
> +  Status = EFI_SUCCESS;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointMaxPacketSize - Entry\n"));
> +
> +  switch (EndpointType) {
> +    case UsbEndpointControl:
> +#ifdef SUPPORT_SUPER_SPEED
> +      *MaxPacketSize = USB_EP0_MAX_PKT_SIZE_SS; // Default to super Speed
> +#else
> +      *MaxPacketSize = USB_EP0_MAX_PKT_SIZE_HS; // Default to high Speed
> +#endif
> +      break;
> +
> +    case UsbEndpointBulk:
> +#ifdef SUPPORT_SUPER_SPEED
> +      *MaxPacketSize = USB_BULK_EP_PKT_SIZE_SS; // Default to super Speed
> +#else
> +      *MaxPacketSize = USB_BULK_EP_PKT_SIZE_HS; // Default to high Speed
> +#endif
> +      break;
> +
> +    case UsbEndpointInterrupt:
> +      *MaxPacketSize = 1;
> +      break;
> +
> +    case UsbEndpointIsochronous:
> +    default:
> +      Status = EFI_DEVICE_ERROR;
> +      break;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointMaxPacketSize - Exit %r\n", Status));
> +  return Status;
> +}
> +
> +
> +/**
> +  Returns the maximum supported transfer size.
> +
> +  @param[in] This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in] MaxTransferSize    The maximum supported transfer size, in bytes.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetMaxTransferSize (
> +  IN EFI_USBFN_IO_PROTOCOL     *This,
> +  OUT UINTN                    *MaxTransferSize
> +  )
> +{
> +  //
> +  // Need to check, Make max transfer package to 8MB
> +  //
> +  *MaxTransferSize = MAX_TRANSFER_PACKET;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This function returns the unique device ID of the device--this matches
> +  what is populated in the SMBIOS table.
> +
> +  @param[in/out] BufferSize     On input, the size of the Buffer in bytes.
> +                                On output, the amount of data returned in Buffer
> +                                in bytes.
> +
> +  @param[out] Buffer            A pointer to a Buffer to return the requested
> +                                information as a Unicode string. What string are
> +                                we talking about
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_BUFFER_TOO_SMALL  A parameter is invalid.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GetDeviceSerialNumber (
> +    IN OUT UINTN *BufferSize,
> +    OUT VOID *Buffer OPTIONAL
> +  )
> +{
> +    EFI_STATUS Status = EFI_SUCCESS;
> +    CHAR16 UuidString[CHARS_IN_GUID];
> +    UINTN CharsCopied;
> +
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "+GetDeviceSerialNumber\n"));
> +    //
> +    // check bounds
> +    //
> +    if (*BufferSize < sizeof(UuidString)) {
> +        Status = EFI_BUFFER_TOO_SMALL;
> +        *BufferSize = 0;
> +        goto Error;
> +    }
> +
> +    //
> +    // The rest of mSmBiosUniqueGuid will be same. Note that we cannot
> +    // read the SMBIOS table directly, as it might not be ready by the time we
> +    // are to read it. The population of the data from the eMMC is ready
> +    // by the time we are here.
> +    //
> +
> +    //
> +    // Print to to a string, and copy it off
> +    //
> +    CharsCopied = UnicodeSPrint(UuidString, sizeof(UuidString), L"%g", &mSmBiosUniqueGuid);
> +    if (CharsCopied != (CHARS_IN_GUID - 1))
> +    {
> +        Status = EFI_BUFFER_TOO_SMALL;
> +        *BufferSize = 0;
> +        goto Error;
> +    }
> +    CopyMem(Buffer, UuidString, sizeof(UuidString));
> +    *BufferSize = sizeof(UuidString);
> +
> +Error:
> +
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "-GetDeviceSerialNumber, Status = 0x%08x\r\n", Status));
> +
> +    return Status;
> +}
> +
> +
> +/**
> +  Returns device specific information Based on the supplied identifier as
> +  a Unicode string
> +
> +  @param[in] This               A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in] Id                 Requested information id.
> +  @param[in] BufferSize         On input, the size of the Buffer in bytes.
> +                                On output, the amount of data returned in Buffer
> +                                in bytes.
> +  @param[in] Buffer             A pointer to a Buffer to return the requested
> +                                information as a Unicode string. What string are
> +                                we talking about
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetDeviceInfo (
> +  IN EFI_USBFN_IO_PROTOCOL      *This,
> +  IN EFI_USBFN_DEVICE_INFO_ID   Id,
> +  IN OUT UINTN                  *BufferSize,
> +  OUT VOID                      *Buffer OPTIONAL
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  USB_XDCI_DEV_CONTEXT          *UsbFuncIoDevPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  Status = EFI_SUCCESS;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "GetDeviceInfo - Entry\n"));
> +
> +  if ((BufferSize == 0) || (Buffer == NULL)) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto FUN_EXIT;
> +  }
> +
> +  switch (Id) {
> +
> +    //
> +    // FIXME: Get real serial number of board
> +    //
> +    case EfiUsbDeviceInfoSerialNumber:
> +        if (*BufferSize < sizeof(mUsbFnDxeSerialNumber)) {
> +            Status = EFI_BUFFER_TOO_SMALL;
> +            *BufferSize = 0;
> +            goto FUN_EXIT;
> +        }
> +        CopyMem(Buffer, mUsbFnDxeSerialNumber, sizeof(mUsbFnDxeSerialNumber));
> +        *BufferSize = sizeof(mUsbFnDxeSerialNumber);
> +        break;
> +
> +    case EfiUsbDeviceInfoManufacturerName:
> +        if (*BufferSize < sizeof(mUsbFnDxeMfgString)) {
> +            Status = EFI_BUFFER_TOO_SMALL;
> +            *BufferSize = 0;
> +            goto FUN_EXIT;
> +        }
> +        CopyMem(Buffer, mUsbFnDxeMfgString, sizeof(mUsbFnDxeMfgString));
> +        *BufferSize = sizeof(mUsbFnDxeMfgString);
> +        break;
> +
> +    case EfiUsbDeviceInfoProductName:
> +        if (*BufferSize < sizeof(mUsbFnDxeProductString)) {
> +            Status = EFI_BUFFER_TOO_SMALL;
> +            *BufferSize = 0;
> +            goto FUN_EXIT;
> +        }
> +        CopyMem(Buffer, mUsbFnDxeProductString, sizeof(mUsbFnDxeProductString));
> +        *BufferSize = sizeof(mUsbFnDxeProductString);
> +        break;
> +
> +    case EfiUsbDeviceInfoUnknown:
> +    default:
> +      Status = EFI_UNSUPPORTED;
> +      *BufferSize = 0;
> +      DEBUG ((USB_FUIO_DEBUG_ERROR, "Unknown ID %d encountered.\r\n", Id));
> +      break;
> +  }
> +
> +FUN_EXIT:
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - ConfigDescriptor addr 0x%08x \n", (UINTN)UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor));
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "GetDeviceInfo - Exit %r\n", Status));
> +  return Status;
> +}
> +
> +
> +/**
> +  Returns vendor-id and product-id of the device.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[out] Vid               Returned vendor-id of the device.
> +  @param[out] Pid               Returned product-id of the device.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_NOT_FOUND         Unable to return vid or pid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetVendorIdProductId (
> +  IN EFI_USBFN_IO_PROTOCOL      *This,
> +  OUT UINT16                    *Vid,
> +  OUT UINT16                    *Pid
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  //
> +  //   *Vid = 0x8086
> +  //   *Pid = 0x0A65
> +  //
> +  *Vid = UsbFuncIoDevPtr->VendorId;
> +  *Pid = UsbFuncIoDevPtr->DeviceId;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Aborts transfer on the specified endpoint.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  EndpointIndex     Indicates the endpoint on which the ongoing
> +                                transfer needs to be canceled.
> +  @param[in]  Direction         Direction of the endpoint.
> +
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AbortTransfer (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +  XDCI_CORE_HANDLE                  *XdciCorePtr;
> +  USB_DEV_CORE                      *UsbDeviceCorePtr;
> +  USB_EP_INFO                       EpInfo;
> +  EFI_STATUS                        Status;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "FU:AbortTransfer - Entry\n"));
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  Status = EFI_SUCCESS;
> +
> +  if (UsbFuncIoDevPtr->DevResetFlag == TRUE) {
> +    return Status;
> +  }
> +
> +  EpInfo.EpNum = EndpointIndex;
> +  EpInfo.EpDir = Direction? UsbEpDirIn : UsbEpDirOut;
> +
> +  Status = UsbDeviceEpCancelTransfer (UsbFuncIoDevPtr->DrvCore, &EpInfo);
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "FU:AbortTransfer - Exit %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  Returns the stall state on the specified endpoint.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  EndpointIndex     Indicates the endpoint on which the ongoing
> +                                transfer needs to be canceled.
> +  @param[in]  Direction         Direction of the endpoint.
> +  @param[in]  State             Boolean, true value indicates that the endpoint
> +                                is in a stalled state, false otherwise.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetEndpointStallState (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN OUT BOOLEAN                  *State
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +  XDCI_CORE_HANDLE                  *XdciCorePtr;
> +  UINT32                            EndPoint;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointStallState - Entry\n"));
> +
> +  EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
> +
> +  XdciCorePtr = UsbFuncIoDevPtr->XdciDrvIfHandle;
> +
> +  if (XdciCorePtr->EpHandles[EndPoint].State == USB_EP_STATE_STALLED) {
> +    *State = TRUE;
> +  } else {
> +    *State = FALSE;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointStallState - Exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +UsbSetAddress (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT32                        Address
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +  XDCI_CORE_HANDLE                  *XdciCorePtr;
> +  USB_DEV_CORE                      *UsbDeviceCorePtr;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetAddress - 0x%04x Entry\n", Address));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  Status = EFI_SUCCESS;
> +
> +  Status = UsbDeviceSetAddress (UsbDeviceCorePtr, (UINT32)Address);
> +
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto EXIT_SET_ADDRESS;
> +  }
> +
> +  Status = UsbDeviceEp0TxStatus (UsbDeviceCorePtr);
> +
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_NO_RESPONSE;
> +    goto EXIT_SET_ADDRESS;
> +  }
> +
> +EXIT_SET_ADDRESS:
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetAddress - Exit %r\n", Status));
> +  return Status;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +UsbSetconfigure (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT32                       InterFaceIndex
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  UINT32                          InterfaceNum;
> +  UINT32                          EndPointNum;
> +  UINT32                          EndPointIndex;
> +  EFI_USB_INTERFACE_INFO          *InterfaceInfoPtr;
> +  USB_EP_INFO                     EpInfo;
> +  USB_DEVICE_ENDPOINT_INFO        EpDescInfo;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - 0x%04x Entry\n", InterFaceIndex));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  Status = EFI_SUCCESS;
> +
> +  InterfaceNum = UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->NumInterfaces;
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - ConfigDescriptor addr 0x%08x \n", (UINTN)UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor));
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - DescriptorType 0x%04x ; ConfigurationValue 0x%04x\n",
> +          UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->DescriptorType,
> +          UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->ConfigurationValue
> +          ));
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - InterfaceNum 0x%04x \n", InterfaceNum));
> +  if (InterfaceNum < InterFaceIndex) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto EXIT__SET_CONFIGURE;
> +  }
> +
> +  //
> +  // Arry strart form '0', Index start from '1'.
> +  //
> +  InterfaceInfoPtr = UsbFuncIoDevPtr->IndexPtrConfig.InterfaceInfoTable[InterFaceIndex - 1];
> +  EndPointNum = InterfaceInfoPtr->InterfaceDescriptor->NumEndpoints;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - Total EP NUM 0x%04x \n", EndPointNum));
> +
> +  for (EndPointIndex = 0; EndPointIndex < EndPointNum; EndPointIndex++) {
> +    EpDescInfo.EndpointDesc = InterfaceInfoPtr->EndpointDescriptorTable[EndPointIndex];
> +    EpDescInfo.EndpointCompDesc = NULL;
> +    UsbFnSetEpInfo (&EpInfo, &EpDescInfo);
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "EndpointAddress 0x%02x\n", EpDescInfo.EndpointDesc->EndpointAddress));
> +
> +    if (UsbDeviceInitEp (UsbDeviceCorePtr, &EpInfo) == EFI_SUCCESS) {
> +       if (UsbDeviceEpEnable (UsbDeviceCorePtr, &EpInfo) == EFI_SUCCESS) {
> +       } else {
> +         Status = EFI_DEVICE_ERROR;
> +         DEBUG ((DEBUG_INFO, "UsbDeviceEpEnable() - Failed to enable endpoint\n"));
> +       }
> +    } else {
> +       Status = EFI_DEVICE_ERROR;
> +       DEBUG ((DEBUG_INFO, "UsbDeviceInitEp() - Failed to initialize endpoint\n"));
> +    }
> +  }
> +
> +  Status = UsbDeviceEp0TxStatus (UsbDeviceCorePtr);
> +
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_NO_RESPONSE;
> +    goto EXIT__SET_CONFIGURE;
> +  }
> +
> +
> +EXIT__SET_CONFIGURE:
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - Exit %r\n", Status));
> +
> +  return Status;
> +}
> +
> +/**
> +  Sets or clears the stall state on the specified endpoint.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  EndpointIndex     Indicates the endpoint on which the ongoing
> +                                transfer needs to be canceled.
> +  @param[in]  Direction         Direction of the endpoint.
> +  @param[in]  State             Requested stall state on the specified endpoint.
> +                                True value causes the endpoint to stall;
> +                                false value clears an existing stall.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SetEndpointStallState (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN BOOLEAN                      State
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +  USB_EP_INFO                       pEpInfo;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointStallState - Entry\n"));
> +  Status = EFI_SUCCESS;
> +
> +  pEpInfo.EpNum = EndpointIndex;
> +  pEpInfo.EpDir = Direction? UsbEpDirIn : UsbEpDirOut;
> +
> +  if (State == TRUE) {
> +    Status = UsbDeviceEpStall (UsbFuncIoDevPtr->DrvCore, (VOID*)(UINTN) &pEpInfo);
> +  } else {
> +    Status = UsbDeviceEpClearStall (UsbFuncIoDevPtr->DrvCore, (VOID*)(UINTN) &pEpInfo);
> +  }
> +
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointStallState - Exit\n"));
> +  return Status;
> +}
> +
> +EFI_STATUS
> +DeviceEventCheck(
> +  IN  EFI_USBFN_IO_PROTOCOL       *This,
> +  IN  USBD_EVENT_BUF              *EventIndex,
> +  OUT UINT32                      *ProcessSize,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  OUT BOOLEAN                     *EventFlag
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  UINT32                          EventReg;
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "\n FUEV::DeviceEvent entry....\n"));
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  EventReg = (EventIndex->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK);
> +  EventReg >>= DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS;
> +  *EventFlag = FALSE;
> +
> +  //
> +  // Assume default event size. Change it in switch case if
> +  // different
> +  //
> +  *ProcessSize =  DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
> +
> +  switch (EventReg) {
> +    case DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT\n"));
> +      *Message = EfiUsbMsgBusEventDetach;
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT\n"));
> +      //
> +      //  In resetDet will prepare setup Xfer package
> +      //
> +      UsbFuncIoDevPtr->DevReConnect = FALSE;
> +      UsbFuncIoDevPtr->DevResetFlag = TRUE;
> +
> +      usbProcessDeviceResetDet (XdciCorePtr);
> +      UsbDeviceSetAddress (UsbDeviceCorePtr, 0);
> +      *Message = EfiUsbMsgBusEventReset;
> +      *EventFlag = TRUE;
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT\n"));
> +      usbProcessDeviceResetDone(XdciCorePtr);
> +      UsbDeviceSetAddress(UsbDeviceCorePtr, 0);
> +      UsbFuncIoDevPtr->DevReConnect = TRUE;
> +      UsbFuncIoDevPtr->DevResetFlag = FALSE;
> +      *EventFlag = TRUE;
> +      *Message = EfiUsbMsgNone;
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT\n"));
> +      *Message = EfiUsbMsgBusEventSuspend;
> +      *EventFlag = TRUE;
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT\n"));
> +      *Message = EfiUsbMsgBusEventResume;
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT:
> +      *ProcessSize = DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES;
> +      *Message = EfiUsbMsgNone;
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFUDwcXdciProcessDeviceEvent: UNHANDLED device event: %x\n", EventReg));
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT\n"));
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT\n"));
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT\n"));
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT\n"));
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT\n"));
> +      break;
> +
> +    default:
> +      *EventFlag = FALSE;
> +      *Message = EfiUsbMsgNone;
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFUWcXdciProcessDeviceEvent: UNHANDLED device event: %x\n", EventReg));
> +      break;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "\n FUEV::DeviceEvent entry exit.... \n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +Ep0XferDone(
> +  IN  EFI_USBFN_IO_PROTOCOL       *This,
> +  IN  UINT32                      EndPointNum,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload
> +  )
> +{
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  DWC_XDCI_ENDPOINT               *EpHandle;
> +  DWC_XDCI_TRB                    *Trb;
> +  UINT32                          TrbCtrl;
> +  UINT32                          TrbSts;
> +  UINT32                          BufferLen;
> +  EFI_STATUS                      DevStatus;
> +  USB_EP_INFO                     EpInfo;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  EpHandle = &XdciCorePtr->EpHandles[EndPointNum];
> +  Trb = XdciCorePtr->Trbs + (EndPointNum * DWC_XDCI_TRB_NUM);
> +
> +  if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0XferDone. HW owns TRB: %x!!!\n", (UINT32)(UINTN)Trb));
> +  }
> +
> +  DevStatus = EFI_SUCCESS;
> +  BufferLen = 0;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "EndPointNum:%d, TRB: Addr 0x%08x!!!\n", EndPointNum, (UINTN)Trb));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->TrbCtrl: %x!!!\n", (UINT32)Trb->TrbCtrl));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->LenXferParams: %x!!!\n", (UINT32)Trb->LenXferParams));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->BuffPtrLow: %x!!!\n", (UINT32)Trb->BuffPtrLow));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->BuffPtrHigh: %x!!!\n", (UINT32)Trb->BuffPtrHigh));
> +
> +  //
> +  // Set CheckFlag to FALSE for 'DwcXdciEpRxData' function
> +  // check the RX request complete and continue next transfer request
> +  //
> +  EpHandle->CheckFlag = FALSE;
> +  EpHandle->CurrentXferRscIdx = 0;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D01!!\n"));
> +  TrbCtrl = (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D02!!\n"));
> +  TrbSts = (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_TRB_STATUS_BIT_POS;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D03!!\n" ));
> +  BufferLen = Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D04 TrbCtrl :: %x!!\n", TrbCtrl));
> +  switch (TrbCtrl) {
> +    case DWC_XDCI_TRB_CTRL_TYPE_SETUP:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done DWC_XDCI_TRB_CTRL_TYPE_SETUP!!\n"));
> +      //
> +      // This is delay for other host USB controller(none Intel), identify device get fail issue.
> +      //
> +      gBS->Stall(130);
> +      BufferLen = 8;
> +
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_TRB_CTRL_TYPE_SETUP!!\n"));
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "AlignedSetupBuffer::0x%08x!!\n", XdciCorePtr->AlignedSetupBuffer));
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Payload::0x%08x!!\n", (UINTN)Payload));
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "BufferLen::0x%08x!!\n", (UINTN)BufferLen));
> +      *Message = EfiUsbMsgSetupPacket;
> +      CopyMem (Payload, XdciCorePtr->AlignedSetupBuffer, BufferLen);
> +
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D06!!\n"));
> +      if (!(XdciCorePtr->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIRECTION_MASK)) {
> +        if ((XdciCorePtr->AlignedSetupBuffer[0]  == 0x00) ) {
> +          if ((XdciCorePtr->AlignedSetupBuffer[1]  == USB_DEV_SET_ADDRESS)) {
> +            //
> +            // set address
> +            //
> +            UsbSetAddress (
> +              This,
> +              (UINT32)(XdciCorePtr->AlignedSetupBuffer[3] << 8 | XdciCorePtr->AlignedSetupBuffer[2])
> +              );
> +
> +            *Message = EfiUsbMsgNone;
> +          } else if ((XdciCorePtr->AlignedSetupBuffer[1]  == USB_DEV_SET_CONFIGURATION)) {
> +            DEBUG ((USB_FUIO_DEBUG_EVENT_I, "\n set configure !!!"));
> +            UsbSetconfigure (
> +              This,
> +              (UINT32)(XdciCorePtr->AlignedSetupBuffer[3] << 8 | XdciCorePtr->AlignedSetupBuffer[2])
> +              );
> +            *Message = EfiUsbMsgNone;
> +          }
> +        }
> +      }
> +
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D07!!\n"));
> +      break;
> +
> +    case DWC_XDCI_TRB_CTRL_TYPE_DATA:
> +      DEBUG ((DEBUG_INFO, "Ep0 done DWC_XDCI_TRB_CTRL_TYPE_DATA!!\n"));
> +	  //
> +      // Notify upper layer of control transfer completion
> +      // if a callback function was registerd
> +      //
> +      if ((EndPointNum & 0x01) == 0) {
> +        *Message = EfiUsbMsgEndpointStatusChangedRx;
> +      } else {
> +        *Message = EfiUsbMsgEndpointStatusChangedTx;
> +      }
> +      Payload->utr.EndpointIndex = (UINT8)(EndPointNum >> 1);
> +      Payload->utr.Direction = (UINT8)(EndPointNum & 0x01);
> +      Payload->utr.Buffer = (VOID*)(UINTN)(Trb->BuffPtrLow);
> +
> +      DEBUG ((DEBUG_INFO, "Ep0 EndPointNum: %x!!!\n", (UINT32)EndPointNum));
> +      DEBUG ((DEBUG_INFO, "Ep0 done XferLength: %x!!!\n", (UINT32)UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferLength));
> +      Payload->utr.Buffer = (VOID*)UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferAddress;
> +      Payload->utr.BytesTransferred = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferLength;
> +
> +      if (TrbSts == 0) {
> +        if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) == 0) {
> +          Payload->utr.TransferStatus = UsbTransferStatusComplete;
> +        } else {
> +          Payload->utr.TransferStatus = UsbTransferStatusActive;
> +        }
> +      } else if (TrbSts != 0) {
> +        Trb->TrbCtrl |= DWC_XDCI_TRB_CTRL_HWO_MASK;
> +        *Message = EfiUsbMsgNone;
> +        Payload->utr.TransferStatus = UsbTransferStatusAborted;
> +        DEBUG ((DEBUG_INFO, "Flush FIFO!!!\n" ));
> +        EpInfo.EpNum = 0;
> +        EpInfo.EpDir =UsbEpDirIn;
> +        UsbXdciCoreFlushEpFifo(XdciCorePtr, &EpInfo);
> +        EpInfo.EpNum = 0;
> +        EpInfo.EpDir =UsbEpDirOut;
> +        UsbXdciCoreFlushEpFifo(XdciCorePtr, &EpInfo);
> +        DevStatus = UsbDeviceEp0RxSetup (UsbDeviceCorePtr, XdciCorePtr->AlignedSetupBuffer);
> +      }
> +
> +      break;
> +
> +    case DWC_XDCI_TRB_CTRL_TYPE_STATUS2:
> +    case DWC_XDCI_TRB_CTRL_TYPE_STATUS3:
> +      Payload->utr.Buffer = (VOID*) UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferAddress;
> +      Payload->utr.BytesTransferred = 0;
> +      Payload->utr.EndpointIndex = (UINT8)(EndPointNum >> 1);
> +      if ((EndPointNum & 0x01) == 0) {
> +        *Message = EfiUsbMsgEndpointStatusChangedRx;
> +      } else {
> +        *Message = EfiUsbMsgEndpointStatusChangedTx;
> +      }
> +
> +      if (TrbSts == 0) {
> +        if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) == 0) {
> +          Payload->utr.TransferStatus = UsbTransferStatusComplete;
> +        } else {
> +          Payload->utr.TransferStatus = UsbTransferStatusActive;
> +        }
> +      } else if (TrbSts != 0) {
> +        Payload->utr.TransferStatus = UsbTransferStatusAborted;
> +      }
> +
> +      DevStatus = UsbDeviceEp0RxSetup (UsbDeviceCorePtr, XdciCorePtr->AlignedSetupBuffer);
> +
> +      if (DevStatus) {
> +        DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to queue SETUP\n"));
> +      }
> +      DEBUG ((DEBUG_INFO, "Status phase done. Queue next SETUP packet==>\n"));
> +      break;
> +
> +    default:
> +      *Message = EfiUsbMsgNone;
> +      DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: UNHANDLED STATE in TRB\n"));
> +      break;
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +NoneEp0XferDone(
> +  IN  EFI_USBFN_IO_PROTOCOL       *This,
> +  IN  UINT32                      EndPointNum,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload
> +  )
> +{
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  DWC_XDCI_ENDPOINT               *EpHandle;
> +  DWC_XDCI_TRB                    *Trb;
> +  UINT32                          TrbCtrl;
> +  UINT32                          TrbSts;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  EpHandle = &XdciCorePtr->EpHandles[EndPointNum];
> +  Trb = XdciCorePtr->Trbs + (EndPointNum * DWC_XDCI_TRB_NUM);
> +
> +  if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, "NoneEp0XferDone. HW owns TRB: %x!!!, EndPointNum: %x\n", (UINT32)(UINTN)Trb, EndPointNum));
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, " TRB: Addr 0x%08x!!!\n", (UINTN)Trb));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->BuffPtrLow: %x!!!\n", (UINT32)Trb->BuffPtrLow));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->BuffPtrHigh: %x!!!\n", (UINT32)Trb->BuffPtrHigh));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->LenXferParams: %x!!!\n", (UINT32)Trb->LenXferParams));
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->TrbCtrl: %x!!!\n", (UINT32)Trb->TrbCtrl));
> +
> +  //
> +  // Set CheckFlag to FALSE for 'DwcXdciEpRxData' function
> +  // check the RX request complete and continue next transfer request
> +  //
> +  EpHandle->CheckFlag = FALSE;
> +  EpHandle->CurrentXferRscIdx = 0;
> +  *Message = EfiUsbMsgNone;
> +
> +  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;
> +
> +  Payload->utr.BytesTransferred = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferLength;
> +  Payload->utr.EndpointIndex = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].LogEpNum;
> +  Payload->utr.Direction = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].Direction;
> +  Payload->utr.Buffer = (VOID*)(UINTN)(Trb->BuffPtrLow);
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].Complete = TRUE;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "EndPointAddress = 0x%08x\n", Payload->utr.EndpointIndex));
> +  if (Payload->utr.Direction == EfiUsbEndpointDirectionDeviceTx) {
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Direction::EfiUsbEndpointDirectionDeviceTx\n"));
> +    *Message = EfiUsbMsgEndpointStatusChangedTx;
> +  } else {
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Direction::EfiUsbEndpointDirectionDeviceRx\n"));
> +    *Message = EfiUsbMsgEndpointStatusChangedRx;
> +  }
> +
> +  if (TrbSts == 0) {
> +    if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) == 0) {
> +      Payload->utr.TransferStatus = UsbTransferStatusComplete;
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusComplete\n"));
> +    } else {
> +      Payload->utr.TransferStatus = UsbTransferStatusComplete;
> +      Payload->utr.BytesTransferred -= (Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK);
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusComplete\n"));
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::Length %d \n", Payload->utr.BytesTransferred ));
> +    }
> +  } else if (TrbSts != 0) {
> +    Payload->utr.TransferStatus = UsbTransferStatusAborted;
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusAborted\n"));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +Ep0XferNotReady(
> +  IN  EFI_USBFN_IO_PROTOCOL       *This,
> +  IN  UINT32                      EndPointNum,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload,
> +  IN  UINT32                      EpStatus
> +  )
> +{
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +
> +  *Message = EfiUsbMsgNone;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EpEventCheck(
> +  IN  EFI_USBFN_IO_PROTOCOL       *This,
> +  IN  USBD_EVENT_BUF              *EventIndex,
> +  OUT UINT32                      *ProcessSize,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload,
> +  OUT BOOLEAN                     *EventFlag
> +  )
> +{
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  UINT32                          EventReg;
> +  UINT32                          EpEvent;
> +  UINT32                          EndPointNumber;
> +  UINT32                          EventStatus;
> +  USB_EP_STATE                    Ep_State;
> +  UINTN                           TmpBufferSize;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV::EndPoint Event....\n"));
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
> +
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  EventReg = EventIndex->Event;
> +  *ProcessSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
> +  *EventFlag = TRUE;
> +  TmpBufferSize = 0;
> +
> +  //
> +  // Get EP num
> +  //
> +  EndPointNumber = (EventReg & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS;
> +
> +  EventStatus = EventReg & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK;
> +
> +  //
> +  // Interpret event and handle transfer completion here
> +  //
> +  EpEvent = (EventReg & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_EVENT_BUFF_EP_EVENT_BIT_POS;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFU_EP EventReg 0x%08x\n", EventReg));
> +
> +  switch (EpEvent) {
> +    case DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT\n"));
> +      if (EndPointNumber > 1) {
> +        DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP None_Control transfer\n"));
> +        NoneEp0XferDone (This, EndPointNumber, Message, PayloadSize, Payload);
> +      } else {
> +        //
> +        // Control transfer
> +        //
> +        DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP Control transfer\n"));
> +        Ep0XferDone (This, EndPointNumber, Message, PayloadSize, Payload);
> +      }
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY\n"));
> +      *Message = EfiUsbMsgNone;
> +      if(EndPointNumber < (sizeof(UsbFuncIoDevPtr->EndPointXferRec) / sizeof(UsbFuncIoDevPtr->EndPointXferRec[0]))) {
> +        if ((UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].ZlpFlag == TRUE) && \
> +              (UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].Complete == TRUE)) {
> +          DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Request send ZLP\n"));
> +          if ((EndPointNumber & 0x01) != 0) {
> +            Transfer(This,
> +                     UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc->EndpointAddress,
> +                     EfiUsbEndpointDirectionDeviceTx,
> +                     &TmpBufferSize,
> +                     NULL
> +                    );
> +            UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].ZlpFlag = FALSE;
> +          }
> +
> +        }
> +      } else {
> +        //
> +        // Is it data stage or status stage
> +        //
> +        // Data Statge
> +        //
> +        Ep_State = USB_EP_STATE_DATA;
> +        //
> +        // Control transfer
> +        //
> +        DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP Control transfer not ready\n"));
> +        Ep0XferNotReady (This, EndPointNumber, Message, PayloadSize, Payload, EventStatus);
> +        *EventFlag = FALSE;
> +      }
> +      break;
> +
> +    case DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS\n"));
> +      break;
> +
> +    default:
> +      DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFUDwcXdciProcessEpEvent: UNKNOWN EP event\n"));
> +      break;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV::EndPoint Event....exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +ProcessIntLineEvents(
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT32                       EventCount,
> +  IN UINT32                       *ProceSsEvent,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload,
> +  OUT BOOLEAN                     *EventFlag
> +  )
> +{
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  UINT32                          CurrentEventAddr;
> +  UINT32                          ProceSsEventSize;
> +  BOOLEAN                         EventReport;
> +  BOOLEAN                         EpEventReport;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  CurrentEventAddr = (UINT32)(UINTN)(XdciCorePtr->CurrentEventBuffer);
> +  EventReport = FALSE;
> +  EpEventReport = FALSE;
> +  ProceSsEventSize = 0;
> +   DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV:: ProcessIntLineEvents Entry\n"));
> +
> +   DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV:: XdciCorePtr->CurrentEventBuffer 0x%08x\n", XdciCorePtr->CurrentEventBuffer));
> +   DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV::EventCount0x%08x\n", EventCount));
> +   DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV::CurrentEventAddr 0x%08x\n", CurrentEventAddr));
> +
> +  while ((EventCount != 0) && (EventReport == FALSE)) {
> +     DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV::event0x%08x\n", XdciCorePtr->CurrentEventBuffer->Event));
> +     if ((XdciCorePtr->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) != 0) {
> +       //
> +       // Device event
> +       //
> +       DeviceEventCheck (
> +         This,
> +         (USBD_EVENT_BUF*)(UINTN)CurrentEventAddr,
> +         &ProceSsEventSize,
> +         Message,
> +         &EventReport
> +         );
> +       if (EventReport == TRUE) {
> +         *EventFlag = TRUE;
> +       }
> +
> +     } else {
> +       //
> +       // EndPoint Event
> +       //
> +       EpEventCheck (
> +         This,
> +         (USBD_EVENT_BUF*)(UINTN)CurrentEventAddr,
> +         &ProceSsEventSize,
> +         Message,
> +         PayloadSize,
> +         Payload,
> +         &EpEventReport
> +         );
> +     }
> +
> +     if ((*Message != EfiUsbMsgNone) || (EpEventReport == TRUE)) {
> +       EventReport = TRUE;
> +       *EventFlag = TRUE;
> +     }
> +
> +     DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: CurrentEventAddr 0x%08x :: ProceSsEventSize 0x%08x\n", (UINTN)CurrentEventAddr,ProceSsEventSize));
> +
> +     EventCount -= ProceSsEventSize;
> +     *ProceSsEvent += ProceSsEventSize;
> +     if ((CurrentEventAddr + ProceSsEventSize) >= \
> +         ((UINT32)(UINTN)(XdciCorePtr->AlignedEventBuffers) +
> +          (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))) {
> +       CurrentEventAddr = (UINT32)(UINTN)(XdciCorePtr->AlignedEventBuffers);
> +    } else {
> +      CurrentEventAddr += ProceSsEventSize;
> +    }
> +    DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: CurrentEventAddr Update 0x%08x :: ProceSsEventSize 0x%08x\n", CurrentEventAddr,ProceSsEventSize));
> +
> +    XdciCorePtr->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER*)(UINTN)CurrentEventAddr;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV:: ProcessIntLineEvents Exit\n\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  ISR inokes Event Handler.  Look at which interrupt has happened and see
> +  if there are event handler registerd and if so fire them 1 by one.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  Message           Indicates the event that initiated this
> +                                notification.
> +  @param[in]  PayloadSize       On input, the size of the memory pointed by Payload.
> +                                On output, the amount of data returned in Payload.
> +  @param[in]  Payload           A pointer to EFI_USBFN_MESSAGE_PAYLOAD instance to
> +                                return additional payload for current message.
> +
> +
> +
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +  @retval EFI_BUFFER_TOO_SMALL  Supplied Buffer not large enough to hold
> +                                the message payload.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EventHandler(
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload
> +  )
> +{
> +  UINT32                          EventCount;
> +  UINT32                          PeventCount;
> +  USB_XDCI_DEV_CONTEXT            *UsbFuncIoDevPtr;
> +  UINT32                          MaxIntNum;
> +  UINT32                          IntIndex;
> +  USB_DEV_CORE                    *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                *XdciCorePtr;
> +  BOOLEAN                         EventFlag;
> +  EFI_TPL                         OriginalTpl;
> +
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFU_ EventHandler Entry\n"));
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  if (UsbFuncIoDevPtr->StartUpController == FALSE) {
> +    UsbFnInitDevice (This);
> +  }
> +  OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +  *Message = EfiUsbMsgNone;
> +  MaxIntNum = (UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_GHWPARAMS1_REG) &
> +                 DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
> +                 DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS;
> +
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  EventFlag = TRUE;
> +
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "XdciCorePtr->MaxDevIntLines 0x%08x\n", XdciCorePtr->MaxDevIntLines));
> +  EventCount = UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(0));
> +
> +  for (IntIndex = 0; IntIndex < XdciCorePtr->MaxDevIntLines ; IntIndex++) {
> +    //
> +    // Get the number of events HW has written for this
> +    //  interrupt line
> +    //
> +    EventCount = UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(IntIndex));
> +    EventCount &= DWC_XDCI_EVNTCOUNT_MASK;
> +    PeventCount = 0;
> +
> +    //
> +    // Process interrupt line Buffer only if count is non-zero
> +    //
> +    if (EventCount) {
> +      //
> +      // Process events in this Buffer
> +      //
> +      ProcessIntLineEvents (
> +        This,
> +        EventCount,
> +        &PeventCount,
> +        Message,
> +        PayloadSize,
> +        Payload,
> +        &EventFlag
> +        );
> +
> +      //
> +      // Write back the Processed number of events so HW decrements it from current
> +      // event count
> +      //
> +      UsbRegWrite ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(IntIndex), PeventCount);
> +
> +      //
> +      // for debug
> +      //
> +      if (*Message != EfiUsbMsgNone) {
> +        break;
> +      }
> +
> +      if (EventFlag == TRUE) {
> +        break;
> +      }
> +    }
> +  }
> +
> +  gBS->RestoreTPL (OriginalTpl);
> +  //
> +  //EVENT_EXIT:
> +  //
> +  DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFU_ EventHandler Exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +
> +/**
> +  Copies relevant endpoint data from standard USB endpoint descriptors
> +  to the usbEpInfo structure used by the XDCI
> +
> +  @param pEpDest   destination structure
> +  @param pEpSrc    source structure
> +
> +  @return VOID
> +
> +**/
> +VOID
> +UsbFnSetEpInfo (
> +  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;
> +    DEBUG ((DEBUG_INFO, "EpDest->EpNum 0x%02x\n", EpDest->EpNum));
> +    DEBUG ((DEBUG_INFO, "EpDest->EpDir 0x%02x\n", EpDest->EpDir));
> +    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;
> +}
> +
> +
> +EFI_STATUS
> +SetFnIoReqInfo(
> +  IN     EFI_USBFN_IO_PROTOCOL         *This,
> +  IN     UINT8                         EndpointIndex,
> +  IN     EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN OUT UINTN                         *BufferSize,
> +  IN OUT VOID                          *Buffer,
> +  IN OUT USB_XFER_REQUEST              *XfIoreq
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT     *UsbFuncIoDevPtr;
> +  EFI_STATUS               Status;
> +  UINTN                    ReqPacket;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  Status = EFI_SUCCESS;
> +  ReqPacket = 0;
> +
> +  switch (EndpointIndex) {
> +    case 0: // Control endpoint
> +      XfIoreq->EpInfo.EpNum = 0;
> +      XfIoreq->EpInfo.EpDir = Direction? UsbEpDirIn : UsbEpDirOut;
> +      break;
> +
> +
> +    default:
> +      if (Direction == EfiUsbEndpointDirectionDeviceTx) {
> +        UsbFnSetEpInfo (&XfIoreq->EpInfo, &UsbFuncIoDevPtr->IndexPtrInEp);
> +      } else {
> +        UsbFnSetEpInfo (&XfIoreq->EpInfo, &UsbFuncIoDevPtr->IndexPtrOutEp);
> +        //
> +        // reference from "UsbDeviceMode.c", function UsbdEpRxData
> +        //
> +
> +        //
> +        // Transfer length should be multiple of USB packet size.
> +        //
> +        ReqPacket = *BufferSize/ XfIoreq->EpInfo.MaxPktSize;
> +        ReqPacket = ((XfIoreq->XferLen % XfIoreq->EpInfo.MaxPktSize) == 0)? ReqPacket : ReqPacket + 1;
> +        XfIoreq->XferLen = (UINT32)ReqPacket * XfIoreq->EpInfo.MaxPktSize;
> +
> +      }
> +      break;
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  XfIoreq->XferBuffer = Buffer;
> +  XfIoreq->XferLen = (UINT32)(*BufferSize);
> +  XfIoreq->XferDone = NULL;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Primary function to handle transfer in either direction Based on specified
> +  direction and on the specified endpoint.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  EndpointIndex     Indicates the endpoint on which TX or RX transfer
> +                                needs to take place.
> +  @param[in]  Direction         Direction of the endpoint.
> +  @param[in]  BufferSize        If Direction is EfiUsbEndpointDirectionDeviceRx:
> +                                On input, the size of the Buffer in bytes.
> +                                On output, the amount of data returned in Buffer in bytes.
> +                                If Direction is EfiUsbEndpointDirectionDeviceTx:
> +                                On input, the size of the Buffer in bytes.
> +                                On output, the amount of data actually transmitted in bytes.
> +  @param[in]  Buffer            If Direction is EfiUsbEndpointDirectionDeviceRx:
> +                                The Buffer to return the received data.
> +                                If Direction is EfiUsbEndpointDirectionDeviceTx:
> +                                The Buffer that contains the data to be transmitted.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_NOT_READY         The physical device is busy or not ready to
> +                                process this request.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Transfer (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN OUT UINTN                     *BufferSize,
> +  IN OUT VOID                      *Buffer
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT              *UsbFuncIoDevPtr;
> +  USB_DEV_CORE                      *UsbDeviceCorePtr;
> +  XDCI_CORE_HANDLE                  *XdciCorePtr;
> +  EFI_STATUS                        Status;
> +  USB_XFER_REQUEST                  XferReq;
> +  UINT32                            EndPoint;
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:Transfer - Entry\n"));
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:EndpointIndex 0x%02x\n", EndpointIndex));
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:Direction 0x%02x\n", Direction));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
> +  XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
> +  EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
> +
> +  Status = SetFnIoReqInfo (
> +             This,
> +             EndpointIndex,
> +             Direction,
> +             BufferSize,
> +             Buffer,
> +             &XferReq
> +             );
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "Set SetFnIoReqInfo - Error Stop!!!\n"));
> +    while(1);
> +    Status = EFI_DEVICE_ERROR;
> +    goto FUN_EXIT;
> +  }
> +
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].EpNum = EndPoint;
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].Direction = Direction;
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].XferAddress = (UINTN)Buffer;
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].XferLength = (UINT32)(*BufferSize);
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].LogEpNum = EndpointIndex;
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].Complete = FALSE;
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag = FALSE;
> +
> +  Status = EFI_DEVICE_ERROR;
> +  switch (EndpointIndex) {
> +    case 0: // Control endpoint
> +      if (*BufferSize == 0) {
> +        if (Direction == EfiUsbEndpointDirectionDeviceTx) {
> +          Status = UsbDeviceEp0TxStatus(UsbDeviceCorePtr);
> +        } else {
> +          Status = UsbDeviceEp0RxStatus(UsbDeviceCorePtr);
> +        }
> +      } else if (Direction == EfiUsbEndpointDirectionDeviceTx) {
> +        Status = UsbXdciDeviceEpTxData(UsbDeviceCorePtr, &XferReq);
> +      } else if (Direction == EfiUsbEndpointDirectionDeviceRx) {
> +        DEBUG ((USB_FUIO_DEBUG_LOAD, "\n Set Setup Package - ??? Stop!!!\n"));
> +      }
> +      break;
> +
> +    default:
> +      Status = EFI_SUCCESS;
> +      if (Direction == EfiUsbEndpointDirectionDeviceTx) {
> +        DEBUG ((USB_FUIO_DEBUG_LOAD, "\n EfiUsbEndpointDirectionDeviceTx Size = %d\n",(*BufferSize) ));
> +        XferReq.Zlp = TRUE;
> +        if ((((*BufferSize) % 512) == 0) && ((*BufferSize) != 0)) {
> +          UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag = TRUE;
> +          DEBUG ((USB_FUIO_DEBUG_LOAD, "\n Set Zlp flag\n"));
> +        }
> +        Status = UsbXdciDeviceEpTxData (UsbDeviceCorePtr, &XferReq);
> +      } else {
> +        DEBUG ((USB_FUIO_DEBUG_LOAD, "\n EfiUsbEndpointDirectionDeviceRx Size = %d\n",(*BufferSize) ));
> +        Status = UsbXdciDeviceEpRxData (UsbDeviceCorePtr, &XferReq);
> +      }
> +      break;
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    goto FUN_EXIT;
> +  }
> +
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +FUN_EXIT:
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "FU:Transfer - Exit %r\n", Status));
> +  return Status;
> +}
> +
> +
> +/**
> +  This function supplies power to the USB controller if needed, initialize
> +  hardware and internal data structures, and then return.
> +  The port must not be activated by this function.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +**/
> +EFI_STATUS
> +EFIAPI
> +StartXdciController (
> +  IN EFI_USBFN_IO_PROTOCOL    *This
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT         *UsbFuncIoDevPtr;
> +  USB_DEV_CONFIG_PARAMS        ConfigParams;
> +  EFI_STATUS                   Status;
> +
> +  Status = EFI_SUCCESS;
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  if (UsbFuncIoDevPtr->StartUpController == TRUE) {
> +    goto EXIT_START_CONTROLLER;
> +  }
> +
> +  ConfigParams.ControllerId = USB_ID_DWC_XDCI;
> +  ConfigParams.BaseAddress = (UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr;
> +  ConfigParams.Role = USB_ROLE_DEVICE;
> +  ConfigParams.Speed = USB_SPEED_HIGH;
> +
> +  //
> +  //*Vid = 0x8086
> +  //*Pid = 0x0A65
> +  //
> +  UsbFuncIoDevPtr->VendorId = USBFU_VID;
> +  UsbFuncIoDevPtr->DeviceId = USBFU_PID;
> +  UsbFuncIoDevPtr->StartUpController = TRUE;
> +
> +  Status = UsbDeviceInit (&ConfigParams, (VOID **)&UsbFuncIoDevPtr->DrvCore);
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto EXIT_START_CONTROLLER;
> +  }
> +
> +  UsbFuncIoDevPtr->XdciDrvIfHandle = UsbFuncIoDevPtr->DrvCore->ControllerHandle;
> +
> +EXIT_START_CONTROLLER:
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "StartXdciController - Exit :: %r\n", Status));
> +  return Status;
> +}
> +
> +
> +/**
> +  This function disables the hardware device by resetting the run/stop bit
> +  and power off the USB controller if needed.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +**/
> +EFI_STATUS
> +EFIAPI
> +StopXdciController (
> +  IN EFI_USBFN_IO_PROTOCOL    *This
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT  *UsbFuncIoDevPtr;
> +  EFI_STATUS            DevStatus;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "StopController - Entry\n"));
> +
> +  if (UsbFuncIoDevPtr->StartUpController == FALSE) {
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "The Controller not yet start up skip deinit\n"));
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DevStatus = UsbDeviceDeinit (UsbFuncIoDevPtr->DrvCore, TRUE);
> +
> +  UsbFuncIoDevPtr->DrvCore = NULL;
> +  UsbFuncIoDevPtr->XdciDrvIfHandle = NULL;
> +  UsbFuncIoDevPtr->StartUpController = FALSE;
> +
> +  if (DevStatus != EFI_SUCCESS) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "StopController - Exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This function sets the configuration policy for the specified non-control endpoint.
> +  Refer to the description for calling restrictions
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  EndpointIndex     Indicates the non-control endpoint for
> +                                which the policy needs to be set.
> +  @param[in]  Direction         Direction of the endpoint.
> +  @param[in]  PolicyType        Policy type the user is trying to set for
> +                                the specified non-control endpoint.
> +  @param[in]  BufferSize        The size of the Buffer in bytes.
> +  @param[in]  Buffer            The new value for the policy parameter that
> +                                PolicyType specifies.
> +
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_UNSUPPORTED       Changing this policy value is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SetEndpointPolicy (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN EFI_USBFN_POLICY_TYPE        PolicyType,
> +  IN UINTN                        BufferSize,
> +  IN VOID                         *Buffer
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT  *UsbFuncIoDevPtr;
> +  EFI_STATUS            Status;
> +  UINT32                EndPoint;
> +  UINT8                 *FlagPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  FlagPtr = NULL;
> +
> +  switch (PolicyType) {
> +    case EfiUsbPolicyUndefined:
> +    case EfiUsbPolicyMaxTransactionSize:
> +    case EfiUsbPolicyZeroLengthTerminationSupport:
> +
> +     Status = EFI_UNSUPPORTED;
> +     break;
> +
> +    default:
> +     FlagPtr = Buffer;
> +     Status = EFI_SUCCESS;
> +     break;
> +  }
> +
> +  if (BufferSize < 1) {
> +    Status = EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointPolicy - ERROR %r\n", Status));
> +    return Status;
> +  }
> +
> +  EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
> +
> +  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag = *FlagPtr;
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  This function retrieves the configuration policy for the specified non-control
> +  endpoint. There are no associated calling restrictions for this function.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  EndpointIndex     Indicates the non-control endpoint for
> +                                which the policy needs to be set.
> +  @param[in]  Direction         Direction of the endpoint.
> +  @param[in]  PolicyType        Policy type the user is trying to set for
> +                                the specified non-control endpoint.
> +  @param[in]  BufferSize        The size of the Buffer in bytes.
> +  @param[in]  Buffer            The new value for the policy parameter that
> +                                PolicyType specifies.
> +
> +
> +  @retval EFI_SUCCESS           The function returned successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_DEVICE_ERROR      The physical device reported an error.
> +  @retval EFI_UNSUPPORTED       Changing this policy value is not supported.
> +  @retval EFI_BUFFER_TOO_SMALL  Supplied Buffer is not large enough to
> +                                hold requested policy value.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetEndpointPolicy (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN EFI_USBFN_POLICY_TYPE        PolicyType,
> +  IN OUT UINTN                    *BufferSize,
> +  IN OUT VOID                     *Buffer
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT  *UsbFuncIoDevPtr;
> +  EFI_STATUS            Status;
> +  UINT32                EndPoint;
> +  UINT32                MaxPacketSize;
> +  BOOLEAN               SetFlag;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +  MaxPacketSize = 0;
> +  SetFlag = FALSE;
> +
> +  switch (PolicyType) {
> +    case EfiUsbPolicyUndefined:
> +
> +     Status = EFI_UNSUPPORTED;
> +     break;
> +
> +    case EfiUsbPolicyMaxTransactionSize:
> +    case EfiUsbPolicyZeroLengthTerminationSupport:
> +    default:
> +     if (Buffer == NULL) {
> +       Status = EFI_INVALID_PARAMETER;
> +     } else {
> +       Status = EFI_SUCCESS;
> +     }
> +     break;
> +  }
> +
> +  EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointPolicy - ERROR %r\n", Status));
> +    return Status;
> +  }
> +
> +  if (PolicyType == EfiUsbPolicyMaxTransactionSize) {
> +
> +    if (*BufferSize < sizeof(UINT32)) {
> +       Status = EFI_INVALID_PARAMETER;
> +    } else {
> +      MaxPacketSize = MAX_TRANSFER_PACKET;
> +      CopyMem (Buffer, &MaxPacketSize, sizeof(UINT32));
> +    }
> +
> +  } else if (PolicyType == EfiUsbPolicyZeroLengthTerminationSupport) {
> +    if (*BufferSize < sizeof(BOOLEAN)) {
> +       Status = EFI_INVALID_PARAMETER;
> +    } else {
> +      SetFlag = TRUE;
> +      CopyMem (Buffer, &SetFlag, sizeof(BOOLEAN));
> +    }
> +
> +  } else if (PolicyType == EfiUsbPolicyZeroLengthTermination) {
> +    if (*BufferSize < sizeof(BOOLEAN)) {
> +       Status = EFI_INVALID_PARAMETER;
> +    } else {
> +      SetFlag =  UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag;
> +      CopyMem (Buffer, &SetFlag, sizeof(BOOLEAN));
> +    }
> +  } else {
> +    Status = EFI_INVALID_PARAMETER;
> +  }
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +UsbFnInitDevice (
> +  IN EFI_USBFN_IO_PROTOCOL        *This
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  USB_XDCI_DEV_CONTEXT         *UsbFuncIoDevPtr;
> +
> +  Status = EFI_SUCCESS;
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  PlatformSpecificInit ();
> +
> +  UsbFuncIoDevPtr->StartUpController = FALSE;
> +  Status = StartXdciController (&UsbFuncIoDevPtr->UsbFunIoProtocol);
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto DEV_INIT_EXIT;
> +  }
> +
> +  Status = UsbXdciDeviceConnect (UsbFuncIoDevPtr->DrvCore);
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbXdciDeviceConnect Status %x\n", Status));
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto DEV_INIT_EXIT;
> +  }
> +
> +
> +DEV_INIT_EXIT:
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +StartController (
> +  IN EFI_USBFN_IO_PROTOCOL        *This
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +UsbFnDeInitDevice (
> +  IN EFI_USBFN_IO_PROTOCOL        *This
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  USB_XDCI_DEV_CONTEXT         *UsbFuncIoDevPtr;
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  if (UsbFuncIoDevPtr->StartUpController == FALSE) {
> +    DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFn:StopController:The Controller not yet start up force return EFI_SUCCESS\n"));
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // disconnect
> +  //
> +  Status = UsbDeviceDisconnect (UsbFuncIoDevPtr->DrvCore);
> +  DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbDeviceDisconnect Status %x\n", Status));
> +  if (Status != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto DEV_DEINIT_EXIT;
> +  }
> +
> +  //
> +  // StopController
> +  //
> +  Status = StopXdciController (&UsbFuncIoDevPtr->UsbFunIoProtocol);
> +  UsbFuncIoDevPtr->StartUpController = FALSE;
> +
> +DEV_DEINIT_EXIT:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +StopController (
> +  IN EFI_USBFN_IO_PROTOCOL        *This
> +  )
> +{
> +  return UsbFnDeInitDevice(This);
> +}
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.h
> new file mode 100644
> index 0000000000..ad3d296db9
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbFuncIo.h
> @@ -0,0 +1,234 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 __EFI_USB_FUNCTION_IO_INTERFACE_H__
> +#define __EFI_USB_FUNCTION_IO_INTERFACE_H__
> +
> +#include <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/DriverLib.h>
> +#include <Library/PcdLib.h>
> +#include <Protocol/EfiUsbFnIo.h>
> +#include <Library/PmicLib.h>
> +#include <Library/UsbDeviceLib.h>
> +#include <Library/PrintLib.h>
> +#include "UsbIoNode.h"
> +#include "XdciDWC.h"
> +#include "UsbDeviceMode.h"
> +
> +//
> +// Debug message setting
> +//
> +#define USB_FUIO_DEBUG_INFO              EFI_D_INFO
> +#define USB_FUIO_DEBUG_LOAD              EFI_D_LOAD
> +#define USB_FUIO_DEBUG_ERROR             EFI_D_ERROR
> +#define USB_FUIO_DEBUG_EVENT_I           0 //DEBUG_INIT
> +#define USB_FUIO_DEBUG_EVENT_D           EFI_D_ERROR
> +#define USB_FUIO_DEBUG_EVENT_NOTREADY_D  EFI_D_ERROR
> +#define USB_FUIO_DEBUG_EVENT_NOTREADY_I  0 //DEBUG_INIT
> +
> +#define MAX_TRANSFER_PACKET     (8 * 1024 * 1024)
> +
> +#define USBFU_VID     0x8086
> +#define USBFU_PID     0x0A65
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT8                     ProgInterface;
> +  UINT8                     SubClassCode;
> +  UINT8                     BaseCode;
> +} USB_CLASSC;
> +
> +//
> +// Event Buffer Struct
> +//
> +typedef struct  {
> +  UINT32 Event;
> +  UINT32 DevTstLmp1;
> +  UINT32 DevTstLmp2;
> +  UINT32 Reserved;
> +} USBD_EVENT_BUF;
> +
> +typedef struct  {
> +  UINT32                        EpNum;
> +  EFI_USBFN_ENDPOINT_DIRECTION  Direction;
> +  UINTN                         XferAddress;
> +  UINT32                        XferLength;
> +  UINT8                         LogEpNum;
> +  BOOLEAN                       Complete;
> +  BOOLEAN                       ZlpFlag;
> +} USBD_EP_XFER_REC;
> +
> +#pragma pack()
> +
> +EFI_STATUS
> +UsbFnInitDevice (
> +  IN EFI_USBFN_IO_PROTOCOL        *This
> +  );
> +
> +EFI_STATUS
> +UsbFnDeInitDevice (
> +  IN EFI_USBFN_IO_PROTOCOL        *This
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +DetectPort (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  OUT EFI_USBFN_PORT_TYPE          *PortType
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +AllocateTransferBuffer (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINTN                         Size,
> +  OUT VOID                         **Buffer
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +FreeTransferBuffer (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN VOID                          *Buffer
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +ConfigureEnableEndpoints (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN EFI_USB_DEVICE_INFO           *DeviceInfo
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +GetEndpointMaxPacketSize (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN EFI_USB_ENDPOINT_TYPE         EndpointType,
> +  IN EFI_USB_BUS_SPEED             BusSpeed,
> +  OUT UINT16                       *MaxPacketSize
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +GetMaxTransferSize (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  OUT UINTN                        *MaxTransferSize
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +GetDeviceInfo (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN EFI_USBFN_DEVICE_INFO_ID      Id,
> +  IN OUT UINTN                     *BufferSize,
> +  OUT VOID                         *Buffer OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +GetVendorIdProductId (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  OUT UINT16                       *Vid,
> +  OUT UINT16                       *Pid
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +AbortTransfer (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +GetEndpointStallState (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN OUT BOOLEAN                   *State
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SetEndpointStallState (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN BOOLEAN                       State
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +EventHandler (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  OUT EFI_USBFN_MESSAGE            *Message,
> +  IN OUT UINTN                     *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD    *Payload
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +Transfer (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN OUT UINTN                     *BufferSize,
> +  IN OUT VOID                      *Buffer
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +StartController (
> +  IN EFI_USBFN_IO_PROTOCOL         *This
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +StopController (
> +  IN EFI_USBFN_IO_PROTOCOL         *This
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SetEndpointPolicy (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN EFI_USBFN_POLICY_TYPE         PolicyType,
> +  IN UINTN                         BufferSize,
> +  IN VOID                          *Buffer
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +GetEndpointPolicy (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN EFI_USBFN_POLICY_TYPE         PolicyType,
> +  IN OUT UINTN                     *BufferSize,
> +  IN OUT VOID                      *Buffer
> +  );
> +
> +VOID
> +UsbFnSetEpInfo (
> +  IN USB_EP_INFO                 *EpDest,
> +  IN USB_DEVICE_ENDPOINT_INFO    *EpSrc
> +  );
> +
> +extern EFI_USBFN_IO_PROTOCOL         mUsbFunIoProtocol;
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.c
> new file mode 100644
> index 0000000000..8fc6e10046
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.c
> @@ -0,0 +1,177 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 "UsbDeviceDxe.h"
> +
> +
> +/**
> +  The SearchNode function search a memory address for record the driver allocate
> +  memory region and the node to the head link list.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  Buffer            The driver alocate memory address.
> +  @param[out] Node              The match node record of the driver aloocate
> +                                memory region.
> +  @param[out] PNode             The pervious match node record of the driver
> +                                aloocate memory region.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_NOT_FOUND         The memory Buffer didn't find.
> +**/
> +EFI_STATUS
> +SearchNode (
> +  IN  EFI_USBFN_IO_PROTOCOL    *This,
> +  IN  VOID                     *Buffer,
> +  OUT USB_MEM_NODE             **Node,
> +  OUT USB_MEM_NODE             **PNode
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr;
> +  USB_MEM_NODE         *NodeL;
> +  USB_MEM_NODE         *PNodeL;
> +  EFI_STATUS           Status;
> +
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "SearchNode - Entry\n"));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
> +  NodeL = UsbFuncIoDevPtr->FirstNodePtr;
> +  PNodeL = NULL;
> +  Status = EFI_NOT_FOUND;
> +
> +  while (Node != NULL) {
> +    if (NodeL->AllocatePtr == Buffer) {
> +      break;
> +    }
> +
> +    PNodeL = NodeL;
> +    NodeL = NodeL->NextPtr;
> +  }
> +
> +  if (NodeL != NULL && Node != NULL) {
> +    *Node = NodeL;
> +    *PNode = PNodeL;
> +    Status = EFI_SUCCESS;
> +  }
> +
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "SearchNode - Exit %r\n", Status));
> +  return Status;
> +}
> +
> +/**
> +  The InsertNewNodeToHead function remove a memory for record the driver allocate
> +  memory region and the node to the head link list.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  Buffer            The driver alocate memory address.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_NOT_FOUND         The memory Buffer didn't find.
> +**/
> +EFI_STATUS
> +RemoveNode (
> +  IN  EFI_USBFN_IO_PROTOCOL    *This,
> +  IN  VOID                     *Buffer
> +  )
> +{
> +  USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr;
> +  USB_MEM_NODE         *Node;
> +  USB_MEM_NODE         *PNode;
> +  EFI_STATUS           Status;
> +
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "RemoveNode - Entry\n"));
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
> +
> +  Status = SearchNode (This, Buffer, &Node, &PNode);
> +
> +  if (EFI_ERROR(Status) || PNode == NULL) {
> +    DEBUG ((USB_DEBUG_MEM_NODE_ERROR, "RemoveNode - Node Not Found\n"));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  if (Node != UsbFuncIoDevPtr->FirstNodePtr) {
> +    PNode->NextPtr = Node->NextPtr;
> +  } else {
> +    UsbFuncIoDevPtr->FirstNodePtr = Node->NextPtr;
> +  }
> +
> +  FreePool (Node->AllocatePtr);
> +  FreePool (Node);
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "RemoveNode - Exit\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  The InsertNewNodeToHead function allocates a memory for record the driver allocate
> +  memory region and insert the node to the head link list.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[out] USB_MEM_NODE      return the new node address.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_OUT_OF_RESOURCES  The requested transfer Buffer could not be allocated.
> +
> +**/
> +EFI_STATUS
> +InsertNewNodeToHead (
> +  IN  EFI_USBFN_IO_PROTOCOL    *This,
> +  OUT USB_MEM_NODE             **Node
> +  )
> +{
> +  USB_MEM_NODE         *NewNodePtr;
> +  USB_MEM_NODE         *CurrentNodePtr;
> +  USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr;
> +  EFI_STATUS           Status;
> +
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "CreateNewNode - Entry\n"));
> +
> +  if (This == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto ErrorExit;
> +  }
> +
> +  UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
> +
> +  //
> +  // Create the new node
> +  //
> +  NewNodePtr = AllocateZeroPool (sizeof(USB_MEM_NODE));
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "NewNodePtr - Addr = 0x%08x\n",(UINTN)NewNodePtr));
> +
> +  if (NewNodePtr == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ErrorExit;
> +  }
> +
> +  //
> +  // insert the new node
> +  //
> +  CurrentNodePtr = UsbFuncIoDevPtr->FirstNodePtr;
> +  UsbFuncIoDevPtr->FirstNodePtr = NewNodePtr;
> +
> +  if (CurrentNodePtr != NULL) {
> +    NewNodePtr->NextPtr = CurrentNodePtr;
> +  }
> +
> +  *Node = NewNodePtr;
> +
> +  DEBUG ((USB_DEBUG_MEM_NODE_INFO, "CreateNewNode - Exit\n"));
> +  return EFI_SUCCESS;
> +
> +ErrorExit:
> +
> +  DEBUG ((USB_DEBUG_MEM_NODE_ERROR, "CreateNewNode - error %r\n",Status));
> +  return Status;
> +}
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.h
> new file mode 100644
> index 0000000000..ecedb2748b
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/UsbIoNode.h
> @@ -0,0 +1,90 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 __EFI_USB_FUIO_MEM_NODE__
> +#define __EFI_USB_FUIO_MEM_NODE__
> +
> +#include <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/DriverLib.h>
> +
> +#define  USB_DEBUG_MEM_NODE_INFO  EFI_D_INIT
> +#define  USB_DEBUG_MEM_NODE_ERROR EFI_D_ERROR
> +
> +
> +typedef struct {
> +  UINTN                         Size;
> +  VOID                          *AllocatePtr;
> +  VOID                          *NextPtr;
> +} USB_MEM_NODE;
> +
> +/**
> +  The SearchNode function search a memory address for record the driver allocate
> +  memory region and the node to the head link list.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  Buffer            The driver alocate memory address.
> +  @param[out] Node              The match node record of the driver aloocate
> +                                memory region.
> +  @param[out] PNode             The pervious match node record of the driver
> +                                aloocate memory region.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_NOT_FOUND         The memory Buffer didn't find.
> +**/
> +EFI_STATUS
> +SearchNode (
> +  IN  EFI_USBFN_IO_PROTOCOL    *This,
> +  IN  VOID                     *Buffer,
> +  OUT USB_MEM_NODE             **Node,
> +  OUT USB_MEM_NODE             **PNode
> +  );
> +
> +/**
> +  The InsertNewNodeToHead function remove a memory for record the driver allocate
> +  memory region and the node to the head link list.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[in]  Buffer            The driver alocate memory address.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_NOT_FOUND         The memory Buffer didn't find.
> +**/
> +EFI_STATUS
> +RemoveNode (
> +  IN  EFI_USBFN_IO_PROTOCOL    *This,
> +  IN  VOID                     *Buffer
> +  );
> +
> +/**
> +  The InsertNewNodeToHead function allocates a memory for record the driver allocate
> +  memory region and insert the node to the head link list.
> +
> +  @param[in]  This              A pointer to the EFI_USBFN_IO_PROTOCOL instance.
> +  @param[out] USB_MEM_NODE      return the new node address.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_OUT_OF_RESOURCES  The requested transfer Buffer could not be allocated.
> +
> +**/
> +EFI_STATUS
> +InsertNewNodeToHead (
> +  IN  EFI_USBFN_IO_PROTOCOL    *This,
> +  OUT USB_MEM_NODE             **Node
> +  );
> +
> +  #endif
> +
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciCommon.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciCommon.h
> new file mode 100644
> index 0000000000..6a53068681
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciCommon.h
> @@ -0,0 +1,156 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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_COMMON_H_
> +#define _XDCI_COMMON_H_
> +
> +#define USB_SETUP_DATA_PHASE_DIRECTION_MASK  (0x80)
> +
> +//
> +// EP direction
> +//
> +typedef enum {
> +  UsbEpDirOut = 0,
> +  UsbEpDirIn  = 1
> +} USB_EP_DIR;
> +
> +//
> +// USB Speeds
> +//
> +typedef enum {
> +  USB_SPEED_HIGH  = 0,
> +  USB_SPEED_FULL,
> +  USB_SPEED_LOW,
> +  USB_SPEED_SUPER = 4
> +} USB_SPEED;
> +
> +typedef enum {
> +  USB_ID_DWC_XDCI = 0,
> +  USB_CORE_ID_MAX
> +} USB_CONTROLLER_ID;
> +
> +typedef enum {
> +  USB_ROLE_HOST = 1,
> +  USB_ROLE_DEVICE,
> +  USB_ROLE_OTG
> +} USB_ROLE;
> +
> +typedef enum {
> +  USB_XFER_QUEUED    = 0,
> +  USB_XFER_SUCCESSFUL,
> +  USB_XFER_STALL
> +} USB_XFER_STATUS;
> +
> +typedef enum {
> +  USB_DEVICE_DISCONNECT_EVENT       = 0,
> +  USB_DEVICE_RESET_EVENT,
> +  USB_DEVICE_CONNECTION_DONE,
> +  USB_DEVICE_STATE_CHANGE_EVENT,
> +  USB_DEVICE_WAKEUP_EVENT,
> +  USB_DEVICE_HIBERNATION_REQ_EVENT,
> +  USB_DEVICE_SOF_EVENT              = 7,
> +  USB_DEVICE_ERRATIC_ERR_EVENT      = 9,
> +  USB_DEVICE_CMD_CMPLT_EVENT,
> +  USB_DEVICE_BUFF_OVERFLOW_EVENT,
> +  USB_DEVICE_TEST_LMP_RX_EVENT,
> +  USB_DEVICE_SETUP_PKT_RECEIVED,
> +  USB_DEVICE_XFER_NRDY,
> +  USB_DEVICE_XFER_DONE
> +} USB_DEVICE_EVENT_ID;
> +
> +typedef enum {
> +  U0 = 0,
> +  U1,
> +  U2,
> +  U3,
> +  SS_DIS,
> +  RX_DET,
> +  SS_INACT,
> +  POLL,
> +  RECOV,
> +  HRESET,
> +  CMPLY,
> +  LPBK,
> +  RESUME_RESET = 15
> +} USB_DEVICE_SS_LINK_STATE;
> +
> +typedef enum {
> +  CTRL_SETUP_PHASE,
> +  CTRL_DATA_PHASE,
> +  CTRL_STATUS_PHASE
> +} USB_CONTROL_XFER_PHASE;
> +
> +typedef enum  {
> +  USB_EP_STATE_DISABLED = 0,
> +  USB_EP_STATE_ENABLED,
> +  USB_EP_STATE_STALLED,
> +  USB_EP_STATE_SETUP,
> +  USB_EP_STATE_IN_DATA,
> +  USB_EP_STATE_OUT_DATA,
> +  USB_EP_STATE_DATA,
> +  USB_EP_STATE_STATUS
> +} USB_EP_STATE;
> +
> +typedef struct  {
> +  VOID                      *ParentHandle;
> +  UINT32                    Hird;
> +  UINT32                    EpNum;
> +  USB_SPEED                 Speed;
> +  USB_EP_STATE              EpState;
> +  USB_EP_DIR                EpDir;
> +  UINT8                     EpType;
> +  USB_DEVICE_SS_LINK_STATE  LinkState;
> +  UINT8                     *Buffer;
> +  BOOLEAN                   SsEvent;
> +} USB_DEVICE_CALLBACK_PARAM;
> +
> +//
> +// USB endpoint
> +//
> +typedef struct {
> +  UINT32       EpNum;
> +  USB_EP_DIR   EpDir;
> +  UINT8        EpType;
> +  UINT32       MaxPktSize;
> +  UINT32       MaxStreams;
> +  UINT32       BurstSize;
> +  UINT32       Interval;
> +  UINT32       Mult;
> +} USB_EP_INFO;
> +
> +//
> +// USB transfer request
> +//
> +typedef struct _USB_XFER_REQUEST USB_XFER_REQUEST;
> +
> +typedef
> +VOID
> +(EFIAPI *USB_XFER_DONE_CALLBACK) (
> +  IN VOID                    *XdciHndl,
> +  IN USB_XFER_REQUEST        *XferReq
> +  );
> +
> +struct _USB_XFER_REQUEST {
> +  VOID                      *XferBuffer;     // Buffer address. bus-width aligned
> +  UINT32                    XferLen;         // Requested transfer length
> +  UINT32                    ActualXferLen;  // Actual transfer length at completion callback stage
> +  UINT32                    StreamId;        // Stream ID. Only relevant for bulk streaming
> +  UINT32                    FrameNum;        // Only relevant for periodic transfer
> +  USB_XFER_STATUS           XferStatus;      // Transfer status
> +  USB_EP_INFO               EpInfo;          // EP info
> +  USB_XFER_DONE_CALLBACK    XferDone;        // Transfer completion callback
> +  BOOLEAN                   Zlp;              // Do zero-length transfer
> +};
> +
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.c
> new file mode 100644
> index 0000000000..3569ba6975
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.c
> @@ -0,0 +1,4030 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 "UsbDeviceMode.h"
> +#include "XdciInterface.h"
> +#include "XdciDWC.h"
> +
> +
> +UINT32
> +UsbRegRead (
> +  IN UINT32    Base,
> +  IN UINT32    Offset
> +  )
> +{
> +  volatile UINT32 *addr = (volatile UINT32 *)((UINTN)(Base) + (UINTN)(Offset));
> +  return *addr;
> +}
> +
> +VOID
> +UsbRegWrite (
> +  IN UINT32    Base,
> +  IN UINT32    Offset,
> +  IN UINT32    val
> +  )
> +{
> +  volatile UINT32 *addr = (volatile UINT32 *)((UINTN)(Base) + (UINTN)(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
> +      gBS->Stall (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
> +      gBS->Stall (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 (
> +  IN XDCI_CORE_HANDLE    *CoreHandle,
> +  IN UINT32              EpNum
> +  )
> +{
> +  UINT32 BaseAddr;
> +  UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
> +  UINT32 fifoNum;
> +
> +  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.
> +  //
> +  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
> +      gBS->Stall (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 (
> +  IN XDCI_CORE_HANDLE    *CoreHandle,
> +  IN 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 (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;
> +
> +  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 {
> +      gBS->Stall (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"));
> +
> +  //
> +  // 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) {
> +    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)
> +                            LocalCoreHandle->UnalignedTrbs +
> +                            (UINTN)(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 (
> +  IN VOID      *CoreHandle,
> +  IN 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;
> +
> +  if (CoreHandle == NULL) {
> +    DEBUG ((DEBUG_INFO, "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 {
> +      gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS);
> +    }
> +  } while (--MaxDelayIter);
> +
> +  if (!MaxDelayIter) {
> +    DEBUG ((DEBUG_INFO, "Failed to run the device controller\n"));
> +    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 {
> +      gBS->Stall (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 (
> +  IN VOID      *CoreHandle,
> +  IN 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
> +      gBS->Stall (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
> +      gBS->Stall (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 {
> +      gBS->Stall (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)
> +                            LocalCoreHandle->UnalignedTrbs +
> +                            (UINTN)(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/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.h
> new file mode 100644
> index 0000000000..9c1b2d1d85
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDWC.h
> @@ -0,0 +1,741 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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"
> +
> +#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];                  // EPs
> +  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
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.c
> new file mode 100644
> index 0000000000..7c94de0a60
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.c
> @@ -0,0 +1,695 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 <Library/UsbDeviceLib.h>
> +#include "XdciCommon.h"
> +#include "XdciDevice.h"
> +#include "XdciInterface.h"
> +#include "UsbDeviceMode.h"
> +
> +/**
> +  This function is used to initialize the device controller
> +  @configParams: Parameters from app to configure the core
> +  @DevCoreHandle: Return parameter for upper layers to use
> +  for all HW-independent APIs
> +
> +**/
> +EFI_STATUS
> +UsbDeviceInit (
> +  IN USB_DEV_CONFIG_PARAMS    *ConfigParams,
> +  IN OUT VOID                 **DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE    *DevCorePtr;
> +  EFI_STATUS      Status = EFI_INVALID_PARAMETER;
> +
> +  DEBUG ((DEBUG_INFO, "Call UsbDeviceInit start\n"));
> +
> +  //
> +  // Allocate device handle
> +  //
> +  DevCorePtr = AllocateZeroPool (sizeof (USB_DEV_CORE));
> +  DEBUG ((DEBUG_INFO, "device handle = 0x%x\n", DevCorePtr));
> +
> +  if (DevCorePtr == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceInit. ERROR: Failed to allocate memory\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "call UsbDeviceGetCoreDriver, ID=%x, \n", ConfigParams->ControllerId));
> +
> +  //
> +  // Get the driver for this USB device core
> +  //
> +  DevCorePtr->CoreDriver = UsbDeviceGetCoreDriver(ConfigParams->ControllerId);
> +  if (DevCorePtr->CoreDriver != NULL) {
> +    DEBUG ((DEBUG_INFO, "call DevCoreInit\n"));
> +    Status = DevCorePtr->CoreDriver->DevCoreInit(
> +                                        ConfigParams,
> +                                        (VOID*)DevCorePtr,
> +                                        &DevCorePtr->ControllerHandle);
> +  } else {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceInit. ERROR: Driver not found\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *DevCoreHandle = (VOID *)DevCorePtr;
> +  return Status;
> +}
> +
> +/**
> +  This function is used to de-initialize the device controller
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @flags: Flags indicating what type of de-initialization is required
> +
> +**/
> +EFI_STATUS
> +UsbDeviceDeinit (
> +  IN VOID      *DevCoreHandle,
> +  IN UINT32    Flags
> +  )
> +{
> +  USB_DEV_CORE    *Core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS      Status = EFI_DEVICE_ERROR;
> +
> +  if (Core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceDeinit: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    if (Core->CoreDriver != NULL) {
> +      Status = Core->CoreDriver->DevCoreDeinit(
> +                                    Core->ControllerHandle,
> +                                    Flags
> +                                    );
> +      FreePool(DevCoreHandle);
> +    } else {
> +      DEBUG ((DEBUG_INFO, "UsbDeviceDeinit: Driver not found\n"));
> +      Status = EFI_INVALID_PARAMETER;
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to register callback function for
> +  specified event
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @event: Event for which callback is to be registered
> +  @callbackFn: Callback function to be called by the
> +  controller driver for above event after critical processing
> +
> +**/
> +EFI_STATUS
> +UsbDeviceRegisterCallback (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_DEVICE_EVENT_ID       EventId,
> +  IN USB_DEVICE_CALLBACK_FUNC  CallbackFunc
> +  )
> +{
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +
> +  DEBUG ((DEBUG_INFO, "UsbDeviceRegisterCallback start\n"));
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceRegisterCallback: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    if (core->CoreDriver != NULL) {
> +      DEBUG ((DEBUG_INFO, "Call DevCoreRegisterCallback\n"));
> +      Status = core->CoreDriver->DevCoreRegisterCallback (
> +                                    core->ControllerHandle,
> +                                    EventId,
> +                                    CallbackFunc
> +                                    );
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to register callback function for
> +  specified event
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @eventId: Event for which callback is to be unregistered
> +
> +**/
> +EFI_STATUS
> +UsbDeviceUnregisterCallback (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_DEVICE_EVENT_ID       EventId
> +  )
> +{
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceUnregisterCallback: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    if (core->CoreDriver != NULL) {
> +      Status = core->CoreDriver->DevCoreUnregisterCallback(
> +                                    core->ControllerHandle,
> +                                    EventId
> +                                    );
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to service interrupt events on device
> +  controller. Use this API in your OS/stack-specific ISR framework
> +  In polled mode scenario, invoke this API in a loop to service the
> +  events
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +
> +**/
> +EFI_STATUS
> +UsbDeviceIsrRoutine (
> +  IN VOID                      *DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceIsrRoutine: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    if (core->CoreDriver != NULL) {
> +      Status = core->CoreDriver->DevCoreIsrRoutine (core->ControllerHandle);
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  This function is used to service interrupt events on device
> +  controller. Use this API in your OS/stack-specific ISR framework
> +  In polled mode scenario, invoke this API in a loop to service the
> +  events
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +
> +**/
> +EFI_STATUS
> +UsbDeviceIsrRoutineTimerBased (
> +  IN VOID                      *DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceIsrRoutine: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    if (core->CoreDriver != NULL) {
> +      Status = core->CoreDriver->DevCoreIsrRoutineTimerBased (core->ControllerHandle);
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  This function is used to enable device controller to connect
> +  to USB host
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +
> +**/
> +EFI_STATUS
> +UsbXdciDeviceConnect (
> +  IN VOID                      *DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbXdciDeviceConnect: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    DEBUG ((DEBUG_INFO, "UsbXdciDeviceConnect\n"));
> +    Status = core->CoreDriver->DevCoreConnect (core->ControllerHandle);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to disconnect device controller
> +  from USB host
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +
> +**/
> +EFI_STATUS
> +UsbDeviceDisconnect (
> +  IN VOID                      *DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE  *core =(USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceDisconnect: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceDisconnect\n"));
> +    Status = core->CoreDriver->DevCoreDisconnect(core->ControllerHandle);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to obtain USB bus Speed after bus reset complete
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @Speed: negotiated Speed
> +
> +**/
> +EFI_STATUS
> +UsbDeviceGetSpeed (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_SPEED                 *Speed
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceGetSpeed: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreGetSpeed(core->ControllerHandle, Speed);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to set USB device address
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @address: USB device address to set
> +
> +**/
> +EFI_STATUS
> +UsbDeviceSetAddress (
> +  IN VOID                      *DevCoreHandle,
> +  IN UINT32                    Address
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: enter......\n"));
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreSetAddress(core->ControllerHandle, Address);
> +  }
> +  DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: exit......\n"));
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to do device controller-specific processing
> +  of set configuration device framework request
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @ConfigNum: configuration number selected by USB host
> +
> +**/
> +EFI_STATUS
> +UsbDeviceSetConfiguration (
> +  IN VOID                      *DevCoreHandle,
> +  IN UINT32                    ConfigNum
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceSetConfiguration: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreSetConfig (core->ControllerHandle, ConfigNum);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to set desired link state in device controller
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @state: Desired link state
> +
> +**/
> +EFI_STATUS
> +UsbDeviceSetLinkState (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_DEVICE_SS_LINK_STATE  State
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceSetLinkState: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreSetLinkState (core->ControllerHandle, State);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to initialize non-EP0 endpoints
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint information for EP to be initialized
> +
> +**/
> +EFI_STATUS
> +UsbDeviceInitEp (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceInitEp: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreInitEp (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to enable an endpoint
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint information for EP to be enabled
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEpEnable (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEpEnable: ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpEnable (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to disable an endpoint
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint information for EP to be disabled
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEpDisable (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEpDisable ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpDisable (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to STALL an endpoint
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint information for EP to be stalled
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEpStall (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEpStall ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpStall (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to clear STALL on an endpoint
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint information for which STALL needs to be cleared
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEpClearStall (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEpClearStall ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpClearStall (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to set EP not ready state
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint information for EP that needs to be
> +  set in not ready state
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEpSetNrdy (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEpSetNrdy ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpSetNrdy (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to queue request to receive SETUP packet
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @Buffer: Buffer (bus-width aligned) where SETUP packet
> +  needs to be received
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEp0RxSetup (
> +  IN VOID                      *DevCoreHandle,
> +  IN UINT8                     *Buffer
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEp0RxSetup ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEp0RxSetupPkt (core->ControllerHandle, Buffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to queue request to receive status phase
> +  for control transfer on EP0
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEp0RxStatus (
> +  IN VOID                      *DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEp0RxStatus ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEp0RxStatusPkt (core->ControllerHandle);
> +  }
> +  return Status;
> +}
> +
> +/**
> +  This function is used to queue request to send status phase for
> +  control transfer on EP0
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEp0TxStatus (
> +  IN VOID                      *DevCoreHandle
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEp0TxStatus ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEp0TxStatusPkt (core->ControllerHandle);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to queue a single request to transmit data on
> +  an endpoint. If more than one request need to be queued before
> +  previous requests complete then a request queue needs to be
> +  implemented in upper layers. This API should be not be invoked until
> +  current request completes.
> +  Callback for transfer completion is invoked when requested transfer length
> +  is reached or if a short packet is received
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @XferReq: Address to transfer request describing this transfer
> +
> +**/
> +EFI_STATUS
> +UsbXdciDeviceEpTxData (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_XFER_REQUEST          *XferReq
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbXdciDeviceEpTxData ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpTxData (core->ControllerHandle, XferReq);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to queue a single request to receive data on
> +  an endpoint. If more than one request need to be queued before
> +  previous requests complete then a request queue needs to be implemented
> +  in upper layers. This API should be not be invoked until current request
> +  completes.
> +  Callback for transfer completion is invoked when requested transfer length
> +  is reached or if a short packet is received
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @XferReq: Address to transfer request describing this transfer
> +
> +**/
> +EFI_STATUS
> +UsbXdciDeviceEpRxData (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_XFER_REQUEST          *XferReq
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbXdciDeviceEpRxData ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpRxData (core->ControllerHandle, XferReq);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function is used to cancel a transfer request that was
> +  previously queued on an endpoint
> +  @DevCoreHandle: Handle to HW-independent APIs for device
> +  controller
> +  @EpInfo: Endpoint info where transfer needs to be cancelled
> +
> +**/
> +EFI_STATUS
> +UsbDeviceEpCancelTransfer (
> +  IN VOID                      *DevCoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  )
> +{
> +  USB_DEV_CORE  *core = (USB_DEV_CORE *)DevCoreHandle;
> +  EFI_STATUS    Status = EFI_DEVICE_ERROR;
> +
> +  if (core == NULL) {
> +    DEBUG ((DEBUG_INFO, "UsbDeviceEpCancelTransfer ERROR: INVALID HANDLE\n"));
> +  } else {
> +    Status = core->CoreDriver->DevCoreEpCancelTransfer (core->ControllerHandle, EpInfo);
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.h
> new file mode 100644
> index 0000000000..a10ec61732
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciDevice.h
> @@ -0,0 +1,184 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciInterface.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciInterface.h
> new file mode 100644
> index 0000000000..75ce0ecab3
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciInterface.h
> @@ -0,0 +1,241 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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_DCD_IF_H_
> +#define _USB_DCD_IF_H_
> +
> +/* Core driver for device controller
> + * @DevCoreInit: Intializes device controller
> + * @DevCoreDeinit: De-initializes device controller
> + * @DevCoreRegisterCallback: Registers callback function for
> + * an event to be called by the controller driver
> + * @DevCoreUnregisterCallback: Unregisters callback function
> + * for an event
> + * @DevCoreIsrRoutine: core interrupt service routine for
> + * device controller to be used by OS/stack-i/f layer
> + * @DevCoreConnect: Enable device controller to connect to USB host
> + * @DevCoreDisconnect: Soft disconnect device controller from
> + * USB host
> + * @DevCoreGetSpeed: Get USB bus Speed on which device controller
> + * is attached
> + * @DevCoreSetAddress: Set USB device address in device controller
> + * @DevCoreSetConfig: Set configuration number for device controller
> + * @DevCoreSetLinkState: Set link state for device controller
> + * @DevCoreInitEp: Initialize non-EP0 endpoint
> + * @DevCoreEpEnable: Enable endpoint
> + * @DevCoreEpDisable: Disable endpoint
> + * @DevCoreEpStall: Stall/Halt endpoint
> + * @DevCoreEpClearStall: Clear Stall/Halt on endpoint
> + * @DevCoreEpSetNrdy: Set endpoint to not ready state
> + * @DevCoreEp0RxSetupPkt: Receive SETUP packet on EP0
> + * @DevCoreEp0RxStatusPkt: Receive status packet on EP0
> + * @DevCoreEp0TxStatusPkt: Transmit status packet from EP0
> + * @DevCoreEpTxData: Transmit data from EP
> + * @DevCoreEpRxData: Received data on EP
> + * @DevCoreEpCancelTransfer: Cancel transfer on EP
> + */
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_INIT) (
> +  IN USB_DEV_CONFIG_PARAMS     *ConfigParams,
> +  IN VOID                      *ParentHandle,
> +  IN VOID                      **CoreHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_DEINIT) (
> +  IN VOID                      *CoreHandle,
> +  IN UINT32                    Flags
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_REG_CALLBACK) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_DEVICE_EVENT_ID       Event,
> +  IN USB_DEVICE_CALLBACK_FUNC  CallbackFn
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_UNREG_CALLBACK) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_DEVICE_EVENT_ID       Event
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_ISR_ROUTINE) (
> +  IN VOID                      *CoreHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_CONNECT) (
> +  IN VOID                      *CoreHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_DISCONNECT) (
> +  IN VOID                      *CoreHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_GET_SPEED) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_SPEED                 *Speed
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_SET_ADDRESS) (
> +  IN VOID                      *CoreHandle,
> +  IN UINT32                    Address
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_SET_CONFIG) (
> +  IN VOID                      *CoreHandle,
> +  IN UINT32                    ConfigNum
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_SET_LINK_STATE) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_DEVICE_SS_LINK_STATE  State
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_INIT_EP) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_ENABLE) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_DISABLE) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_STALL) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_CLEAR_STALL) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_SET_NRDY) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP0_RX_SETUP_PKT) (
> +  IN VOID                      *CoreHandle,
> +  IN UINT8                     *Buffer
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP0_RX_STATUS_PKT) (
> +  IN VOID                      *CoreHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP0_TX_STATUS_PKT) (
> +  IN VOID                      *CoreHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_TX_DATA) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_XFER_REQUEST          *XferHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_RX_DATA) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_XFER_REQUEST          *XferHandle
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *DEV_CORE_EP_CANCEL_TRANSFER) (
> +  IN VOID                      *CoreHandle,
> +  IN USB_EP_INFO               *EpInfo
> +  );
> +
> +struct UsbDeviceCoreDriver {
> +  DEV_CORE_INIT                 DevCoreInit;
> +  DEV_CORE_DEINIT               DevCoreDeinit;
> +  DEV_CORE_REG_CALLBACK         DevCoreRegisterCallback;
> +  DEV_CORE_UNREG_CALLBACK       DevCoreUnregisterCallback;
> +  DEV_CORE_ISR_ROUTINE          DevCoreIsrRoutine;
> +  DEV_CORE_ISR_ROUTINE          DevCoreIsrRoutineTimerBased;
> +  DEV_CORE_CONNECT              DevCoreConnect;
> +  DEV_CORE_DISCONNECT           DevCoreDisconnect;
> +  DEV_CORE_GET_SPEED            DevCoreGetSpeed;
> +  DEV_CORE_SET_ADDRESS          DevCoreSetAddress;
> +  DEV_CORE_SET_CONFIG           DevCoreSetConfig;
> +  DEV_CORE_SET_LINK_STATE       DevCoreSetLinkState;
> +  DEV_CORE_INIT_EP              DevCoreInitEp;
> +  DEV_CORE_EP_ENABLE            DevCoreEpEnable;
> +  DEV_CORE_EP_DISABLE           DevCoreEpDisable;
> +  DEV_CORE_EP_STALL             DevCoreEpStall;
> +  DEV_CORE_EP_CLEAR_STALL       DevCoreEpClearStall;
> +  DEV_CORE_EP_SET_NRDY          DevCoreEpSetNrdy;
> +  DEV_CORE_EP0_RX_SETUP_PKT     DevCoreEp0RxSetupPkt;
> +  DEV_CORE_EP0_RX_STATUS_PKT    DevCoreEp0RxStatusPkt;
> +  DEV_CORE_EP0_TX_STATUS_PKT    DevCoreEp0TxStatusPkt;
> +  DEV_CORE_EP_TX_DATA           DevCoreEpTxData;
> +  DEV_CORE_EP_RX_DATA           DevCoreEpRxData;
> +  DEV_CORE_EP_CANCEL_TRANSFER   DevCoreEpCancelTransfer;
> +};
> +
> +//
> +// This API is used to obtain the driver handle for HW-independent API
> +// @id: The ID of the core for which this driver is requested
> +//
> +const struct UsbDeviceCoreDriver *UsbDeviceGetCoreDriver(
> +  USB_CONTROLLER_ID id);
> +
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciTable.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciTable.c
> new file mode 100644
> index 0000000000..97a97db3db
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciTable.c
> @@ -0,0 +1,55 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 <Library/UsbDeviceLib.h>
> +#include "XdciCommon.h"
> +#include "XdciDevice.h"
> +#include "XdciInterface.h"
> +#include "XdciDWC.h"
> +#include "UsbDeviceMode.h"
> +
> +static const struct UsbDeviceCoreDriver CoreDriverTbl[USB_CORE_ID_MAX] = {
> +  DwcXdciCoreInit,
> +  DwcXdciCoreDeinit,
> +  DwcXdciCoreRegisterCallback,
> +  DwcXdciCoreUnregisterCallback,
> +  DwcXdciCoreIsrRoutine,
> +  DwcXdciCoreIsrRoutineTimerBased,
> +  DwcXdciCoreConnect,
> +  DwcXdciCoreDisconnect,
> +  DwcXdciCoreGetSpeed,
> +  DwcXdciCoreSetAddress,
> +  DwcXdciCoreSetConfig,
> +  DwcXdciSetLinkState,
> +  DwcXdciInitEp,
> +  DwcXdciEpEnable,
> +  DwcXdciEpDisable,
> +  DwcXdciEpStall,
> +  DwcXdciEpClearStall,
> +  DwcXdciEpSetNrdy,
> +  DwcXdciEp0ReceiveSetupPkt,
> +  DwcXdciEp0ReceiveStatusPkt,
> +  DwcXdciEp0SendStatusPkt,
> +  DwcXdciEpTxData,
> +  DwcXdciEpRxData,
> +  DwcXdciEpCancelTransfer
> +};
> +
> +const struct UsbDeviceCoreDriver *UsbDeviceGetCoreDriver(USB_CONTROLLER_ID id)
> +{
> +  if (id >= USB_CORE_ID_MAX)
> +    return NULL;
> +
> +  return &CoreDriverTbl[id];
> +}
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.c b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.c
> new file mode 100644
> index 0000000000..2e02475cd0
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.c
> @@ -0,0 +1,148 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 "XdciUtility.h"
> +
> +VOID
> +PrintDeviceDescriptor (
> +  IN USB_DEVICE_DESCRIPTOR    *DevDesc
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- Device Descriptor ---\n"));
> +  DEBUG ((DEBUG_INFO, "Length            : 0x%x\n", DevDesc->Length));
> +  DEBUG ((DEBUG_INFO, "DescriptorType    : 0x%x\n", DevDesc->DescriptorType));
> +  DEBUG ((DEBUG_INFO, "BcdUSB            : 0x%x\n", DevDesc->BcdUSB));
> +  DEBUG ((DEBUG_INFO, "DeviceClass       : 0x%x\n", DevDesc->DeviceClass));
> +  DEBUG ((DEBUG_INFO, "DeviceSubClass    : 0x%x\n", DevDesc->DeviceSubClass));
> +  DEBUG ((DEBUG_INFO, "DeviceProtocol    : 0x%x\n", DevDesc->DeviceProtocol));
> +  DEBUG ((DEBUG_INFO, "MaxPacketSize0    : 0x%x\n", DevDesc->MaxPacketSize0));
> +  DEBUG ((DEBUG_INFO, "IdVendor          : 0x%x\n", DevDesc->IdVendor));
> +  DEBUG ((DEBUG_INFO, "IdProduct         : 0x%x\n", DevDesc->IdProduct));
> +  DEBUG ((DEBUG_INFO, "BcdDevice         : 0x%x\n", DevDesc->BcdDevice));
> +  DEBUG ((DEBUG_INFO, "StrManufacturer   : 0x%x\n", DevDesc->StrManufacturer));
> +  DEBUG ((DEBUG_INFO, "StrProduct        : 0x%x\n", DevDesc->StrProduct));
> +  DEBUG ((DEBUG_INFO, "StrSerialNumber   : 0x%x\n", DevDesc->StrSerialNumber));
> +  DEBUG ((DEBUG_INFO, "NumConfigurations : 0x%x\n", DevDesc->NumConfigurations));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +VOID
> +PrintConfigDescriptor (
> +  IN EFI_USB_CONFIG_DESCRIPTOR    *ConfigDesc
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- Configuration Descriptor ---\n"));
> +  DEBUG ((DEBUG_INFO, "Length             : 0x%x\n", ConfigDesc->Length));
> +  DEBUG ((DEBUG_INFO, "DescriptorType     : 0x%x\n", ConfigDesc->DescriptorType));
> +  DEBUG ((DEBUG_INFO, "TotalLength        : 0x%x\n", ConfigDesc->TotalLength));
> +  DEBUG ((DEBUG_INFO, "NumInterfaces      : 0x%x\n", ConfigDesc->NumInterfaces));
> +  DEBUG ((DEBUG_INFO, "ConfigurationValue : 0x%x\n", ConfigDesc->ConfigurationValue));
> +  DEBUG ((DEBUG_INFO, "Configuration      : 0x%x\n", ConfigDesc->Configuration));
> +  DEBUG ((DEBUG_INFO, "Attributes         : 0x%x\n", ConfigDesc->Attributes));
> +  DEBUG ((DEBUG_INFO, "MaxPower           : 0x%x\n", ConfigDesc->MaxPower));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +VOID
> +PrintInterfaceDescriptor (
> +  IN EFI_USB_INTERFACE_DESCRIPTOR    *IfDesc
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- Interface Descriptor ---\n"));
> +  DEBUG ((DEBUG_INFO, "Length            : 0x%x\n", IfDesc->Length));
> +  DEBUG ((DEBUG_INFO, "DescriptorType    : 0x%x\n", IfDesc->DescriptorType));
> +  DEBUG ((DEBUG_INFO, "InterfaceNumber   : 0x%x\n", IfDesc->InterfaceNumber));
> +  DEBUG ((DEBUG_INFO, "AlternateSetting  : 0x%x\n", IfDesc->AlternateSetting));
> +  DEBUG ((DEBUG_INFO, "NumEndpoints      : 0x%x\n", IfDesc->NumEndpoints));
> +  DEBUG ((DEBUG_INFO, "InterfaceClass    : 0x%x\n", IfDesc->InterfaceClass));
> +  DEBUG ((DEBUG_INFO, "InterfaceSubClass : 0x%x\n", IfDesc->InterfaceSubClass));
> +  DEBUG ((DEBUG_INFO, "InterfaceProtocol : 0x%x\n", IfDesc->InterfaceProtocol));
> +  DEBUG ((DEBUG_INFO, "Interface         : 0x%x\n", IfDesc->Interface));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +VOID
> +PrintEpDescriptor (
> +  IN EFI_USB_ENDPOINT_DESCRIPTOR    *EpDesc
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- Endpoint Descriptor ---\n"));
> +  DEBUG ((DEBUG_INFO, "Length          : 0x%x\n", EpDesc->Length));
> +  DEBUG ((DEBUG_INFO, "DescriptorType  : 0x%x\n", EpDesc->DescriptorType));
> +  DEBUG ((DEBUG_INFO, "EndpointAddress : 0x%x\n", EpDesc->EndpointAddress));
> +  DEBUG ((DEBUG_INFO, "Attributes      : 0x%x\n", EpDesc->Attributes));
> +  DEBUG ((DEBUG_INFO, "MaxPacketSize   : 0x%x\n", EpDesc->MaxPacketSize));
> +  DEBUG ((DEBUG_INFO, "Interval        : 0x%x\n", EpDesc->Interval));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +VOID
> +PrintEpCompDescriptor (
> +  IN EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR    *EpDesc
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- Endpoint Companion Descriptor ---\n"));
> +  DEBUG ((DEBUG_INFO, "Length           : 0x%x\n", EpDesc->Length));
> +  DEBUG ((DEBUG_INFO, "DescriptorType   : 0x%x\n", EpDesc->DescriptorType));
> +  DEBUG ((DEBUG_INFO, "MaxBurst         : 0x%x\n", EpDesc->MaxBurst));
> +  DEBUG ((DEBUG_INFO, "Attributes       : 0x%x\n", EpDesc->Attributes));
> +  DEBUG ((DEBUG_INFO, "BytesPerInterval : 0x%x\n", EpDesc->BytesPerInterval));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +VOID
> +PrintStringDescriptor (
> +  IN USB_STRING_DESCRIPTOR    *StrDesc
> +  )
> +{
> +  UINT16 StrLen = 0;
> +
> +  if (StrDesc->Length > 2) {
> +    StrLen = ((StrDesc->Length - 2) >> 1);
> +    DEBUG ((DEBUG_INFO, "--- String Descriptor ---\n"));
> +    DEBUG ((DEBUG_INFO, "Length         : 0x%x\n", StrDesc->Length));
> +    DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", StrDesc->DescriptorType));
> +    DEBUG ((DEBUG_INFO, "String         : %s\n",   StrDesc->LangID));
> +  }
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +VOID
> +PrintDeviceRequest (
> +  IN EFI_USB_DEVICE_REQUEST    *DevReq
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- Device Request ---\n"));
> +  DEBUG ((DEBUG_INFO, "RequestType : 0x%x\n", DevReq->RequestType));
> +  DEBUG ((DEBUG_INFO, "Request     : 0x%x\n", DevReq->Request));
> +  DEBUG ((DEBUG_INFO, "Value       : 0x%x\n", DevReq->Value));
> +  DEBUG ((DEBUG_INFO, "Index       : 0x%x\n", DevReq->Index));
> +  DEBUG ((DEBUG_INFO, "Length      : 0x%x\n", DevReq->Length));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +
> +#ifdef SUPPORT_SUPER_SPEED
> +VOID
> +PrintBOSDescriptor (
> +  IN EFI_USB_BOS_DESCRIPTOR    *BosDesc
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "--- BOS Descriptor ---\n"));
> +  DEBUG ((DEBUG_INFO, "Length           : 0x%x\n", BosDesc->Length));
> +  DEBUG ((DEBUG_INFO, "DescriptorType   : 0x%x\n", BosDesc->DescriptorType));
> +  DEBUG ((DEBUG_INFO, "TotalLength      : 0x%x\n", BosDesc->TotalLength));
> +  DEBUG ((DEBUG_INFO, "NumDeviceCaps    : 0x%x\n", BosDesc->NumDeviceCaps));
> +  DEBUG ((DEBUG_INFO, "\n"));
> +}
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.h b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.h
> new file mode 100644
> index 0000000000..e3d004e579
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Drivers/UsbDeviceDxe/XdciUtility.h
> @@ -0,0 +1,62 @@
> +/** @file
> +  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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_UTILITY_H_
> +#define _XDCI_UTILITY_H_
> +
> +#include <Library/UsbDeviceLib.h>
> +
> +VOID
> +PrintDeviceDescriptor (
> +  IN USB_DEVICE_DESCRIPTOR    *DevDesc
> +  );
> +
> +VOID
> +PrintConfigDescriptor (
> +  IN EFI_USB_CONFIG_DESCRIPTOR    *ConfigDesc
> +  );
> +
> +VOID
> +PrintInterfaceDescriptor (
> +  IN EFI_USB_INTERFACE_DESCRIPTOR    *IfDesc
> +  );
> +
> +VOID
> +PrintEpDescriptor (
> +  IN EFI_USB_ENDPOINT_DESCRIPTOR    *EpDesc
> +  );
> +
> +VOID
> +PrintEpCompDescriptor (
> +  IN EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR    *EpDesc
> +  );
> +
> +VOID
> +PrintStringDescriptor (
> +  IN USB_STRING_DESCRIPTOR    *StrDesc
> +  );
> +
> +VOID
> +PrintDeviceRequest (
> +  IN EFI_USB_DEVICE_REQUEST    *DevReq
> +  );
> +
> +#ifdef SUPPORT_SUPER_SPEED
> +VOID
> +PrintBOSDescriptor (
> +  IN EFI_USB_BOS_DESCRIPTOR    *BosDesc
> +  );
> +#endif
> +
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Include/Library/UsbDeviceLib.h b/Silicon/Synopsys/DesignWare/Include/Library/UsbDeviceLib.h
> new file mode 100644
> index 0000000000..fe5f3bcd03
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Include/Library/UsbDeviceLib.h
> @@ -0,0 +1,323 @@
> +/** @file
> +  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
> +
> +  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 _EFI_XDCI_LIB_H_
> +#define _EFI_XDCI_LIB_H_
> +
> +#include <Uefi.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/UsbIo.h>
> +
> +#define MAX_DESCRIPTOR_SIZE         64
> +#define STRING_ARR_SIZE             (MAX_DESCRIPTOR_SIZE - 2)
> +#define USB_ADDRESS_TABLE_SIZE      16  //4
> +
> +//
> +// Endpoint Zero
> +//
> +#define USB_EP0_MAX_PKT_SIZE_HS     0x40 // High Speed mode is explicitly set as 64 bytes
> +#define USB_EP0_MAX_PKT_SIZE_SS     0x9  // Must be 0x9 (2^9 = 512 Bytes) in SuperSpeed mode
> +#define USB_EPO_MAX_PKT_SIZE_ALL    512  // Overall max bytes for any type
> +
> +//
> +// Bulk Endpoints
> +//
> +#define USB_BULK_EP_PKT_SIZE_HS     0x200 // Bulk-Endpoint HighSpeed
> +#define USB_BULK_EP_PKT_SIZE_SS     0x400 // Bulk-Endpoint SuperSpeed
> +#define USB_BULK_EP_PKT_SIZE_MAX    USB_BULK_EP_PKT_SIZE_SS
> +
> +//
> +// Transmit Direction Bits
> +//
> +#define USB_ENDPOINT_DIR_OUT                 0x00
> +
> +//
> +// Endpoint Companion Bulk Attributes
> +//
> +#define USB_EP_BULK_BM_ATTR_MASK    0x1F
> +
> +//
> +// Configuration Modifiers (Attributes)
> +//
> +#define USB_BM_ATTR_RESERVED        0x80
> +#define USB_BM_ATTR_SELF_POWERED    0x40
> +#define USB_BM_ATTR_REMOTE_WAKE     0X20
> +
> +//
> +// USB BCD version
> +//
> +#define USB_BCD_VERSION_LS          0x0110
> +#define USB_BCD_VERSION_HS          0x0200
> +#define USB_BCD_VERSION_SS          0x0300
> +
> +//
> +// Device RequestType Flags
> +//
> +#define USB_RT_TX_DIR_H_TO_D        (0x0)       // Tx direction Host to Device
> +#define USB_RT_TX_DIR_D_TO_H        (0x1 << 7)  // Tx direction Device to Host
> +#define USB_RT_TX_DIR_MASK          (0x80)
> +
> +//
> +// USB request type
> +//
> +#define USB_REQ_TYPE_MASK           (0x60)
> +
> +//
> +// Usb control transfer target
> +//
> +#define USB_TARGET_MASK             (0x1F)
> +
> +//
> +// Device GetStatus bits
> +//
> +#define USB_STATUS_SELFPOWERED      (0x01)
> +#define USB_STATUS_REMOTEWAKEUP     (0x02)
> +
> +//
> +// USB Device class identifiers
> +//
> +#define USB_DEVICE_MS_CLASS         (0x08)
> +#define USB_DEVICE_VENDOR_CLASS     (0xFF)
> +
> +//
> +// USB Descriptor types
> +//
> +#define USB_DESC_TYPE_BOS                    0x0F
> +#define USB_DESC_TYPE_DEVICE_CAPABILITY      0x10
> +#define USB_DESC_TYPE_SS_ENDPOINT_COMPANION  0x30
> +
> +#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
> +
> +//
> +// USB device states from USB spec sec 9.1
> +//
> +typedef enum {
> +  UsbDevStateOff = 0,
> +  UsbDevStateInit,
> +  UsbDevStateAttached,
> +  UsbDevStatePowered,
> +  UsbDevStateDefault,
> +  UsbDevStateAddress,
> +  UsbDevStateConfigured,
> +  UsbDevStateSuspended,
> +  UsbDevStateError
> +} USB_DEVICE_STATE;
> +
> +//
> +// The following set of structs are used during USB data transaction
> +// operatitions, including requests and completion events.
> +//
> +#pragma pack(1)
> +
> +typedef struct {
> +  UINT32     EndpointNum;
> +  UINT8      EndpointDir;
> +  UINT8      EndpointType;
> +  UINT32     Length;
> +  VOID       *Buffer;
> +} EFI_USB_DEVICE_XFER_INFO;
> +
> +//
> +// SuperSpeed Endpoint companion descriptor
> +// USB3 table 9-22
> +//
> +typedef struct {
> +  UINT8      Length;
> +  UINT8      DescriptorType;
> +  UINT8      MaxBurst;
> +  UINT8      Attributes;
> +  UINT16     BytesPerInterval;
> +} EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR;
> +
> +typedef struct {
> +  EFI_USB_ENDPOINT_DESCRIPTOR              *EndpointDesc;
> +  EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR    *EndpointCompDesc;
> +} USB_DEVICE_ENDPOINT_INFO, USB_DEVICE_ENDPOINT_OBJ;
> +
> +typedef struct {
> +  VOID        *Buffer;
> +  UINT32      Length;
> +} USB_DEVICE_IO_INFO;
> +
> +typedef struct {
> +  USB_DEVICE_IO_INFO           IoInfo;
> +  USB_DEVICE_ENDPOINT_INFO     EndpointInfo;
> +} USB_DEVICE_IO_REQ;
> +
> +//
> +// Optional string descriptor
> +//
> +typedef struct {
> +  UINT8           Length;
> +  UINT8           DescriptorType;
> +  UINT16          LangID[STRING_ARR_SIZE];
> +} USB_STRING_DESCRIPTOR;
> +
> +//
> +// The following structures abstract the device descriptors a class
> +// driver needs to provide to the USBD core.
> +// These structures are filled & owned by the class/function layer.
> +//
> +typedef struct {
> +  EFI_USB_INTERFACE_DESCRIPTOR         *InterfaceDesc;
> +  USB_DEVICE_ENDPOINT_OBJ              *EndpointObjs;
> +} USB_DEVICE_INTERFACE_OBJ;
> +
> +typedef struct {
> +  EFI_USB_CONFIG_DESCRIPTOR     *ConfigDesc;
> +  VOID                          *ConfigAll;
> +  USB_DEVICE_INTERFACE_OBJ      *InterfaceObjs;
> +} USB_DEVICE_CONFIG_OBJ;
> +
> +#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
> +(EFIAPI *EFI_USB_CONFIG_CALLBACK) (
> +  IN UINT8                      CfgVal
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_SETUP_CALLBACK) (
> +  IN EFI_USB_DEVICE_REQUEST     *CtrlRequest,
> +  IN USB_DEVICE_IO_INFO         *IoInfo
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DATA_CALLBACK) (
> +  IN EFI_USB_DEVICE_XFER_INFO   *XferInfo
> +  );
> +
> +typedef struct {
> +  USB_DEVICE_DESCRIPTOR       *DeviceDesc;
> +  USB_DEVICE_CONFIG_OBJ       *ConfigObjs;
> +  USB_STRING_DESCRIPTOR       *StringTable;
> +#ifdef SUPPORT_SUPER_SPEED
> +  EFI_USB_BOS_DESCRIPTOR      *BosDesc;
> +#endif
> +  UINT8                       StrTblEntries;
> +  EFI_USB_CONFIG_CALLBACK     ConfigCallback;
> +  EFI_USB_SETUP_CALLBACK      SetupCallback;
> +  EFI_USB_DATA_CALLBACK       DataCallback;
> +} USB_DEVICE_OBJ;
> +
> +//
> +// Main USBD driver object structure containing all data necessary
> +// for USB device mode processing at this layer
> +//
> +typedef struct {
> +  USB_DEVICE_OBJ              *UsbdDevObj;      /* pointer to a Device Object */
> +  VOID                        *XdciDrvObj;      /* Opaque handle to XDCI driver */
> +  BOOLEAN                     XdciInitialized;  /* flag to specify if the XDCI driver is initialized */
> +  USB_DEVICE_CONFIG_OBJ       *ActiveConfigObj; /* pointer to currently active configuraiton */
> +  USB_DEVICE_STATE            State;            /* current state of the USB Device state machine */
> +  UINT8                       Address;          /* configured device address */
> +} USB_DEVICE_DRIVER_OBJ;
> +
> +#pragma pack()
> +
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Include/Protocol/EfiUsbFnIo.h b/Silicon/Synopsys/DesignWare/Include/Protocol/EfiUsbFnIo.h
> new file mode 100644
> index 0000000000..97f276f1cc
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Include/Protocol/EfiUsbFnIo.h
> @@ -0,0 +1,430 @@
> +/** @file
> +  EFI USB function IO Protocol
> +  This protocol supports Usb Function IO API.
> +  Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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 __EFI_USB_FUNC_IO_H__
> +#define __EFI_USB_FUNC_IO_H__
> +
> +#include <IndustryStandard/Usb.h>
> +
> +#define EFI_USBFN_IO_PROTOCOL_REVISION   0x00010001
> +
> +//
> +// {32D2963A-FE5D-4f30-B633-6E5DC55803CC}
> +// #define EFI_USBFN_IO_PROTOCOL_GUID  {0x32d2963a, 0xfe5d, 0x4f30, 0xb6, 0x33, 0x6e, 0x5d, 0xc5, 0x58, 0x3, 0xcc };
> +//
> +
> +typedef struct _EFI_USBFN_IO_PROTOCOL   EFI_USBFN_IO_PROTOCOL;
> +
> +//
> +// USB standard descriptors and reqeust
> +//
> +typedef USB_DEVICE_REQUEST        EFI_USB_DEVICE_REQUEST;
> +typedef USB_DEVICE_DESCRIPTOR     EFI_USB_DEVICE_DESCRIPTOR;
> +typedef USB_CONFIG_DESCRIPTOR     EFI_USB_CONFIG_DESCRIPTOR;
> +typedef USB_INTERFACE_DESCRIPTOR  EFI_USB_INTERFACE_DESCRIPTOR;
> +typedef USB_ENDPOINT_DESCRIPTOR   EFI_USB_ENDPOINT_DESCRIPTOR;
> +
> +typedef enum _EFI_USBFN_PORT_TYPE {
> +  EfiUsbUnknownPort = 0,
> +  EfiUsbStandardDownstreamPort,
> +  EfiUsbChargingDownstreamPort,
> +  EfiUsbDedicatedChargingPort,
> +  EfiUsbInvalidDedicatedChargingPort
> +} EFI_USBFN_PORT_TYPE;
> +
> +/**
> + USB_DEVICE_DESCRIPTOR, USB_CONFIG_DESCRIPTOR, USB_INTERFACE_DESCRIPTOR, and
> + USB_ENDPOINT_DESCRIPTOR are already defined
> + in UEFI spec 2.3, as par USB 2.0 spec.
> +**/
> +
> +typedef struct {
> +  EFI_USB_INTERFACE_DESCRIPTOR        *InterfaceDescriptor;
> +  EFI_USB_ENDPOINT_DESCRIPTOR         **EndpointDescriptorTable;
> +} EFI_USB_INTERFACE_INFO;
> +
> +typedef struct {
> +  EFI_USB_CONFIG_DESCRIPTOR           *ConfigDescriptor;
> +  EFI_USB_INTERFACE_INFO              **InterfaceInfoTable;
> +} EFI_USB_CONFIG_INFO;
> +
> +typedef struct {
> +  EFI_USB_DEVICE_DESCRIPTOR           *DeviceDescriptor;
> +  EFI_USB_CONFIG_INFO                 **ConfigInfoTable;
> +} EFI_USB_DEVICE_INFO;
> +
> +
> +typedef enum _EFI_USB_ENDPOINT_TYPE {
> +  UsbEndpointControl     = 0x00,
> +  UsbEndpointIsochronous = 0x01,
> +  UsbEndpointBulk        = 0x02,
> +  UsbEndpointInterrupt   = 0x03
> +} EFI_USB_ENDPOINT_TYPE;
> +
> +
> +typedef enum _EFI_USBFN_DEVICE_INFO_ID {
> +  EfiUsbDeviceInfoUnknown = 0,
> +  EfiUsbDeviceInfoSerialNumber,
> +  EfiUsbDeviceInfoManufacturerName,
> +  EfiUsbDeviceInfoProductName
> +} EFI_USBFN_DEVICE_INFO_ID;
> +
> +
> +typedef enum _EFI_USBFN_ENDPOINT_DIRECTION {
> +  EfiUsbEndpointDirectionHostOut  = 0,
> +  EfiUsbEndpointDirectionHostIn,
> +  EfiUsbEndpointDirectionDeviceTx = EfiUsbEndpointDirectionHostIn,
> +  EfiUsbEndpointDirectionDeviceRx = EfiUsbEndpointDirectionHostOut
> +} EFI_USBFN_ENDPOINT_DIRECTION;
> +
> +
> +typedef enum _EFI_USBFN_MESSAGE {
> +  //
> +  // Nothing
> +  //
> +  EfiUsbMsgNone = 0,
> +  //
> +  // SETUP packet is received, returned Buffer contains
> +  // EFI_USB_DEVICE_REQUEST struct
> +  //
> +  EfiUsbMsgSetupPacket,
> +  //
> +  // Indicates that some of the requested data has been received from the
> +  // host. It is the responsibility of the class driver to determine if it
> +  // needs to wait for any remaining data. Returned Buffer contains
> +  // EFI_USBFN_TRANSFER_RESULT struct containing endpoint number, transfer
> +  // status and count of bytes received.
> +  //
> +  EfiUsbMsgEndpointStatusChangedRx,
> +  //
> +  // Indicates that some of the requested data has been transmitted to the
> +  // host. It is the responsibility of the class driver to determine if any
> +  // remaining data needs to be resent. Returned Buffer contains
> +  // EFI_USBFN_TRANSFER_RESULT struct containing endpoint number, transfer
> +  // status and count of bytes sent.
> +  //
> +  EfiUsbMsgEndpointStatusChangedTx,
> +  //
> +  // DETACH bus event signaled
> +  //
> +  EfiUsbMsgBusEventDetach,
> +  //
> +  // ATTACH bus event signaled
> +  //
> +  EfiUsbMsgBusEventAttach,
> +  //
> +  // RESET bus event signaled
> +  //
> +  EfiUsbMsgBusEventReset,
> +  //
> +  // SUSPEND bus event signaled
> +  //
> +  EfiUsbMsgBusEventSuspend,
> +  //
> +  // RESUME bus event signaled
> +  //
> +  EfiUsbMsgBusEventResume,
> +  //
> +  // Bus speed updated, returned buffer indicated bus speed using
> +  // following enumeration named EFI_USB_BUS_SPEED
> +  //
> +  EfiUsbMsgBusEventSpeed
> +} EFI_USBFN_MESSAGE;
> +
> +
> +typedef enum _EFI_USBFN_TRANSFER_STATUS {
> +  UsbTransferStatusUnknown = 0,
> +  UsbTransferStatusComplete,
> +  UsbTransferStatusAborted,
> +  UsbTransferStatusActive,
> +  UsbTransferStatusNone
> +} EFI_USBFN_TRANSFER_STATUS;
> +
> +
> +typedef struct _EFI_USBFN_TRANSFER_RESULT {
> +  UINTN                         BytesTransferred;
> +  EFI_USBFN_TRANSFER_STATUS     TransferStatus;
> +  UINT8                         EndpointIndex;
> +  EFI_USBFN_ENDPOINT_DIRECTION  Direction;
> +  VOID                          *Buffer;
> +} EFI_USBFN_TRANSFER_RESULT;
> +
> +typedef enum _EFI_USB_BUS_SPEED {
> +  UsbBusSpeedUnknown = 0,
> +  UsbBusSpeedLow,
> +  UsbBusSpeedFull,
> +  UsbBusSpeedHigh,
> +  UsbBusSpeedSuper,
> +  UsbBusSpeedMaximum = UsbBusSpeedSuper
> +} EFI_USB_BUS_SPEED;
> +
> +typedef union _EFI_USBFN_MESSAGE_PAYLOAD {
> +  EFI_USB_DEVICE_REQUEST      udr;
> +  EFI_USBFN_TRANSFER_RESULT   utr;
> +  EFI_USB_BUS_SPEED           ubs;
> +} EFI_USBFN_MESSAGE_PAYLOAD;
> +
> +typedef enum _EFI_USBFN_POLICY_TYPE {
> +  EfiUsbPolicyUndefined = 0,
> +  EfiUsbPolicyMaxTransactionSize,
> +  EfiUsbPolicyZeroLengthTerminationSupport,
> +  EfiUsbPolicyZeroLengthTermination
> +} EFI_USBFN_POLICY_TYPE;
> +
> +
> +/**
> +
> + Allocates transfer buffer of the specified size that satisfies
> + controller requirements.
> +
> + The AllocateTransferBuffer function allocates a memory region of Size bytes and
> + returns the address of the allocated memory that satisfies underlying
> + controller requirements in the location referenced by Buffer.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_ALLOCATE_TRANSFER_BUFFER) (
> +  IN EFI_USBFN_IO_PROTOCOL    *This,
> +  IN UINTN                    Size,
> +  OUT VOID                    **Buffer
> +  );
> +
> +/**
> +
> +  Deallocates the memory allocated for the transfer buffer by AllocateTransferBuffer function.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_FREE_TRANSFER_BUFFER) (
> +  IN EFI_USBFN_IO_PROTOCOL    *This,
> +  IN VOID                     *Buffer
> +  );
> +
> +/**
> +  Returns information about what type of device was attached.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_DETECT_PORT) (
> +  IN EFI_USBFN_IO_PROTOCOL   *This,
> +  OUT EFI_USBFN_PORT_TYPE    *PortType
> +  );
> +
> +/**
> +  Configure endpoints based on supplied device and configuration descriptors.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_CONFIGURE_ENABLE_ENDPOINTS) (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN EFI_USB_DEVICE_INFO           *DeviceInfo
> +  );
> +
> +
> +/**
> +  Returns the maximum packet size of the specified endpoint type for the supplied bus speed.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_GET_ENDPOINT_MAXPACKET_SIZE) (
> +  IN EFI_USBFN_IO_PROTOCOL       *This,
> +  IN EFI_USB_ENDPOINT_TYPE       EndpointType,
> +  IN EFI_USB_BUS_SPEED           BusSpeed,
> +  OUT UINT16                     *MaxPacketSize
> +  );
> +
> +/**
> +  Returns the maximum supported transfer size.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_GET_MAXTRANSFER_SIZE) (
> +  IN EFI_USBFN_IO_PROTOCOL     *This,
> +  OUT UINTN                    *MaxTransferSize
> +  );
> +
> +/**
> +  Returns device specific information based on the supplied identifier as a
> +  Unicode string.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_GET_DEVICE_INFO) (
> +  IN EFI_USBFN_IO_PROTOCOL      *This,
> +  IN EFI_USBFN_DEVICE_INFO_ID   Id,
> +  IN OUT UINTN                  *BufferSize,
> +  OUT VOID                      *Buffer OPTIONAL
> +  );
> +
> +/**
> +  Returns vendor-id and product-id of the device.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_GET_VENDOR_ID_PRODUCT_ID) (
> +  IN EFI_USBFN_IO_PROTOCOL      *This,
> +  OUT UINT16                    *Vid,
> +  OUT UINT16                    *Pid
> +  );
> +
> +/**
> +  Aborts transfer on the specified endpoint.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_ABORT_TRANSFER) (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction
> +  );
> +
> +/**
> +  Returns the stall state on the specified endpoint.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_GET_ENDPOINT_STALL_STATE) (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN OUT BOOLEAN                  *State
> +  );
> +
> +/**
> +  Sets or clears the stall state on the specified endpoint.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_SET_ENDPOINT_STALL_STATE) (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN BOOLEAN                      State
> +  );
> +
> +
> +/**
> +  This function is called repeatedly to receive updates on USB bus states,
> +  receive, transmit status changes on endpoints and setup packet on endpoint 0.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_EVENTHANDLER) (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  OUT EFI_USBFN_MESSAGE           *Message,
> +  IN OUT UINTN                    *PayloadSize,
> +  OUT EFI_USBFN_MESSAGE_PAYLOAD   *Payload
> +  );
> +
> +/**
> +  Primary function to handle transfer in either direction based on specified
> +  direction and on the specified endpoint.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USBFN_IO_TRANSFER) (
> +  IN EFI_USBFN_IO_PROTOCOL         *This,
> +  IN UINT8                         EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION  Direction,
> +  IN OUT UINTN                     *BufferSize,
> +  IN OUT VOID                      *Buffer
> +  );
> +
> +/**
> +  This function supplies power to the USB controller if needed,
> +  initialize hardware and internal data structures, and then return.
> +
> +  The port must not be activated by this function.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_START_CONTROLLER) (
> +    IN EFI_USBFN_IO_PROTOCOL    *This
> +    );
> +
> +/**
> +  This function disables the hardware device by resetting the run/stop bit and
> +  power off the USB controller if needed.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_STOP_CONTROLLER) (
> +    IN EFI_USBFN_IO_PROTOCOL    *This
> +    );
> +
> +/**
> +  This function sets the configuration policy for the specified non-control endpoint.
> +
> +  Refer to the description for calling restrictions.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_SET_ENDPOINT_POLICY) (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN EFI_USBFN_POLICY_TYPE        PolicyType,
> +  IN UINTN                        BufferSize,
> +  IN VOID                         *Buffer
> +  );
> +
> +/**
> +  This function retrieves the configuration policy for the specified non-control endpoint.
> +
> +  There are no associated calling restrictions for this function.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_USBFN_IO_GET_ENDPOINT_POLICY) (
> +  IN EFI_USBFN_IO_PROTOCOL        *This,
> +  IN UINT8                        EndpointIndex,
> +  IN EFI_USBFN_ENDPOINT_DIRECTION Direction,
> +  IN EFI_USBFN_POLICY_TYPE        PolicyType,
> +  IN OUT UINTN                    *BufferSize,
> +  IN OUT VOID                     *Buffer
> +  );
> +
> +
> +struct _EFI_USBFN_IO_PROTOCOL {
> +  UINT32                                      Revision;
> +  EFI_USBFN_IO_DETECT_PORT                    DetectPort;
> +  EFI_USBFN_IO_CONFIGURE_ENABLE_ENDPOINTS     ConfigureEnableEndpoints;
> +  EFI_USBFN_IO_GET_ENDPOINT_MAXPACKET_SIZE    GetEndpointMaxPacketSize;
> +  EFI_USBFN_IO_GET_DEVICE_INFO                GetDeviceInfo;
> +  EFI_USBFN_IO_GET_VENDOR_ID_PRODUCT_ID       GetVendorIdProductId;
> +  EFI_USBFN_IO_ABORT_TRANSFER                 AbortTransfer;
> +  EFI_USBFN_IO_GET_ENDPOINT_STALL_STATE       GetEndpointStallState;
> +  EFI_USBFN_IO_SET_ENDPOINT_STALL_STATE       SetEndpointStallState;
> +  EFI_USBFN_IO_EVENTHANDLER                   EventHandler;
> +  EFI_USBFN_IO_TRANSFER                       Transfer;
> +  EFI_USBFN_IO_GET_MAXTRANSFER_SIZE           GetMaxTransferSize;
> +  EFI_USBFN_IO_ALLOCATE_TRANSFER_BUFFER       AllocateTransferBuffer;
> +  EFI_USBFN_IO_FREE_TRANSFER_BUFFER           FreeTransferBuffer;
> +  //
> +  // Valid for version EFI_USBFN_IO_PROTOCOL_REVISION2 and above
> +  //
> +  EFI_USBFN_IO_START_CONTROLLER               StartController;
> +  EFI_USBFN_IO_STOP_CONTROLLER                StopController;
> +  EFI_USBFN_IO_SET_ENDPOINT_POLICY            SetEndpointPolicy;
> +  EFI_USBFN_IO_GET_ENDPOINT_POLICY            GetEndpointPolicy;
> +};
> +
> +
> +extern EFI_GUID gEfiUsbFnIoProtocolGuid;
> +#endif
> +
> diff --git a/Silicon/Synopsys/DesignWare/Include/Protocol/UsbDeviceModeProtocol.h b/Silicon/Synopsys/DesignWare/Include/Protocol/UsbDeviceModeProtocol.h
> new file mode 100644
> index 0000000000..c301fa00d3
> --- /dev/null
> +++ b/Silicon/Synopsys/DesignWare/Include/Protocol/UsbDeviceModeProtocol.h
> @@ -0,0 +1,104 @@
> +/** @file
> +  Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> +  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_MODE_PROTOCOL_H_
> +#define _USB_DEVICE_MODE_PROTOCOL_H_
> +
> +#include <Library/UsbDeviceLib.h>
> +
> +///
> +/// UsbDeviceMode Protocol GUID.
> +///
> +#define EFI_USB_DEVICE_MODE_PROTOCOL_GUID \
> +  {0xC9923F7E, 0x1746, 0x4802, { 0x86, 0x2e, 0x1, 0x1c, 0x2c, 0x2d, 0x9d, 0x86 } }
> +
> +typedef struct _EFI_USB_DEVICE_MODE_PROTOCOL EFI_USB_DEVICE_MODE_PROTOCOL;
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_INIT_XDCI) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_CONNECT) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_DISCONNECT) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_EP_TX_DATA) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This,
> +  IN USB_DEVICE_IO_REQ                          *IoRequest
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_EP_RX_DATA) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This,
> +  IN USB_DEVICE_IO_REQ                          *IoRequest
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_BIND) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This,
> +  IN USB_DEVICE_OBJ                             *UsbdDevObj
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_UNBIND) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_STOP) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This
> +  );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_USB_DEVICE_MODE_RUN) (
> +  IN EFI_USB_DEVICE_MODE_PROTOCOL               *This,
> +  IN UINT32                                     TimeoutMs
> +  );
> +
> +///
> +/// Usb Device Mode Protocol Structure.
> +///
> +struct _EFI_USB_DEVICE_MODE_PROTOCOL {
> +  EFI_USB_DEVICE_MODE_INIT_XDCI            InitXdci;
> +  EFI_USB_DEVICE_MODE_CONNECT              Connect;
> +  EFI_USB_DEVICE_MODE_DISCONNECT           DisConnect;
> +  EFI_USB_DEVICE_EP_TX_DATA                EpTxData;
> +  EFI_USB_DEVICE_EP_RX_DATA                EpRxData;
> +  EFI_USB_DEVICE_MODE_BIND                 Bind;
> +  EFI_USB_DEVICE_MODE_UNBIND               UnBind;
> +  EFI_USB_DEVICE_MODE_RUN                  Run;
> +  EFI_USB_DEVICE_MODE_STOP                 Stop;
> +};
> +
> +extern EFI_GUID gEfiUsbDeviceModeProtocolGuid;
> +
> +#endif
> +
> -- 
> 2.27.0.windows.1
> 

  reply	other threads:[~2020-07-20 17:43 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-17 10:01 [edk2-platforms PATCH 1/5] Silicon/Synopsys/DesignWare: Import DesignWare USB3 peripheral driver Vin Xue
2020-07-20 17:43 ` Leif Lindholm [this message]
2020-07-21  3:51   ` Vin Xue
2020-07-30 12:18     ` Leif Lindholm
2020-08-05 10:50       ` Vin Xue
2020-07-21  8:17   ` Meenakshi Aggarwal (OSS)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200720174324.GR12303@vanye \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox