MdeModulePkg EhciPei: Support IoMmu
authorStar Zeng <star.zeng@intel.com>
Wed, 15 Nov 2017 05:35:11 +0000 (13:35 +0800)
committerStar Zeng <star.zeng@intel.com>
Fri, 17 Nov 2017 03:14:16 +0000 (11:14 +0800)
V2: Halt HC at EndOfPei.

Update the EhciPei driver to consume IOMMU_PPI to allocate DMA buffer.

If no IOMMU_PPI exists, this driver still calls PEI service to allocate
DMA buffer, with assumption that DRAM==DMA.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c
MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c
MdeModulePkg/Bus/Pci/EhciPei/EhciUrb.c
MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c
MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.h

diff --git a/MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c b/MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c
new file mode 100644 (file)
index 0000000..1330f53
--- /dev/null
@@ -0,0 +1,250 @@
+/** @file\r
+The DMA memory help functions.\r
+\r
+Copyright (c) 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
+of the BSD License which accompanies this distribution.  The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "EhcPeim.h"\r
+\r
+/**\r
+  Provides the controller-specific addresses required to access system memory from a\r
+  DMA bus master.\r
+\r
+  @param IoMmu                  Pointer to IOMMU PPI.\r
+  @param Operation              Indicates if the bus master is going to read or write to system memory.\r
+  @param HostAddress            The system memory address to map to the PCI controller.\r
+  @param NumberOfBytes          On input the number of bytes to map. On output the number of bytes\r
+                                that were mapped.\r
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param Mapping                A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.\r
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.\r
+\r
+**/\r
+EFI_STATUS\r
+IoMmuMap (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN EDKII_IOMMU_OPERATION  Operation,\r
+  IN VOID                   *HostAddress,\r
+  IN OUT UINTN              *NumberOfBytes,\r
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,\r
+  OUT VOID                  **Mapping\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT64        Attribute;\r
+\r
+  if (IoMmu != NULL) {\r
+    Status = IoMmu->Map (\r
+                      IoMmu,\r
+                      Operation,\r
+                      HostAddress,\r
+                      NumberOfBytes,\r
+                      DeviceAddress,\r
+                      Mapping\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    switch (Operation) {\r
+    case EdkiiIoMmuOperationBusMasterRead:\r
+    case EdkiiIoMmuOperationBusMasterRead64:\r
+      Attribute = EDKII_IOMMU_ACCESS_READ;\r
+      break;\r
+    case EdkiiIoMmuOperationBusMasterWrite:\r
+    case EdkiiIoMmuOperationBusMasterWrite64:\r
+      Attribute = EDKII_IOMMU_ACCESS_WRITE;\r
+      break;\r
+    case EdkiiIoMmuOperationBusMasterCommonBuffer:\r
+    case EdkiiIoMmuOperationBusMasterCommonBuffer64:\r
+      Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;\r
+      break;\r
+    default:\r
+      ASSERT(FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Status = IoMmu->SetAttribute (\r
+                      IoMmu,\r
+                      *Mapping,\r
+                      Attribute\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      IoMmu->Unmap (IoMmu, Mapping);\r
+      *Mapping = NULL;\r
+      return Status;\r
+    }\r
+  } else {\r
+    *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
+    *Mapping = NULL;\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Completes the Map() operation and releases any corresponding resources.\r
+\r
+  @param IoMmu              Pointer to IOMMU PPI.\r
+  @param Mapping            The mapping value returned from Map().\r
+\r
+**/\r
+VOID\r
+IoMmuUnmap (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN VOID                  *Mapping\r
+  )\r
+{\r
+  if (IoMmu != NULL) {\r
+    IoMmu->SetAttribute (IoMmu, Mapping, 0);\r
+    IoMmu->Unmap (IoMmu, Mapping);\r
+  }\r
+}\r
+\r
+/**\r
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
+  OperationBusMasterCommonBuffer64 mapping.\r
+\r
+  @param IoMmu                  Pointer to IOMMU PPI.\r
+  @param Pages                  The number of pages to allocate.\r
+  @param HostAddress            A pointer to store the base system memory address of the\r
+                                allocated range.\r
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param Mapping                A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+IoMmuAllocateBuffer (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN UINTN                  Pages,\r
+  OUT VOID                  **HostAddress,\r
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,\r
+  OUT VOID                  **Mapping\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINTN                 NumberOfBytes;\r
+  EFI_PHYSICAL_ADDRESS  HostPhyAddress;\r
+\r
+  *HostAddress = NULL;\r
+  *DeviceAddress = 0;\r
+  *Mapping = NULL;\r
+\r
+  if (IoMmu != NULL) {\r
+    Status = IoMmu->AllocateBuffer (\r
+                      IoMmu,\r
+                      EfiBootServicesData,\r
+                      Pages,\r
+                      HostAddress,\r
+                      0\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);\r
+    Status = IoMmu->Map (\r
+                      IoMmu,\r
+                      EdkiiIoMmuOperationBusMasterCommonBuffer,\r
+                      *HostAddress,\r
+                      &NumberOfBytes,\r
+                      DeviceAddress,\r
+                      Mapping\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
+      *HostAddress = NULL;\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Status = IoMmu->SetAttribute (\r
+                      IoMmu,\r
+                      *Mapping,\r
+                      EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      IoMmu->Unmap (IoMmu, *Mapping);\r
+      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
+      *Mapping = NULL;\r
+      *HostAddress = NULL;\r
+      return Status;\r
+    }\r
+  } else {\r
+    Status = PeiServicesAllocatePages (\r
+               EfiBootServicesCode,\r
+               Pages,\r
+               &HostPhyAddress\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    *HostAddress = (VOID *) (UINTN) HostPhyAddress;\r
+    *DeviceAddress = HostPhyAddress;\r
+    *Mapping = NULL;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Frees memory that was allocated with AllocateBuffer().\r
+\r
+  @param IoMmu              Pointer to IOMMU PPI.\r
+  @param Pages              The number of pages to free.\r
+  @param HostAddress        The base system memory address of the allocated range.\r
+  @param Mapping            The mapping value returned from Map().\r
+\r
+**/\r
+VOID\r
+IoMmuFreeBuffer (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN UINTN                  Pages,\r
+  IN VOID                   *HostAddress,\r
+  IN VOID                   *Mapping\r
+  )\r
+{\r
+  if (IoMmu != NULL) {\r
+    IoMmu->SetAttribute (IoMmu, Mapping, 0);\r
+    IoMmu->Unmap (IoMmu, Mapping);\r
+    IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);\r
+  }\r
+}\r
+\r
+/**\r
+  Initialize IOMMU.\r
+\r
+  @param IoMmu              Pointer to pointer to IOMMU PPI.\r
+\r
+**/\r
+VOID\r
+IoMmuInit (\r
+  OUT EDKII_IOMMU_PPI       **IoMmu\r
+  )\r
+{\r
+  PeiServicesLocatePpi (\r
+    &gEdkiiIoMmuPpiGuid,\r
+    0,\r
+    NULL,\r
+    (VOID **) IoMmu\r
+    );\r
+}\r
+\r
index 31647ff..5cad25e 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) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 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
@@ -1140,6 +1140,36 @@ ON_EXIT:
   return Status;\r
 }\r
 \r
+/**\r
+  One notified function to stop the Host Controller at the end of PEI\r
+\r
+  @param[in]  PeiServices        Pointer to PEI Services Table.\r
+  @param[in]  NotifyDescriptor   Pointer to the descriptor for the Notification event that\r
+                                 caused this function to execute.\r
+  @param[in]  Ppi                Pointer to the PPI data associated with this function.\r
+\r
+  @retval     EFI_SUCCESS  The function completes successfully\r
+  @retval     others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EhcEndOfPei (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,\r
+  IN VOID                       *Ppi\r
+  )\r
+{\r
+  PEI_USB2_HC_DEV   *Ehc;\r
+\r
+  Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor);\r
+\r
+  EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
+\r
+  EhcFreeSched (Ehc);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   @param  FileHandle  Handle of the file being invoked.\r
   @param  PeiServices Describes the list of possible PEI Services.\r
@@ -1219,6 +1249,8 @@ EhcPeimEntry (
 \r
     EhcDev->Signature = USB2_HC_DEV_SIGNATURE;\r
 \r
+    IoMmuInit (&EhcDev->IoMmu);\r
+\r
     EhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;\r
 \r
 \r
@@ -1250,6 +1282,12 @@ EhcPeimEntry (
       continue;\r
     }\r
 \r
+    EhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
+    EhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;\r
+    EhcDev->EndOfPeiNotifyList.Notify = EhcEndOfPei;\r
+\r
+    PeiServicesNotifyPpi (&EhcDev->EndOfPeiNotifyList);\r
+\r
     Index++;\r
   }\r
 \r
index d7a68d9..2794074 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Private Header file for Usb Host Controller PEIM\r
 \r
-Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 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
@@ -21,6 +21,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Ppi/UsbController.h>\r
 #include <Ppi/Usb2HostController.h>\r
+#include <Ppi/IoMmu.h>\r
+#include <Ppi/EndOfPeiPhase.h>\r
 \r
 #include <Library/DebugLib.h>\r
 #include <Library/PeimEntryPoint.h>\r
@@ -94,7 +96,13 @@ typedef struct _PEI_USB2_HC_DEV PEI_USB2_HC_DEV;
 struct _PEI_USB2_HC_DEV {\r
   UINTN                               Signature;\r
   PEI_USB2_HOST_CONTROLLER_PPI        Usb2HostControllerPpi;\r
-  EFI_PEI_PPI_DESCRIPTOR              PpiDescriptor;                    \r
+  EDKII_IOMMU_PPI                     *IoMmu;\r
+  EFI_PEI_PPI_DESCRIPTOR              PpiDescriptor;\r
+  //\r
+  // EndOfPei callback is used to stop the XHC DMA operation\r
+  // after exit PEI phase.\r
+  //\r
+  EFI_PEI_NOTIFY_DESCRIPTOR           EndOfPeiNotifyList;\r
   UINT32                              UsbHostControllerBaseAddress;\r
   PEI_URB                             *Urb;\r
   USBHC_MEM_POOL                      *MemPool;\r
@@ -122,7 +130,6 @@ struct _PEI_USB2_HC_DEV {
   // Periodic (interrupt) transfer schedule data:\r
   //\r
   VOID                                *PeriodFrame;     // Mapped as common buffer \r
-  VOID                                *PeriodFrameHost;\r
   VOID                                *PeriodFrameMap;\r
                                       \r
   PEI_EHC_QH                          *PeriodOne;\r
@@ -138,6 +145,7 @@ struct _PEI_USB2_HC_DEV {
 };\r
 \r
 #define PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(a)  CR (a, PEI_USB2_HC_DEV, Usb2HostControllerPpi, USB2_HC_DEV_SIGNATURE)\r
+#define PEI_RECOVERY_USB_EHC_DEV_FROM_THIS_NOTIFY(a) CR (a, PEI_USB2_HC_DEV, EndOfPeiNotifyList, USB2_HC_DEV_SIGNATURE)\r
 \r
 /**\r
   @param  EhcDev                 EHCI Device.\r
@@ -173,7 +181,8 @@ UsbHcInitMemPool (
             \r
 /**\r
   Release the memory management pool.\r
-  \r
+\r
+  @param  Ehc                   The EHCI device.\r
   @param  Pool                  The USB memory pool to free.\r
 \r
   @retval EFI_DEVICE_ERROR      Fail to free the memory pool.\r
@@ -182,6 +191,7 @@ UsbHcInitMemPool (
 **/\r
 EFI_STATUS\r
 UsbHcFreeMemPool (\r
+  IN PEI_USB2_HC_DEV      *Ehc,\r
   IN USBHC_MEM_POOL       *Pool\r
   )\r
 ;\r
@@ -208,6 +218,7 @@ UsbHcAllocateMem (
 /**\r
   Free the allocated memory back to the memory pool.\r
 \r
+  @param  Ehc            The EHCI device.\r
   @param  Pool           The memory pool of the host controller.\r
   @param  Mem            The memory to free.\r
   @param  Size           The size of the memory to free.\r
@@ -215,10 +226,110 @@ UsbHcAllocateMem (
 **/\r
 VOID\r
 UsbHcFreeMem (\r
+  IN PEI_USB2_HC_DEV      *Ehc,\r
   IN USBHC_MEM_POOL       *Pool,\r
   IN VOID                 *Mem,\r
   IN UINTN                Size\r
   )\r
 ;\r
 \r
+/**\r
+  Provides the controller-specific addresses required to access system memory from a\r
+  DMA bus master.\r
+\r
+  @param IoMmu                  Pointer to IOMMU PPI.\r
+  @param Operation              Indicates if the bus master is going to read or write to system memory.\r
+  @param HostAddress            The system memory address to map to the PCI controller.\r
+  @param NumberOfBytes          On input the number of bytes to map. On output the number of bytes\r
+                                that were mapped.\r
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param Mapping                A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.\r
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.\r
+\r
+**/\r
+EFI_STATUS\r
+IoMmuMap (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN EDKII_IOMMU_OPERATION  Operation,\r
+  IN VOID                   *HostAddress,\r
+  IN OUT UINTN              *NumberOfBytes,\r
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,\r
+  OUT VOID                  **Mapping\r
+  );\r
+\r
+/**\r
+  Completes the Map() operation and releases any corresponding resources.\r
+\r
+  @param IoMmu              Pointer to IOMMU PPI.\r
+  @param Mapping            The mapping value returned from Map().\r
+\r
+**/\r
+VOID\r
+IoMmuUnmap (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN VOID                  *Mapping\r
+  );\r
+\r
+/**\r
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
+  OperationBusMasterCommonBuffer64 mapping.\r
+\r
+  @param IoMmu                  Pointer to IOMMU PPI.\r
+  @param Pages                  The number of pages to allocate.\r
+  @param HostAddress            A pointer to store the base system memory address of the\r
+                                allocated range.\r
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param Mapping                A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+IoMmuAllocateBuffer (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN UINTN                  Pages,\r
+  OUT VOID                  **HostAddress,\r
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,\r
+  OUT VOID                  **Mapping\r
+  );\r
+\r
+/**\r
+  Frees memory that was allocated with AllocateBuffer().\r
+\r
+  @param IoMmu              Pointer to IOMMU PPI.\r
+  @param Pages              The number of pages to free.\r
+  @param HostAddress        The base system memory address of the allocated range.\r
+  @param Mapping            The mapping value returned from Map().\r
+\r
+**/\r
+VOID\r
+IoMmuFreeBuffer (\r
+  IN EDKII_IOMMU_PPI        *IoMmu,\r
+  IN UINTN                  Pages,\r
+  IN VOID                   *HostAddress,\r
+  IN VOID                   *Mapping\r
+  );\r
+\r
+/**\r
+  Initialize IOMMU.\r
+\r
+  @param IoMmu              Pointer to pointer to IOMMU PPI.\r
+\r
+**/\r
+VOID\r
+IoMmuInit (\r
+  OUT EDKII_IOMMU_PPI       **IoMmu\r
+  );\r
+\r
 #endif\r
index 7083f86..813ccc9 100644 (file)
@@ -4,7 +4,7 @@
 # It produces gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
 # which is used to enable recovery function from USB Drivers.\r
 #\r
-# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2010 - 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
@@ -43,6 +43,7 @@
   EhciSched.h\r
   EhciUrb.h\r
   UsbHcMem.h\r
+  DmaMem.c\r
 \r
 \r
 [Packages]\r
@@ -61,7 +62,8 @@
 [Ppis]\r
   gPeiUsb2HostControllerPpiGuid                 ## PRODUCES\r
   gPeiUsbControllerPpiGuid                      ## CONSUMES\r
-\r
+  gEdkiiIoMmuPpiGuid                            ## CONSUMES\r
+  gEfiEndOfPeiSignalPpiGuid                     ## CONSUMES\r
 \r
 [Depex]\r
   gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid\r
index e992d4f..606a53d 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) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 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
@@ -107,11 +107,13 @@ EhcInitSched (
   IN PEI_USB2_HC_DEV      *Ehc\r
   )\r
 {\r
+  VOID                  *Buf;\r
   EFI_PHYSICAL_ADDRESS  PhyAddr;\r
   VOID                  *Map;\r
   UINTN                 Index;\r
   UINT32                *Desc;\r
   EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  PciAddr;\r
 \r
   //\r
   // First initialize the periodical schedule data:\r
@@ -124,15 +126,19 @@ EhcInitSched (
   // The Frame List ocupies 4K bytes,\r
   // and must be aligned on 4-Kbyte boundaries.\r
   //\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
+             Ehc->IoMmu,\r
              1,\r
-             &PhyAddr\r
+             &Buf,\r
+             &PhyAddr,\r
+             &Map\r
              );\r
 \r
-  Map = NULL;\r
-  Ehc->PeriodFrameHost  = (VOID *)(UINTN)PhyAddr;\r
-  Ehc->PeriodFrame      = (VOID *)(UINTN)PhyAddr;\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ehc->PeriodFrame      = Buf;\r
   Ehc->PeriodFrameMap   = Map;\r
   Ehc->High32bitAddr    = EHC_HIGH_32BIT (PhyAddr);\r
 \r
@@ -161,19 +167,20 @@ EhcInitSched (
   // Initialize the frame list entries then set the registers\r
   //\r
   Desc = (UINT32 *) Ehc->PeriodFrame;\r
-\r
+  PciAddr  = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));\r
   for (Index = 0; Index < EHC_FRAME_LEN; Index++) {\r
-    Desc[Index] = QH_LINK (Ehc->PeriodOne, EHC_TYPE_QH, FALSE);\r
+    Desc[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
   }\r
 \r
-  EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (Ehc->PeriodFrame));\r
+  EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr));\r
 \r
   //\r
   // Second initialize the asynchronous schedule:\r
   // Only need to set the AsynListAddr register to\r
   // the reclamation header\r
   //\r
