From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c06::229; helo=mail-io0-x229.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-io0-x229.google.com (mail-io0-x229.google.com [IPv6:2607:f8b0:4001:c06::229]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 52FDC224A9EB3 for ; Fri, 30 Mar 2018 08:30:51 -0700 (PDT) Received: by mail-io0-x229.google.com with SMTP id x77so5155124ioi.2 for ; Fri, 30 Mar 2018 08:30:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=Sgj8zideFEM6/6m/tBOXZqQmIdtoXE3PmbKJ4TGfNyU=; b=OxLzgXhvarwNiNgLMd0bCJS4V6MJsyI88JwShxe620KB6KA5FgWUMn4aASgannAQoj M+dbhcYDNQcqHQZZOZy7CnYWW+z2ut5gRJkEPFEZaEdAKX/n+Xo16vh37ganlLPr5JkL NrchrVaJfNqz0+hh3hlrwG4N4e5UfAXnedD88= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=Sgj8zideFEM6/6m/tBOXZqQmIdtoXE3PmbKJ4TGfNyU=; b=uDrsS8idj9GUiwrl2ciILC4dEK5449pZ0kSayRX8XBiWZvITaFQdhAp8FbkHNhm3sa nduXBvqHzo8w15wnzJsHdzTSZHD0PGb6XIKbY1GGhUiLUC2Z6+G7T0B+O3V0gII5tQHY iON1irdcXL+93qMV3xH7ZSd4CLBz5YneaUmI+OPgcShU1nT3XS8plCLTQ2J8nzHmFJiR hcRbnYzo45fo3Z17do1jUnQXtuiCGcXSWYOckXBA0Frf3CNep/fap1JmvYg9jLAqcEA7 +tUL/OfNYNse0geJUFU7EPX6S9llbjnWL+lfSDtNQdotz2CBaovHCHlQNOhmMlRYt76Z hATg== X-Gm-Message-State: AElRT7FKgrcPsuCZDoeRrxlTh0YJNp4KyviRdVC4rHbtERX7H7JvCZmG PGTbfv/3fKyvMt0RAMmQW38gjtZl/ccEOLKSLkm2tg== X-Google-Smtp-Source: AIpwx49ZM0lMb2enAdBLrJSQNMvps1pxeoHVObi5L+iLNwpteLWLkTC64/hnBYMnftQRLTrupdo14qWvibH/IP7teuk= X-Received: by 10.107.139.212 with SMTP id n203mr15094488iod.107.1522423848949; Fri, 30 Mar 2018 08:30:48 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.187.67 with HTTP; Fri, 30 Mar 2018 08:30:48 -0700 (PDT) In-Reply-To: <1521594198-52523-9-git-send-email-heyi.guo@linaro.org> References: <1521594198-52523-1-git-send-email-heyi.guo@linaro.org> <1521594198-52523-9-git-send-email-heyi.guo@linaro.org> From: Ard Biesheuvel Date: Fri, 30 Mar 2018 16:30:48 +0100 Message-ID: To: Heyi Guo Cc: "edk2-devel@lists.01.org" , Leif Lindholm , Michael D Kinney Subject: Re: [PATCH edk2-platforms 08/12] Hisilicon: add PciCpuIo2Dxe X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Mar 2018 15:30:51 -0000 Content-Type: text/plain; charset="UTF-8" On 21 March 2018 at 01:03, Heyi Guo wrote: > This is to prepare for switching to generic PciHostBridge, and > CpuIo2Dxe is needed by generic PciHostBridge driver. > > The driver is copied from ArmPkg/Drivers/ArmPciCpuIo2Dxe and changed > for D0x. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Heyi Guo > Cc: Ard Biesheuvel > Cc: Leif Lindholm > Cc: Michael D Kinney > --- > Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf | 48 ++ > Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c | 557 ++++++++++++++++++++ > 2 files changed, 605 insertions(+) > > diff --git a/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf b/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf > new file mode 100644 > index 000000000000..fbb28319ca87 > --- /dev/null > +++ b/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf > @@ -0,0 +1,48 @@ > +## @file > +# Produces the CPU I/O 2 Protocol by using the services of the I/O Library. > +# > +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> +# Copyright (c) 2016 - 2018, Linaro Ltd. All rights reserved.
> +# Copyright (c) 2018, Hisilicon Ltd. 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 IMPLIED. > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = ArmPciCpuIo2Dxe > + FILE_GUID = 94577c7e-0bce-11e8-b4e8-286ed489ee9b > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = ArmPciCpuIo2Initialize > + > +# > +# The following information is for reference only and not required by the build tools. > +# > +# VALID_ARCHITECTURES = ARM AARCH64 > +# > + > +[Sources] > + ArmPciCpuIo2Dxe.c > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + UefiDriverEntryPoint > + BaseLib > + DebugLib > + IoLib > + > +[Protocols] > + gEfiCpuIo2ProtocolGuid ## PRODUCES > + > +[Depex] > + TRUE > diff --git a/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c b/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c > new file mode 100644 > index 000000000000..8426c5935c8a > --- /dev/null > +++ b/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c > @@ -0,0 +1,557 @@ > +/** @file > + Produces the CPU I/O 2 Protocol. > + > +Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
> +Copyright (c) 2016 - 2018, Linaro Ltd. All rights reserved.
> +Copyright (c) 2018, Hisilicon Ltd. 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 IMPLIED. > + > +**/ > + > +#include > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +// The translated IO PORT address is already a MMIO address, so we make it the > +// same as memory address for range check. > +#define MAX_IO_PORT_ADDRESS MAX_ADDRESS > + > +// > +// Lookup table for increment values based on transfer widths > +// > +STATIC CONST UINT8 mInStride[] = { > + 1, // EfiCpuIoWidthUint8 > + 2, // EfiCpuIoWidthUint16 > + 4, // EfiCpuIoWidthUint32 > + 8, // EfiCpuIoWidthUint64 > + 0, // EfiCpuIoWidthFifoUint8 > + 0, // EfiCpuIoWidthFifoUint16 > + 0, // EfiCpuIoWidthFifoUint32 > + 0, // EfiCpuIoWidthFifoUint64 > + 1, // EfiCpuIoWidthFillUint8 > + 2, // EfiCpuIoWidthFillUint16 > + 4, // EfiCpuIoWidthFillUint32 > + 8 // EfiCpuIoWidthFillUint64 > +}; > + > +// > +// Lookup table for increment values based on transfer widths > +// > +STATIC CONST UINT8 mOutStride[] = { > + 1, // EfiCpuIoWidthUint8 > + 2, // EfiCpuIoWidthUint16 > + 4, // EfiCpuIoWidthUint32 > + 8, // EfiCpuIoWidthUint64 > + 1, // EfiCpuIoWidthFifoUint8 > + 2, // EfiCpuIoWidthFifoUint16 > + 4, // EfiCpuIoWidthFifoUint32 > + 8, // EfiCpuIoWidthFifoUint64 > + 0, // EfiCpuIoWidthFillUint8 > + 0, // EfiCpuIoWidthFillUint16 > + 0, // EfiCpuIoWidthFillUint32 > + 0 // EfiCpuIoWidthFillUint64 > +}; > + > +/** > + Check parameters to a CPU I/O 2 Protocol service request. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will > + be handled by the driver. > + > + @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[in] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The parameters for this request pass the checks. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +CpuIoCheckParameter ( > + IN BOOLEAN MmioOperation, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + UINT64 MaxCount; > + UINT64 Limit; > + > + // > + // Check to see if Buffer is NULL > + // > + if (Buffer == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check to see if Width is in the valid range > + // > + if ((UINT32)Width >= EfiCpuIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // For FIFO type, the target address won't increase during the access, > + // so treat Count as 1 > + // > + if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { > + Count = 1; > + } > + > + // > + // Check to see if Width is in the valid range for I/O Port operations > + // > + Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check to see if Address is aligned > + // > + if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Check to see if any address associated with this transfer exceeds the maximum > + // allowed address. The maximum address implied by the parameters passed in is > + // Address + Size * Count. If the following condition is met, then the transfer > + // is not supported. > + // > + // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1 > + // > + // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count > + // can also be the maximum integer value supported by the CPU, this range > + // check must be adjusted to avoid all oveflow conditions. > + // > + // The following form of the range check is equivalent but assumes that > + // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1). > + // > + Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); > + if (Count == 0) { > + if (Address > Limit) { > + return EFI_UNSUPPORTED; > + } > + } else { > + MaxCount = RShiftU64 (Limit, Width); > + if (MaxCount < (Count - 1)) { > + return EFI_UNSUPPORTED; > + } > + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { > + return EFI_UNSUPPORTED; > + } > + } > + > + // > + // Check to see if Buffer is aligned > + // > + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) { > + return EFI_UNSUPPORTED; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Reads memory-mapped registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will > + be handled by the driver. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[out] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuMemoryServiceRead ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + *Uint8Buffer = MmioRead8 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint64) { > + *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); > + } > + } > + return EFI_SUCCESS; > +} > + > +/** > + Writes memory-mapped registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will > + be handled by the driver. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[in] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuMemoryServiceWrite ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + MmioWrite8 ((UINTN)Address, *Uint8Buffer); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); > + } else if (OperationWidth == EfiCpuIoWidthUint64) { > + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); > + } > + } > + return EFI_SUCCESS; > +} > + > +/** > + Reads I/O registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will > + be handled by the driver. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[out] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuIoServiceRead ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + > + // Assuming address has already been translated into MMIO address by PCI host > + // bridge driver, so we call MmioRead/Write directly. As noted in the previous patch, this is not correct. This is where the type translation should occur, from I/O address in the CPU view to an address covered by the I/O host bridge window that translates to I/O TLPs on the PCI side. > + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + *Uint8Buffer = MmioRead8 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Write I/O registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will > + be handled by the driver. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[in] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuIoServiceWrite ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + // > + // Make sure the parameters are valid > + // > + Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + > + // Assuming address has already been translated into MMIO address by PCI host > + // bridge driver, so we call MmioRead/Write directly. > + for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + MmioWrite8 ((UINTN)Address, *Uint8Buffer); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); > + } > + } > + > + return EFI_SUCCESS; > +} > + > +// > +// CPU I/O 2 Protocol instance > +// > +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 = { > + { > + CpuMemoryServiceRead, > + CpuMemoryServiceWrite > + }, > + { > + CpuIoServiceRead, > + CpuIoServiceWrite > + } > +}; > + > + > +/** > + The user Entry Point for module CpuIo2Dxe. The user code starts with this function. > + > + @param[in] ImageHandle The firmware allocated handle for the EFI image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully. > + @retval other Some error occurs when executing this entry point. > + > +**/ > +EFI_STATUS > +EFIAPI > +ArmPciCpuIo2Initialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid); > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &ImageHandle, > + &gEfiCpuIo2ProtocolGuid, &mCpuIo2, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + > + return Status; > +} > -- > 2.7.4 >