From nobody Sat May 4 08:02:38 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1511254867331250.03773121417726; Tue, 21 Nov 2017 01:01:07 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 0B4782035689D; Tue, 21 Nov 2017 00:56:51 -0800 (PST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id EFA8A2034711E for ; Tue, 21 Nov 2017 00:56:49 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 21 Nov 2017 01:00:53 -0800 Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.158.46]) by orsmga002.jf.intel.com with ESMTP; 21 Nov 2017 01:00:51 -0800 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.100; helo=mga07.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,432,1505804400"; d="scan'208";a="10219508" From: Star Zeng To: edk2-devel@lists.01.org Date: Tue, 21 Nov 2017 17:00:49 +0800 Message-Id: <1511254849-6468-1-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 Subject: [edk2] [PATCH] MdeModulePkg UhciPei: Support IoMmu X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jiewen Yao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Update the UhciPei 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=3D=3DDMA. Cc: Jiewen Yao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng Reviewed-by: Jiewen.yao@intel.com --- MdeModulePkg/Bus/Pci/UhciPei/DmaMem.c | 251 +++++++++++++++++++ MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c | 398 +++++++++++++++++++++++----= ---- MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h | 164 ++++++++++++- MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf | 5 +- 4 files changed, 719 insertions(+), 99 deletions(-) create mode 100644 MdeModulePkg/Bus/Pci/UhciPei/DmaMem.c diff --git a/MdeModulePkg/Bus/Pci/UhciPei/DmaMem.c b/MdeModulePkg/Bus/Pci/U= hciPei/DmaMem.c new file mode 100644 index 000000000000..c92bee429835 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/UhciPei/DmaMem.c @@ -0,0 +1,251 @@ +/** @file +The DMA memory help functions. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "UhcPeim.h" + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param IoMmu Pointer to IOMMU PPI. + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_PPI *IoMmu, + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + + if (IoMmu !=3D NULL) { + Status =3D IoMmu->Map ( + IoMmu, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + Attribute =3D EDKII_IOMMU_ACCESS_READ; + break; + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + Attribute =3D EDKII_IOMMU_ACCESS_WRITE; + break; + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + Attribute =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + Status =3D IoMmu->SetAttribute ( + IoMmu, + *Mapping, + Attribute + ); + if (EFI_ERROR (Status)) { + IoMmu->Unmap (IoMmu, Mapping); + *Mapping =3D NULL; + return Status; + } + } else { + *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + *Mapping =3D NULL; + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @param IoMmu Pointer to IOMMU PPI. + @param Mapping The mapping value returned from Map(). + +**/ +VOID +IoMmuUnmap ( + IN EDKII_IOMMU_PPI *IoMmu, + IN VOID *Mapping + ) +{ + if (IoMmu !=3D NULL) { + IoMmu->SetAttribute (IoMmu, Mapping, 0); + IoMmu->Unmap (IoMmu, Mapping); + } +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param IoMmu Pointer to IOMMU PPI. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN EDKII_IOMMU_PPI *IoMmu, + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS HostPhyAddress; + + *HostAddress =3D NULL; + *DeviceAddress =3D 0; + *Mapping =3D NULL; + + if (IoMmu !=3D NULL) { + Status =3D IoMmu->AllocateBuffer ( + IoMmu, + EfiBootServicesData, + Pages, + HostAddress, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + NumberOfBytes =3D EFI_PAGES_TO_SIZE (Pages); + Status =3D IoMmu->Map ( + IoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + *HostAddress, + &NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress); + *HostAddress =3D NULL; + return EFI_OUT_OF_RESOURCES; + } + Status =3D IoMmu->SetAttribute ( + IoMmu, + *Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + IoMmu->Unmap (IoMmu, *Mapping); + IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress); + *Mapping =3D NULL; + *HostAddress =3D NULL; + return Status; + } + } else { + Status =3D PeiServicesAllocatePages ( + EfiBootServicesData, + Pages, + &HostPhyAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + *HostAddress =3D (VOID *) (UINTN) HostPhyAddress; + *DeviceAddress =3D HostPhyAddress; + *Mapping =3D NULL; + } + return Status; +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param IoMmu Pointer to IOMMU PPI. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocate= d range. + @param Mapping The mapping value returned from Map(). + +**/ +VOID +IoMmuFreeBuffer ( + IN EDKII_IOMMU_PPI *IoMmu, + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ) +{ + if (IoMmu !=3D NULL) { + IoMmu->SetAttribute (IoMmu, Mapping, 0); + IoMmu->Unmap (IoMmu, Mapping); + IoMmu->FreeBuffer (IoMmu, Pages, HostAddress); + } +} + +/** + Initialize IOMMU. + + @param IoMmu Pointer to pointer to IOMMU PPI. + +**/ +VOID +IoMmuInit ( + OUT EDKII_IOMMU_PPI **IoMmu + ) +{ + *IoMmu =3D NULL; + PeiServicesLocatePpi ( + &gEdkiiIoMmuPpiGuid, + 0, + NULL, + (VOID **) IoMmu + ); +} + diff --git a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c b/MdeModulePkg/Bus/Pci/= UhciPei/UhcPeim.c index 37b2124c67ca..b7d60db0c94e 100644 --- a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c +++ b/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c @@ -2,7 +2,7 @@ PEIM to produce gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpi= Guid which is used to enable recovery function from USB Drivers. =20 -Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -18,6 +18,78 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHE= R EXPRESS OR IMPLIED. #include "UhcPeim.h" =20 /** + Stop the host controller. + + @param Uhc The UHCI device. + @param Timeout Max time allowed. + + @retval EFI_SUCCESS The host controller is stopped. + @retval EFI_TIMEOUT Failed to stop the host controller. + +**/ +EFI_STATUS +UhciStopHc ( + IN USB_UHC_DEV *Uhc, + IN UINTN Timeout + ) +{ + UINT16 CommandContent; + UINT16 UsbSts; + UINTN Index; + + CommandContent =3D USBReadPortW (Uhc, Uhc->UsbHostControllerBaseAddress = + USBCMD); + CommandContent &=3D USBCMD_RS; + USBWritePortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBCMD, CommandC= ontent); + + // + // ensure the HC is in halt status after send the stop command + // Timeout is in us unit. + // + for (Index =3D 0; Index < (Timeout / 50) + 1; Index++) { + UsbSts =3D USBReadPortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBS= TS); + + if ((UsbSts & USBSTS_HCH) =3D=3D USBSTS_HCH) { + return EFI_SUCCESS; + } + + MicroSecondDelay (50); + } + + return EFI_TIMEOUT; +} + +/** + One notified function to stop the Host Controller at the end of PEI + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation event that + caused this function to execute. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + @retval others +**/ +EFI_STATUS +EFIAPI +UhcEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + USB_UHC_DEV *Uhc; + + Uhc =3D PEI_RECOVERY_USB_UHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor); + + // + // Stop the Host Controller + // + UhciStopHc (Uhc, 1000 * 1000); + + return EFI_SUCCESS; +} + +/** Initializes Usb Host Controller. =20 @param FileHandle Handle of the file being invoked. @@ -98,6 +170,7 @@ UhcPeimEntry ( =20 UhcDev =3D (USB_UHC_DEV *) ((UINTN) TempPtr); UhcDev->Signature =3D USB_UHC_DEV_SIGNATURE; + IoMmuInit (&UhcDev->IoMmu); UhcDev->UsbHostControllerBaseAddress =3D (UINT32) BaseAddress; =20 // @@ -133,6 +206,12 @@ UhcPeimEntry ( continue; } =20 + UhcDev->EndOfPeiNotifyList.Flags =3D (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CA= LLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + UhcDev->EndOfPeiNotifyList.Guid =3D &gEfiEndOfPeiSignalPpiGuid; + UhcDev->EndOfPeiNotifyList.Notify =3D UhcEndOfPei; + + PeiServicesNotifyPpi (&UhcDev->EndOfPeiNotifyList); + Index++; } =20 @@ -190,9 +269,11 @@ UhcControlTransfer ( TD_STRUCT *PtrStatusTD; EFI_STATUS Status; UINT32 DataLen; - UINT8 *PtrDataSource; - UINT8 *Ptr; UINT8 DataToggle; + UINT8 *RequestPhy; + VOID *RequestMap; + UINT8 *DataPhy; + VOID *DataMap; =20 UhcDev =3D PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS (This); =20 @@ -217,6 +298,24 @@ UhcControlTransfer ( ClearStatusReg (UhcDev, StatusReg); =20 // + // Map the Request and data for bus master access, + // then create a list of TD for this transfer + // + Status =3D UhciMapUserRequest (UhcDev, Request, &RequestPhy, &RequestMap= ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D UhciMapUserData (UhcDev, TransferDirection, Data, DataLength,= &PktID, &DataPhy, &DataMap); + + if (EFI_ERROR (Status)) { + if (RequestMap !=3D NULL) { + IoMmuUnmap (UhcDev->IoMmu, RequestMap); + } + return Status; + } + + // // generate Setup Stage TD // =20 @@ -228,6 +327,7 @@ UhcControlTransfer ( 0, DeviceSpeed, (UINT8 *) Request, + RequestPhy, (UINT8) sizeof (EFI_USB_DEVICE_REQUEST), &PtrSetupTD ); @@ -242,38 +342,11 @@ UhcControlTransfer ( // // Data Stage of Control Transfer // - switch (TransferDirection) { - - case EfiUsbDataIn: - PktID =3D INPUT_PACKET_ID; - PtrDataSource =3D Data; - DataLen =3D (UINT32) *DataLength; - Ptr =3D PtrDataSource; - break; - - case EfiUsbDataOut: - PktID =3D OUTPUT_PACKET_ID; - PtrDataSource =3D Data; - DataLen =3D (UINT32) *DataLength; - Ptr =3D PtrDataSource; - break; - - // - // no data stage - // - case EfiUsbNoData: - if (*DataLength !=3D 0) { - return EFI_INVALID_PARAMETER; - } - - PktID =3D OUTPUT_PACKET_ID; - PtrDataSource =3D NULL; - DataLen =3D 0; - Ptr =3D NULL; - break; =20 - default: - return EFI_INVALID_PARAMETER; + if (TransferDirection =3D=3D EfiUsbNoData) { + DataLen =3D 0; + } else { + DataLen =3D (UINT32) *DataLength; } =20 DataToggle =3D 1; @@ -297,7 +370,8 @@ UhcControlTransfer ( UhcDev, DeviceAddress, 0, - Ptr, + Data, + DataPhy, PacketSize, PktID, DataToggle, @@ -312,7 +386,8 @@ UhcControlTransfer ( PtrPreTD =3D PtrTD; =20 DataToggle ^=3D 1; - Ptr +=3D PacketSize; + Data =3D (VOID *) ((UINT8 *) Data + PacketSize); + DataPhy +=3D PacketSize; DataLen -=3D PacketSize; } =20 @@ -365,14 +440,19 @@ UhcControlTransfer ( // if has errors that cause host controller halt, then return EFI_DEVICE= _ERROR directly. // if (!IsStatusOK (UhcDev, StatusReg)) { - - ClearStatusReg (UhcDev, StatusReg); *TransferResult |=3D EFI_USB_ERR_SYSTEM; - return EFI_DEVICE_ERROR; + Status =3D EFI_DEVICE_ERROR; } =20 ClearStatusReg (UhcDev, StatusReg); =20 + if (DataMap !=3D NULL) { + IoMmuUnmap (UhcDev->IoMmu, DataMap); + } + if (RequestMap !=3D NULL) { + IoMmuUnmap (UhcDev->IoMmu, RequestMap); + } + return Status; } =20 @@ -431,8 +511,6 @@ UhcBulkTransfer ( TD_STRUCT *PtrPreTD; =20 UINT8 PktID; - UINT8 *PtrDataSource; - UINT8 *Ptr; =20 BOOLEAN IsFirstTD; =20 @@ -444,6 +522,9 @@ UhcBulkTransfer ( =20 UINT16 CommandContent; =20 + UINT8 *DataPhy; + VOID *DataMap; + UhcDev =3D PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS (This); =20 // @@ -467,7 +548,6 @@ UhcBulkTransfer ( PtrFirstTD =3D NULL; PtrPreTD =3D NULL; DataLen =3D 0; - Ptr =3D NULL; =20 ShortPacketEnable =3D FALSE; =20 @@ -495,33 +575,24 @@ UhcBulkTransfer ( =20 ClearStatusReg (UhcDev, StatusReg); =20 + // + // Map the source data buffer for bus master access, + // then create a list of TDs + // if ((EndPointAddress & 0x80) !=3D 0) { TransferDirection =3D EfiUsbDataIn; } else { TransferDirection =3D EfiUsbDataOut; } =20 - switch (TransferDirection) { + Status =3D UhciMapUserData (UhcDev, TransferDirection, Data, DataLength,= &PktID, &DataPhy, &DataMap); =20 - case EfiUsbDataIn: - ShortPacketEnable =3D TRUE; - PktID =3D INPUT_PACKET_ID; - PtrDataSource =3D Data; - DataLen =3D (UINT32) *DataLength; - Ptr =3D PtrDataSource; - break; - - case EfiUsbDataOut: - PktID =3D OUTPUT_PACKET_ID; - PtrDataSource =3D Data; - DataLen =3D (UINT32) *DataLength; - Ptr =3D PtrDataSource; - break; - - default: - break; + if (EFI_ERROR (Status)) { + return Status; } =20 + DataLen =3D (UINT32) *DataLength; + PtrQH =3D UhcDev->BulkQH; =20 IsFirstTD =3D TRUE; @@ -540,7 +611,8 @@ UhcBulkTransfer ( UhcDev, DeviceAddress, EndPointAddress, - Ptr, + Data, + DataPhy, PacketSize, PktID, *DataToggle, @@ -570,7 +642,8 @@ UhcBulkTransfer ( PtrPreTD =3D PtrTD; =20 *DataToggle ^=3D 1; - Ptr +=3D PacketSize; + Data =3D (VOID *) ((UINT8 *) Data + PacketSize); + DataPhy +=3D PacketSize; DataLen -=3D PacketSize; } // @@ -604,14 +677,16 @@ UhcBulkTransfer ( // if has errors that cause host controller halt, then return EFI_DEVICE= _ERROR directly. // if (!IsStatusOK (UhcDev, StatusReg)) { - - ClearStatusReg (UhcDev, StatusReg); *TransferResult |=3D EFI_USB_ERR_SYSTEM; - return EFI_DEVICE_ERROR; + Status =3D EFI_DEVICE_ERROR; } =20 ClearStatusReg (UhcDev, StatusReg); =20 + if (DataMap !=3D NULL) { + IoMmuUnmap (UhcDev->IoMmu, DataMap); + } + return Status; } =20 @@ -1492,7 +1567,8 @@ CreateTD ( @param DevAddr Device address. @param Endpoint Endpoint number. @param DeviceSpeed Device Speed. - @param DevRequest Device reuquest. + @param DevRequest CPU memory address of request structure buffer to t= ransfer. + @param RequestPhy PCI memory address of request structure buffer to t= ransfer. @param RequestLen Request length. @param PtrTD TD_STRUCT generated. =20 @@ -1507,6 +1583,7 @@ GenSetupStageTD ( IN UINT8 Endpoint, IN UINT8 DeviceSpeed, IN UINT8 *DevRequest, + IN UINT8 *RequestPhy, IN UINT8 RequestLen, OUT TD_STRUCT **PtrTD ) @@ -1583,7 +1660,11 @@ GenSetupStageTD ( =20 TdStruct->PtrTDBuffer =3D (UINT8 *) DevRequest; TdStruct->TDBufferLength =3D RequestLen; - SetTDDataBuffer (TdStruct); + // + // Set the beginning address of the buffer that will be used + // during the transaction. + // + TdStruct->TDData.TDBufferPtr =3D (UINT32) (UINTN) RequestPhy; =20 *PtrTD =3D TdStruct; =20 @@ -1596,7 +1677,8 @@ GenSetupStageTD ( @param UhcDev The UHCI device. @param DevAddr Device address. @param Endpoint Endpoint number. - @param PtrData Data buffer. + @param PtrData CPU memory address of user data buffer to transfer. + @param DataPhy PCI memory address of user data buffer to transfer. @param Len Data length. @param PktID PacketID. @param Toggle Data toggle value. @@ -1613,6 +1695,7 @@ GenDataTD ( IN UINT8 DevAddr, IN UINT8 Endpoint, IN UINT8 *PtrData, + IN UINT8 *DataPhy, IN UINT8 Len, IN UINT8 PktID, IN UINT8 Toggle, @@ -1700,7 +1783,11 @@ GenDataTD ( =20 TdStruct->PtrTDBuffer =3D (UINT8 *) PtrData; TdStruct->TDBufferLength =3D Len; - SetTDDataBuffer (TdStruct); + // + // Set the beginning address of the buffer that will be used + // during the transaction. + // + TdStruct->TDData.TDBufferPtr =3D (UINT32) (UINTN) DataPhy; =20 *PtrTD =3D TdStruct; =20 @@ -1803,7 +1890,11 @@ CreateStatusTD ( =20 PtrTDStruct->PtrTDBuffer =3D NULL; PtrTDStruct->TDBufferLength =3D 0; - SetTDDataBuffer (PtrTDStruct); + // + // Set the beginning address of the buffer that will be used + // during the transaction. + // + PtrTDStruct->TDData.TDBufferPtr =3D 0; =20 *PtrTD =3D PtrTDStruct; =20 @@ -2174,25 +2265,6 @@ SetTDTokenPacketID ( } =20 /** - Set the beginning address of the data buffer that will be used - during the transaction. - - @param PtrTDStruct Place to store TD_STRUCT pointer. - -**/ -VOID -SetTDDataBuffer ( - IN TD_STRUCT *PtrTDStruct - ) -{ - // - // Set the beginning address of the data buffer that will be used - // during the transaction. - // - PtrTDStruct->TDData.TDBufferPtr =3D (UINT32) (UINTN) (PtrTDStruct->PtrTD= Buffer); -} - -/** Detect whether the TD is active. =20 @param PtrTDStruct Place to store TD_STRUCT pointer. @@ -2773,25 +2845,29 @@ CreateMemoryBlock ( ) { EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS TempPtr; + UINT8 *TempPtr; UINTN MemPages; UINT8 *Ptr; + VOID *Mapping; + EFI_PHYSICAL_ADDRESS MappedAddr; =20 // // Memory Block uses MemoryBlockSizeInPages pages, // memory management header and bit array use 1 page // MemPages =3D MemoryBlockSizeInPages + 1; - Status =3D PeiServicesAllocatePages ( - EfiBootServicesData, + Status =3D IoMmuAllocateBuffer ( + UhcDev->IoMmu, MemPages, - &TempPtr + (VOID **) &TempPtr, + &MappedAddr, + &Mapping ); if (EFI_ERROR (Status)) { return Status; } =20 - Ptr =3D (UINT8 *) ((UINTN) TempPtr); + Ptr =3D TempPtr; =20 ZeroMem (Ptr, MemPages * EFI_PAGE_SIZE); =20 @@ -2810,7 +2886,7 @@ CreateMemoryBlock ( // // Memory block initial address // - Ptr =3D (UINT8 *) ((UINTN) TempPtr); + Ptr =3D TempPtr; Ptr +=3D EFI_PAGE_SIZE; (*MemoryHeader)->MemoryBlockPtr =3D Ptr; // @@ -3217,3 +3293,135 @@ DelinkMemoryBlock ( } } } + +/** + Map address of request structure buffer. + + @param Uhc The UHCI device. + @param Request The user request buffer. + @param MappedAddr Mapped address of request. + @param Map Identificaion of this mapping to return. + + @return EFI_SUCCESS Success. + @return EFI_DEVICE_ERROR Fail to map the user request. + +**/ +EFI_STATUS +UhciMapUserRequest ( + IN USB_UHC_DEV *Uhc, + IN OUT VOID *Request, + OUT UINT8 **MappedAddr, + OUT VOID **Map + ) +{ + EFI_STATUS Status; + UINTN Len; + EFI_PHYSICAL_ADDRESS PhyAddr; + + Len =3D sizeof (EFI_USB_DEVICE_REQUEST); + Status =3D IoMmuMap ( + Uhc->IoMmu, + EdkiiIoMmuOperationBusMasterRead, + Request, + &Len, + &PhyAddr, + Map + ); + + if (!EFI_ERROR (Status)) { + *MappedAddr =3D (UINT8 *) (UINTN) PhyAddr; + } + + return Status; +} + +/** + Map address of user data buffer. + + @param Uhc The UHCI device. + @param Direction Direction of the data transfer. + @param Data The user data buffer. + @param Len Length of the user data. + @param PktId Packet identificaion. + @param MappedAddr Mapped address to return. + @param Map Identificaion of this mapping to return. + + @return EFI_SUCCESS Success. + @return EFI_DEVICE_ERROR Fail to map the user data. + +**/ +EFI_STATUS +UhciMapUserData ( + IN USB_UHC_DEV *Uhc, + IN EFI_USB_DATA_DIRECTION Direction, + IN VOID *Data, + IN OUT UINTN *Len, + OUT UINT8 *PktId, + OUT UINT8 **MappedAddr, + OUT VOID **Map + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhyAddr; + + Status =3D EFI_SUCCESS; + + switch (Direction) { + case EfiUsbDataIn: + // + // BusMasterWrite means cpu read + // + *PktId =3D INPUT_PACKET_ID; + Status =3D IoMmuMap ( + Uhc->IoMmu, + EdkiiIoMmuOperationBusMasterWrite, + Data, + Len, + &PhyAddr, + Map + ); + + if (EFI_ERROR (Status)) { + goto EXIT; + } + + *MappedAddr =3D (UINT8 *) (UINTN) PhyAddr; + break; + + case EfiUsbDataOut: + *PktId =3D OUTPUT_PACKET_ID; + Status =3D IoMmuMap ( + Uhc->IoMmu, + EdkiiIoMmuOperationBusMasterRead, + Data, + Len, + &PhyAddr, + Map + ); + + if (EFI_ERROR (Status)) { + goto EXIT; + } + + *MappedAddr =3D (UINT8 *) (UINTN) PhyAddr; + break; + + case EfiUsbNoData: + if ((Len !=3D NULL) && (*Len !=3D 0)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + *PktId =3D OUTPUT_PACKET_ID; + *MappedAddr =3D NULL; + *Map =3D NULL; + break; + + default: + Status =3D EFI_INVALID_PARAMETER; + } + +EXIT: + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h b/MdeModulePkg/Bus/Pci/= UhciPei/UhcPeim.h index 460db7eab9c6..9935f522cd0d 100644 --- a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h +++ b/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h @@ -1,7 +1,7 @@ /** @file Private Header file for Usb Host Controller PEIM =20 -Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -22,6 +22,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. =20 #include #include +#include +#include =20 #include #include @@ -177,7 +179,13 @@ struct _MEMORY_MANAGE_HEADER { typedef struct { UINTN Signature; PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi; + EDKII_IOMMU_PPI *IoMmu; EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; + // + // EndOfPei callback is used to stop the UHC DMA operation + // after exit PEI phase. + // + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; =20 UINT32 UsbHostControllerBaseAddress; FRAMELIST_ENTRY *FrameListEntry; @@ -191,6 +199,7 @@ typedef struct { } USB_UHC_DEV; =20 #define PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS(a) CR (a, USB_UHC_DEV, Us= bHostControllerPpi, USB_UHC_DEV_SIGNATURE) +#define PEI_RECOVERY_USB_UHC_DEV_FROM_THIS_NOTIFY(a) CR (a, USB_UHC_DEV, E= ndOfPeiNotifyList, USB_UHC_DEV_SIGNATURE) =20 /** Submits control transfer to a target USB device. @@ -654,7 +663,8 @@ CreateTD ( @param DevAddr Device address. @param Endpoint Endpoint number. @param DeviceSpeed Device Speed. - @param DevRequest Device reuquest. + @param DevRequest CPU memory address of request structure buffer to t= ransfer. + @param RequestPhy PCI memory address of request structure buffer to t= ransfer. @param RequestLen Request length. @param PtrTD TD_STRUCT generated. =20 @@ -669,6 +679,7 @@ GenSetupStageTD ( IN UINT8 Endpoint, IN UINT8 DeviceSpeed, IN UINT8 *DevRequest, + IN UINT8 *RequestPhy, IN UINT8 RequestLen, OUT TD_STRUCT **PtrTD ); @@ -679,7 +690,8 @@ GenSetupStageTD ( @param UhcDev The UHCI device. @param DevAddr Device address. @param Endpoint Endpoint number. - @param PtrData Data buffer. + @param PtrData CPU memory address of user data buffer to transfer. + @param DataPhy PCI memory address of user data buffer to transfer. @param Len Data length. @param PktID PacketID. @param Toggle Data toggle value. @@ -696,6 +708,7 @@ GenDataTD ( IN UINT8 DevAddr, IN UINT8 Endpoint, IN UINT8 *PtrData, + IN UINT8 *DataPhy, IN UINT8 Len, IN UINT8 PktID, IN UINT8 Toggle, @@ -1330,4 +1343,149 @@ DelinkMemoryBlock ( IN MEMORY_MANAGE_HEADER *FreeMemoryHeader ); =20 +/** + Map address of request structure buffer. + + @param Uhc The UHCI device. + @param Request The user request buffer. + @param MappedAddr Mapped address of request. + @param Map Identificaion of this mapping to return. + + @return EFI_SUCCESS Success. + @return EFI_DEVICE_ERROR Fail to map the user request. + +**/ +EFI_STATUS +UhciMapUserRequest ( + IN USB_UHC_DEV *Uhc, + IN OUT VOID *Request, + OUT UINT8 **MappedAddr, + OUT VOID **Map + ); + +/** + Map address of user data buffer. + + @param Uhc The UHCI device. + @param Direction Direction of the data transfer. + @param Data The user data buffer. + @param Len Length of the user data. + @param PktId Packet identificaion. + @param MappedAddr Mapped address to return. + @param Map Identificaion of this mapping to return. + + @return EFI_SUCCESS Success. + @return EFI_DEVICE_ERROR Fail to map the user data. + +**/ +EFI_STATUS +UhciMapUserData ( + IN USB_UHC_DEV *Uhc, + IN EFI_USB_DATA_DIRECTION Direction, + IN VOID *Data, + IN OUT UINTN *Len, + OUT UINT8 *PktId, + OUT UINT8 **MappedAddr, + OUT VOID **Map + ); + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param IoMmu Pointer to IOMMU PPI. + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_PPI *IoMmu, + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param IoMmu Pointer to IOMMU PPI. + @param Mapping The mapping value returned from Map(). + +**/ +VOID +IoMmuUnmap ( + IN EDKII_IOMMU_PPI *IoMmu, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param IoMmu Pointer to IOMMU PPI. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN EDKII_IOMMU_PPI *IoMmu, + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param IoMmu Pointer to IOMMU PPI. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocate= d range. + @param Mapping The mapping value returned from Map(). + +**/ +VOID +IoMmuFreeBuffer ( + IN EDKII_IOMMU_PPI *IoMmu, + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ); + +/** + Initialize IOMMU. + + @param IoMmu Pointer to pointer to IOMMU PPI. + +**/ +VOID +IoMmuInit ( + OUT EDKII_IOMMU_PPI **IoMmu + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf b/MdeModulePkg/Bus/Pc= i/UhciPei/UhciPei.inf index 7baa07612d01..95ddea21626e 100644 --- a/MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf +++ b/MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf @@ -4,7 +4,7 @@ # It produces gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpiGu= id which is used # to enable recovery function from USB Drivers. # -# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions @@ -36,6 +36,7 @@ [Defines] [Sources] UhcPeim.c UhcPeim.h + DmaMem.c =20 =20 [Packages] @@ -55,6 +56,8 @@ [LibraryClasses] [Ppis] gPeiUsbHostControllerPpiGuid ## PRODUCES gPeiUsbControllerPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 =20 [Depex] --=20 2.7.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel