]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
MdeModulePkg/XhciDxe: Separate common logic to XhcTransfer
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / Xhci.c
index 30eb3ea916a30ef74bcc6da3702f4ebfb3b18d4a..e3cbdbc800387670d060ada28fe2f0b755c876b4 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The XHCI controller driver.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2017, 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
@@ -14,11 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "Xhci.h"\r
 \r
-//\r
-// The device context array which supports up to 255 devices, entry 0 is reserved and should not be used.\r
-//\r
-USB_DEV_CONTEXT UsbDevContext[256];\r
-\r
 //\r
 // Two arrays used to translate the XHCI port state (change)\r
 // to the UEFI protocol's port state (change).\r
@@ -37,6 +32,35 @@ USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
   {XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}\r
 };\r
 \r
+USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {\r
+  {XHC_PORTSC_CSC, EfiUsbPortConnectChange},\r
+  {XHC_PORTSC_PEC, EfiUsbPortEnableChange},\r
+  {XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange},\r
+  {XHC_PORTSC_PRC, EfiUsbPortResetChange}\r
+};\r
+\r
+USB_PORT_STATE_MAP  mUsbHubPortStateMap[] = {\r
+  {XHC_HUB_PORTSC_CCS,   USB_PORT_STAT_CONNECTION},\r
+  {XHC_HUB_PORTSC_PED,   USB_PORT_STAT_ENABLE},\r
+  {XHC_HUB_PORTSC_OCA,   USB_PORT_STAT_OVERCURRENT},\r
+  {XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET}\r
+};\r
+\r
+USB_PORT_STATE_MAP  mUsbHubPortChangeMap[] = {\r
+  {XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},\r
+  {XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},\r
+  {XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},\r
+  {XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}\r
+};\r
+\r
+USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {\r
+  {XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange},\r
+  {XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange},\r
+  {XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange},\r
+  {XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange},\r
+  {XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange}\r
+};\r
+\r
 EFI_DRIVER_BINDING_PROTOCOL  gXhciDriverBinding = {\r
   XhcDriverBindingSupported,\r
   XhcDriverBindingStart,\r
@@ -46,6 +70,27 @@ EFI_DRIVER_BINDING_PROTOCOL  gXhciDriverBinding = {
   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
@@ -68,8 +113,8 @@ XhcGetCapability (
   OUT UINT8                 *Is64BitCapable\r
   )\r
 {\r
-  USB_XHCI_DEV    *Xhc;\r
-  EFI_TPL         OldTpl;\r
+  USB_XHCI_INSTANCE  *Xhc;\r
+  EFI_TPL            OldTpl;\r
 \r
   if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -80,7 +125,7 @@ XhcGetCapability (
   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
+  *Is64BitCapable = (UINT8) Xhc->Support64BitDma;\r
   DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
 \r
   gBS->RestoreTPL (OldTpl);\r
@@ -109,13 +154,24 @@ XhcReset (
   IN UINT16                Attributes\r
   )\r
 {\r
-  USB_XHCI_DEV    *Xhc;\r
-  EFI_STATUS      Status;\r
-  EFI_TPL         OldTpl;\r
+  USB_XHCI_INSTANCE  *Xhc;\r
+  EFI_STATUS         Status;\r
+  EFI_TPL            OldTpl;\r
 \r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+  Xhc = XHC_FROM_THIS (This);\r
+  \r
+  if (Xhc->DevicePath != NULL) {\r
+    //\r
+    // Report Status Code to indicate reset happens\r
+    //\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_PROGRESS_CODE,\r
+      (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),\r
+      Xhc->DevicePath\r
+      );\r
+  }  \r
 \r
-  Xhc    = XHC_FROM_THIS (This);\r
+  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
 \r
   switch (Attributes) {\r
   case EFI_USB_HC_RESET_GLOBAL:\r
@@ -123,6 +179,11 @@ XhcReset (
   // Flow through, same behavior as Host Controller Reset\r
   //\r
   case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
+    if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) &&\r
+        ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0)) {\r
+      Status = EFI_SUCCESS;\r
+      goto ON_EXIT;\r
+    }\r
     //\r
     // Host Controller must be Halt when Reset it\r
     //\r
@@ -188,8 +249,8 @@ XhcGetState (
   OUT EFI_USB_HC_STATE      *State\r
   )\r
 {\r
-  USB_XHCI_DEV    *Xhc;\r
-  EFI_TPL         OldTpl;\r
+  USB_XHCI_INSTANCE  *Xhc;\r
+  EFI_TPL            OldTpl;\r
 \r
   if (State == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -230,7 +291,7 @@ XhcSetState (
   IN EFI_USB_HC_STATE      State\r
   )\r
 {\r
-  USB_XHCI_DEV        *Xhc;\r
+  USB_XHCI_INSTANCE   *Xhc;\r
   EFI_STATUS          Status;\r
   EFI_USB_HC_STATE    CurState;\r
   EFI_TPL             OldTpl;\r
@@ -309,7 +370,7 @@ XhcGetRootHubPortStatus (
   OUT EFI_USB_PORT_STATUS   *PortStatus\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT32                  Offset;\r
   UINT32                  State;\r
   UINT32                  TotalPort;\r
@@ -386,6 +447,14 @@ XhcGetRootHubPortStatus (
     }\r
   }\r
 \r
+  MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
+\r
+  for (Index = 0; Index < MapSize; Index++) {\r
+    if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {\r
+      XhcClearRootHubPortFeature (This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);\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
@@ -419,12 +488,10 @@ XhcSetRootHubPortFeature (
   IN EFI_USB_PORT_FEATURE  PortFeature\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\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
@@ -480,24 +547,13 @@ XhcSetRootHubPortFeature (
       }\r
     }\r
 \r
-    RouteChart.Field.RouteString = 0;\r
-    RouteChart.Field.RootPortNum = PortNumber + 1;\r
-    RouteChart.Field.TierNum     = 1;\r
     //\r
-    // BUGBUG: 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
+    // 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
-    SlotId = XhcRouteStringToSlotId (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
+    State |= XHC_PORTSC_RESET;\r
+    XhcWriteOpReg (Xhc, Offset, State);\r
+    XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);\r
     break;\r
 \r
   case EfiUsbPortPower:\r
@@ -549,7 +605,7 @@ XhcClearRootHubPortFeature (
   IN EFI_USB_PORT_FEATURE  PortFeature\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT32                  Offset;\r
   UINT32                  State;\r
   UINT32                  TotalPort;\r
@@ -660,6 +716,97 @@ ON_EXIT:
   return Status;\r
 }\r
 \r
+/**\r
+  Submits a new transaction to a target USB device.\r
+\r
+  @param  Xhc                   The XHCI Instance.\r
+  @param  DeviceAddress         The target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7\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  Type                  The transaction type.\r
+  @param  Request               USB device request to send.\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  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
+EFI_STATUS\r
+XhcTransfer (\r
+  IN     USB_XHCI_INSTANCE                   *Xhc,\r
+  IN     UINT8                               DeviceAddress,\r
+  IN     UINT8                               EndPointAddress,\r
+  IN     UINT8                               DeviceSpeed,\r
+  IN     UINTN                               MaximumPacketLength,\r
+  IN     UINTN                               Type,\r
+  IN     EFI_USB_DEVICE_REQUEST              *Request,\r
+  IN OUT VOID                                *Data,\r
+  IN OUT UINTN                               *DataLength,\r
+  IN     UINTN                               Timeout,\r
+  OUT    UINT32                              *TransferResult\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_STATUS              RecoveryStatus;\r
+  URB                     *Urb;\r
+\r
+  ASSERT ((Type == XHC_CTRL_TRANSFER) || (Type == XHC_BULK_TRANSFER) || (Type == XHC_INT_TRANSFER_SYNC));\r
+  Urb = XhcCreateUrb (\r
+          Xhc,\r
+          DeviceAddress,\r
+          EndPointAddress,\r
+          DeviceSpeed,\r
+          MaximumPacketLength,\r
+          Type,\r
+          Request,\r
+          Data,\r
+          *DataLength,\r
+          NULL,\r
+          NULL\r
+          );\r
+\r
+  if (Urb == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: failed to create URB!\n", Type));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
+\r
+  *TransferResult = Urb->Result;\r
+  *DataLength     = Urb->Completed;\r
+\r
+  if (Status == EFI_TIMEOUT) {\r
+    //\r
+    // The transfer timed out. Abort the transfer by dequeueing of the TD.\r
+    //\r
+    RecoveryStatus = XhcDequeueTrbFromEndpoint (Xhc, Urb);\r
+    if (EFI_ERROR (RecoveryStatus)) {\r
+      DEBUG((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed\n", Type));\r
+    }\r
+  } else {\r
+    if (*TransferResult == EFI_USB_NOERROR) {\r
+      Status = EFI_SUCCESS;\r
+    } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+      RecoveryStatus = XhcRecoverHaltedEndpoint (Xhc, Urb);\r
+      if (EFI_ERROR (RecoveryStatus)) {\r
+        DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcRecoverHaltedEndpoint failed\n", Type));\r
+      }\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  Xhc->PciIo->Flush (Xhc->PciIo);\r
+  XhcFreeUrb (Xhc, Urb);\r
+  return Status;\r
+}\r
 \r
 /**\r
   Submits control transfer to a target USB device.\r
@@ -674,7 +821,7 @@ ON_EXIT:
   @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  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
@@ -696,16 +843,14 @@ XhcControlTransfer (
   IN     EFI_USB_DATA_DIRECTION              TransferDirection,\r
   IN OUT VOID                                *Data,\r
   IN OUT UINTN                               *DataLength,\r
-  IN     UINTN                               TimeOut,\r
+  IN     UINTN                               Timeout,\r
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
   OUT    UINT32                              *TransferResult\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
-  URB                     *Urb;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT8                   Endpoint;\r
   UINT8                   Index;\r
-  UINT8                   XhciDevAddr;\r
   UINT8                   DescriptorType;\r
   UINT8                   SlotId;\r
   UINT8                   TTT;\r
@@ -714,10 +859,11 @@ XhcControlTransfer (
   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
+  EFI_USB_DEVICE_REQUEST  ClearPortRequest;\r
+  UINTN                   Len;\r
 \r
   //\r
   // Validate parameters\r
@@ -763,6 +909,7 @@ XhcControlTransfer (
 \r
   Status          = EFI_DEVICE_ERROR;\r
   *TransferResult = EFI_USB_ERR_SYSTEM;\r
+  Len             = 0;\r
 \r
   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
     DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));\r
@@ -772,55 +919,43 @@ XhcControlTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\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
+  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 (!UsbDevContext[Index + 1].Enabled &&\r
-          (UsbDevContext[Index + 1].SlotId != 0) &&\r
-          (UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {\r
-        UsbDevContext[Index + 1].BusDevAddr = 0;\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
+    if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto ON_EXIT;\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
-    UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
+    Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
     Status = EFI_SUCCESS;\r
     goto ON_EXIT;\r
   }\r
-  \r
-  //\r
-  // BUGBUG: 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->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
@@ -830,111 +965,125 @@ XhcControlTransfer (
   // combination of Ep addr and its direction.\r
   //\r
   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          XhciDevAddr,\r
-          Endpoint,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_CTRL_TRANSFER,\r
-          Request,\r
-          Data,\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
+  Status = XhcTransfer (\r
+             Xhc,\r
+             DeviceAddress,\r
+             Endpoint,\r
+             DeviceSpeed,\r
+             MaximumPacketLength,\r
+             XHC_CTRL_TRANSFER,\r
+             Request,\r
+             Data,\r
+             DataLength,\r
+             Timeout,\r
+             TransferResult\r
+             );\r
 \r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
+  if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r
-  ASSERT (Urb->EvtRing == &Xhc->CtrlTrEventRing);\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
-             (*TransferResult == EFI_USB_ERR_TIMEOUT)) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    ASSERT_EFI_ERROR (RecoveryStatus);\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
+  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
+    if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {\r
+        ASSERT (Data != NULL);\r
         //\r
         // Store a copy of device scriptor as hub device need this info to configure endpoint.\r
         //\r
-        CopyMem (&UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
-        if (UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\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 << UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
+          MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
         } else {\r
-          MaxPacket0 = UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
+          MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
         }\r
-        UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
-        Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);\r
-        ASSERT_EFI_ERROR (Status);\r
-    } else if ((DescriptorType == USB_DESC_TYPE_CONFIG) && (*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 < UsbDevContext[SlotId].DevDesc.NumConfigurations);\r
-      UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);\r
-      CopyMem (UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\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
+        } else {\r
+          Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);\r
+        }\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
+        // Default to use AlternateSetting 0 for all interfaces.\r
+        //\r
+        Xhc->UsbDevContext[SlotId].ActiveAlternateSetting = AllocateZeroPool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->NumInterfaces * sizeof (UINT8));\r
+      }\r
     } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||\r
-               (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED))) {\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 (UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
+      if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
         //\r
-        // BUGBUG: Don't support multi-TT feature for super speed hub.\r
+        // Don't support multi-TT feature for super speed hub now.\r
         //\r
-        MTT = 1;\r
-        ASSERT (FALSE);\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
-      Status = XhcConfigHubContext (\r
-                 Xhc,\r
-                 SlotId,\r
-                 HubDesc->NumPorts,\r
-                 TTT,\r
-                 MTT\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
     }\r
-  } else if (Request->Request == USB_REQ_SET_CONFIG) {\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 < UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
-      if (UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
-        XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, UsbDevContext[SlotId].ConfDesc[Index]);\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
         break;\r
       }\r
     }\r
-  } else if (Request->Request == USB_REQ_GET_STATUS) {\r
+  } else if ((Request->Request     == USB_REQ_SET_INTERFACE) &&\r
+             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_INTERFACE))) {\r
+    //\r
+    // Hook Set_Interface request from UsbBus as we need configure interface setting.\r
+    // Request->Value indicates AlterlateSetting to set\r
+    // Request->Index indicates Interface to set\r
+    //\r
+    if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] != (UINT8) Request->Value) {\r
+      if (Xhc->HcCParams.Data.Csz == 0) {\r
+        Status = XhcSetInterface (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);\r
+      } else {\r
+        Status = XhcSetInterface64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);\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
@@ -946,47 +1095,70 @@ XhcControlTransfer (
       //\r
       // For super speed hub, its bit10~12 presents the attached device speed.\r
       //\r
-      if ((*(UINT32 *)Data & XHC_PORTSC_PS) >> 10 == 0) {\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
+    } else {\r
       //\r
-      // For high speed hub, its bit9~10 presents the attached device speed.\r
+      // For high or full/low speed hub, its bit9~10 presents the attached device speed.\r
       //\r
-      if (XHC_BIT_IS_SET (*(UINT32 *)Data, BIT9)) {\r
+      if (XHC_BIT_IS_SET (State, BIT9)) {\r
         PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
-      } else if (XHC_BIT_IS_SET (*(UINT32 *)Data, BIT10)) {\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
+    MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
     for (Index = 0; Index < MapSize; Index++) {\r
-      if (XHC_BIT_IS_SET (*(UINT32 *)Data, mUsbPortStateMap[Index].HwState)) {\r
-        PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbPortStateMap[Index].UefiState);\r
+      if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {\r
+        PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);\r
       }\r
     }\r
-    MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
 \r
+    MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
     for (Index = 0; Index < MapSize; Index++) {\r
-      if (XHC_BIT_IS_SET (*(UINT32 *)Data, mUsbPortChangeMap[Index].HwState)) {\r
-      PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
+      if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {\r
+        PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);\r
       }\r
     }\r
 \r
-    XhcPollPortStatusChange (Xhc, UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
-  }\r
+    MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
 \r
-FREE_URB:\r
-  FreePool (Urb);\r
+    for (Index = 0; Index < MapSize; Index++) {\r
+      if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {\r
+        ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
+        ClearPortRequest.RequestType  = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);\r
+        ClearPortRequest.Request      = (UINT8) USB_REQ_CLEAR_FEATURE;\r
+        ClearPortRequest.Value        = mUsbHubClearPortChangeMap[Index].Selector;\r
+        ClearPortRequest.Index        = Request->Index;\r
+        ClearPortRequest.Length       = 0;\r
+\r
+        XhcControlTransfer (\r
+          This, \r
+          DeviceAddress,\r
+          DeviceSpeed,\r
+          MaximumPacketLength,\r
+          &ClearPortRequest,\r
+          EfiUsbNoData,\r
+          NULL,\r
+          &Len,\r
+          Timeout,\r
+          Translator,\r
+          TransferResult\r
+          );\r
+      }\r
+    }\r
 \r
-ON_EXIT:\r
+    XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
+\r
+    *(UINT32 *)Data = *(UINT32*)&PortStatus;\r
+  }\r
 \r
+ON_EXIT:\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
   }\r
@@ -1014,7 +1186,7 @@ ON_EXIT:
   @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
+  @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
@@ -1039,17 +1211,14 @@ XhcBulkTransfer (
   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     UINTN                               Timeout,\r
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
   OUT    UINT32                              *TransferResult\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   XhciDevAddr;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT8                   SlotId;\r
   EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1086,59 +1255,30 @@ XhcBulkTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\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
-          XhciDevAddr,\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->BulkTrEventRing);\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
-             (*TransferResult == EFI_USB_ERR_TIMEOUT)) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    ASSERT_EFI_ERROR (RecoveryStatus);\r
-  }\r
-\r
-  FreePool (Urb);\r
+  Status = XhcTransfer (\r
+             Xhc,\r
+             DeviceAddress,\r
+             EndPointAddress,\r
+             DeviceSpeed,\r
+             MaximumPacketLength,\r
+             XHC_BULK_TRANSFER,\r
+             NULL,\r
+             Data[0],\r
+             DataLength,\r
+             Timeout,\r
+             TransferResult\r
+             );\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
@@ -1193,10 +1333,9 @@ XhcAsyncInterruptTransfer (
   IN     VOID                                *Context OPTIONAL\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   URB                     *Urb;\r
   EFI_STATUS              Status;\r
-  UINT8                   XhciDevAddr;\r
   UINT8                   SlotId;\r
   UINT8                   Index;\r
   UINT8                   *Data;\r
@@ -1235,8 +1374,7 @@ XhcAsyncInterruptTransfer (
     // The delete request may happen after device is detached.\r
     //\r
     for (Index = 0; Index < 255; Index++) {\r
-      if ((UsbDevContext[Index + 1].SlotId != 0) &&\r
-          (UsbDevContext[Index + 1].BusDevAddr == DeviceAddress)) {\r
+      if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {\r
         break;\r
       }\r
     }\r
@@ -1246,13 +1384,8 @@ XhcAsyncInterruptTransfer (
       goto ON_EXIT;\r
     }\r
 \r
-    //\r
-    // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-    //\r
-    XhciDevAddr = UsbDevContext[Index + 1].XhciDevAddr;\r
-\r
-    Status = XhciDelAsyncIntTransfer (Xhc, XhciDevAddr, EndPointAddress);\r
-    DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer, Status = %r\n", Status));\r
+    Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);\r
+    DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));\r
     goto ON_EXIT;\r
   }\r
 \r
@@ -1267,17 +1400,12 @@ XhcAsyncInterruptTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\r
-\r
-  Data = AllocatePool (DataLength);\r
+  Data = AllocateZeroPool (DataLength);\r
 \r
   if (Data == NULL) {\r
     DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
@@ -1287,7 +1415,7 @@ XhcAsyncInterruptTransfer (
 \r
   Urb = XhcCreateUrb (\r
           Xhc,\r
-          XhciDevAddr,\r
+          DeviceAddress,\r
           EndPointAddress,\r
           DeviceSpeed,\r
           MaximumPacketLength,\r
@@ -1306,8 +1434,6 @@ XhcAsyncInterruptTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  ASSERT (Urb->EvtRing == &Xhc->AsynIntTrEventRing);\r
-\r
   InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);\r
   //\r
   // Ring the doorbell\r
@@ -1315,6 +1441,7 @@ XhcAsyncInterruptTransfer (
   Status = RingIntTransferDoorBell (Xhc, Urb);\r
 \r
 ON_EXIT:\r
+  Xhc->PciIo->Flush (Xhc->PciIo);\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r
@@ -1337,7 +1464,7 @@ ON_EXIT:
                                 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  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
@@ -1359,17 +1486,14 @@ XhcSyncInterruptTransfer (
   IN OUT VOID                                *Data,\r
   IN OUT UINTN                               *DataLength,\r
   IN OUT UINT8                               *DataToggle,\r
-  IN     UINTN                               TimeOut,\r
+  IN     UINTN                               Timeout,\r
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
   OUT    UINT32                              *TransferResult\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   XhciDevAddr;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT8                   SlotId;\r
   EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1380,10 +1504,6 @@ XhcSyncInterruptTransfer (
     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
@@ -1409,50 +1529,24 @@ XhcSyncInterruptTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\r
-\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          XhciDevAddr,\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
-             (*TransferResult == EFI_USB_ERR_TIMEOUT)) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    ASSERT_EFI_ERROR (RecoveryStatus);\r
-  }\r
-\r
-  FreePool (Urb);\r
+  Status = XhcTransfer (\r
+             Xhc,\r
+             DeviceAddress,\r
+             EndPointAddress,\r
+             DeviceSpeed,\r
+             MaximumPacketLength,\r
+             XHC_INT_TRANSFER_SYNC,\r
+             NULL,\r
+             Data,\r
+             DataLength,\r
+             Timeout,\r
+             TransferResult\r
+             );\r
 \r
 ON_EXIT:\r
   if (EFI_ERROR (Status)) {\r
@@ -1649,57 +1743,42 @@ ON_EXIT:
 }\r
 \r
 /**\r
-  Create and initialize a USB_XHCI_DEV.\r
+  Create and initialize a USB_XHCI_INSTANCE structure.\r
 \r
   @param  PciIo                  The PciIo on this device.\r
+  @param  DevicePath             The device path of host controller.\r
   @param  OriginalPciAttributes  Original PCI attributes.\r
 \r
-  @return The allocated and initialized USB_XHCI_DEV structure if created,\r
+  @return The allocated and initialized USB_XHCI_INSTANCE structure if created,\r
           otherwise NULL.\r
 \r
 **/\r
-USB_XHCI_DEV*\r
+USB_XHCI_INSTANCE*\r
 XhcCreateUsbHc (\r
-  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
-  IN UINT64               OriginalPciAttributes\r
+  IN EFI_PCI_IO_PROTOCOL       *PciIo,\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN UINT64                    OriginalPciAttributes\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   EFI_STATUS              Status;\r
   UINT32                  PageSize;\r
   UINT16                  ExtCapReg;\r
 \r
-  ZeroMem (UsbDevContext, sizeof (UsbDevContext));\r
-\r
-  Xhc = AllocateZeroPool (sizeof (USB_XHCI_DEV));\r
+  Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));\r
 \r
   if (Xhc == NULL) {\r
     return NULL;\r
   }\r
 \r
   //\r
-  // Init EFI_USB2_HC_PROTOCOL interface and private data structure\r
+  // Initialize private data structure\r
   //\r
-  Xhc->Signature                        = USB_XHCI_DEV_SIGNATURE;\r
-\r
-  Xhc->Usb2Hc.GetCapability             = XhcGetCapability;\r
-  Xhc->Usb2Hc.Reset                     = XhcReset;\r
-  Xhc->Usb2Hc.GetState                  = XhcGetState;\r
-  Xhc->Usb2Hc.SetState                  = XhcSetState;\r
-  Xhc->Usb2Hc.ControlTransfer           = XhcControlTransfer;\r
-  Xhc->Usb2Hc.BulkTransfer              = XhcBulkTransfer;\r
-  Xhc->Usb2Hc.AsyncInterruptTransfer    = XhcAsyncInterruptTransfer;\r
-  Xhc->Usb2Hc.SyncInterruptTransfer     = XhcSyncInterruptTransfer;\r
-  Xhc->Usb2Hc.IsochronousTransfer       = XhcIsochronousTransfer;\r
-  Xhc->Usb2Hc.AsyncIsochronousTransfer  = XhcAsyncIsochronousTransfer;\r
-  Xhc->Usb2Hc.GetRootHubPortStatus      = XhcGetRootHubPortStatus;\r
-  Xhc->Usb2Hc.SetRootHubPortFeature     = XhcSetRootHubPortFeature;\r
-  Xhc->Usb2Hc.ClearRootHubPortFeature   = XhcClearRootHubPortFeature;\r
-  Xhc->Usb2Hc.MajorRevision             = 0x3;\r
-  Xhc->Usb2Hc.MinorRevision             = 0x0;\r
-\r
+  Xhc->Signature             = XHCI_INSTANCE_SIG;\r
   Xhc->PciIo                 = PciIo;\r
+  Xhc->DevicePath            = DevicePath;\r
   Xhc->OriginalPciAttributes = OriginalPciAttributes;\r
+  CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));\r
 \r
   InitializeListHead (&Xhc->AsyncIntTransfers);\r
 \r
@@ -1720,26 +1799,27 @@ XhcCreateUsbHc (
   //\r
   PageSize      = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;\r
   Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);\r
-  ASSERT (Xhc->PageSize == 0x1000);\r
 \r
-  ExtCapReg                 = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
-  Xhc->ExtCapRegBase        = ExtCapReg << 2;\r
-  Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc);\r
+  ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
+  Xhc->ExtCapRegBase   = ExtCapReg << 2;\r
+  Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);\r
+  Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);\r
 \r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: capability length 0x%x\n", Xhc->CapLength));\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: Xhc->UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));\r
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));\r
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));\r
 \r
   //\r
   // Create AsyncRequest Polling Timer\r
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   XhcMonitorAsyncRequests,\r
                   Xhc,\r
                   &Xhc->PollTimer\r
