]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/XhciDxe: Event Ring traverse algorithm enhancement to avoid that those...
authorerictian <erictian@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 27 Mar 2012 12:07:38 +0000 (12:07 +0000)
committererictian <erictian@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 27 Mar 2012 12:07:38 +0000 (12:07 +0000)
Signed-off-by: erictian
Reviewed-by: li-elvin
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13145 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c

index 0c08301e9ba4b92b3ad8a9ac1fbfafecdd37c3e5..566d3a6bc2958ec3df121e6ca2065cb4ab4fe6c8 100644 (file)
-/** @file\r
-  The XHCI controller driver.\r
-\r
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Xhci.h"\r
-\r
-//\r
-// Two arrays used to translate the XHCI port state (change)\r
-// to the UEFI protocol's port state (change).\r
-//\r
-USB_PORT_STATE_MAP  mUsbPortStateMap[] = {\r
-  {XHC_PORTSC_CCS,   USB_PORT_STAT_CONNECTION},\r
-  {XHC_PORTSC_PED,   USB_PORT_STAT_ENABLE},\r
-  {XHC_PORTSC_OCA,   USB_PORT_STAT_OVERCURRENT},\r
-  {XHC_PORTSC_RESET, USB_PORT_STAT_RESET}\r
-};\r
-\r
-USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {\r
-  {XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},\r
-  {XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},\r
-  {XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},\r
-  {XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}\r
-};\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL  gXhciDriverBinding = {\r
-  XhcDriverBindingSupported,\r
-  XhcDriverBindingStart,\r
-  XhcDriverBindingStop,\r
-  0x30,\r
-  NULL,\r
-  NULL\r
-};\r
-\r
-//\r
-// Template for Xhci's Usb2 Host Controller Protocol Instance.\r
-//\r
-EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {\r
-  XhcGetCapability,\r
-  XhcReset,\r
-  XhcGetState,\r
-  XhcSetState,\r
-  XhcControlTransfer,\r
-  XhcBulkTransfer,\r
-  XhcAsyncInterruptTransfer,\r
-  XhcSyncInterruptTransfer,\r
-  XhcIsochronousTransfer,\r
-  XhcAsyncIsochronousTransfer,\r
-  XhcGetRootHubPortStatus,\r
-  XhcSetRootHubPortFeature,\r
-  XhcClearRootHubPortFeature,\r
-  0x3,\r
-  0x0\r
-};\r
-\r
-/**\r
-  Retrieves the capability of root hub ports.\r
-\r
-  @param  This                  The EFI_USB2_HC_PROTOCOL instance.\r
-  @param  MaxSpeed              Max speed supported by the controller.\r
-  @param  PortNumber            Number of the root hub ports.\r
-  @param  Is64BitCapable        Whether the controller supports 64-bit memory\r
-                                addressing.\r
-\r
-  @retval EFI_SUCCESS           Host controller capability were retrieved successfully.\r
-  @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcGetCapability (\r
-  IN  EFI_USB2_HC_PROTOCOL  *This,\r
-  OUT UINT8                 *MaxSpeed,\r
-  OUT UINT8                 *PortNumber,\r
-  OUT UINT8                 *Is64BitCapable\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE  *Xhc;\r
-  EFI_TPL            OldTpl;\r
-\r
-  if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl          = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc             = XHC_FROM_THIS (This);\r
-  *MaxSpeed       = EFI_USB_SPEED_SUPER;\r
-  *PortNumber     = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);\r
-  *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);\r
-  DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Provides software reset for the USB host controller.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  Attributes            A bit mask of the reset operation to perform.\r
-\r
-  @retval EFI_SUCCESS           The reset operation succeeded.\r
-  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
-  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is\r
-                                not currently supported by the host controller.\r
-  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcReset (\r
-  IN EFI_USB2_HC_PROTOCOL  *This,\r
-  IN UINT16                Attributes\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE  *Xhc;\r
-  EFI_STATUS         Status;\r
-  EFI_TPL            OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc    = XHC_FROM_THIS (This);\r
-\r
-  switch (Attributes) {\r
-  case EFI_USB_HC_RESET_GLOBAL:\r
-  //\r
-  // Flow through, same behavior as Host Controller Reset\r
-  //\r
-  case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
-    //\r
-    // Host Controller must be Halt when Reset it\r
-    //\r
-    if (!XhcIsHalt (Xhc)) {\r
-      Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        Status = EFI_DEVICE_ERROR;\r
-        goto ON_EXIT;\r
-      }\r
-    }\r
-\r
-    Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);\r
-    ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-    //\r
-    // Clean up the asynchronous transfers, currently only\r
-    // interrupt supports asynchronous operation.\r
-    //\r
-    XhciDelAllAsyncIntTransfers (Xhc);\r
-    XhcFreeSched (Xhc);\r
-\r
-    XhcInitSched (Xhc);\r
-    break;\r
-\r
-  case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:\r
-  case EFI_USB_HC_RESET_HOST_WITH_DEBUG:\r
-    Status = EFI_UNSUPPORTED;\r
-    break;\r
-\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-ON_EXIT:\r
-  DEBUG ((EFI_D_INFO, "XhcReset: status %r\n", Status));\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Retrieve the current state of the USB host controller.\r
-\r
-  @param  This                   This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  State                  Variable to return the current host controller\r
-                                 state.\r
-\r
-  @retval EFI_SUCCESS            Host controller state was returned in State.\r
-  @retval EFI_INVALID_PARAMETER  State is NULL.\r
-  @retval EFI_DEVICE_ERROR       An error was encountered while attempting to\r
-                                 retrieve the host controller's current state.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcGetState (\r
-  IN  EFI_USB2_HC_PROTOCOL  *This,\r
-  OUT EFI_USB_HC_STATE      *State\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE  *Xhc;\r
-  EFI_TPL            OldTpl;\r
-\r
-  if (State == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc    = XHC_FROM_THIS (This);\r
-\r
-  if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {\r
-    *State = EfiUsbHcStateHalt;\r
-  } else {\r
-    *State = EfiUsbHcStateOperational;\r
-  }\r
-\r
-  DEBUG ((EFI_D_INFO, "XhcGetState: current state %d\n", *State));\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Sets the USB host controller to a specific state.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  State                 The state of the host controller that will be set.\r
-\r
-  @retval EFI_SUCCESS           The USB host controller was successfully placed\r
-                                in the state specified by State.\r
-  @retval EFI_INVALID_PARAMETER State is invalid.\r
-  @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcSetState (\r
-  IN EFI_USB2_HC_PROTOCOL  *This,\r
-  IN EFI_USB_HC_STATE      State\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE   *Xhc;\r
-  EFI_STATUS          Status;\r
-  EFI_USB_HC_STATE    CurState;\r
-  EFI_TPL             OldTpl;\r
-\r
-  Status = XhcGetState (This, &CurState);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  if (CurState == State) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc    = XHC_FROM_THIS (This);\r
-\r
-  switch (State) {\r
-  case EfiUsbHcStateHalt:\r
-    Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-    break;\r
-\r
-  case EfiUsbHcStateOperational:\r
-    if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE)) {\r
-      Status = EFI_DEVICE_ERROR;\r
-      break;\r
-    }\r
-\r
-    //\r
-    // Software must not write a one to this field unless the host controller\r
-    // is in the Halted state. Doing so will yield undefined results.\r
-    // refers to Spec[XHCI1.0-2.3.1]\r
-    //\r
-    if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {\r
-      Status = EFI_DEVICE_ERROR;\r
-      break;\r
-    }\r
-\r
-    Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-    break;\r
-\r
-  case EfiUsbHcStateSuspend:\r
-    Status = EFI_UNSUPPORTED;\r
-    break;\r
-\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  DEBUG ((EFI_D_INFO, "XhcSetState: status %r\n", Status));\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Retrieves the current status of a USB root hub port.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  PortNumber            The root hub port to retrieve the state from.\r
-                                This value is zero-based.\r
-  @param  PortStatus            Variable to receive the port state.\r
-\r
-  @retval EFI_SUCCESS           The status of the USB root hub port specified.\r
-                                by PortNumber was returned in PortStatus.\r
-  @retval EFI_INVALID_PARAMETER PortNumber is invalid.\r
-  @retval EFI_DEVICE_ERROR      Can't read register.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcGetRootHubPortStatus (\r
-  IN  EFI_USB2_HC_PROTOCOL  *This,\r
-  IN  UINT8                 PortNumber,\r
-  OUT EFI_USB_PORT_STATUS   *PortStatus\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  UINT32                  Offset;\r
-  UINT32                  State;\r
-  UINT32                  TotalPort;\r
-  UINTN                   Index;\r
-  UINTN                   MapSize;\r
-  EFI_STATUS              Status;\r
-  USB_DEV_ROUTE           ParentRouteChart;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  if (PortStatus == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc       = XHC_FROM_THIS (This);\r
-  Status    = EFI_SUCCESS;\r
-\r
-  TotalPort = Xhc->HcSParams1.Data.MaxPorts;\r
-\r
-  if (PortNumber >= TotalPort) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Offset                       = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
-  PortStatus->PortStatus       = 0;\r
-  PortStatus->PortChangeStatus = 0;\r
-\r
-  State = XhcReadOpReg (Xhc, Offset);\r
-\r
-  //\r
-  // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.\r
-  //\r
-  switch ((State & XHC_PORTSC_PS) >> 10) {\r
-  case 2:\r
-    PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
-    break;\r
-\r
-  case 3:\r
-    PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
-    break;\r
-\r
-  case 4:\r
-    PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
-    break;\r
-\r
-  default:\r
-    break;\r
-  }\r
-\r
-  //\r
-  // Convert the XHCI port/port change state to UEFI status\r
-  //\r
-  MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
-\r
-  for (Index = 0; Index < MapSize; Index++) {\r
-    if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {\r
-      PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);\r
-    }\r
-  }\r
-  //\r
-  // Bit5~8 reflects its current link state.\r
-  //\r
-  if ((State & XHC_PORTSC_PLS) >> 5 == 3) {\r
-    PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
-  }\r
-\r
-  MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
-\r
-  for (Index = 0; Index < MapSize; Index++) {\r
-    if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {\r
-      PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
-    }\r
-  }\r
-\r
-  //\r
-  // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.\r
-  // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.\r
-  //\r
-  ParentRouteChart.Dword = 0;\r
-  XhcPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Sets a feature for the specified root hub port.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  PortNumber            Root hub port to set.\r
-  @param  PortFeature           Feature to set.\r
-\r
-  @retval EFI_SUCCESS           The feature specified by PortFeature was set.\r
-  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
-  @retval EFI_DEVICE_ERROR      Can't read register.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcSetRootHubPortFeature (\r
-  IN EFI_USB2_HC_PROTOCOL  *This,\r
-  IN UINT8                 PortNumber,\r
-  IN EFI_USB_PORT_FEATURE  PortFeature\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  UINT32                  Offset;\r
-  UINT32                  State;\r
-  UINT32                  TotalPort;\r
-  UINT8                   SlotId;\r
-  USB_DEV_ROUTE           RouteChart;\r
-  EFI_STATUS              Status;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc    = XHC_FROM_THIS (This);\r
-  Status = EFI_SUCCESS;\r
-\r
-  TotalPort = (Xhc->HcSParams1.Data.MaxPorts);\r
-\r
-  if (PortNumber >= TotalPort) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
-  State  = XhcReadOpReg (Xhc, Offset);\r
-\r
-  //\r
-  // Mask off the port status change bits, these bits are\r
-  // write clean bit\r
-  //\r
-  State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);\r
-\r
-  switch (PortFeature) {\r
-  case EfiUsbPortEnable:\r
-    //\r
-    // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.\r
-    // A port may be disabled by software writing a '1' to this flag.\r
-    //\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  case EfiUsbPortSuspend:\r
-    State |= XHC_PORTSC_LWS;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    State &= ~XHC_PORTSC_PLS;\r
-    State |= (3 << 5) ;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortReset:\r
-    DEBUG ((EFI_D_INFO, "XhcUsbPortReset!\n"));\r
-    //\r
-    // Make sure Host Controller not halt before reset it\r
-    //\r
-    if (XhcIsHalt (Xhc)) {\r
-      Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature :failed to start HC - %r\n", Status));\r
-        break;\r
-      }\r
-    }\r
-\r
-    RouteChart.Route.RouteString = 0;\r
-    RouteChart.Route.RootPortNum = PortNumber + 1;\r
-    RouteChart.Route.TierNum     = 1;\r
-    //\r
-    // If the port reset operation happens after the usb super speed device is enabled,\r
-    // The subsequent configuration, such as getting device descriptor, will fail.\r
-    // So here a workaround is introduced to skip the reset operation if the device is enabled.\r
-    //\r
-    SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
-    if (SlotId == 0) {\r
-      //\r
-      // 4.3.1 Resetting a Root Hub Port\r
-      // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.\r
-      //\r
-      State |= XHC_PORTSC_RESET;\r
-      XhcWriteOpReg (Xhc, Offset, State);\r
-      XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);\r
-    }\r
-    break;\r
-\r
-  case EfiUsbPortPower:\r
-    //\r
-    // Not supported, ignore the operation\r
-    //\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  case EfiUsbPortOwner:\r
-    //\r
-    // XHCI root hub port don't has the owner bit, ignore the operation\r
-    //\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-ON_EXIT:\r
-  DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature: status %r\n", Status));\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Clears a feature for the specified root hub port.\r
-\r
-  @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-  @param  PortNumber            Specifies the root hub port whose feature is\r
-                                requested to be cleared.\r
-  @param  PortFeature           Indicates the feature selector associated with the\r
-                                feature clear request.\r
-\r
-  @retval EFI_SUCCESS           The feature specified by PortFeature was cleared\r
-                                for the USB root hub port specified by PortNumber.\r
-  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
-  @retval EFI_DEVICE_ERROR      Can't read register.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcClearRootHubPortFeature (\r
-  IN EFI_USB2_HC_PROTOCOL  *This,\r
-  IN UINT8                 PortNumber,\r
-  IN EFI_USB_PORT_FEATURE  PortFeature\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  UINT32                  Offset;\r
-  UINT32                  State;\r
-  UINT32                  TotalPort;\r
-  EFI_STATUS              Status;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc       = XHC_FROM_THIS (This);\r
-  Status    = EFI_SUCCESS;\r
-\r
-  TotalPort = (Xhc->HcSParams1.Data.MaxPorts);\r
-\r
-  if (PortNumber >= TotalPort) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Offset = XHC_PORTSC_OFFSET + (0x10 * PortNumber);\r
-\r
-  //\r
-  // Mask off the port status change bits, these bits are\r
-  // write clean bit\r
-  //\r
-  State  = XhcReadOpReg (Xhc, Offset);\r
-  State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);\r
-\r
-  switch (PortFeature) {\r
-  case EfiUsbPortEnable:\r
-    //\r
-    // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.\r
-    // A port may be disabled by software writing a '1' to this flag.\r
-    //\r
-    State |= XHC_PORTSC_PED;\r
-    State &= ~XHC_PORTSC_RESET;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortSuspend:\r
-    State |= XHC_PORTSC_LWS;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    State &= ~XHC_PORTSC_PLS;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortReset:\r
-    //\r
-    // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:\r
-    // Register bits indicate status when read, a clear bit may be set by\r
-    // writing a '1'. Writing a '0' to RW1S bits has no effect.\r
-    //\r
-    break;\r
-\r
-  case EfiUsbPortOwner:\r
-    //\r
-    // XHCI root hub port don't has the owner bit, ignore the operation\r
-    //\r
-    break;\r
-\r
-  case EfiUsbPortConnectChange:\r
-    //\r
-    // Clear connect status change\r
-    //\r
-    State |= XHC_PORTSC_CSC;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortEnableChange:\r
-    //\r
-    // Clear enable status change\r
-    //\r
-    State |= XHC_PORTSC_PEC;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortOverCurrentChange:\r
-    //\r
-    // Clear PortOverCurrent change\r
-    //\r
-    State |= XHC_PORTSC_OCC;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortResetChange:\r
-    //\r
-    // Clear Port Reset change\r
-    //\r
-    State |= XHC_PORTSC_PRC;\r
-    XhcWriteOpReg (Xhc, Offset, State);\r
-    break;\r
-\r
-  case EfiUsbPortPower:\r
-  case EfiUsbPortSuspendChange:\r
-    //\r
-    // Not supported or not related operation\r
-    //\r
-    break;\r
-\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-    break;\r
-  }\r
-\r
-ON_EXIT:\r
-  DEBUG ((EFI_D_INFO, "XhcClearRootHubPortFeature: status %r\n", Status));\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Submits control transfer to a target USB device.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress         The target device address.\r
-  @param  DeviceSpeed           Target device speed.\r
-  @param  MaximumPacketLength   Maximum packet size the default control transfer\r
-                                endpoint is capable of sending or receiving.\r
-  @param  Request               USB device request to send.\r
-  @param  TransferDirection     Specifies the data direction for the data stage\r
-  @param  Data                  Data buffer to be transmitted or received from USB\r
-                                device.\r
-  @param  DataLength            The size (in bytes) of the data buffer.\r
-  @param  Timeout               Indicates the maximum timeout, in millisecond.\r
-  @param  Translator            Transaction translator to be used by this device.\r
-  @param  TransferResult        Return the result of this control transfer.\r
-\r
-  @retval EFI_SUCCESS           Transfer was completed successfully.\r
-  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.\r
-  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
-  @retval EFI_TIMEOUT           Transfer failed due to timeout.\r
-  @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcControlTransfer (\r
-  IN     EFI_USB2_HC_PROTOCOL                *This,\r
-  IN     UINT8                               DeviceAddress,\r
-  IN     UINT8                               DeviceSpeed,\r
-  IN     UINTN                               MaximumPacketLength,\r
-  IN     EFI_USB_DEVICE_REQUEST              *Request,\r
-  IN     EFI_USB_DATA_DIRECTION              TransferDirection,\r
-  IN OUT VOID                                *Data,\r
-  IN OUT UINTN                               *DataLength,\r
-  IN     UINTN                               Timeout,\r
-  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
-  OUT    UINT32                              *TransferResult\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   Endpoint;\r
-  UINT8                   Index;\r
-  UINT8                   DescriptorType;\r
-  UINT8                   SlotId;\r
-  UINT8                   TTT;\r
-  UINT8                   MTT;\r
-  UINT32                  MaxPacket0;\r
-  EFI_USB_HUB_DESCRIPTOR  *HubDesc;\r
-  EFI_TPL                 OldTpl;\r
-  EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
-  UINTN                   MapSize;\r
-  EFI_USB_PORT_STATUS     PortStatus;\r
-  UINT32                  State;\r
-\r
-  //\r
-  // Validate parameters\r
-  //\r
-  if ((Request == NULL) || (TransferResult == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((TransferDirection != EfiUsbDataIn) &&\r
-      (TransferDirection != EfiUsbDataOut) &&\r
-      (TransferDirection != EfiUsbNoData)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((TransferDirection == EfiUsbNoData) &&\r
-      ((Data != NULL) || (*DataLength != 0))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((TransferDirection != EfiUsbNoData) &&\r
-     ((Data == NULL) || (*DataLength == 0))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&\r
-      (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&\r
-      (MaximumPacketLength != 512)\r
-      ) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc             = XHC_FROM_THIS (This);\r
-\r
-  Status          = EFI_DEVICE_ERROR;\r
-  *TransferResult = EFI_USB_ERR_SYSTEM;\r
-\r
-  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Check if the device is still enabled before every transaction.\r
-  //\r
-  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
-  if (SlotId == 0) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Hook the Set_Address request from UsbBus.\r
-  // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.\r
-  //\r
-  if ((Request->Request     == USB_REQ_SET_ADDRESS) &&\r
-      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
-    //\r
-    // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.\r
-    // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().\r
-    //\r
-    for (Index = 0; Index < 255; Index++) {\r
-      if (!Xhc->UsbDevContext[Index + 1].Enabled &&\r
-          (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&\r
-          (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {\r
-        Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;\r
-      }\r
-    }\r
-    //\r
-    // The actual device address has been assigned by XHCI during initializing the device slot.\r
-    // So we just need establish the mapping relationship between the device address requested from UsbBus\r
-    // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface\r
-    // can find out the actual device address by it.\r
-    //\r
-    Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
-    Status = EFI_SUCCESS;\r
-    goto ON_EXIT;\r
-  }\r
-  \r
-  //\r
-  // If the port reset operation happens after the usb super speed device is enabled,\r
-  // The subsequent configuration, such as getting device descriptor, will fail.\r
-  // So here a workaround is introduced to skip the reset operation if the device is enabled.\r
-  //\r
-  if ((Request->Request     == USB_REQ_SET_FEATURE) &&\r
-      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)) &&\r
-      (Request->Value       == EfiUsbPortReset)) {\r
-    if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
-      Status = EFI_SUCCESS;\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Create a new URB, insert it into the asynchronous\r
-  // schedule list, then poll the execution status.\r
-  // Note that we encode the direction in address although default control\r
-  // endpoint is bidirectional. XhcCreateUrb expects this\r
-  // combination of Ep addr and its direction.\r
-  //\r
-  Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          Endpoint,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_CTRL_TRANSFER,\r
-          Request,\r
-          Data,\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
-\r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-  ASSERT (Urb->EvtRing == &Xhc->EventRing);\r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
-\r
-  //\r
-  // Get the status from URB. The result is updated in XhcCheckUrbResult\r
-  // which is called by XhcExecTransfer\r
-  //\r
-  *TransferResult = Urb->Result;\r
-  *DataLength     = Urb->Completed;\r
-\r
-  if (*TransferResult == EFI_USB_NOERROR) {\r
-    Status = EFI_SUCCESS;\r
-  } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    ASSERT_EFI_ERROR (RecoveryStatus);\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto FREE_URB;\r
-  } else {\r
-    goto FREE_URB;\r
-  }\r
-\r
-  //\r
-  // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.\r
-  // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.\r
-  // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
-  //\r
-  if ((Request->Request     == USB_REQ_GET_DESCRIPTOR) &&\r
-      ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) || \r
-      ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {\r
-    DescriptorType = (UINT8)(Request->Value >> 8);\r
-    if ((DescriptorType == USB_DESC_TYPE_DEVICE) && (*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR))) {\r
-        ASSERT (Data != NULL);\r
-        //\r
-        // Store a copy of device scriptor as hub device need this info to configure endpoint.\r
-        //\r
-        CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
-        if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\r
-          //\r
-          // If it's a usb3.0 device, then its max packet size is a 2^n.\r
-          //\r
-          MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
-        } else {\r
-          MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
-        }\r
-        Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
-        if (Xhc->HcCParams.Data.Csz == 0) {\r
-          Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);\r\r
-        } else {\r
-          Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);\r\r
-        }\r
-        ASSERT_EFI_ERROR (Status);\r
-    } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {\r
-      ASSERT (Data != NULL);\r
-      if (*DataLength == ((UINT16 *)Data)[1]) {\r
-        //\r
-        // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.\r
-        //\r
-        Index = (UINT8)Request->Value;\r
-        ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);\r
-        Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);\r
-        CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\r
-      }\r
-    } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||\r
-               (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {\r
-      ASSERT (Data != NULL);\r
-      HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;\r
-      ASSERT (HubDesc->NumPorts <= 15);\r
-      //\r
-      // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.\r
-      //\r
-      TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);\r
-      if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
-        //\r
-        // Don't support multi-TT feature for super speed hub now.\r
-        //\r
-        MTT = 0;\r
-        DEBUG ((EFI_D_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));\r
-      } else {\r
-        MTT = 0;\r
-      }\r
-\r
-      if (Xhc->HcCParams.Data.Csz == 0) {\r
-        Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);\r
-      } else {\r
-        Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);\r
-      }\r
-      ASSERT_EFI_ERROR (Status);\r
-    }\r
-  } else if ((Request->Request     == USB_REQ_SET_CONFIG) &&\r
-             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
-    //\r
-    // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
-    //\r
-    for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
-      if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
-        if (Xhc->HcCParams.Data.Csz == 0) {\r
-          Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
-        } else {\r
-          Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
-        }\r
-        ASSERT_EFI_ERROR (Status);\r
-        break;\r
-      }\r
-    }\r
-  } else if ((Request->Request     == USB_REQ_GET_STATUS) &&\r
-             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {\r
-    ASSERT (Data != NULL);\r
-    //\r
-    // Hook Get_Status request from UsbBus to keep track of the port status change.\r
-    //\r
-    State                       = *(UINT32 *)Data;\r
-    PortStatus.PortStatus       = 0;\r
-    PortStatus.PortChangeStatus = 0;\r
-\r
-    if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
-      //\r
-      // For super speed hub, its bit10~12 presents the attached device speed.\r
-      //\r
-      if ((State & XHC_PORTSC_PS) >> 10 == 0) {\r
-        PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
-      }\r
-    } else if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
-      //\r
-      // For high speed hub, its bit9~10 presents the attached device speed.\r
-      //\r
-      if (XHC_BIT_IS_SET (State, BIT9)) {\r
-        PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
-      } else if (XHC_BIT_IS_SET (State, BIT10)) {\r
-        PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
-      }\r
-    } else {\r
-      ASSERT (0);\r
-    }\r
-\r
-    //\r
-    // Convert the XHCI port/port change state to UEFI status\r
-    //\r
-    MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
-    for (Index = 0; Index < MapSize; Index++) {\r
-      if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {\r
-        PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbPortStateMap[Index].UefiState);\r
-      }\r
-    }\r
-    MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
-\r
-    for (Index = 0; Index < MapSize; Index++) {\r
-      if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {\r
-      PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
-      }\r
-    }\r
-\r
-    XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
-  }\r
-\r
-FREE_URB:\r
-  FreePool (Urb);\r
-\r
-ON_EXIT:\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
-  }\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Submits bulk transfer to a bulk endpoint of a USB device.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress         Target device address.\r
-  @param  EndPointAddress       Endpoint number and its direction in bit 7.\r
-  @param  DeviceSpeed           Device speed, Low speed device doesn't support bulk\r
-                                transfer.\r
-  @param  MaximumPacketLength   Maximum packet size the endpoint is capable of\r
-                                sending or receiving.\r
-  @param  DataBuffersNumber     Number of data buffers prepared for the transfer.\r
-  @param  Data                  Array of pointers to the buffers of data to transmit\r
-                                from or receive into.\r
-  @param  DataLength            The lenght of the data buffer.\r
-  @param  DataToggle            On input, the initial data toggle for the transfer;\r
-                                On output, it is updated to to next data toggle to\r
-                                use of the subsequent bulk transfer.\r
-  @param  Timeout               Indicates the maximum time, in millisecond, which\r
-                                the transfer is allowed to complete.\r
-  @param  Translator            A pointr to the transaction translator data.\r
-  @param  TransferResult        A pointer to the detailed result information of the\r
-                                bulk transfer.\r
-\r
-  @retval EFI_SUCCESS           The transfer was completed successfully.\r
-  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
-  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
-  @retval EFI_TIMEOUT           The transfer failed due to timeout.\r
-  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcBulkTransfer (\r
-  IN     EFI_USB2_HC_PROTOCOL                *This,\r
-  IN     UINT8                               DeviceAddress,\r
-  IN     UINT8                               EndPointAddress,\r
-  IN     UINT8                               DeviceSpeed,\r
-  IN     UINTN                               MaximumPacketLength,\r
-  IN     UINT8                               DataBuffersNumber,\r
-  IN OUT VOID                                *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
-  IN OUT UINTN                               *DataLength,\r
-  IN OUT UINT8                               *DataToggle,\r
-  IN     UINTN                               Timeout,\r
-  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
-  OUT    UINT32                              *TransferResult\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   SlotId;\r
-  EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  //\r
-  // Validate the parameters\r
-  //\r
-  if ((DataLength == NULL) || (*DataLength == 0) ||\r
-      (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((*DataToggle != 0) && (*DataToggle != 1)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||\r
-      ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
-      ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)) ||\r
-      ((EFI_USB_SPEED_SUPER == DeviceSpeed) && (MaximumPacketLength > 1024))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc             = XHC_FROM_THIS (This);\r
-\r
-  *TransferResult = EFI_USB_ERR_SYSTEM;\r
-  Status          = EFI_DEVICE_ERROR;\r
-\r
-  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: HC is halted\n"));\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Check if the device is still enabled before every transaction.\r
-  //\r
-  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
-  if (SlotId == 0) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Create a new URB, insert it into the asynchronous\r
-  // schedule list, then poll the execution status.\r
-  //\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          EndPointAddress,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_BULK_TRANSFER,\r
-          NULL,\r
-          Data[0],\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
-\r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  ASSERT (Urb->EvtRing == &Xhc->EventRing);\r
-\r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
-\r
-  *TransferResult = Urb->Result;\r
-  *DataLength     = Urb->Completed;\r
-\r
-  if (*TransferResult == EFI_USB_NOERROR) {\r
-    Status = EFI_SUCCESS;\r
-  } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    ASSERT_EFI_ERROR (RecoveryStatus);\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  FreePool (Urb);\r
-\r
-ON_EXIT:\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
-  }\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Submits an asynchronous interrupt transfer to an\r
-  interrupt endpoint of a USB device.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress         Target device address.\r
-  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7\r
-  @param  DeviceSpeed           Indicates device speed.\r
-  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable\r
-  @param  IsNewTransfer         If TRUE, to submit an new asynchronous interrupt\r
-                                transfer If FALSE, to remove the specified\r
-                                asynchronous interrupt.\r
-  @param  DataToggle            On input, the initial data toggle to use; on output,\r
-                                it is updated to indicate the next data toggle.\r
-  @param  PollingInterval       The he interval, in milliseconds, that the transfer\r
-                                is polled.\r
-  @param  DataLength            The length of data to receive at the rate specified\r
-                                by  PollingInterval.\r
-  @param  Translator            Transaction translator to use.\r
-  @param  CallBackFunction      Function to call at the rate specified by\r
-                                PollingInterval.\r
-  @param  Context               Context to CallBackFunction.\r
-\r
-  @retval EFI_SUCCESS           The request has been successfully submitted or canceled.\r
-  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
-  @retval EFI_OUT_OF_RESOURCES  The request failed due to a lack of resources.\r
-  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcAsyncInterruptTransfer (\r
-  IN     EFI_USB2_HC_PROTOCOL                *This,\r
-  IN     UINT8                               DeviceAddress,\r
-  IN     UINT8                               EndPointAddress,\r
-  IN     UINT8                               DeviceSpeed,\r
-  IN     UINTN                               MaximumPacketLength,\r
-  IN     BOOLEAN                             IsNewTransfer,\r
-  IN OUT UINT8                               *DataToggle,\r
-  IN     UINTN                               PollingInterval,\r
-  IN     UINTN                               DataLength,\r
-  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
-  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     CallBackFunction,\r
-  IN     VOID                                *Context OPTIONAL\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
-  EFI_STATUS              Status;\r
-  UINT8                   SlotId;\r
-  UINT8                   Index;\r
-  UINT8                   *Data;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  //\r
-  // Validate parameters\r
-  //\r
-  if (!XHCI_IS_DATAIN (EndPointAddress)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (IsNewTransfer) {\r
-    if (DataLength == 0) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    if ((PollingInterval > 255) || (PollingInterval < 1)) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc    = XHC_FROM_THIS (This);\r
-\r
-  //\r
-  // Delete Async interrupt transfer request.\r
-  //\r
-  if (!IsNewTransfer) {\r
-    //\r
-    // The delete request may happen after device is detached.\r
-    //\r
-    for (Index = 0; Index < 255; Index++) {\r
-      if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {\r
-        break;\r
-      }\r
-    }\r
-\r
-    if (Index == 255) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ON_EXIT;\r
-    }\r
-\r
-    Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);\r
-    DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer, Status = %r\n", Status));\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = EFI_SUCCESS;\r
-\r
-  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: HC is halt\n"));\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Check if the device is still enabled before every transaction.\r
-  //\r
-  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
-  if (SlotId == 0) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Data = AllocateZeroPool (DataLength);\r
-\r
-  if (Data == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          EndPointAddress,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_INT_TRANSFER_ASYNC,\r
-          NULL,\r
-          Data,\r
-          DataLength,\r
-          CallBackFunction,\r
-          Context\r
-          );\r
-\r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));\r
-    FreePool (Data);\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  ASSERT (Urb->EvtRing == &Xhc->EventRing);\r
-\r
-  InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);\r
-  //\r
-  // Ring the doorbell\r
-  //\r
-  Status = RingIntTransferDoorBell (Xhc, Urb);\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Submits synchronous interrupt transfer to an interrupt endpoint\r
-  of a USB device.\r
-\r
-  @param  This                  This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress         Target device address.\r
-  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7\r
-  @param  DeviceSpeed           Indicates device speed.\r
-  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable\r
-                                of sending or receiving.\r
-  @param  Data                  Buffer of data that will be transmitted to  USB\r
-                                device or received from USB device.\r
-  @param  DataLength            On input, the size, in bytes, of the data buffer; On\r
-                                output, the number of bytes transferred.\r
-  @param  DataToggle            On input, the initial data toggle to use; on output,\r
-                                it is updated to indicate the next data toggle.\r
-  @param  Timeout               Maximum time, in second, to complete.\r
-  @param  Translator            Transaction translator to use.\r
-  @param  TransferResult        Variable to receive the transfer result.\r
-\r
-  @return EFI_SUCCESS           The transfer was completed successfully.\r
-  @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
-  @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
-  @return EFI_TIMEOUT           The transfer failed due to timeout.\r
-  @return EFI_DEVICE_ERROR      The failed due to host controller or device error\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcSyncInterruptTransfer (\r
-  IN     EFI_USB2_HC_PROTOCOL                *This,\r
-  IN     UINT8                               DeviceAddress,\r
-  IN     UINT8                               EndPointAddress,\r
-  IN     UINT8                               DeviceSpeed,\r
-  IN     UINTN                               MaximumPacketLength,\r
-  IN OUT VOID                                *Data,\r
-  IN OUT UINTN                               *DataLength,\r
-  IN OUT UINT8                               *DataToggle,\r
-  IN     UINTN                               Timeout,\r
-  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
-  OUT    UINT32                              *TransferResult\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   SlotId;\r
-  EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  //\r
-  // Validates parameters\r
-  //\r
-  if ((DataLength == NULL) || (*DataLength == 0) ||\r
-      (Data == NULL) || (TransferResult == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (!XHCI_IS_DATAIN (EndPointAddress)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8))  ||\r
-      ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
-      ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  Xhc     = XHC_FROM_THIS (This);\r
-\r
-  *TransferResult = EFI_USB_ERR_SYSTEM;\r
-  Status          = EFI_DEVICE_ERROR;\r
-\r
-  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
-    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Check if the device is still enabled before every transaction.\r
-  //\r
-  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
-  if (SlotId == 0) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          EndPointAddress,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_INT_TRANSFER_SYNC,\r
-          NULL,\r
-          Data,\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
-\r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
-\r
-  *TransferResult = Urb->Result;\r
-  *DataLength     = Urb->Completed;\r
-\r
-  if (*TransferResult == EFI_USB_NOERROR) {\r
-    Status = EFI_SUCCESS;\r
-  } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    ASSERT_EFI_ERROR (RecoveryStatus);\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  FreePool (Urb);\r
-\r
-ON_EXIT:\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
-  }\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Submits isochronous transfer to a target USB device.\r
-\r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address.\r
-  @param  EndPointAddress      End point address with its direction.\r
-  @param  DeviceSpeed          Device speed, Low speed device doesn't support this\r
-                               type.\r
-  @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of\r
-                               sending or receiving.\r
-  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.\r
-  @param  Data                 Array of pointers to the buffers of data that will\r
-                               be transmitted to USB device or received from USB\r
-                               device.\r
-  @param  DataLength           The size, in bytes, of the data buffer.\r
-  @param  Translator           Transaction translator to use.\r
-  @param  TransferResult       Variable to receive the transfer result.\r
-\r
-  @return EFI_UNSUPPORTED      Isochronous transfer is unsupported.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcIsochronousTransfer (\r
-  IN     EFI_USB2_HC_PROTOCOL                *This,\r
-  IN     UINT8                               DeviceAddress,\r
-  IN     UINT8                               EndPointAddress,\r
-  IN     UINT8                               DeviceSpeed,\r
-  IN     UINTN                               MaximumPacketLength,\r
-  IN     UINT8                               DataBuffersNumber,\r
-  IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
-  IN     UINTN                               DataLength,\r
-  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
-  OUT    UINT32                              *TransferResult\r
-  )\r
-{\r
-  return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
-  Submits Async isochronous transfer to a target USB device.\r
-\r
-  @param  This                 This EFI_USB2_HC_PROTOCOL instance.\r
-  @param  DeviceAddress        Target device address.\r
-  @param  EndPointAddress      End point address with its direction.\r
-  @param  DeviceSpeed          Device speed, Low speed device doesn't support this\r
-                               type.\r
-  @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of\r
-                               sending or receiving.\r
-  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.\r
-  @param  Data                 Array of pointers to the buffers of data that will\r
-                               be transmitted to USB device or received from USB\r
-                               device.\r
-  @param  DataLength           The size, in bytes, of the data buffer.\r
-  @param  Translator           Transaction translator to use.\r
-  @param  IsochronousCallBack  Function to be called when the transfer complete.\r
-  @param  Context              Context passed to the call back function as\r
-                               parameter.\r
-\r
-  @return EFI_UNSUPPORTED      Isochronous transfer isn't supported.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcAsyncIsochronousTransfer (\r
-  IN     EFI_USB2_HC_PROTOCOL                *This,\r
-  IN     UINT8                               DeviceAddress,\r
-  IN     UINT8                               EndPointAddress,\r
-  IN     UINT8                               DeviceSpeed,\r
-  IN     UINTN                               MaximumPacketLength,\r
-  IN     UINT8                               DataBuffersNumber,\r
-  IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
-  IN     UINTN                               DataLength,\r
-  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
-  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,\r
-  IN     VOID                                *Context\r
-  )\r
-{\r
-  return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
-  Entry point for EFI drivers.\r
-\r
-  @param  ImageHandle       EFI_HANDLE.\r
-  @param  SystemTable       EFI_SYSTEM_TABLE.\r
-\r
-  @retval EFI_SUCCESS       Success.\r
-  @retval Others            Fail.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcDriverEntryPoint (\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
-  )\r
-{\r
-  return EfiLibInstallDriverBindingComponentName2 (\r
-           ImageHandle,\r
-           SystemTable,\r
-           &gXhciDriverBinding,\r
-           ImageHandle,\r
-           &gXhciComponentName,\r
-           &gXhciComponentName2\r
-           );\r
-}\r
-\r
-\r
-/**\r
-  Test to see if this driver supports ControllerHandle. Any\r
-  ControllerHandle that has Usb2HcProtocol installed will\r
-  be supported.\r
-\r
-  @param  This                 Protocol instance pointer.\r
-  @param  Controller           Handle of device to test.\r
-  @param  RemainingDevicePath  Not used.\r
-\r
-  @return EFI_SUCCESS          This driver supports this device.\r
-  @return EFI_UNSUPPORTED      This driver does not support this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcDriverBindingSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  EFI_PCI_IO_PROTOCOL     *PciIo;\r
-  USB_CLASSC              UsbClassCReg;\r
-\r
-  //\r
-  // Test whether there is PCI IO Protocol attached on the controller handle.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  (VOID **) &PciIo,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Status = PciIo->Pci.Read (\r
-                        PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        PCI_CLASSCODE_OFFSET,\r
-                        sizeof (USB_CLASSC) / sizeof (UINT8),\r
-                        &UsbClassCReg\r
-                        );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    Status = EFI_UNSUPPORTED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Test whether the controller belongs to Xhci type\r
-  //\r
-  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
-      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
-      (UsbClassCReg.ProgInterface != PCI_IF_XHCI)) {\r
-    Status = EFI_UNSUPPORTED;\r
-  }\r
-\r
-ON_EXIT:\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiPciIoProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Create and initialize a USB_XHCI_INSTANCE structure.\r
-\r
-  @param  PciIo                  The PciIo on this device.\r
-  @param  OriginalPciAttributes  Original PCI attributes.\r
-\r
-  @return The allocated and initialized USB_XHCI_INSTANCE structure if created,\r
-          otherwise NULL.\r
-\r
-**/\r
-USB_XHCI_INSTANCE*\r
-XhcCreateUsbHc (\r
-  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
-  IN UINT64               OriginalPciAttributes\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  EFI_STATUS              Status;\r
-  UINT32                  PageSize;\r
-  UINT16                  ExtCapReg;\r
-\r
-  Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));\r
-\r
-  if (Xhc == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Initialize private data structure\r
-  //\r
-  Xhc->Signature             = XHCI_INSTANCE_SIG;\r
-  Xhc->PciIo                 = PciIo;\r
-  Xhc->OriginalPciAttributes = OriginalPciAttributes;\r
-  CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));\r
-\r
-  InitializeListHead (&Xhc->AsyncIntTransfers);\r
-\r
-  //\r
-  // Be caution that the Offset passed to XhcReadCapReg() should be Dword align\r
-  //\r
-  Xhc->CapLength        = XhcReadCapReg8 (Xhc, XHC_CAPLENGTH_OFFSET);\r
-  Xhc->HcSParams1.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS1_OFFSET);\r
-  Xhc->HcSParams2.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS2_OFFSET);\r
-  Xhc->HcCParams.Dword  = XhcReadCapReg (Xhc, XHC_HCCPARAMS_OFFSET);\r
-  Xhc->DBOff            = XhcReadCapReg (Xhc, XHC_DBOFF_OFFSET);\r
-  Xhc->RTSOff           = XhcReadCapReg (Xhc, XHC_RTSOFF_OFFSET);\r
-\r
-  //\r
-  // This PageSize field defines the page size supported by the xHC implementation.\r
-  // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,\r
-  // if bit 0 is Set, the xHC supports 4k byte page sizes.\r
-  //\r
-  PageSize      = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;\r
-  Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);\r
-\r
-  ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
-  Xhc->ExtCapRegBase   = ExtCapReg << 2;\r
-  Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc);\r
-\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));\r
-\r
-  //\r
-  // Create AsyncRequest Polling Timer\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  XhcMonitorAsyncRequests,\r
-                  Xhc,\r
-                  &Xhc->PollTimer\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  return Xhc;\r
-\r
-ON_ERROR:\r
-  FreePool (Xhc);\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
-\r
-  @param  Event                   Pointer to this event\r
-  @param  Context                 Event hanlder private data\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-XhcExitBootService (\r
-  EFI_EVENT  Event,\r
-  VOID       *Context\r
-  )\r
-\r
-{\r
-  USB_XHCI_INSTANCE    *Xhc;\r
-  EFI_PCI_IO_PROTOCOL  *PciIo;\r
-\r
-  Xhc = (USB_XHCI_INSTANCE*) Context;\r
-  PciIo = Xhc->PciIo;\r
-\r
-  //\r
-  // Stop AsyncRequest Polling timer then stop the XHCI driver\r
-  // and uninstall the XHCI protocl.\r
-  //\r
-  gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);\r
-  XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-\r
-  if (Xhc->PollTimer != NULL) {\r
-    gBS->CloseEvent (Xhc->PollTimer);\r
-  }\r
-\r
-  //\r
-  // Restore original PCI attributes\r
-  //\r
-  PciIo->Attributes (\r
-                  PciIo,\r
-                  EfiPciIoAttributeOperationSet,\r
-                  Xhc->OriginalPciAttributes,\r
-                  NULL\r
-                  );\r
-\r
-  XhcClearBiosOwnership (Xhc);\r
-}\r
-\r
-/**\r
-  Starting the Usb XHCI Driver.\r
-\r
-  @param  This                 Protocol instance pointer.\r
-  @param  Controller           Handle of device to test.\r
-  @param  RemainingDevicePath  Not used.\r
-\r
-  @return EFI_SUCCESS          supports this device.\r
-  @return EFI_UNSUPPORTED      do not support this device.\r
-  @return EFI_DEVICE_ERROR     cannot be started due to device Error.\r
-  @return EFI_OUT_OF_RESOURCES cannot allocate resources.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcDriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  EFI_PCI_IO_PROTOCOL     *PciIo;\r
-  UINT64                  Supports;\r
-  UINT64                  OriginalPciAttributes;\r
-  BOOLEAN                 PciAttributesSaved;\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-\r
-  //\r
-  // Open the PciIo Protocol, then enable the USB host controller\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  (VOID **) &PciIo,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  PciAttributesSaved = FALSE;\r
-  //\r
-  // Save original PCI attributes\r
-  //\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationGet,\r
-                    0,\r
-                    &OriginalPciAttributes\r
-                    );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto CLOSE_PCIIO;\r
-  }\r
-  PciAttributesSaved = TRUE;\r
-\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationSupported,\r
-                    0,\r
-                    &Supports\r
-                    );\r
-  if (!EFI_ERROR (Status)) {\r
-    Supports &= EFI_PCI_DEVICE_ENABLE;\r
-    Status = PciIo->Attributes (\r
-                      PciIo,\r
-                      EfiPciIoAttributeOperationEnable,\r
-                      Supports,\r
-                      NULL\r
-                      );\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to enable controller\n"));\r
-    goto CLOSE_PCIIO;\r
-  }\r
-\r
-  //\r
-  // Create then install USB2_HC_PROTOCOL\r
-  //\r
-  Xhc = XhcCreateUsbHc (PciIo, OriginalPciAttributes);\r
-\r
-  if (Xhc == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  XhcSetBiosOwnership (Xhc);\r
-\r
-  XhcResetHC (Xhc, XHC_RESET_TIMEOUT);\r
-  ASSERT (XhcIsHalt (Xhc));\r
-\r
-  //\r
-  // After Chip Hardware Reset wait until the Controller Not Ready (CNR) flag\r
-  // in the USBSTS is '0' before writing any xHC Operational or Runtime registers.\r
-  //\r
-  ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));\r
-\r
-  //\r
-  // Initialize the schedule\r
-  //\r
-  XhcInitSched (Xhc);\r
-\r
-  //\r
-  // Start the Host Controller\r
-  //\r
-  XhcRunHC(Xhc, XHC_GENERIC_TIMEOUT);\r
-\r
-  //\r
-  // Start the asynchronous interrupt monitor\r
-  //\r
-  Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
-    XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-    goto FREE_POOL;\r
-  }\r
-\r
-  //\r
-  // Create event to stop the HC when exit boot service.\r
-  //\r
-  Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  XhcExitBootService,\r
-                  Xhc,\r
-                  &gEfiEventExitBootServicesGuid,\r
-                  &Xhc->ExitBootServiceEvent\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto FREE_POOL;\r
-  }\r
-\r
-  //\r
-  // Install the component name protocol, don't fail the start\r
-  // because of something for display.\r
-  //\r
-  AddUnicodeString2 (\r
-    "eng",\r
-    gXhciComponentName.SupportedLanguages,\r
-    &Xhc->ControllerNameTable,\r
-    L"eXtensible Host Controller (USB 3.0)",\r
-    TRUE\r
-    );\r
-  AddUnicodeString2 (\r
-    "en",\r
-    gXhciComponentName2.SupportedLanguages,\r
-    &Xhc->ControllerNameTable,\r
-    L"eXtensible Host Controller (USB 3.0)",\r
-    FALSE\r
-    );\r
-\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &Controller,\r
-                  &gEfiUsb2HcProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &Xhc->Usb2Hc\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to install USB2_HC Protocol\n"));\r
-    goto FREE_POOL;\r
-  }\r
-\r
-  DEBUG ((EFI_D_INFO, "XhcDriverBindingStart: XHCI started for controller @ %x\n", Controller));\r
-  return EFI_SUCCESS;\r
-\r
-FREE_POOL:\r
-  gBS->CloseEvent (Xhc->PollTimer);\r
-  XhcFreeSched (Xhc);\r
-  FreePool (Xhc);\r
-\r
-CLOSE_PCIIO:\r
-  if (PciAttributesSaved) {\r
-    //\r
-    // Restore original PCI attributes\r
-    //\r
-    PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationSet,\r
-                    OriginalPciAttributes,\r
-                    NULL\r
-                    );\r
-  }\r
-\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiPciIoProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Stop this driver on ControllerHandle. Support stoping any child handles\r
-  created by this driver.\r
-\r
-  @param  This                 Protocol instance pointer.\r
-  @param  Controller           Handle of device to stop driver on.\r
-  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.\r
-  @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
-\r
-  @return EFI_SUCCESS          Success.\r
-  @return EFI_DEVICE_ERROR     Fail.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-XhcDriverBindingStop (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  Controller,\r
-  IN UINTN                       NumberOfChildren,\r
-  IN EFI_HANDLE                  *ChildHandleBuffer\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  EFI_USB2_HC_PROTOCOL  *Usb2Hc;\r
-  EFI_PCI_IO_PROTOCOL   *PciIo;\r
-  USB_XHCI_INSTANCE     *Xhc;\r
-  UINT8                 Index;\r
-\r
-  //\r
-  // Test whether the Controller handler passed in is a valid\r
-  // Usb controller handle that should be supported, if not,\r
-  // return the error status directly\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiUsb2HcProtocolGuid,\r
-                  (VOID **) &Usb2Hc,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Xhc   = XHC_FROM_THIS (Usb2Hc);\r
-  PciIo = Xhc->PciIo;\r
-\r
-  //\r
-  // Stop AsyncRequest Polling timer then stop the XHCI driver\r
-  // and uninstall the XHCI protocl.\r
-  //\r
-  gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);\r
-\r
-  //\r
-  // Disable the device slots occupied by these devices on its downstream ports.\r
-  // Entry 0 is reserved.\r
-  //\r
-  for (Index = 0; Index < 255; Index++) {\r
-    if (!Xhc->UsbDevContext[Index + 1].Enabled ||\r
-        (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {\r
-      continue;\r
-    }\r
-    if (Xhc->HcCParams.Data.Csz == 0) {\r
-      XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
-    } else {\r
-      XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
-    }\r
-  }\r
-\r
-  XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-  XhcClearBiosOwnership (Xhc);\r
-\r
-  Status = gBS->UninstallProtocolInterface (\r
-                  Controller,\r
-                  &gEfiUsb2HcProtocolGuid,\r
-                  Usb2Hc\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (Xhc->PollTimer != NULL) {\r
-    gBS->CloseEvent (Xhc->PollTimer);\r
-  }\r
-\r
-  if (Xhc->ExitBootServiceEvent != NULL) {\r
-    gBS->CloseEvent (Xhc->ExitBootServiceEvent);\r
-  }\r
-\r
-  XhciDelAllAsyncIntTransfers (Xhc);\r
-  XhcFreeSched (Xhc);\r
-\r
-  if (Xhc->ControllerNameTable) {\r
-    FreeUnicodeStringTable (Xhc->ControllerNameTable);\r
-  }\r
-\r
-  //\r
-  // Restore original PCI attributes\r
-  //\r
-  PciIo->Attributes (\r
-           PciIo,\r
-           EfiPciIoAttributeOperationSet,\r
-           Xhc->OriginalPciAttributes,\r
-           NULL\r
-           );\r
-\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiPciIoProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-\r
-  FreePool (Xhc);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
+/** @file
+  The XHCI controller driver.
+
+Copyright (c) 2011 - 2012, 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 "Xhci.h"
+
+//
+// Two arrays used to translate the XHCI port state (change)
+// to the UEFI protocol's port state (change).
+//
+USB_PORT_STATE_MAP  mUsbPortStateMap[] = {
+  {XHC_PORTSC_CCS,   USB_PORT_STAT_CONNECTION},
+  {XHC_PORTSC_PED,   USB_PORT_STAT_ENABLE},
+  {XHC_PORTSC_OCA,   USB_PORT_STAT_OVERCURRENT},
+  {XHC_PORTSC_RESET, USB_PORT_STAT_RESET}
+};
+
+USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
+  {XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
+  {XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
+  {XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
+  {XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}
+};
+
+USB_PORT_STATE_MAP  mUsbHubPortStateMap[] = {
+  {XHC_HUB_PORTSC_CCS,   USB_PORT_STAT_CONNECTION},
+  {XHC_HUB_PORTSC_PED,   USB_PORT_STAT_ENABLE},
+  {XHC_HUB_PORTSC_OCA,   USB_PORT_STAT_OVERCURRENT},
+  {XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET}
+};
+
+USB_PORT_STATE_MAP  mUsbHubPortChangeMap[] = {
+  {XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
+  {XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
+  {XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
+  {XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}
+};
+
+EFI_DRIVER_BINDING_PROTOCOL  gXhciDriverBinding = {
+  XhcDriverBindingSupported,
+  XhcDriverBindingStart,
+  XhcDriverBindingStop,
+  0x30,
+  NULL,
+  NULL
+};
+
+//
+// Template for Xhci's Usb2 Host Controller Protocol Instance.
+//
+EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {
+  XhcGetCapability,
+  XhcReset,
+  XhcGetState,
+  XhcSetState,
+  XhcControlTransfer,
+  XhcBulkTransfer,
+  XhcAsyncInterruptTransfer,
+  XhcSyncInterruptTransfer,
+  XhcIsochronousTransfer,
+  XhcAsyncIsochronousTransfer,
+  XhcGetRootHubPortStatus,
+  XhcSetRootHubPortFeature,
+  XhcClearRootHubPortFeature,
+  0x3,
+  0x0
+};
+
+/**
+  Retrieves the capability of root hub ports.
+
+  @param  This                  The EFI_USB2_HC_PROTOCOL instance.
+  @param  MaxSpeed              Max speed supported by the controller.
+  @param  PortNumber            Number of the root hub ports.
+  @param  Is64BitCapable        Whether the controller supports 64-bit memory
+                                addressing.
+
+  @retval EFI_SUCCESS           Host controller capability were retrieved successfully.
+  @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcGetCapability (
+  IN  EFI_USB2_HC_PROTOCOL  *This,
+  OUT UINT8                 *MaxSpeed,
+  OUT UINT8                 *PortNumber,
+  OUT UINT8                 *Is64BitCapable
+  )
+{
+  USB_XHCI_INSTANCE  *Xhc;
+  EFI_TPL            OldTpl;
+
+  if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl          = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc             = XHC_FROM_THIS (This);
+  *MaxSpeed       = EFI_USB_SPEED_SUPER;
+  *PortNumber     = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);
+  *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);
+  DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
+
+  gBS->RestoreTPL (OldTpl);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Provides software reset for the USB host controller.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  Attributes            A bit mask of the reset operation to perform.
+
+  @retval EFI_SUCCESS           The reset operation succeeded.
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.
+  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
+                                not currently supported by the host controller.
+  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcReset (
+  IN EFI_USB2_HC_PROTOCOL  *This,
+  IN UINT16                Attributes
+  )
+{
+  USB_XHCI_INSTANCE  *Xhc;
+  EFI_STATUS         Status;
+  EFI_TPL            OldTpl;
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc    = XHC_FROM_THIS (This);
+
+  switch (Attributes) {
+  case EFI_USB_HC_RESET_GLOBAL:
+  //
+  // Flow through, same behavior as Host Controller Reset
+  //
+  case EFI_USB_HC_RESET_HOST_CONTROLLER:
+    //
+    // Host Controller must be Halt when Reset it
+    //
+    if (!XhcIsHalt (Xhc)) {
+      Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
+
+      if (EFI_ERROR (Status)) {
+        Status = EFI_DEVICE_ERROR;
+        goto ON_EXIT;
+      }
+    }
+
+    Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
+    ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
+
+    if (EFI_ERROR (Status)) {
+      goto ON_EXIT;
+    }
+    //
+    // Clean up the asynchronous transfers, currently only
+    // interrupt supports asynchronous operation.
+    //
+    XhciDelAllAsyncIntTransfers (Xhc);
+    XhcFreeSched (Xhc);
+
+    XhcInitSched (Xhc);
+    break;
+
+  case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
+  case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
+    Status = EFI_UNSUPPORTED;
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+ON_EXIT:
+  DEBUG ((EFI_D_INFO, "XhcReset: status %r\n", Status));
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+
+/**
+  Retrieve the current state of the USB host controller.
+
+  @param  This                   This EFI_USB2_HC_PROTOCOL instance.
+  @param  State                  Variable to return the current host controller
+                                 state.
+
+  @retval EFI_SUCCESS            Host controller state was returned in State.
+  @retval EFI_INVALID_PARAMETER  State is NULL.
+  @retval EFI_DEVICE_ERROR       An error was encountered while attempting to
+                                 retrieve the host controller's current state.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcGetState (
+  IN  EFI_USB2_HC_PROTOCOL  *This,
+  OUT EFI_USB_HC_STATE      *State
+  )
+{
+  USB_XHCI_INSTANCE  *Xhc;
+  EFI_TPL            OldTpl;
+
+  if (State == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc    = XHC_FROM_THIS (This);
+
+  if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
+    *State = EfiUsbHcStateHalt;
+  } else {
+    *State = EfiUsbHcStateOperational;
+  }
+
+  DEBUG ((EFI_D_INFO, "XhcGetState: current state %d\n", *State));
+  gBS->RestoreTPL (OldTpl);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets the USB host controller to a specific state.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  State                 The state of the host controller that will be set.
+
+  @retval EFI_SUCCESS           The USB host controller was successfully placed
+                                in the state specified by State.
+  @retval EFI_INVALID_PARAMETER State is invalid.
+  @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSetState (
+  IN EFI_USB2_HC_PROTOCOL  *This,
+  IN EFI_USB_HC_STATE      State
+  )
+{
+  USB_XHCI_INSTANCE   *Xhc;
+  EFI_STATUS          Status;
+  EFI_USB_HC_STATE    CurState;
+  EFI_TPL             OldTpl;
+
+  Status = XhcGetState (This, &CurState);
+
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (CurState == State) {
+    return EFI_SUCCESS;
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc    = XHC_FROM_THIS (This);
+
+  switch (State) {
+  case EfiUsbHcStateHalt:
+    Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
+    break;
+
+  case EfiUsbHcStateOperational:
+    if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE)) {
+      Status = EFI_DEVICE_ERROR;
+      break;
+    }
+
+    //
+    // Software must not write a one to this field unless the host controller
+    // is in the Halted state. Doing so will yield undefined results.
+    // refers to Spec[XHCI1.0-2.3.1]
+    //
+    if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
+      Status = EFI_DEVICE_ERROR;
+      break;
+    }
+
+    Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
+    break;
+
+  case EfiUsbHcStateSuspend:
+    Status = EFI_UNSUPPORTED;
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((EFI_D_INFO, "XhcSetState: status %r\n", Status));
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
+  Retrieves the current status of a USB root hub port.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  PortNumber            The root hub port to retrieve the state from.
+                                This value is zero-based.
+  @param  PortStatus            Variable to receive the port state.
+
+  @retval EFI_SUCCESS           The status of the USB root hub port specified.
+                                by PortNumber was returned in PortStatus.
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid.
+  @retval EFI_DEVICE_ERROR      Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcGetRootHubPortStatus (
+  IN  EFI_USB2_HC_PROTOCOL  *This,
+  IN  UINT8                 PortNumber,
+  OUT EFI_USB_PORT_STATUS   *PortStatus
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  UINT32                  Offset;
+  UINT32                  State;
+  UINT32                  TotalPort;
+  UINTN                   Index;
+  UINTN                   MapSize;
+  EFI_STATUS              Status;
+  USB_DEV_ROUTE           ParentRouteChart;
+  EFI_TPL                 OldTpl;
+
+  if (PortStatus == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc       = XHC_FROM_THIS (This);
+  Status    = EFI_SUCCESS;
+
+  TotalPort = Xhc->HcSParams1.Data.MaxPorts;
+
+  if (PortNumber >= TotalPort) {
+    Status = EFI_INVALID_PARAMETER;
+    goto ON_EXIT;
+  }
+
+  Offset                       = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));
+  PortStatus->PortStatus       = 0;
+  PortStatus->PortChangeStatus = 0;
+
+  State = XhcReadOpReg (Xhc, Offset);
+
+  //
+  // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.
+  //
+  switch ((State & XHC_PORTSC_PS) >> 10) {
+  case 2:
+    PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+    break;
+
+  case 3:
+    PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+    break;
+
+  case 4:
+    PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
+    break;
+
+  default:
+    break;
+  }
+
+  //
+  // Convert the XHCI port/port change state to UEFI status
+  //
+  MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
+
+  for (Index = 0; Index < MapSize; Index++) {
+    if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
+      PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
+    }
+  }
+  //
+  // Bit5~8 reflects its current link state.
+  //
+  if ((State & XHC_PORTSC_PLS) >> 5 == 3) {
+    PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+  }
+
+  MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
+
+  for (Index = 0; Index < MapSize; Index++) {
+    if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
+      PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
+    }
+  }
+
+  //
+  // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
+  // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
+  //
+  ParentRouteChart.Dword = 0;
+  XhcPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+
+/**
+  Sets a feature for the specified root hub port.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  PortNumber            Root hub port to set.
+  @param  PortFeature           Feature to set.
+
+  @retval EFI_SUCCESS           The feature specified by PortFeature was set.
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+  @retval EFI_DEVICE_ERROR      Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSetRootHubPortFeature (
+  IN EFI_USB2_HC_PROTOCOL  *This,
+  IN UINT8                 PortNumber,
+  IN EFI_USB_PORT_FEATURE  PortFeature
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  UINT32                  Offset;
+  UINT32                  State;
+  UINT32                  TotalPort;
+  UINT8                   SlotId;
+  USB_DEV_ROUTE           RouteChart;
+  EFI_STATUS              Status;
+  EFI_TPL                 OldTpl;
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc    = XHC_FROM_THIS (This);
+  Status = EFI_SUCCESS;
+
+  TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
+
+  if (PortNumber >= TotalPort) {
+    Status = EFI_INVALID_PARAMETER;
+    goto ON_EXIT;
+  }
+
+  Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));
+  State  = XhcReadOpReg (Xhc, Offset);
+
+  //
+  // Mask off the port status change bits, these bits are
+  // write clean bit
+  //
+  State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
+
+  switch (PortFeature) {
+  case EfiUsbPortEnable:
+    //
+    // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
+    // A port may be disabled by software writing a '1' to this flag.
+    //
+    Status = EFI_SUCCESS;
+    break;
+
+  case EfiUsbPortSuspend:
+    State |= XHC_PORTSC_LWS;
+    XhcWriteOpReg (Xhc, Offset, State);
+    State &= ~XHC_PORTSC_PLS;
+    State |= (3 << 5) ;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortReset:
+    DEBUG ((EFI_D_INFO, "XhcUsbPortReset!\n"));
+    //
+    // Make sure Host Controller not halt before reset it
+    //
+    if (XhcIsHalt (Xhc)) {
+      Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
+
+      if (EFI_ERROR (Status)) {
+        DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
+        break;
+      }
+    }
+
+    RouteChart.Route.RouteString = 0;
+    RouteChart.Route.RootPortNum = PortNumber + 1;
+    RouteChart.Route.TierNum     = 1;
+    //
+    // If the port reset operation happens after the usb super speed device is enabled,
+    // The subsequent configuration, such as getting device descriptor, will fail.
+    // So here a workaround is introduced to skip the reset operation if the device is enabled.
+    //
+    SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);
+    if (SlotId == 0) {
+      //
+      // 4.3.1 Resetting a Root Hub Port
+      // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
+      //
+      State |= XHC_PORTSC_RESET;
+      XhcWriteOpReg (Xhc, Offset, State);
+      XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
+    }
+    break;
+
+  case EfiUsbPortPower:
+    //
+    // Not supported, ignore the operation
+    //
+    Status = EFI_SUCCESS;
+    break;
+
+  case EfiUsbPortOwner:
+    //
+    // XHCI root hub port don't has the owner bit, ignore the operation
+    //
+    Status = EFI_SUCCESS;
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+ON_EXIT:
+  DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature: status %r\n", Status));
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+
+/**
+  Clears a feature for the specified root hub port.
+
+  @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.
+  @param  PortNumber            Specifies the root hub port whose feature is
+                                requested to be cleared.
+  @param  PortFeature           Indicates the feature selector associated with the
+                                feature clear request.
+
+  @retval EFI_SUCCESS           The feature specified by PortFeature was cleared
+                                for the USB root hub port specified by PortNumber.
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+  @retval EFI_DEVICE_ERROR      Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcClearRootHubPortFeature (
+  IN EFI_USB2_HC_PROTOCOL  *This,
+  IN UINT8                 PortNumber,
+  IN EFI_USB_PORT_FEATURE  PortFeature
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  UINT32                  Offset;
+  UINT32                  State;
+  UINT32                  TotalPort;
+  EFI_STATUS              Status;
+  EFI_TPL                 OldTpl;
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc       = XHC_FROM_THIS (This);
+  Status    = EFI_SUCCESS;
+
+  TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
+
+  if (PortNumber >= TotalPort) {
+    Status = EFI_INVALID_PARAMETER;
+    goto ON_EXIT;
+  }
+
+  Offset = XHC_PORTSC_OFFSET + (0x10 * PortNumber);
+
+  //
+  // Mask off the port status change bits, these bits are
+  // write clean bit
+  //
+  State  = XhcReadOpReg (Xhc, Offset);
+  State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
+
+  switch (PortFeature) {
+  case EfiUsbPortEnable:
+    //
+    // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
+    // A port may be disabled by software writing a '1' to this flag.
+    //
+    State |= XHC_PORTSC_PED;
+    State &= ~XHC_PORTSC_RESET;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortSuspend:
+    State |= XHC_PORTSC_LWS;
+    XhcWriteOpReg (Xhc, Offset, State);
+    State &= ~XHC_PORTSC_PLS;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortReset:
+    //
+    // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
+    // Register bits indicate status when read, a clear bit may be set by
+    // writing a '1'. Writing a '0' to RW1S bits has no effect.
+    //
+    break;
+
+  case EfiUsbPortOwner:
+    //
+    // XHCI root hub port don't has the owner bit, ignore the operation
+    //
+    break;
+
+  case EfiUsbPortConnectChange:
+    //
+    // Clear connect status change
+    //
+    State |= XHC_PORTSC_CSC;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortEnableChange:
+    //
+    // Clear enable status change
+    //
+    State |= XHC_PORTSC_PEC;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortOverCurrentChange:
+    //
+    // Clear PortOverCurrent change
+    //
+    State |= XHC_PORTSC_OCC;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortResetChange:
+    //
+    // Clear Port Reset change
+    //
+    State |= XHC_PORTSC_PRC;
+    XhcWriteOpReg (Xhc, Offset, State);
+    break;
+
+  case EfiUsbPortPower:
+  case EfiUsbPortSuspendChange:
+    //
+    // Not supported or not related operation
+    //
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+ON_EXIT:
+  DEBUG ((EFI_D_INFO, "XhcClearRootHubPortFeature: status %r\n", Status));
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+
+/**
+  Submits control transfer to a target USB device.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress         The target device address.
+  @param  DeviceSpeed           Target device speed.
+  @param  MaximumPacketLength   Maximum packet size the default control transfer
+                                endpoint is capable of sending or receiving.
+  @param  Request               USB device request to send.
+  @param  TransferDirection     Specifies the data direction for the data stage
+  @param  Data                  Data buffer to be transmitted or received from USB
+                                device.
+  @param  DataLength            The size (in bytes) of the data buffer.
+  @param  Timeout               Indicates the maximum timeout, in millisecond.
+  @param  Translator            Transaction translator to be used by this device.
+  @param  TransferResult        Return the result of this control transfer.
+
+  @retval EFI_SUCCESS           Transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_TIMEOUT           Transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcControlTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     EFI_USB_DEVICE_REQUEST              *Request,
+  IN     EFI_USB_DATA_DIRECTION              TransferDirection,
+  IN OUT VOID                                *Data,
+  IN OUT UINTN                               *DataLength,
+  IN     UINTN                               Timeout,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  OUT    UINT32                              *TransferResult
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
+  UINT8                   Endpoint;
+  UINT8                   Index;
+  UINT8                   DescriptorType;
+  UINT8                   SlotId;
+  UINT8                   TTT;
+  UINT8                   MTT;
+  UINT32                  MaxPacket0;
+  EFI_USB_HUB_DESCRIPTOR  *HubDesc;
+  EFI_TPL                 OldTpl;
+  EFI_STATUS              Status;
+  EFI_STATUS              RecoveryStatus;
+  UINTN                   MapSize;
+  EFI_USB_PORT_STATUS     PortStatus;
+  UINT32                  State;
+
+  //
+  // Validate parameters
+  //
+  if ((Request == NULL) || (TransferResult == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((TransferDirection != EfiUsbDataIn) &&
+      (TransferDirection != EfiUsbDataOut) &&
+      (TransferDirection != EfiUsbNoData)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((TransferDirection == EfiUsbNoData) &&
+      ((Data != NULL) || (*DataLength != 0))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((TransferDirection != EfiUsbNoData) &&
+     ((Data == NULL) || (*DataLength == 0))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
+      (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&
+      (MaximumPacketLength != 512)
+      ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc             = XHC_FROM_THIS (This);
+
+  Status          = EFI_DEVICE_ERROR;
+  *TransferResult = EFI_USB_ERR_SYSTEM;
+
+  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
+    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));
+    goto ON_EXIT;
+  }
+
+  //
+  // Check if the device is still enabled before every transaction.
+  //
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
+  if (SlotId == 0) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Hook the Set_Address request from UsbBus.
+  // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
+  //
+  if ((Request->Request     == USB_REQ_SET_ADDRESS) &&
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
+    //
+    // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
+    // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().
+    //
+    for (Index = 0; Index < 255; Index++) {
+      if (!Xhc->UsbDevContext[Index + 1].Enabled &&
+          (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&
+          (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {
+        Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
+      }
+    }
+    //
+    // The actual device address has been assigned by XHCI during initializing the device slot.
+    // So we just need establish the mapping relationship between the device address requested from UsbBus
+    // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface
+    // can find out the actual device address by it.
+    //
+    Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;
+    Status = EFI_SUCCESS;
+    goto ON_EXIT;
+  }
+  
+  //
+  // If the port reset operation happens after the usb super speed device is enabled,
+  // The subsequent configuration, such as getting device descriptor, will fail.
+  // So here a workaround is introduced to skip the reset operation if the device is enabled.
+  //
+  if ((Request->Request     == USB_REQ_SET_FEATURE) &&
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)) &&
+      (Request->Value       == EfiUsbPortReset)) {
+    if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
+      Status = EFI_SUCCESS;
+      goto ON_EXIT;
+    }
+  }
+
+  //
+  // Create a new URB, insert it into the asynchronous
+  // schedule list, then poll the execution status.
+  // Note that we encode the direction in address although default control
+  // endpoint is bidirectional. XhcCreateUrb expects this
+  // combination of Ep addr and its direction.
+  //
+  Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          Endpoint,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_CTRL_TRANSFER,
+          Request,
+          Data,
+          *DataLength,
+          NULL,
+          NULL
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+  //
+  // Get the status from URB. The result is updated in XhcCheckUrbResult
+  // which is called by XhcExecTransfer
+  //
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  } else if (*TransferResult == EFI_USB_ERR_STALL) {
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
+    ASSERT_EFI_ERROR (RecoveryStatus);
+    Status = EFI_DEVICE_ERROR;
+    goto FREE_URB;
+  } else {
+    goto FREE_URB;
+  }
+
+  //
+  // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
+  // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
+  // Hook Set_Config request from UsbBus as we need configure device endpoint.
+  //
+  if ((Request->Request     == USB_REQ_GET_DESCRIPTOR) &&
+      ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) || 
+      ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {
+    DescriptorType = (UINT8)(Request->Value >> 8);
+    if ((DescriptorType == USB_DESC_TYPE_DEVICE) && (*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR))) {
+        ASSERT (Data != NULL);
+        //
+        // Store a copy of device scriptor as hub device need this info to configure endpoint.
+        //
+        CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
+        if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {
+          //
+          // If it's a usb3.0 device, then its max packet size is a 2^n.
+          //
+          MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
+        } else {
+          MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
+        }
+        Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
+        if (Xhc->HcCParams.Data.Csz == 0) {
+          Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
+        } else {
+          Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
+        }
+        ASSERT_EFI_ERROR (Status);
+    } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
+      ASSERT (Data != NULL);
+      if (*DataLength == ((UINT16 *)Data)[1]) {
+        //
+        // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.
+        //
+        Index = (UINT8)Request->Value;
+        ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
+        Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);
+        CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
+      }
+    } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
+               (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {
+      ASSERT (Data != NULL);
+      HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;
+      ASSERT (HubDesc->NumPorts <= 15);
+      //
+      // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
+      //
+      TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);
+      if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {
+        //
+        // Don't support multi-TT feature for super speed hub now.
+        //
+        MTT = 0;
+        DEBUG ((EFI_D_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
+      } else {
+        MTT = 0;
+      }
+
+      if (Xhc->HcCParams.Data.Csz == 0) {
+        Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
+      } else {
+        Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
+      }
+      ASSERT_EFI_ERROR (Status);
+    }
+  } else if ((Request->Request     == USB_REQ_SET_CONFIG) &&
+             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
+    //
+    // Hook Set_Config request from UsbBus as we need configure device endpoint.
+    //
+    for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
+      if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {
+        if (Xhc->HcCParams.Data.Csz == 0) {
+          Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
+        } else {
+          Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
+        }
+        ASSERT_EFI_ERROR (Status);
+        break;
+      }
+    }
+  } else if ((Request->Request     == USB_REQ_GET_STATUS) &&
+             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {
+    ASSERT (Data != NULL);
+    //
+    // Hook Get_Status request from UsbBus to keep track of the port status change.
+    //
+    State                       = *(UINT32 *)Data;
+    PortStatus.PortStatus       = 0;
+    PortStatus.PortChangeStatus = 0;
+
+    if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
+      //
+      // For super speed hub, its bit10~12 presents the attached device speed.
+      //
+      if ((State & XHC_PORTSC_PS) >> 10 == 0) {
+        PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;
+      }
+    } else if (DeviceSpeed == EFI_USB_SPEED_HIGH) {
+      //
+      // For high speed hub, its bit9~10 presents the attached device speed.
+      //
+      if (XHC_BIT_IS_SET (State, BIT9)) {
+        PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;
+      } else if (XHC_BIT_IS_SET (State, BIT10)) {
+        PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+      }
+    } else {
+      ASSERT (0);
+    }
+
+    //
+    // Convert the XHCI port/port change state to UEFI status
+    //
+    MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);
+    for (Index = 0; Index < MapSize; Index++) {
+      if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {
+        PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);
+      }
+    }
+
+    MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
+    for (Index = 0; Index < MapSize; Index++) {
+      if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {
+        PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);
+      }
+    }
+
+    XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
+
+    *(UINT32 *)Data = *(UINT32*)&PortStatus;
+  }
+
+FREE_URB:
+  FreePool (Urb);
+
+ON_EXIT:
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
+  }
+
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+
+/**
+  Submits bulk transfer to a bulk endpoint of a USB device.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress         Target device address.
+  @param  EndPointAddress       Endpoint number and its direction in bit 7.
+  @param  DeviceSpeed           Device speed, Low speed device doesn't support bulk
+                                transfer.
+  @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
+                                sending or receiving.
+  @param  DataBuffersNumber     Number of data buffers prepared for the transfer.
+  @param  Data                  Array of pointers to the buffers of data to transmit
+                                from or receive into.
+  @param  DataLength            The lenght of the data buffer.
+  @param  DataToggle            On input, the initial data toggle for the transfer;
+                                On output, it is updated to to next data toggle to
+                                use of the subsequent bulk transfer.
+  @param  Timeout               Indicates the maximum time, in millisecond, which
+                                the transfer is allowed to complete.
+  @param  Translator            A pointr to the transaction translator data.
+  @param  TransferResult        A pointer to the detailed result information of the
+                                bulk transfer.
+
+  @retval EFI_SUCCESS           The transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcBulkTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               EndPointAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     UINT8                               DataBuffersNumber,
+  IN OUT VOID                                *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+  IN OUT UINTN                               *DataLength,
+  IN OUT UINT8                               *DataToggle,
+  IN     UINTN                               Timeout,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  OUT    UINT32                              *TransferResult
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
+  UINT8                   SlotId;
+  EFI_STATUS              Status;
+  EFI_STATUS              RecoveryStatus;
+  EFI_TPL                 OldTpl;
+
+  //
+  // Validate the parameters
+  //
+  if ((DataLength == NULL) || (*DataLength == 0) ||
+      (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((*DataToggle != 0) && (*DataToggle != 1)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
+      ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
+      ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)) ||
+      ((EFI_USB_SPEED_SUPER == DeviceSpeed) && (MaximumPacketLength > 1024))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc             = XHC_FROM_THIS (This);
+
+  *TransferResult = EFI_USB_ERR_SYSTEM;
+  Status          = EFI_DEVICE_ERROR;
+
+  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
+    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: HC is halted\n"));
+    goto ON_EXIT;
+  }
+
+  //
+  // Check if the device is still enabled before every transaction.
+  //
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
+  if (SlotId == 0) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Create a new URB, insert it into the asynchronous
+  // schedule list, then poll the execution status.
+  //
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          EndPointAddress,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_BULK_TRANSFER,
+          NULL,
+          Data[0],
+          *DataLength,
+          NULL,
+          NULL
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  } else if (*TransferResult == EFI_USB_ERR_STALL) {
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
+    ASSERT_EFI_ERROR (RecoveryStatus);
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  FreePool (Urb);
+
+ON_EXIT:
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
+  Submits an asynchronous interrupt transfer to an
+  interrupt endpoint of a USB device.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress         Target device address.
+  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
+  @param  DeviceSpeed           Indicates device speed.
+  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
+  @param  IsNewTransfer         If TRUE, to submit an new asynchronous interrupt
+                                transfer If FALSE, to remove the specified
+                                asynchronous interrupt.
+  @param  DataToggle            On input, the initial data toggle to use; on output,
+                                it is updated to indicate the next data toggle.
+  @param  PollingInterval       The he interval, in milliseconds, that the transfer
+                                is polled.
+  @param  DataLength            The length of data to receive at the rate specified
+                                by  PollingInterval.
+  @param  Translator            Transaction translator to use.
+  @param  CallBackFunction      Function to call at the rate specified by
+                                PollingInterval.
+  @param  Context               Context to CallBackFunction.
+
+  @retval EFI_SUCCESS           The request has been successfully submitted or canceled.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request failed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcAsyncInterruptTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               EndPointAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     BOOLEAN                             IsNewTransfer,
+  IN OUT UINT8                               *DataToggle,
+  IN     UINTN                               PollingInterval,
+  IN     UINTN                               DataLength,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     CallBackFunction,
+  IN     VOID                                *Context OPTIONAL
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
+  EFI_STATUS              Status;
+  UINT8                   SlotId;
+  UINT8                   Index;
+  UINT8                   *Data;
+  EFI_TPL                 OldTpl;
+
+  //
+  // Validate parameters
+  //
+  if (!XHCI_IS_DATAIN (EndPointAddress)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsNewTransfer) {
+    if (DataLength == 0) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((*DataToggle != 1) && (*DataToggle != 0)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((PollingInterval > 255) || (PollingInterval < 1)) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc    = XHC_FROM_THIS (This);
+
+  //
+  // Delete Async interrupt transfer request.
+  //
+  if (!IsNewTransfer) {
+    //
+    // The delete request may happen after device is detached.
+    //
+    for (Index = 0; Index < 255; Index++) {
+      if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {
+        break;
+      }
+    }
+
+    if (Index == 255) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
+    DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));
+    goto ON_EXIT;
+  }
+
+  Status = EFI_SUCCESS;
+
+  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
+    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: HC is halt\n"));
+    Status = EFI_DEVICE_ERROR;
+    goto ON_EXIT;
+  }
+
+  //
+  // Check if the device is still enabled before every transaction.
+  //
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
+  if (SlotId == 0) {
+    goto ON_EXIT;
+  }
+
+  Data = AllocateZeroPool (DataLength);
+
+  if (Data == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          EndPointAddress,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_INT_TRANSFER_ASYNC,
+          NULL,
+          Data,
+          DataLength,
+          CallBackFunction,
+          Context
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));
+    FreePool (Data);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
+  //
+  // Ring the doorbell
+  //
+  Status = RingIntTransferDoorBell (Xhc, Urb);
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+
+/**
+  Submits synchronous interrupt transfer to an interrupt endpoint
+  of a USB device.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress         Target device address.
+  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
+  @param  DeviceSpeed           Indicates device speed.
+  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
+                                of sending or receiving.
+  @param  Data                  Buffer of data that will be transmitted to  USB
+                                device or received from USB device.
+  @param  DataLength            On input, the size, in bytes, of the data buffer; On
+                                output, the number of bytes transferred.
+  @param  DataToggle            On input, the initial data toggle to use; on output,
+                                it is updated to indicate the next data toggle.
+  @param  Timeout               Maximum time, in second, to complete.
+  @param  Translator            Transaction translator to use.
+  @param  TransferResult        Variable to receive the transfer result.
+
+  @return EFI_SUCCESS           The transfer was completed successfully.
+  @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
+  @return EFI_INVALID_PARAMETER Some parameters are invalid.
+  @return EFI_TIMEOUT           The transfer failed due to timeout.
+  @return EFI_DEVICE_ERROR      The failed due to host controller or device error
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSyncInterruptTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               EndPointAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN OUT VOID                                *Data,
+  IN OUT UINTN                               *DataLength,
+  IN OUT UINT8                               *DataToggle,
+  IN     UINTN                               Timeout,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  OUT    UINT32                              *TransferResult
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
+  UINT8                   SlotId;
+  EFI_STATUS              Status;
+  EFI_STATUS              RecoveryStatus;
+  EFI_TPL                 OldTpl;
+
+  //
+  // Validates parameters
+  //
+  if ((DataLength == NULL) || (*DataLength == 0) ||
+      (Data == NULL) || (TransferResult == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!XHCI_IS_DATAIN (EndPointAddress)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((*DataToggle != 1) && (*DataToggle != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8))  ||
+      ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
+      ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  Xhc     = XHC_FROM_THIS (This);
+
+  *TransferResult = EFI_USB_ERR_SYSTEM;
+  Status          = EFI_DEVICE_ERROR;
+
+  if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
+    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
+    goto ON_EXIT;
+  }
+
+  //
+  // Check if the device is still enabled before every transaction.
+  //
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
+  if (SlotId == 0) {
+    goto ON_EXIT;
+  }
+
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          EndPointAddress,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_INT_TRANSFER_SYNC,
+          NULL,
+          Data,
+          *DataLength,
+          NULL,
+          NULL
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  } else if (*TransferResult == EFI_USB_ERR_STALL) {
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
+    ASSERT_EFI_ERROR (RecoveryStatus);
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  FreePool (Urb);
+
+ON_EXIT:
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+
+/**
+  Submits isochronous transfer to a target USB device.
+
+  @param  This                 This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress        Target device address.
+  @param  EndPointAddress      End point address with its direction.
+  @param  DeviceSpeed          Device speed, Low speed device doesn't support this
+                               type.
+  @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
+                               sending or receiving.
+  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
+  @param  Data                 Array of pointers to the buffers of data that will
+                               be transmitted to USB device or received from USB
+                               device.
+  @param  DataLength           The size, in bytes, of the data buffer.
+  @param  Translator           Transaction translator to use.
+  @param  TransferResult       Variable to receive the transfer result.
+
+  @return EFI_UNSUPPORTED      Isochronous transfer is unsupported.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcIsochronousTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               EndPointAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     UINT8                               DataBuffersNumber,
+  IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+  IN     UINTN                               DataLength,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  OUT    UINT32                              *TransferResult
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+
+/**
+  Submits Async isochronous transfer to a target USB device.
+
+  @param  This                 This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress        Target device address.
+  @param  EndPointAddress      End point address with its direction.
+  @param  DeviceSpeed          Device speed, Low speed device doesn't support this
+                               type.
+  @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
+                               sending or receiving.
+  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
+  @param  Data                 Array of pointers to the buffers of data that will
+                               be transmitted to USB device or received from USB
+                               device.
+  @param  DataLength           The size, in bytes, of the data buffer.
+  @param  Translator           Transaction translator to use.
+  @param  IsochronousCallBack  Function to be called when the transfer complete.
+  @param  Context              Context passed to the call back function as
+                               parameter.
+
+  @return EFI_UNSUPPORTED      Isochronous transfer isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcAsyncIsochronousTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               EndPointAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     UINT8                               DataBuffersNumber,
+  IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+  IN     UINTN                               DataLength,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
+  IN     VOID                                *Context
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Entry point for EFI drivers.
+
+  @param  ImageHandle       EFI_HANDLE.
+  @param  SystemTable       EFI_SYSTEM_TABLE.
+
+  @retval EFI_SUCCESS       Success.
+  @retval Others            Fail.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDriverEntryPoint (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,
+           &gXhciDriverBinding,
+           ImageHandle,
+           &gXhciComponentName,
+           &gXhciComponentName2
+           );
+}
+
+
+/**
+  Test to see if this driver supports ControllerHandle. Any
+  ControllerHandle that has Usb2HcProtocol installed will
+  be supported.
+
+  @param  This                 Protocol instance pointer.
+  @param  Controller           Handle of device to test.
+  @param  RemainingDevicePath  Not used.
+
+  @return EFI_SUCCESS          This driver supports this device.
+  @return EFI_UNSUPPORTED      This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDriverBindingSupported (
+  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;
+
+  //
+  // Test whether there is PCI IO Protocol attached on the controller handle.
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (EFI_ERROR (Status)) {
+    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 Xhci type
+  //
+  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
+      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
+      (UsbClassCReg.ProgInterface != PCI_IF_XHCI)) {
+    Status = EFI_UNSUPPORTED;
+  }
+
+ON_EXIT:
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  return Status;
+}
+
+/**
+  Create and initialize a USB_XHCI_INSTANCE structure.
+
+  @param  PciIo                  The PciIo on this device.
+  @param  OriginalPciAttributes  Original PCI attributes.
+
+  @return The allocated and initialized USB_XHCI_INSTANCE structure if created,
+          otherwise NULL.
+
+**/
+USB_XHCI_INSTANCE*
+XhcCreateUsbHc (
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN UINT64               OriginalPciAttributes
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
+  EFI_STATUS              Status;
+  UINT32                  PageSize;
+  UINT16                  ExtCapReg;
+
+  Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));
+
+  if (Xhc == NULL) {
+    return NULL;
+  }
+
+  //
+  // Initialize private data structure
+  //
+  Xhc->Signature             = XHCI_INSTANCE_SIG;
+  Xhc->PciIo                 = PciIo;
+  Xhc->OriginalPciAttributes = OriginalPciAttributes;
+  CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));
+
+  InitializeListHead (&Xhc->AsyncIntTransfers);
+
+  //
+  // Be caution that the Offset passed to XhcReadCapReg() should be Dword align
+  //
+  Xhc->CapLength        = XhcReadCapReg8 (Xhc, XHC_CAPLENGTH_OFFSET);
+  Xhc->HcSParams1.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS1_OFFSET);
+  Xhc->HcSParams2.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS2_OFFSET);
+  Xhc->HcCParams.Dword  = XhcReadCapReg (Xhc, XHC_HCCPARAMS_OFFSET);
+  Xhc->DBOff            = XhcReadCapReg (Xhc, XHC_DBOFF_OFFSET);
+  Xhc->RTSOff           = XhcReadCapReg (Xhc, XHC_RTSOFF_OFFSET);
+
+  //
+  // This PageSize field defines the page size supported by the xHC implementation.
+  // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
+  // if bit 0 is Set, the xHC supports 4k byte page sizes.
+  //
+  PageSize      = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;
+  Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);
+
+  ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);
+  Xhc->ExtCapRegBase   = ExtCapReg << 2;
+  Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc);
+
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));
+
+  //
+  // Create AsyncRequest Polling Timer
+  //
+  Status = gBS->CreateEvent (
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  XhcMonitorAsyncRequests,
+                  Xhc,
+                  &Xhc->PollTimer
+                  );
+
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  return Xhc;
+
+ON_ERROR:
+  FreePool (Xhc);
+  return NULL;
+}
+
+/**
+  One notified function to stop the Host Controller when gBS->ExitBootServices() called.
+
+  @param  Event                   Pointer to this event
+  @param  Context                 Event hanlder private data
+
+**/
+VOID
+EFIAPI
+XhcExitBootService (
+  EFI_EVENT  Event,
+  VOID       *Context
+  )
+
+{
+  USB_XHCI_INSTANCE    *Xhc;
+  EFI_PCI_IO_PROTOCOL  *PciIo;
+
+  Xhc = (USB_XHCI_INSTANCE*) Context;
+  PciIo = Xhc->PciIo;
+
+  //
+  // Stop AsyncRequest Polling timer then stop the XHCI driver
+  // and uninstall the XHCI protocl.
+  //
+  gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
+  XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
+
+  if (Xhc->PollTimer != NULL) {
+    gBS->CloseEvent (Xhc->PollTimer);
+  }
+
+  //
+  // Restore original PCI attributes
+  //
+  PciIo->Attributes (
+                  PciIo,
+                  EfiPciIoAttributeOperationSet,
+                  Xhc->OriginalPciAttributes,
+                  NULL
+                  );
+
+  XhcClearBiosOwnership (Xhc);
+}
+
+/**
+  Starting the Usb XHCI Driver.
+
+  @param  This                 Protocol instance pointer.
+  @param  Controller           Handle of device to test.
+  @param  RemainingDevicePath  Not used.
+
+  @return EFI_SUCCESS          supports this device.
+  @return EFI_UNSUPPORTED      do not support this device.
+  @return EFI_DEVICE_ERROR     cannot be started due to device Error.
+  @return EFI_OUT_OF_RESOURCES cannot allocate resources.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  EFI_STATUS              Status;
+  EFI_PCI_IO_PROTOCOL     *PciIo;
+  UINT64                  Supports;
+  UINT64                  OriginalPciAttributes;
+  BOOLEAN                 PciAttributesSaved;
+  USB_XHCI_INSTANCE       *Xhc;
+
+  //
+  // Open the PciIo Protocol, then enable the USB host controller
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  PciAttributesSaved = FALSE;
+  //
+  // Save original PCI attributes
+  //
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationGet,
+                    0,
+                    &OriginalPciAttributes
+                    );
+
+  if (EFI_ERROR (Status)) {
+    goto CLOSE_PCIIO;
+  }
+  PciAttributesSaved = TRUE;
+
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationSupported,
+                    0,
+                    &Supports
+                    );
+  if (!EFI_ERROR (Status)) {
+    Supports &= EFI_PCI_DEVICE_ENABLE;
+    Status = PciIo->Attributes (
+                      PciIo,
+                      EfiPciIoAttributeOperationEnable,
+                      Supports,
+                      NULL
+                      );
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to enable controller\n"));
+    goto CLOSE_PCIIO;
+  }
+
+  //
+  // Create then install USB2_HC_PROTOCOL
+  //
+  Xhc = XhcCreateUsbHc (PciIo, OriginalPciAttributes);
+
+  if (Xhc == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  XhcSetBiosOwnership (Xhc);
+
+  XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
+  ASSERT (XhcIsHalt (Xhc));
+
+  //
+  // After Chip Hardware Reset wait until the Controller Not Ready (CNR) flag
+  // in the USBSTS is '0' before writing any xHC Operational or Runtime registers.
+  //
+  ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
+
+  //
+  // Initialize the schedule
+  //
+  XhcInitSched (Xhc);
+
+  //
+  // Start the Host Controller
+  //
+  XhcRunHC(Xhc, XHC_GENERIC_TIMEOUT);
+
+  //
+  // Start the asynchronous interrupt monitor
+  //
+  Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));
+    XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
+    goto FREE_POOL;
+  }
+
+  //
+  // Create event to stop the HC when exit boot service.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  XhcExitBootService,
+                  Xhc,
+                  &gEfiEventExitBootServicesGuid,
+                  &Xhc->ExitBootServiceEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FREE_POOL;
+  }
+
+  //
+  // Install the component name protocol, don't fail the start
+  // because of something for display.
+  //
+  AddUnicodeString2 (
+    "eng",
+    gXhciComponentName.SupportedLanguages,
+    &Xhc->ControllerNameTable,
+    L"eXtensible Host Controller (USB 3.0)",
+    TRUE
+    );
+  AddUnicodeString2 (
+    "en",
+    gXhciComponentName2.SupportedLanguages,
+    &Xhc->ControllerNameTable,
+    L"eXtensible Host Controller (USB 3.0)",
+    FALSE
+    );
+
+  Status = gBS->InstallProtocolInterface (
+                  &Controller,
+                  &gEfiUsb2HcProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &Xhc->Usb2Hc
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
+    goto FREE_POOL;
+  }
+
+  DEBUG ((EFI_D_INFO, "XhcDriverBindingStart: XHCI started for controller @ %x\n", Controller));
+  return EFI_SUCCESS;
+
+FREE_POOL:
+  gBS->CloseEvent (Xhc->PollTimer);
+  XhcFreeSched (Xhc);
+  FreePool (Xhc);
+
+CLOSE_PCIIO:
+  if (PciAttributesSaved) {
+    //
+    // Restore original PCI attributes
+    //
+    PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationSet,
+                    OriginalPciAttributes,
+                    NULL
+                    );
+  }
+
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  return Status;
+}
+
+
+/**
+  Stop this driver on ControllerHandle. Support stoping any child handles
+  created by this driver.
+
+  @param  This                 Protocol instance pointer.
+  @param  Controller           Handle of device to stop driver on.
+  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
+  @param  ChildHandleBuffer    List of handles for the children we need to stop.
+
+  @return EFI_SUCCESS          Success.
+  @return EFI_DEVICE_ERROR     Fail.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  Controller,
+  IN UINTN                       NumberOfChildren,
+  IN EFI_HANDLE                  *ChildHandleBuffer
+  )
+{
+  EFI_STATUS            Status;
+  EFI_USB2_HC_PROTOCOL  *Usb2Hc;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+  USB_XHCI_INSTANCE     *Xhc;
+  UINT8                 Index;
+
+  //
+  // Test whether the Controller handler passed in is a valid
+  // Usb controller handle that should be supported, if not,
+  // return the error status directly
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiUsb2HcProtocolGuid,
+                  (VOID **) &Usb2Hc,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Xhc   = XHC_FROM_THIS (Usb2Hc);
+  PciIo = Xhc->PciIo;
+
+  //
+  // Stop AsyncRequest Polling timer then stop the XHCI driver
+  // and uninstall the XHCI protocl.
+  //
+  gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
+
+  //
+  // Disable the device slots occupied by these devices on its downstream ports.
+  // Entry 0 is reserved.
+  //
+  for (Index = 0; Index < 255; Index++) {
+    if (!Xhc->UsbDevContext[Index + 1].Enabled ||
+        (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {
+      continue;
+    }
+    if (Xhc->HcCParams.Data.Csz == 0) {
+      XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
+    } else {
+      XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
+    }
+  }
+
+  XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
+  XhcClearBiosOwnership (Xhc);
+
+  Status = gBS->UninstallProtocolInterface (
+                  Controller,
+                  &gEfiUsb2HcProtocolGuid,
+                  Usb2Hc
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Xhc->PollTimer != NULL) {
+    gBS->CloseEvent (Xhc->PollTimer);
+  }
+
+  if (Xhc->ExitBootServiceEvent != NULL) {
+    gBS->CloseEvent (Xhc->ExitBootServiceEvent);
+  }
+
+  XhciDelAllAsyncIntTransfers (Xhc);
+  XhcFreeSched (Xhc);
+
+  if (Xhc->ControllerNameTable) {
+    FreeUnicodeStringTable (Xhc->ControllerNameTable);
+  }
+
+  //
+  // Restore original PCI attributes
+  //
+  PciIo->Attributes (
+           PciIo,
+           EfiPciIoAttributeOperationSet,
+           Xhc->OriginalPciAttributes,
+           NULL
+           );
+
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  FreePool (Xhc);
+
+  return EFI_SUCCESS;
+}
+
index f6da016bfb8ee8589b8105cb40d44248265600d9..a486413086d51c18ea0f7a5fe7c1fe7c14dbe1ab 100644 (file)
@@ -2,7 +2,7 @@
 \r
   Provides some data structure definitions used by the XHCI host controller driver.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -71,10 +71,10 @@ typedef struct _USB_DEV_CONTEXT      USB_DEV_CONTEXT;
 //\r
 #define XHC_TPL                      TPL_NOTIFY\r
 \r
-#define CMD_RING_TRB_NUMBER          0x40\r
-#define TR_RING_TRB_NUMBER           0x40\r
+#define CMD_RING_TRB_NUMBER          0x100\r
+#define TR_RING_TRB_NUMBER           0x100\r
 #define ERST_NUMBER                  0x01\r
-#define EVENT_RING_TRB_NUMBER        0x80\r
+#define EVENT_RING_TRB_NUMBER        0x200\r
 \r
 #define CMD_INTER                    0\r
 #define CTRL_INTER                   1\r
index 26ead70bb44fa0a0cbb9f36e95c0d1a9ad9ab8f2..eea468bbd78026aa85186a3c1db9dd5ffccb7c69 100644 (file)
@@ -2,7 +2,7 @@
 \r
   This file contains the register definition of XHCI host controller.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -172,6 +172,15 @@ typedef union {
 #define XHC_PORTSC_CEC                     BIT23 // Port Config Error Change\r
 #define XHC_PORTSC_CAS                     BIT24 // Cold Attach Status\r
 \r
+#define XHC_HUB_PORTSC_CCS                 BIT0  // Hub's Current Connect Status\r
+#define XHC_HUB_PORTSC_PED                 BIT1  // Hub's Port Enabled/Disabled\r
+#define XHC_HUB_PORTSC_OCA                 BIT3  // Hub's Over-current Active\r
+#define XHC_HUB_PORTSC_RESET               BIT4  // Hub's Port Reset\r
+#define XHC_HUB_PORTSC_PP                  BIT9  // Hub's Port Power\r
+#define XHC_HUB_PORTSC_CSC                 BIT16 // Hub's Connect Status Change\r
+#define XHC_HUB_PORTSC_PEC                 BIT17 // Hub's Port Enabled/Disabled Change\r
+#define XHC_HUB_PORTSC_OCC                 BIT19 // Hub's Over-Current Change\r
+#define XHC_HUB_PORTSC_PRC                 BIT20 // Hub's Port Reset Change\r
 #define XHC_IMAN_IP                        BIT0  // Interrupt Pending\r
 #define XHC_IMAN_IE                        BIT1  // Interrupt Enable\r
 \r
index 372702d3f08239f11432dbf549595530db420e27..5d1f2b96ddb142b8c17491f4ab30f039654f86ad 100644 (file)
@@ -47,10 +47,6 @@ XhcCreateCmdTrb (
   Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;\r
   Urb->TrbEnd             = Urb->TrbStart;\r
 \r
-  Urb->EvtRing     = &Xhc->EventRing;\r
-  XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-  Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
   return Urb;\r
 }\r
 \r
@@ -106,10 +102,8 @@ XhcCmdTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  ASSERT (Urb->EvtRing == &Xhc->EventRing);\r
-\r
   Status  = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);\r
-  *EvtTrb = Urb->EvtTrbStart;\r
+  *EvtTrb = Urb->EvtTrb;\r
 \r
   if (Urb->Result == EFI_USB_NOERROR) {\r
     Status = EFI_SUCCESS;\r
@@ -216,6 +210,12 @@ XhcCreateTransferTrb (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  Urb->Finished  = FALSE;\r
+  Urb->StartDone = FALSE;\r
+  Urb->EndDone   = FALSE;\r
+  Urb->Completed = 0;\r
+  Urb->Result    = EFI_USB_NOERROR;\r
+\r
   Dci       = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
   ASSERT (Dci < 32);\r
   EPRing    = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];\r
@@ -234,9 +234,6 @@ XhcCreateTransferTrb (
   Urb->TrbStart = EPRing->RingEnqueue;\r
   switch (EPType) {\r
     case ED_CONTROL_BIDIR:\r
-      Urb->EvtRing     = &Xhc->EventRing;\r
-      XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-      Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
       //\r
       // For control transfer, create SETUP_STAGE_TRB first.\r
       //\r
@@ -325,10 +322,6 @@ XhcCreateTransferTrb (
 \r
     case ED_BULK_OUT:\r
     case ED_BULK_IN:\r
-      Urb->EvtRing     = &Xhc->EventRing;\r
-      XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-      Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
       TotalLen = 0;\r
       Len      = 0;\r
       TrbNum   = 0;\r
@@ -364,10 +357,6 @@ XhcCreateTransferTrb (
 \r
     case ED_INTERRUPT_OUT:\r
     case ED_INTERRUPT_IN:\r
-      Urb->EvtRing = &Xhc->EventRing;\r
-      XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-      Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
       TotalLen = 0;\r
       Len      = 0;\r
       TrbNum   = 0;\r
@@ -829,39 +818,78 @@ XhcFreeSched (
 }\r
 \r
 /**\r
-  Check if it is ring TRB.\r
+  Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list.\r
 \r
-  @param Ring   The transfer ring\r
-  @param Trb    The TRB to check if it's in the transfer ring\r
+  @param Xhc    The XHCI Instance.\r
+  @param Trb    The TRB to be checked.\r
+  @param Urb    The pointer to the matched Urb.\r
 \r
-  @retval TRUE  It is in the ring\r
-  @retval FALSE It is not in the ring\r
+  @retval TRUE  The Trb is matched with a transaction of the URBs in the async list.\r
+  @retval FALSE The Trb is not matched with any URBs in the async list.\r
+\r
+**/\r
+BOOLEAN\r
+IsAsyncIntTrb (\r
+  IN  USB_XHCI_INSTANCE   *Xhc,\r
+  IN  TRB_TEMPLATE        *Trb,\r
+  OUT URB                 **Urb\r
+  )\r
+{\r
+  LIST_ENTRY              *Entry;\r
+  LIST_ENTRY              *Next;\r
+  TRB_TEMPLATE            *CheckedTrb;\r
+  URB                     *CheckedUrb;\r
+  UINTN                   Index;\r
+\r
+  EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
+    CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
+    CheckedTrb = CheckedUrb->TrbStart;\r
+    for (Index = 0; Index < CheckedUrb->TrbNum; Index++) {\r
+      if (Trb == CheckedTrb) {\r
+        *Urb = CheckedUrb;\r
+        return TRUE;\r
+      }\r
+      CheckedTrb++;\r
+      if ((UINTN)CheckedTrb >= ((UINTN) CheckedUrb->Ring->RingSeg0 + sizeof (TRB_TEMPLATE) * CheckedUrb->Ring->TrbNumber)) {\r
+        CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0;\r
+      }\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if the Trb is a transaction of the URB.\r
+\r
+  @param Trb    The TRB to be checked\r
+  @param Urb    The transfer ring to be checked.\r
+\r
+  @retval TRUE  It is a transaction of the URB.\r
+  @retval FALSE It is not any transaction of the URB.\r
 \r
 **/\r
 BOOLEAN\r
 IsTransferRingTrb (\r
-  IN  TRANSFER_RING       *Ring,\r
-  IN  TRB_TEMPLATE        *Trb\r
+  IN  TRB_TEMPLATE        *Trb,\r
+  IN  URB                 *Urb\r
   )\r
 {\r
-  BOOLEAN       Flag;\r
-  TRB_TEMPLATE  *Trb1;\r
+  TRB_TEMPLATE  *CheckedTrb;\r
   UINTN         Index;\r
 \r
-  Trb1 = Ring->RingSeg0;\r
-  Flag = FALSE;\r
+  CheckedTrb = Urb->Ring->RingSeg0;\r
 \r
-  ASSERT (Ring->TrbNumber == CMD_RING_TRB_NUMBER || Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
+  ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
 \r
-  for (Index = 0; Index < Ring->TrbNumber; Index++) {\r
-    if (Trb == Trb1) {\r
-      Flag = TRUE;\r
-      break;\r
+  for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) {\r
+    if (Trb == CheckedTrb) {\r
+      return TRUE;\r
     }\r
-    Trb1++;\r
+    CheckedTrb++;\r
   }\r
 \r
-  return Flag;\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -880,20 +908,26 @@ XhcCheckUrbResult (
   IN  URB                 *Urb\r
   )\r
 {\r
-  BOOLEAN                 StartDone;\r
-  BOOLEAN                 EndDone;\r
   EVT_TRB_TRANSFER        *EvtTrb;\r
   TRB_TEMPLATE            *TRBPtr;\r
   UINTN                   Index;\r
   UINT8                   TRBType;\r
   EFI_STATUS              Status;\r
+  URB                     *AsyncUrb;\r
+  URB                     *CheckedUrb;\r
+  UINT64                  XhcDequeue;\r
+  UINT32                  High;\r
+  UINT32                  Low;\r
 \r
   ASSERT ((Xhc != NULL) && (Urb != NULL));\r
 \r
-  Urb->Completed  = 0;\r
-  Urb->Result     = EFI_USB_NOERROR;\r
-  Status          = EFI_SUCCESS;\r
-  EvtTrb          = NULL;\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (Urb->Finished) {\r
+    goto EXIT;\r
+  }\r
+\r
+  EvtTrb = NULL;\r
 \r
   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
     Urb->Result |= EFI_USB_ERR_SYSTEM;\r
@@ -902,16 +936,15 @@ XhcCheckUrbResult (
   }\r
 \r
   //\r
-  // Restore the EventRingDequeue and poll the transfer event ring from beginning\r
+  // Traverse the event ring to find out all new events from the previous check.\r
   //\r
-  StartDone = FALSE;\r
-  EndDone   = FALSE;\r
-  Urb->EvtRing->EventRingDequeue = Urb->EvtTrbStart;\r
-  for (Index = 0; Index < Urb->EvtRing->TrbNumber; Index++) {\r
-    XhcSyncEventRing (Xhc, Urb->EvtRing);\r
-    Status = XhcCheckNewEvent (Xhc, Urb->EvtRing, ((TRB_TEMPLATE **)&EvtTrb));\r
+  XhcSyncEventRing (Xhc, &Xhc->EventRing);\r
+  for (Index = 0; Index < Xhc->EventRing.TrbNumber; Index++) {\r
+    Status = XhcCheckNewEvent (Xhc, &Xhc->EventRing, ((TRB_TEMPLATE **)&EvtTrb));\r
     if (Status == EFI_NOT_READY) {\r
-      Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
+      //\r
+      // All new events are handled, return directly.\r
+      //\r
       goto EXIT;\r
     }\r
 \r
@@ -923,78 +956,106 @@ XhcCheckUrbResult (
     }\r
 \r
     TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));\r
-    if (IsTransferRingTrb (Urb->Ring, TRBPtr)) {\r
-      switch (EvtTrb->Completecode) {\r
-        case TRB_COMPLETION_STALL_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_STALL;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
 \r
-        case TRB_COMPLETION_BABBLE_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_BABBLE;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
+    //\r
+    // Update the status of Urb according to the finished event regardless of whether\r
+    // the urb is current checked one or in the XHCI's async transfer list.\r
+    // This way is used to avoid that those completed async transfer events don't get\r
+    // handled in time and are flushed by newer coming events.\r
+    //\r
+    if (IsTransferRingTrb (TRBPtr, Urb)) {\r
+      CheckedUrb = Urb;\r
+    } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) {    \r
+      CheckedUrb = AsyncUrb;\r
+    } else {\r
+      continue;\r
+    }\r
+  \r
+    switch (EvtTrb->Completecode) {\r
+      case TRB_COMPLETION_STALL_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_STALL;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+        break;\r
 \r
-        case TRB_COMPLETION_DATA_BUFFER_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_BUFFER;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
+      case TRB_COMPLETION_BABBLE_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_BABBLE;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+        break;\r
 \r
-        case TRB_COMPLETION_USB_TRANSACTION_ERROR:\r
-          Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
-          Status       = EFI_DEVICE_ERROR;\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
-          goto EXIT;\r
-          break;\r
+      case TRB_COMPLETION_DATA_BUFFER_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_BUFFER;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));\r
+        break;\r
 \r
-        case TRB_COMPLETION_SHORT_PACKET:\r
-        case TRB_COMPLETION_SUCCESS:\r
-          if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {\r
-            DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));\r
-          }\r
+      case TRB_COMPLETION_USB_TRANSACTION_ERROR:\r
+        CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;\r
+        CheckedUrb->Finished = TRUE;\r
+        DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+        break;\r
 \r
-          TRBType = (UINT8) (TRBPtr->Type);\r
-          if ((TRBType == TRB_TYPE_DATA_STAGE) ||\r
-              (TRBType == TRB_TYPE_NORMAL) ||\r
-              (TRBType == TRB_TYPE_ISOCH)) {\r
-            Urb->Completed += (Urb->DataLen - EvtTrb->Lenth);\r
-          }\r
+      case TRB_COMPLETION_SHORT_PACKET:\r
+      case TRB_COMPLETION_SUCCESS:\r
+        if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {\r
+          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));\r
+        }\r
 \r
-          Status = EFI_SUCCESS;\r
-          break;\r
+        TRBType = (UINT8) (TRBPtr->Type);\r
+        if ((TRBType == TRB_TYPE_DATA_STAGE) ||\r
+            (TRBType == TRB_TYPE_NORMAL) ||\r
+            (TRBType == TRB_TYPE_ISOCH)) {\r
+          CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Lenth);\r
+        }\r
 \r
-        default:\r
-          DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
-          Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
-          Status = EFI_DEVICE_ERROR;\r
-          goto EXIT;\r
-          break;\r
-      }\r
+        break;\r
 \r
