]> 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 39c28ab7d83d20cab8d0d6c1f246303ec160ac26..43c53bad4e4a654f4ca10c9d50a6a6d85327054e 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   The XHCI controller driver.\r
 \r
-Copyright (c) 2011 - 2015, 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
@@ -125,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
@@ -159,7 +153,7 @@ XhcReset (
   EFI_TPL            OldTpl;\r
 \r
   Xhc = XHC_FROM_THIS (This);\r
-  \r
+\r
   if (Xhc->DevicePath != NULL) {\r
     //\r
     // Report Status Code to indicate reset happens\r
@@ -169,7 +163,7 @@ XhcReset (
       (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),\r
       Xhc->DevicePath\r
       );\r
-  }  \r
+  }\r
 \r
   OldTpl = gBS->RaiseTPL (XHC_TPL);\r
 \r
@@ -403,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
@@ -415,6 +410,7 @@ XhcGetRootHubPortStatus (
     break;\r
 \r
   case 4:\r
+  case 5:\r
     PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
     break;\r
 \r
@@ -716,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
@@ -758,7 +851,6 @@ XhcControlTransfer (
   )\r
 {\r
   USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
   UINT8                   Endpoint;\r
   UINT8                   Index;\r
   UINT8                   DescriptorType;\r
@@ -769,7 +861,6 @@ 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
@@ -876,77 +967,31 @@ XhcControlTransfer (
   // combination of Ep addr and its direction.\r
   //\r
   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          Endpoint,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_CTRL_TRANSFER,\r
-          Request,\r
-          Data,\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
+  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
 \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 (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((EFI_D_ERROR, "XhcControlTransfer: XhcDequeueTrbFromEndpoint failed\n"));\r
-    }\r
-    goto FREE_URB;\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 ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
-      }\r
-      Status = EFI_DEVICE_ERROR;\r
-      goto FREE_URB;\r
-    } else {\r
-      goto FREE_URB;\r
-    }\r
-  }\r
-\r
-  Xhc->PciIo->Flush (Xhc->PciIo);\r
-  \r
-  if (Urb->DataMap != NULL) {\r
-    Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);\r
-    ASSERT_EFI_ERROR (Status);\r
-    if (EFI_ERROR (Status)) {\r
-      Status = EFI_DEVICE_ERROR;\r
-      goto FREE_URB;\r
-    }  \r
-  }\r
-\r
   //\r
   // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.\r
   // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.\r
   // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
   //\r
   if ((Request->Request     == USB_REQ_GET_DESCRIPTOR) &&\r
-      ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) || \r
+      ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_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)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {\r
@@ -955,7 +1000,7 @@ XhcControlTransfer (
         // 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
@@ -1095,7 +1140,7 @@ XhcControlTransfer (
         ClearPortRequest.Length       = 0;\r
 \r
         XhcControlTransfer (\r
-          This, \r
+          This,\r
           DeviceAddress,\r
           DeviceSpeed,\r
           MaximumPacketLength,\r
@@ -1115,11 +1160,7 @@ XhcControlTransfer (
     *(UINT32 *)Data = *(UINT32*)&PortStatus;\r
   }\r
 \r
-FREE_URB:\r
-  FreePool (Urb);\r
-\r
 ON_EXIT:\r
-\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
   }\r
@@ -1178,10 +1219,8 @@ XhcBulkTransfer (
   )\r
 {\r
   USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
   UINT8                   SlotId;\r
   EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1227,56 +1266,21 @@ XhcBulkTransfer (
   // Create a new URB, insert it into the asynchronous\r
   // schedule list, then poll the execution status.\r
   //\r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          EndPointAddress,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_BULK_TRANSFER,\r
-          NULL,\r
-          Data[0],\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
-\r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  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((EFI_D_ERROR, "XhcBulkTransfer: XhcDequeueTrbFromEndpoint failed\n"));\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 ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
-      }\r
-      Status = EFI_DEVICE_ERROR;\r
-    }\r
-  }\r
-\r
-  Xhc->PciIo->Flush (Xhc->PciIo);\r
-  XhcFreeUrb (Xhc, 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
@@ -1336,7 +1340,6 @@ XhcAsyncInterruptTransfer (
   EFI_STATUS              Status;\r
   UINT8                   SlotId;\r
   UINT8                   Index;\r
-  UINT8                   *Data;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1403,36 +1406,21 @@ XhcAsyncInterruptTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  Data = AllocateZeroPool (DataLength);\r
-\r
-  if (Data == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Urb = XhcCreateUrb (\r
+  Urb = XhciInsertAsyncIntTransfer (\r
           Xhc,\r
           DeviceAddress,\r
           EndPointAddress,\r
           DeviceSpeed,\r
           MaximumPacketLength,\r
-          XHC_INT_TRANSFER_ASYNC,\r
-          NULL,\r
-          Data,\r
           DataLength,\r
           CallBackFunction,\r
           Context\r
           );\r
-\r
   if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));\r
-    FreePool (Data);\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
 \r
-  InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);\r
   //\r
   // Ring the doorbell\r
   //\r
@@ -1490,10 +1478,8 @@ XhcSyncInterruptTransfer (
   )\r
 {\r
   USB_XHCI_INSTANCE       *Xhc;\r
-  URB                     *Urb;\r
   UINT8                   SlotId;\r
   EFI_STATUS              Status;\r
-  EFI_STATUS              RecoveryStatus;\r
   EFI_TPL                 OldTpl;\r
 \r
   //\r
@@ -1534,53 +1520,19 @@ XhcSyncInterruptTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  Urb = XhcCreateUrb (\r
-          Xhc,\r
-          DeviceAddress,\r
-          EndPointAddress,\r
-          DeviceSpeed,\r
-          MaximumPacketLength,\r
-          XHC_INT_TRANSFER_SYNC,\r
-          NULL,\r
-          Data,\r
-          *DataLength,\r
-          NULL,\r
-          NULL\r
-          );\r
-\r
-  if (Urb == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
-\r
-  *TransferResult = Urb->Result;\r
-  *DataLength     = Urb->Completed;\r
-\r
-  if (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((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcDequeueTrbFromEndpoint failed\n"));\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 ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
-      }\r
-      Status = EFI_DEVICE_ERROR;\r
-    }\r
-  }\r
-\r
-  Xhc->PciIo->Flush (Xhc->PciIo);\r
-  XhcFreeUrb (Xhc, 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
@@ -1798,6 +1750,7 @@ XhcCreateUsbHc (
   EFI_STATUS              Status;\r
   UINT32                  PageSize;\r
   UINT16                  ExtCapReg;\r
+  UINT8                   ReleaseNumber;\r
 \r
   Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));\r
 \r
@@ -1814,6 +1767,19 @@ XhcCreateUsbHc (
   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
@@ -2020,6 +1986,26 @@ XhcDriverBindingStart (
     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
@@ -2129,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