]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / Xhci.c
index 5ccb78e55b05bb17cf3bccb2f14c126f3091b5d1..43c53bad4e4a654f4ca10c9d50a6a6d85327054e 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   The XHCI controller driver.\r
 \r
-Copyright (c) 2011, 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
+Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -32,6 +26,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
@@ -96,7 +119,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
@@ -129,9 +152,20 @@ XhcReset (
   EFI_STATUS         Status;\r
   EFI_TPL            OldTpl;\r
 \r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+  Xhc = XHC_FROM_THIS (This);\r
 \r
-  Xhc    = XHC_FROM_THIS (This);\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
+  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
 \r
   switch (Attributes) {\r
   case EFI_USB_HC_RESET_GLOBAL:\r
@@ -139,6 +173,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
@@ -358,7 +397,8 @@ XhcGetRootHubPortStatus (
   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
+  // According to XHCI 1.1 spec November 2017,\r
+  // 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
@@ -370,6 +410,7 @@ XhcGetRootHubPortStatus (
     break;\r
 \r
   case 4:\r
+  case 5:\r
     PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
     break;\r
 \r
@@ -402,6 +443,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
@@ -439,8 +488,6 @@ XhcSetRootHubPortFeature (
   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
@@ -496,24 +543,13 @@ XhcSetRootHubPortFeature (
       }\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
+    // 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 (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
+    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
@@ -676,6 +712,103 @@ 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
+  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 (RecoveryStatus == EFI_ALREADY_STARTED) {\r
+      //\r
+      // The URB is finished just before stopping endpoint.\r
+      // Change returning status from EFI_TIMEOUT to EFI_SUCCESS.\r
+      //\r
+      ASSERT (Urb->Result == EFI_USB_NOERROR);\r
+      Status = EFI_SUCCESS;\r
+      DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: pending URB is finished, Length = %d.\n", Type, Urb->Completed));\r
+    } else if (EFI_ERROR(RecoveryStatus)) {\r
+      DEBUG((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed!\n", Type));\r
+    }\r
+  }\r
+\r
+  *TransferResult = Urb->Result;\r
+  *DataLength     = Urb->Completed;\r
+\r
+  if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {\r
+    ASSERT (Status == EFI_DEVICE_ERROR);\r
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+    if (EFI_ERROR (RecoveryStatus)) {\r
+      DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcRecoverHaltedEndpoint failed!\n", Type));\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
@@ -718,10 +851,8 @@ XhcControlTransfer (
   )\r
 {\r
   USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
   UINT8                   Endpoint;\r
   UINT8                   Index;\r
-  UINT8                   XhciDevAddr;\r
   UINT8                   DescriptorType;\r
   UINT8                   SlotId;\r
   UINT8                   TTT;\r
@@ -730,10 +861,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
@@ -779,6 +911,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
@@ -793,11 +926,6 @@ XhcControlTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = Xhc->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
@@ -810,11 +938,16 @@ XhcControlTransfer (
     //\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].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
@@ -825,20 +958,6 @@ XhcControlTransfer (
     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
@@ -848,43 +967,23 @@ 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
@@ -892,15 +991,16 @@ XhcControlTransfer (
   // 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_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 (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
-        if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\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
@@ -909,8 +1009,11 @@ XhcControlTransfer (
           MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
         }\r
         Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
-        Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);\r
-        ASSERT_EFI_ERROR (Status);\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
@@ -921,11 +1024,16 @@ XhcControlTransfer (
         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
+    } 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
@@ -934,19 +1042,17 @@ XhcControlTransfer (
         //\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
              (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
@@ -955,10 +1061,28 @@ XhcControlTransfer (
     //\r
     for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
       if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
-        XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\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_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
@@ -976,44 +1100,67 @@ XhcControlTransfer (
       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 (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
+    MapSize = sizeof (mUsbHubPortStateMap) / 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
+      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 (State, 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
+    MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
+\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
     XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
-  }\r
 \r
-FREE_URB:\r
-  FreePool (Urb);\r
+    *(UINT32 *)Data = *(UINT32*)&PortStatus;\r
+  }\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
@@ -1072,11 +1219,8 @@ XhcBulkTransfer (
   )\r
 {\r
   USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   XhciDevAddr;\r
   UINT8                   SlotId;\r
   EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1118,54 +1262,25 @@ XhcBulkTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = Xhc->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
@@ -1223,10 +1338,8 @@ XhcAsyncInterruptTransfer (
   USB_XHCI_INSTANCE       *Xhc;\r
   URB                     *Urb;\r
   EFI_STATUS              Status;\r
-  UINT8                   XhciDevAddr;\r
   UINT8                   SlotId;\r
   UINT8                   Index;\r
-  UINT8                   *Data;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1262,8 +1375,7 @@ XhcAsyncInterruptTransfer (
     // The delete request may happen after device is detached.\r
     //\r
     for (Index = 0; Index < 255; Index++) {\r
-      if ((Xhc->UsbDevContext[Index + 1].SlotId != 0) &&\r
-          (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress)) {\r
+      if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {\r
         break;\r
       }\r
     }\r
@@ -1273,13 +1385,8 @@ XhcAsyncInterruptTransfer (
       goto ON_EXIT;\r
     }\r
 \r
-    //\r
-    // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-    //\r
-    XhciDevAddr = Xhc->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
@@ -1299,49 +1406,28 @@ XhcAsyncInterruptTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;\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
+  Urb = XhciInsertAsyncIntTransfer (\r
           Xhc,\r
-          XhciDevAddr,\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->AsynIntTrEventRing);\r
-\r
-  InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);\r
   //\r
   // Ring the doorbell\r
   //\r
   Status = RingIntTransferDoorBell (Xhc, Urb);\r
 \r
 ON_EXIT:\r
+  Xhc->PciIo->Flush (Xhc->PciIo);\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r
@@ -1392,11 +1478,8 @@ XhcSyncInterruptTransfer (
   )\r
 {\r
   USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
-  UINT8                   XhciDevAddr;\r
   UINT8                   SlotId;\r
   EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1407,10 +1490,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
@@ -1441,45 +1520,19 @@ XhcSyncInterruptTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
-  //\r
-  XhciDevAddr = Xhc->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
@@ -1679,6 +1732,7 @@ ON_EXIT:
   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_INSTANCE structure if created,\r
@@ -1687,14 +1741,16 @@ ON_EXIT:
 **/\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_INSTANCE       *Xhc;\r
   EFI_STATUS              Status;\r
   UINT32                  PageSize;\r
   UINT16                  ExtCapReg;\r
+  UINT8                   ReleaseNumber;\r
 \r
   Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));\r
 \r
@@ -1707,9 +1763,23 @@ XhcCreateUsbHc (
   //\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
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        XHC_PCI_SBRN_OFFSET,\r
+                        1,\r
+                        &ReleaseNumber\r
+                        );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Xhc->Usb2Hc.MajorRevision = (ReleaseNumber & 0xF0) >> 4;\r
+    Xhc->Usb2Hc.MinorRevision = (ReleaseNumber & 0x0F);\r
+  }\r
+\r
   InitializeListHead (&Xhc->AsyncIntTransfers);\r
 \r
   //\r
@@ -1732,7 +1802,8 @@ XhcCreateUsbHc (
 \r
   ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
   Xhc->ExtCapRegBase   = ExtCapReg << 2;\r
-  Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc);\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: HcSParams1 0x%x\n", Xhc->HcSParams1));\r
@@ -1741,13 +1812,14 @@ XhcCreateUsbHc (
   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
+  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
@@ -1768,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
@@ -1796,6 +1868,8 @@ XhcExitBootService (
     gBS->CloseEvent (Xhc->PollTimer);\r
   }\r
 \r
+  XhcClearBiosOwnership (Xhc);\r
+\r
   //\r
   // Restore original PCI attributes\r
   //\r
@@ -1805,8 +1879,6 @@ XhcExitBootService (
                   Xhc->OriginalPciAttributes,\r
                   NULL\r
                   );\r
-\r
-  XhcClearBiosOwnership (Xhc);\r
 }\r
 \r
 /**\r
@@ -1836,6 +1908,7 @@ XhcDriverBindingStart (
   UINT64                  OriginalPciAttributes;\r
   BOOLEAN                 PciAttributesSaved;\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
@@ -1853,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
@@ -1876,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
@@ -1893,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
@@ -2009,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
@@ -2054,6 +2160,16 @@ XhcDriverBindingStop (
     return Status;\r
   }\r
 \r
+  Status = gBS->UninstallProtocolInterface (\r
+                  Controller,\r
+                  &gEfiUsb2HcProtocolGuid,\r
+                  Usb2Hc\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Xhc   = XHC_FROM_THIS (Usb2Hc);\r
   PciIo = Xhc->PciIo;\r
 \r
@@ -2072,21 +2188,11 @@ XhcDriverBindingStop (
         (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {\r
       continue;\r
     }\r
-\r
-    XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\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
+    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
@@ -2097,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
@@ -2108,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