]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
MdeModulePkg/XhciPei: Support IoMmu.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciPei / XhciSched.c
index 3632e8a7698ab8e03d8bb1eb08ca6b40c2a4cb6d..e5aee4918b6336a9597fb1a13de5356c2ad8788c 100644 (file)
@@ -2,7 +2,7 @@
 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
 which is used to enable recovery function from USB Drivers.\r
 \r
-Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -200,6 +200,8 @@ XhcPeiFreeUrb (
     return;\r
   }\r
 \r
+  IoMmuUnmap (Urb->DataMap);\r
+\r
   FreePool (Urb);\r
 }\r
 \r
@@ -227,6 +229,10 @@ XhcPeiCreateTransferTrb (
   UINTN                         TotalLen;\r
   UINTN                         Len;\r
   UINTN                         TrbNum;\r
+  EDKII_IOMMU_OPERATION         MapOp;\r
+  EFI_PHYSICAL_ADDRESS          PhyAddr;\r
+  VOID                          *Map;\r
+  EFI_STATUS                    Status;\r
 \r
   SlotId = XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
   if (SlotId == 0) {\r
@@ -249,7 +255,27 @@ XhcPeiCreateTransferTrb (
     EPType  = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;\r
   }\r
 \r
-  Urb->DataPhy = Urb->Data;\r
+  //\r
+  // No need to remap.\r
+  //\r
+  if ((Urb->Data != NULL) && (Urb->DataMap == NULL)) {\r
+    if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {\r
+      MapOp = EdkiiIoMmuOperationBusMasterWrite;\r
+    } else {\r
+      MapOp = EdkiiIoMmuOperationBusMasterRead;\r
+    }\r
+\r
+    Len = Urb->DataLen;\r
+    Status = IoMmuMap (MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
+\r
+    if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
+      DEBUG ((DEBUG_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n"));\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);\r
+    Urb->DataMap  = Map;\r
+  }\r
 \r
   //\r
   // Construct the TRB\r
@@ -683,7 +709,7 @@ XhcPeiCheckUrbResult (
       case TRB_COMPLETION_SHORT_PACKET:\r
       case TRB_COMPLETION_SUCCESS:\r
         if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {\r
-          DEBUG ((EFI_D_ERROR, "XhcPeiCheckUrbResult: short packet happens!\n"));\r
+          DEBUG ((EFI_D_VERBOSE, "XhcPeiCheckUrbResult: short packet happens!\n"));\r
         }\r
 \r
         TRBType = (UINT8) (TRBPtr->Type);\r
@@ -1195,6 +1221,10 @@ XhcPeiInitializeDeviceSlot (
   // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
   //    Context data structure described above.\r
   //\r
+  // Delay 10ms to meet TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5 before sending SetAddress() request\r
+  // to device.\r
+  //\r
+  MicroSecondDelay (XHC_RESET_RECOVERY_DELAY);\r
   ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
   PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
   CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
@@ -1402,6 +1432,10 @@ XhcPeiInitializeDeviceSlot64 (
   // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
   //    Context data structure described above.\r
   //\r
+  // Delay 10ms to meet TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5 before sending SetAddress() request\r
+  // to device.\r
+  //\r
+  MicroSecondDelay (XHC_RESET_RECOVERY_DELAY);\r
   ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
   PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
   CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
@@ -1741,6 +1775,20 @@ XhcPeiSetConfigCmd (
             InputContext->EP[Dci-1].CErr   = 0;\r
             InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
           }\r
+          //\r
+          // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+          // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+          //\r
+          if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+            Interval = EpDesc->Interval;\r
+            ASSERT (Interval >= 1 && Interval <= 16);\r
+            InputContext->EP[Dci-1].Interval = Interval + 2;\r
+          } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+            Interval = EpDesc->Interval;\r
+            ASSERT (Interval >= 1 && Interval <= 16);\r
+            InputContext->EP[Dci-1].Interval = Interval - 1;\r
+          }\r
+\r
           //\r
           // Do not support isochronous transfer now.\r
           //\r
@@ -1944,6 +1992,20 @@ XhcPeiSetConfigCmd64 (
             InputContext->EP[Dci-1].CErr   = 0;\r
             InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
           }\r
+          //\r
+          // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+          // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+          //\r
+          if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+            Interval = EpDesc->Interval;\r
+            ASSERT (Interval >= 1 && Interval <= 16);\r
+            InputContext->EP[Dci-1].Interval = Interval + 2;\r
+          } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+            Interval = EpDesc->Interval;\r
+            ASSERT (Interval >= 1 && Interval <= 16);\r
+            InputContext->EP[Dci-1].Interval = Interval - 1;\r
+          }\r
+\r
           //\r
           // Do not support isochronous transfer now.\r
           //\r
@@ -2776,6 +2838,7 @@ XhcPeiInitSched (
   UINT64                *ScratchEntry;\r
   EFI_PHYSICAL_ADDRESS  ScratchEntryPhy;\r
   UINT32                Index;\r
+  UINTN                 *ScratchEntryMap;\r
   EFI_STATUS            Status;\r
 \r
   //\r
@@ -2811,6 +2874,13 @@ XhcPeiInitSched (
   Xhc->MaxScratchpadBufs = MaxScratchpadBufs;\r
   ASSERT (MaxScratchpadBufs <= 1023);\r
   if (MaxScratchpadBufs != 0) {\r
+    //\r
+    // Allocate the buffer to record the Mapping for each scratch buffer in order to Unmap them\r
+    //\r
+    ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs);\r
+    ASSERT (ScratchEntryMap != NULL);\r
+    Xhc->ScratchEntryMap = ScratchEntryMap;\r
+\r
     //\r
     // Allocate the buffer to record the host address for each entry\r
     //\r
@@ -2823,7 +2893,8 @@ XhcPeiInitSched (
                EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)),\r
                Xhc->PageSize,\r
                (VOID **) &ScratchBuf,\r
-               &ScratchPhy\r
+               &ScratchPhy,\r
+               &Xhc->ScratchMap\r
                );\r
     ASSERT_EFI_ERROR (Status);\r
 \r
@@ -2839,7 +2910,8 @@ XhcPeiInitSched (
                  EFI_SIZE_TO_PAGES (Xhc->PageSize),\r
                  Xhc->PageSize,\r
                  (VOID **) &ScratchEntry[Index],\r
-                 &ScratchEntryPhy\r
+                 &ScratchEntryPhy,\r
+                 (VOID **) &ScratchEntryMap[Index]\r
                  );\r
       ASSERT_EFI_ERROR (Status);\r
       ZeroMem ((VOID *) (UINTN) ScratchEntry[Index], Xhc->PageSize);\r
@@ -2931,12 +3003,13 @@ XhcPeiFreeSched (
       //\r
       // Free Scratchpad Buffers\r
       //\r
-      UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize));\r
+      UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]);\r
     }\r
     //\r
     // Free Scratchpad Buffer Array\r
     //\r
-    UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)));\r
+    UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)), Xhc->ScratchMap);\r
+    FreePool (Xhc->ScratchEntryMap);\r
     FreePool (Xhc->ScratchEntry);\r
   }\r
 \r