-      //\r
-      // Only check first and end Trb event address\r
-      //\r
-      if (TRBPtr == Urb->TrbStart) {\r
-        StartDone = TRUE;\r
-      }\r
+      default:\r
+        DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
+        CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;\r
+        CheckedUrb->Finished = TRUE;\r
+        break;\r
+    }\r
 \r
-      if (TRBPtr == Urb->TrbEnd) {\r
-        EndDone = TRUE;\r
-      }\r
+    //\r
+    // Only check first and end Trb event address\r
+    //\r
+    if (TRBPtr == CheckedUrb->TrbStart) {\r
+      CheckedUrb->StartDone = TRUE;\r
+    }\r
 \r
-      if (StartDone && EndDone) {\r
-        break;\r
-      }\r
+    if (TRBPtr == CheckedUrb->TrbEnd) {\r
+      CheckedUrb->EndDone = TRUE;\r
+    }\r
+\r
+    if (CheckedUrb->StartDone && CheckedUrb->EndDone) {\r
+      CheckedUrb->Finished = TRUE;\r
+      CheckedUrb->EvtTrb   = (TRB_TEMPLATE *)EvtTrb;\r
     }\r
   }\r
 \r
 EXIT:\r
+\r
+  //\r
+  // Advance event ring to last available entry\r
+  //\r
+  // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+  // So divide it to two 32-bytes width register access.\r
+  //\r
+  Low  = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);\r
+  High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);\r
+  XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);\r
+\r
+  if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Xhc->EventRing.EventRingDequeue & (~0x0F))) {\r
+    //\r
+    // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+    // So divide it to two 32-bytes width register access.\r
+    //\r
+    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (Xhc->EventRing.EventRingDequeue) | BIT3);\r
+    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->EventRing.EventRingDequeue));\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -1048,12 +1109,16 @@ XhcExecTransfer (
 \r
   for (Index = 0; Index < Loop; Index++) {\r
     Status = XhcCheckUrbResult (Xhc, Urb);\r
-    if ((Status != EFI_NOT_READY)) {\r
+    if (Urb->Finished) {\r
       break;\r
     }\r
     gBS->Stall (XHC_POLL_DELAY);\r
   }\r
 \r
+  if (Index == Loop) {\r
+    Urb->Result = EFI_USB_ERR_TIMEOUT;\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -1196,7 +1261,7 @@ XhcMonitorAsyncRequests (
     //\r
     Status = XhcCheckUrbResult (Xhc, Urb);\r
 \r
-    if (Status == EFI_NOT_READY) {\r
+    if (!Urb->Finished) {\r
       continue;\r
     }\r
 \r
@@ -1219,8 +1284,6 @@ XhcMonitorAsyncRequests (
       CopyMem (ProcBuf, Urb->Data, Urb->Completed);\r
     }\r
 \r
-    XhcUpdateAsyncRequest (Xhc, Urb);\r
-\r
     //\r
     // Leave error recovery to its related device driver. A\r
     // common case of the error recovery is to re-submit the\r
@@ -1244,6 +1307,8 @@ XhcMonitorAsyncRequests (
     if (ProcBuf != NULL) {\r
       gBS->FreePool (ProcBuf);\r
     }\r
+\r
+    XhcUpdateAsyncRequest (Xhc, Urb);\r
   }\r
   gBS->RestoreTPL (OldTpl);\r
 }\r
@@ -1445,10 +1510,6 @@ XhcSyncEventRing (
 {\r
   UINTN               Index;\r
   TRB_TEMPLATE        *EvtTrb1;\r
-  TRB_TEMPLATE        *EvtTrb2;\r
-  UINT64              XhcDequeue;\r
-  UINT32              High;\r
-  UINT32              Low;\r
 \r
   ASSERT (EvtRing != NULL);\r
 \r
@@ -1456,41 +1517,25 @@ XhcSyncEventRing (
   // Calculate the EventRingEnqueue and EventRingCCS.\r
   // Note: only support single Segment\r
   //\r
-  EvtTrb1 = EvtRing->EventRingSeg0;\r
-  EvtTrb2 = EvtRing->EventRingSeg0;\r
+  EvtTrb1 = EvtRing->EventRingDequeue;\r
 \r
   for (Index = 0; Index < EvtRing->TrbNumber; Index++) {\r
-    if (EvtTrb1->CycleBit != EvtTrb2->CycleBit) {\r
+    if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {\r
       break;\r
     }\r
+\r
     EvtTrb1++;\r
+\r
+    if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+      EvtTrb1 = EvtRing->EventRingSeg0;\r
+      EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;\r
+    }\r
   }\r
 \r
   if (Index < EvtRing->TrbNumber) {\r
     EvtRing->EventRingEnqueue = EvtTrb1;\r
-    EvtRing->EventRingCCS     = (EvtTrb2->CycleBit) ? 1 : 0;\r
   } else {\r
-    EvtRing->EventRingEnqueue = EvtTrb2;\r
-    EvtRing->EventRingCCS     = (EvtTrb2->CycleBit) ? 0 : 1;\r
-  }\r
-\r
-  //\r
-  // Apply the EventRingDequeue to Xhc\r
-  //\r
-  // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
-  // So divide it to two 32-bytes width register access.\r
-  //\r
-  Low  = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);\r
-  High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);\r
-  XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);\r
-\r
-  if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)EvtRing->EventRingDequeue & (~0x0F))) {\r
-    //\r
-    // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
-    // So divide it to two 32-bytes width register access.\r
-    //\r
-    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (EvtRing->EventRingDequeue) | BIT3);\r
-    XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (EvtRing->EventRingDequeue));\r
+    ASSERT (FALSE);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -1579,8 +1624,8 @@ XhcCheckNewEvent (
   OUT TRB_TEMPLATE            **NewEvtTrb\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  TRB_TEMPLATE*EvtTrb;\r
+  EFI_STATUS          Status;\r
+  TRB_TEMPLATE        *EvtTrb;\r
 \r
   ASSERT (EvtRing != NULL);\r
 \r
@@ -1593,15 +1638,11 @@ XhcCheckNewEvent (
 \r
   Status = EFI_SUCCESS;\r
 \r
-  if (((EvtTrb->Status >> 24) & 0xFF) != TRB_COMPLETION_SUCCESS) {\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
   EvtRing->EventRingDequeue++;\r
   //\r
   // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.\r
   //\r
-  if ((UINTN)EvtRing->EventRingDequeue >=  ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+  if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
     EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;\r
   }\r
 \r
@@ -1845,7 +1886,7 @@ XhcInitializeDeviceSlot (
   ASSERT (!EFI_ERROR(Status));\r
 \r
   DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;\r
-  DEBUG ((EFI_D_INFO, "    Address %d assigned succeefully\n", DeviceAddress));\r
+  DEBUG ((EFI_D_INFO, "    Address %d assigned successfully\n", DeviceAddress));\r
 \r
   Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
 \r
@@ -2038,7 +2079,7 @@ XhcInitializeDeviceSlot64 (
   ASSERT (!EFI_ERROR(Status));\r
 \r
   DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;\r
-  DEBUG ((EFI_D_INFO, "    Address %d assigned succeefully\n", DeviceAddress));\r
+  DEBUG ((EFI_D_INFO, "    Address %d assigned successfully\n", DeviceAddress));\r
 \r
   Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
 \r
index f319c56c60e2ac19390ed4540451abb2ad56b51a..227b4552305aa0dabff6c198d17966a86b6089fe 100644 (file)
@@ -2,7 +2,7 @@
 \r
   This file contains the definition for XHCI host controller schedule routines.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -189,8 +189,11 @@ typedef struct _URB {
   TRB_TEMPLATE                    *TrbStart;\r
   TRB_TEMPLATE                    *TrbEnd;\r
   UINTN                           TrbNum;\r
-  EVENT_RING                      *EvtRing;\r
-  TRB_TEMPLATE                    *EvtTrbStart;\r
+  BOOLEAN                         StartDone;\r
+  BOOLEAN                         EndDone;\r
+  BOOLEAN                         Finished;\r
+\r
+  TRB_TEMPLATE                    *EvtTrb;\r
 } URB;\r
 \r
 //\r
index 8d031b90457efa05fb2b068a7cb47806029696fb..f708902f1abe625b0a00c115aba7fd72ce6d99af 100644 (file)
@@ -862,7 +862,7 @@ UsbEnumeratePort (
   }\r
 \r
   DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",\r
-              Port, PortState.PortChangeStatus, PortState.PortStatus, HubIf));\r
+              Port, PortState.PortStatus, PortState.PortChangeStatus, HubIf));\r
 \r
   //\r
   // This driver only process two kinds of events now: over current and\r
index e0f67dd1d94ff88caedd8b17afed2c43213676cb..78af917ca0400826b53352e4841a2165a76b1397 100644 (file)
@@ -2,7 +2,7 @@
 \r
     Unified interface for RootHub and Hub.\r
 \r
-Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR> \r
+Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR> \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -844,12 +844,6 @@ UsbHubGetPortStatus (
 \r
   Status  = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);\r
 \r
-  //\r
-  // Mark the USB_PORT_STAT_SUPER_SPEED bit if SuperSpeed\r
-  //\r
-  if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {\r
-    PortState->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
-  } \r
   return Status;\r
 }\r
 \r