-  EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (Ehc->ReclaimHead));\r
+  PciAddr  = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));\r
+  EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr));\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -192,26 +199,27 @@ EhcFreeSched (
   EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, 0);\r
 \r
   if (Ehc->PeriodOne != NULL) {\r
-    UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));\r
     Ehc->PeriodOne = NULL;\r
   }\r
 \r
   if (Ehc->ReclaimHead != NULL) {\r
-    UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));\r
     Ehc->ReclaimHead = NULL;\r
   }\r
 \r
   if (Ehc->ShortReadStop != NULL) {\r
-    UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (PEI_EHC_QTD));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->ShortReadStop, sizeof (PEI_EHC_QTD));\r
     Ehc->ShortReadStop = NULL;\r
   }\r
 \r
   if (Ehc->MemPool != NULL) {\r
-    UsbHcFreeMemPool (Ehc->MemPool);\r
+    UsbHcFreeMemPool (Ehc, Ehc->MemPool);\r
     Ehc->MemPool = NULL;\r
   }\r
 \r
   if (Ehc->PeriodFrame != NULL) {\r
+    IoMmuFreeBuffer (Ehc->IoMmu, 1, Ehc->PeriodFrame, Ehc->PeriodFrameMap);\r
     Ehc->PeriodFrame = NULL;\r
   }\r
 }\r