@@ -1760,7 +1840,7 @@ ON_ERROR:
   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
+  @param  Context                 Event handler private data\r
 \r
 **/\r
 VOID\r
@@ -1771,23 +1851,25 @@ XhcExitBootService (
   )\r
 \r
 {\r
-  USB_XHCI_DEV         *Xhc;\r
+  USB_XHCI_INSTANCE    *Xhc;\r
   EFI_PCI_IO_PROTOCOL  *PciIo;\r
 \r
-  Xhc = (USB_XHCI_DEV*) Context;\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, XHC_ASYNC_POLL_INTERVAL);\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
+  XhcClearBiosOwnership (Xhc);\r
+\r
   //\r
   // Restore original PCI attributes\r
   //\r
@@ -1797,8 +1879,6 @@ XhcExitBootService (
                   Xhc->OriginalPciAttributes,\r
                   NULL\r
                   );\r
-\r
-  XhcClearBiosOwnership (Xhc);\r
 }\r
 \r
 /**\r
@@ -1827,7 +1907,8 @@ XhcDriverBindingStart (
   UINT64                  Supports;\r
   UINT64                  OriginalPciAttributes;\r
   BOOLEAN                 PciAttributesSaved;\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
+  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;\r
 \r
   //\r
   // Open the PciIo Protocol, then enable the USB host controller\r
@@ -1845,6 +1926,19 @@ XhcDriverBindingStart (
     return Status;\r
   }\r
 \r
+  //\r
+  // Open Device Path Protocol for on USB host controller\r
+  //\r
+  HcDevicePath = NULL;\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &HcDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
   PciAttributesSaved = FALSE;\r
   //\r
   // Save original PCI attributes\r
@@ -1868,7 +1962,7 @@ XhcDriverBindingStart (
                     &Supports\r
                     );\r
   if (!EFI_ERROR (Status)) {\r
-    Supports &= EFI_PCI_DEVICE_ENABLE;\r
+    Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
     Status = PciIo->Attributes (\r
                       PciIo,\r
                       EfiPciIoAttributeOperationEnable,\r
@@ -1885,13 +1979,33 @@ XhcDriverBindingStart (
   //\r
   // Create then install USB2_HC_PROTOCOL\r
   //\r
-  Xhc = XhcCreateUsbHc (PciIo, OriginalPciAttributes);\r
+  Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, 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
+  //\r
+  // Enable 64-bit DMA support in the PCI layer if this controller\r
+  // supports it.\r
+  //\r
+  if (Xhc->HcCParams.Data.Ac64 != 0) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+                      NULL\r
+                      );\r
+    if (!EFI_ERROR (Status)) {\r
+      Xhc->Support64BitDma = TRUE;\r
+    } else {\r
+      DEBUG ((EFI_D_WARN,\r
+        "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",\r
+        __FUNCTION__, Controller, Status));\r
+    }\r
+  }\r
+\r
   XhcSetBiosOwnership (Xhc);\r
 \r
   XhcResetHC (Xhc, XHC_RESET_TIMEOUT);\r
@@ -1916,7 +2030,7 @@ XhcDriverBindingStart (
   //\r
   // Start the asynchronous interrupt monitor\r
   //\r
-  Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_POLL_INTERVAL);\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
@@ -2001,7 +2115,7 @@ CLOSE_PCIIO:
 \r
 \r
 /**\r
-  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  Stop this driver on ControllerHandle. Support stopping any child handles\r
   created by this driver.\r
 \r
   @param  This                 Protocol instance pointer.\r
@@ -2025,7 +2139,8 @@ XhcDriverBindingStop (
   EFI_STATUS            Status;\r
   EFI_USB2_HC_PROTOCOL  *Usb2Hc;\r
   EFI_PCI_IO_PROTOCOL   *PciIo;\r
-  USB_XHCI_DEV          *Xhc;\r
+  USB_XHCI_INSTANCE     *Xhc;\r
+  UINT8                 Index;\r
 \r
   //\r
   // Test whether the Controller handler passed in is a valid\r
@@ -2045,17 +2160,6 @@ XhcDriverBindingStop (
     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, XHC_ASYNC_POLL_INTERVAL);\r
-  XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
-  XhcClearBiosOwnership (Xhc);\r
-\r
   Status = gBS->UninstallProtocolInterface (\r
                   Controller,\r
                   &gEfiUsb2HcProtocolGuid,\r
@@ -2066,6 +2170,31 @@ XhcDriverBindingStop (
     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
   if (Xhc->PollTimer != NULL) {\r
     gBS->CloseEvent (Xhc->PollTimer);\r
   }\r
@@ -2074,6 +2203,8 @@ XhcDriverBindingStop (
     gBS->CloseEvent (Xhc->ExitBootServiceEvent);\r
   }\r
 \r
+  XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+  XhcClearBiosOwnership (Xhc);\r
   XhciDelAllAsyncIntTransfers (Xhc);\r
   XhcFreeSched (Xhc);\r
 \r
@@ -2085,11 +2216,11 @@ XhcDriverBindingStop (
   // Restore original PCI attributes\r
   //\r
   PciIo->Attributes (\r
-                  PciIo,\r
-                  EfiPciIoAttributeOperationSet,\r
-                  Xhc->OriginalPciAttributes,\r
-                  NULL\r
-                  );\r
+           PciIo,\r
+           EfiPciIoAttributeOperationSet,\r
+           Xhc->OriginalPciAttributes,\r
+           NULL\r
+           );\r
 \r
   gBS->CloseProtocol (\r
          Controller,\r