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>
--- /dev/null
+/** @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
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
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
\r
EhcDev->Signature = USB2_HC_DEV_SIGNATURE;\r
\r
+ IoMmuInit (&EhcDev->IoMmu);\r
+\r
EhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;\r
\r
\r
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
/** @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
\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
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
// 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
};\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
\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
**/\r
EFI_STATUS\r
UsbHcFreeMemPool (\r
+ IN PEI_USB2_HC_DEV *Ehc,\r
IN USBHC_MEM_POOL *Pool\r
)\r
;\r
/**\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
**/\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
# 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
EhciSched.h\r
EhciUrb.h\r
UsbHcMem.h\r
+ DmaMem.c\r
\r
\r
[Packages]\r
[Ppis]\r
gPeiUsb2HostControllerPpiGuid ## PRODUCES\r
gPeiUsbControllerPpiGuid ## CONSUMES\r
-\r
+ gEdkiiIoMmuPpiGuid ## CONSUMES\r
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES\r
\r
[Depex]\r
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid\r
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
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
// 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
// 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
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
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
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
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
{\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
//\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
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
\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
/**\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
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
\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
**/\r
EFI_STATUS\r
UsbHcFreeMemPool (\r
+ IN PEI_USB2_HC_DEV *Ehc,\r
IN USBHC_MEM_POOL *Pool\r
)\r
{\r
// 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
/**\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
**/\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
// 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
/** @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
} 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