index 597a494..3dadcd6 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) 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 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
@@ -301,7 +301,7 @@ EhcFreeQtds (
     Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);\r
 \r
     RemoveEntryList (&Qtd->QtdList);\r
-    UsbHcFreeMem (Ehc->MemPool, Qtd, sizeof (PEI_EHC_QTD));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Qtd, sizeof (PEI_EHC_QTD));\r
   }\r
 }\r
 \r
@@ -318,13 +318,21 @@ EhcFreeUrb (
   IN PEI_URB              *Urb\r
   )\r
 {\r
+  if (Urb->RequestPhy != NULL) {\r
+    IoMmuUnmap (Ehc->IoMmu, Urb->RequestMap);\r
+  }\r
+\r
+  if (Urb->DataMap != NULL) {\r
+    IoMmuUnmap (Ehc->IoMmu, Urb->DataMap);\r
+  }\r
+\r
   if (Urb->Qh != NULL) {\r
     //\r
     // Ensure that this queue head has been unlinked from the\r
     // schedule data structures. Free all the associated QTDs\r
     //\r
     EhcFreeQtds (Ehc, &Urb->Qh->Qtds);\r
-    UsbHcFreeMem (Ehc->MemPool, Urb->Qh, sizeof (PEI_EHC_QH));\r
+    UsbHcFreeMem (Ehc, Ehc->MemPool, Urb->Qh, sizeof (PEI_EHC_QH));\r
   }\r
 }\r
 \r
