From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::542; helo=mail-pg1-x542.google.com; envelope-from=ming.huang@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) (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 B11D321B02845 for ; Sun, 22 Jul 2018 18:12:37 -0700 (PDT) Received: by mail-pg1-x542.google.com with SMTP id z8-v6so10991469pgu.8 for ; Sun, 22 Jul 2018 18:12:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=sPu8I7QaMSAQHW4g5VNd5pRykXxK9B5PuYH4PJ1xXhU=; b=LpmbdSINprek0d2CKnZnhfSm2MGhQrg/pOg7HIgCz+xuRXItIBAF6Tf2YKfH3/QkXg +gYJ3INCoFL9nugZZyHiCjIxDJHtUuoMnZkCRRklpTsOi9GA1JuDXAnnZpaqSeK5vZve A/gJgTZFWi9nZwxw/Sl3SJQByLwMfwIK9M9gE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=sPu8I7QaMSAQHW4g5VNd5pRykXxK9B5PuYH4PJ1xXhU=; b=ZyChyUsZrSKxiYhX8W01bFU+gHj+68QKTqSTOqhGWuJnlcmt4BWYk3rMAzRE/0ofXE 8MX1X64axdGIYdEAhV3vt9sJ2szrq2bfudEVS7oa/uTzJYrZGuSw7j0lJV9ci4M5cnqG 9QI8BsjRDnd3lwwI5p229UFXV26xRCjLdq6SHDDCMYCICiloUvlB2ot2vdv2PQKY6HuE nzmUv2tIhUezNGfGec0YbS4ihHfJlNAIrnblJUZ13fuleVz5hemvUApYV7iJ/RhQqYlH WAxghDI6Z1W7PSBxVLs9RpKMnwy3FugrIjScJIK6ISHAY+biq1AX3rzg2fseUfB9izgv sZ3A== X-Gm-Message-State: AOUpUlFU/mrir3PdLgI+RqJZlthEPUJP5yrdDg9mPA2yaxLzsCbl+48F j6nrrMvWkLkKsjg+NbK3VsZLHA== X-Google-Smtp-Source: AAOMgpeRe7C0kTex42uLXuYHBY7kzkmEKjwQin6e4oQpoH5yrVxZhREjZ8gncbnbQRqQsf40cG75xQ== X-Received: by 2002:a65:5b8e:: with SMTP id i14-v6mr10348581pgr.242.1532308356852; Sun, 22 Jul 2018 18:12:36 -0700 (PDT) Received: from [10.144.0.114] ([64.64.108.39]) by smtp.gmail.com with ESMTPSA id r28-v6sm12295911pfd.37.2018.07.22.18.12.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 22 Jul 2018 18:12:35 -0700 (PDT) To: Ard Biesheuvel Cc: Leif Lindholm , linaro-uefi , "edk2-devel@lists.01.org" , Graeme Gregory , guoheyi@huawei.com, wanghuiqiang , huangming , Jason Zhang , huangdaode@hisilicon.com, John Garry , Heyi Guo , Michael D Kinney References: <20180720080242.3777-1-ming.huang@linaro.org> <20180720080242.3777-10-ming.huang@linaro.org> From: Ming Message-ID: Date: Mon, 23 Jul 2018 09:12:19 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 MIME-Version: 1.0 In-Reply-To: Subject: Re: [PATCH edk2-platforms v1 09/13] Hisilicon: add PciCpuIo2Dxe X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Jul 2018 01:12:37 -0000 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit 在 7/20/2018 6:31 PM, Ard Biesheuvel 写道: > (reply to correct version of the patch - apologies for the spam if you > got this twice) > > On 20 July 2018 at 17:02, Ming Huang wrote: >> From: Heyi Guo >> >> 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 > > Why do you need this driver? Can you not simply set > gArmTokenSpaceGuid.PcdPciIoTranslation to 0x0 and use > ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf instead? > Yes, using ArmPciCpuIo2Dxe is a good idea, I will modify it in v2. Thanks. >> --- >> Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c | 557 ++++++++++++++++++++ >> Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf | 48 ++ >> 2 files changed, 605 insertions(+) >> >> diff --git a/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c b/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c >> new file mode 100644 >> index 0000000000..8426c5935c >> --- /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. >> + 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; >> +} >> diff --git a/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf b/Silicon/Hisilicon/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf >> new file mode 100644 >> index 0000000000..fbb28319ca >> --- /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 >> -- >> 2.17.0 >>