@@ -527,13 +535,11 @@ EhcCreateUrb (
 {\r
   USB_ENDPOINT                  *Ep;\r
   EFI_PHYSICAL_ADDRESS          PhyAddr;\r
+  EDKII_IOMMU_OPERATION         MapOp;\r
   EFI_STATUS                    Status;\r
   UINTN                         Len;\r
   PEI_URB                       *Urb;\r
   VOID                          *Map;\r
-\r
-    \r
-  Map = NULL;\r
   \r
   Urb = Ehc->Urb;\r
   Urb->Signature  = EHC_URB_SIG;\r
@@ -576,24 +582,40 @@ EhcCreateUrb (
   //\r
   if (Request != NULL) {\r
     Len     = sizeof (EFI_USB_DEVICE_REQUEST);\r
-    PhyAddr =  (EFI_PHYSICAL_ADDRESS) (UINTN) Request ;\r
-    if ( (Len != sizeof (EFI_USB_DEVICE_REQUEST))) {\r
+    MapOp   = EdkiiIoMmuOperationBusMasterRead;\r
+    Status  = IoMmuMap (Ehc->IoMmu, MapOp, Request, &Len, &PhyAddr, &Map);\r
+\r
+    if (EFI_ERROR (Status) || (Len != sizeof (EFI_USB_DEVICE_REQUEST))) {\r
       goto ON_ERROR;\r
     }\r
 \r
     Urb->RequestPhy = (VOID *) ((UINTN) PhyAddr);\r
     Urb->RequestMap = Map;\r
+  } else {\r
+    Urb->RequestPhy = NULL;\r
+    Urb->RequestMap = NULL;\r
   }\r
 \r
   if (Data != NULL) {\r
     Len      = DataLen;\r
-    PhyAddr  =  (EFI_PHYSICAL_ADDRESS) (UINTN) Data ;\r
-    if ( (Len != DataLen)) {\r
+\r
+    if (Ep->Direction == EfiUsbDataIn) {\r
+      MapOp = EdkiiIoMmuOperationBusMasterWrite;\r
+    } else {\r
+      MapOp = EdkiiIoMmuOperationBusMasterRead;\r
+    }\r
+\r
+    Status  = IoMmuMap (Ehc->IoMmu, MapOp, Data, &Len, &PhyAddr, &Map);\r
+\r
+    if (EFI_ERROR (Status) || (Len != DataLen)) {\r
       goto ON_ERROR;\r
     }\r
 \r
     Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);\r
     Urb->DataMap  = Map;\r
+  } else {\r
+    Urb->DataPhy  = NULL;\r
+    Urb->DataMap  = NULL;\r
   }\r
 \r
   Status = EhcCreateQtds (Ehc, Urb);\r
index 5f9f5f0..a0419bd 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) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 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
@@ -79,16 +79,18 @@ UsbHcAllocMemBlock (
 \r
   Block->Bits  = (UINT8 *)(UINTN)TempPtr;\r
 \r
-  \r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
+             Ehc->IoMmu,\r
              Pages,\r
-             &TempPtr\r
+             (VOID **) &BufHost,\r
+             &MappedAddr,\r
+             &Mapping\r
              );\r
-  ZeroMem ((VOID   *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ZeroMem (BufHost, Pages*EFI_PAGE_SIZE);\r
 \r
-  BufHost  = (VOID *)(UINTN)TempPtr;\r
-  MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost;\r
   //\r
   // Check whether the data structure used by the host controller\r
   // should be restricted into the same 4G\r
@@ -109,17 +111,21 @@ UsbHcAllocMemBlock (
 /**\r
   Free the memory block from the memory pool.\r
 \r
+  @param  Ehc            The EHCI device.\r
   @param  Pool           The memory pool to free the block from.\r
   @param  Block          The memory block to free.\r
 \r
 **/\r
 VOID\r
 UsbHcFreeMemBlock (\r
+  IN PEI_USB2_HC_DEV      *Ehc,\r
   IN USBHC_MEM_POOL       *Pool,\r
   IN USBHC_MEM_BLOCK      *Block\r
   )\r
 {\r
   ASSERT ((Pool != NULL) && (Block != NULL));\r
+\r
+  IoMmuFreeBuffer (Ehc->IoMmu, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Block->Mapping);\r
 }\r
 \r
 /**\r
@@ -195,6 +201,54 @@ UsbHcAllocMemFromBlock (
   return Block->Buf + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;\r
 }\r
 \r
+/**\r
+  Calculate the corresponding pci bus address according to the Mem parameter.\r
+\r
+  @param  Pool           The memory pool of the host controller.\r
+  @param  Mem            The pointer to host memory.\r
+  @param  Size           The size of the memory region.\r
+\r
+  @return the pci memory address\r
+**/\r
+EFI_PHYSICAL_ADDRESS\r
+UsbHcGetPciAddressForHostMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Head;\r
+  USBHC_MEM_BLOCK         *Block;\r
+  UINTN                   AllocSize;\r
+  EFI_PHYSICAL_ADDRESS    PhyAddr;\r
+  UINTN                   Offset;\r
+\r
+  Head      = Pool->Head;\r
+  AllocSize = USBHC_MEM_ROUND (Size);\r
+\r
+  if (Mem == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    //\r
+    // scan the memory block list for the memory block that\r
+    // completely contains the allocated memory.\r
+    //\r
+    if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  ASSERT ((Block != NULL));\r
+  //\r
+  // calculate the pci memory address for host memory address.\r
+  //\r
+  Offset = (UINT8 *)Mem - Block->BufHost;\r
+  PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);\r
+  return PhyAddr;\r
+}\r
+\r
 /**\r
   Insert the memory block to the pool's list of the blocks.\r
 \r
@@ -316,7 +370,8 @@ UsbHcInitMemPool (
 \r
 /**\r
   Release the memory management pool.\r
-  \r
+\r
+  @param  Ehc                   The EHCI device.\r
   @param  Pool                  The USB memory pool to free.\r
 \r
   @retval EFI_DEVICE_ERROR      Fail to free the memory pool.\r
@@ -325,6 +380,7 @@ UsbHcInitMemPool (
 **/\r
 EFI_STATUS\r
 UsbHcFreeMemPool (\r
+  IN PEI_USB2_HC_DEV      *Ehc,\r
   IN USBHC_MEM_POOL       *Pool\r
   )\r
 {\r
@@ -337,11 +393,11 @@ UsbHcFreeMemPool (
   // UsbHcUnlinkMemBlock can't be used to unlink and free the\r
   // first block.\r
   //\r
-  for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {\r
-    UsbHcFreeMemBlock (Pool, Block);\r
+  for (Block = Pool->Head->Next; Block != NULL; Block = Block->Next) {\r
+    UsbHcFreeMemBlock (Ehc, Pool, Block);\r
   }\r
 \r
-  UsbHcFreeMemBlock (Pool, Pool->Head);\r
+  UsbHcFreeMemBlock (Ehc, Pool, Pool->Head);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -425,6 +481,7 @@ UsbHcAllocateMem (
 /**\r
   Free the allocated memory back to the memory pool.\r
 \r
+  @param  Ehc            The EHCI device.\r
   @param  Pool           The memory pool of the host controller.\r
   @param  Mem            The memory to free.\r
   @param  Size           The size of the memory to free.\r
@@ -432,6 +489,7 @@ UsbHcAllocateMem (
 **/\r
 VOID\r
 UsbHcFreeMem (\r
+  IN PEI_USB2_HC_DEV      *Ehc,\r
   IN USBHC_MEM_POOL       *Pool,\r
   IN VOID                 *Mem,\r
   IN UINTN                Size\r
@@ -486,7 +544,7 @@ UsbHcFreeMem (
   // Release the current memory block if it is empty and not the head\r
   //\r
   if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {\r
-    UsbHcFreeMemBlock (Pool, Block);\r
+    UsbHcFreeMemBlock (Ehc, Pool, Block);\r
   }\r
 \r
   return ;\r
index 586d12a..717a8c8 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Private Header file for Usb Host Controller PEIM\r
 \r
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 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
@@ -74,4 +74,20 @@ typedef struct _USBHC_MEM_POOL {
           } while (0)       \r
 \r
 \r
+/**\r
+  Calculate the corresponding pci bus address according to the Mem parameter.\r
+\r
+  @param  Pool           The memory pool of the host controller.\r
+  @param  Mem            The pointer to host memory.\r
+  @param  Size           The size of the memory region.\r
+\r
+  @return the pci memory address\r
+**/\r
+EFI_PHYSICAL_ADDRESS\r
+UsbHcGetPciAddressForHostMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  );\r
+\r
 #endif\r