From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-002e3701.pphosted.com (mx0a-002e3701.pphosted.com [148.163.147.86]) by mx.groups.io with SMTP id smtpd.web10.7409.1634634535322290786 for ; Tue, 19 Oct 2021 02:09:01 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@hpe.com header.s=pps0720 header.b=otxHxTlD; spf=temperror, err=temporary DNS error (domain: hpe.com, ip: 148.163.147.86, mailfrom: prvs=0926d272d9=abner.chang@hpe.com) Received: from pps.filterd (m0134422.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19J86JqT021896; Tue, 19 Oct 2021 09:08:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hpe.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pps0720; bh=/jSLew3ZkXLW3bN7FwS/rUZeW39V+rq6z6BRR9+dEKs=; b=otxHxTlDyQ4HOHeAwmVMhlZFJLK/axYHeDKAwwHdJW7KHm7gepqkd4QCoyHqeS5hNE4Y fB3E9P0Ep4tEg7vDVsfoOasXhhvwqEdVpcWZXJbCUuI0+KZbzrkCk9cPSZW35a955zlN drcQo/AYjnqfhX1Qh+mbE8HCselEUPeL6GeCX/JMWSOXQXfpNEZQTExjBJoWqPG7TgBz dXajSAkhttX5TKMwGail0df++aXgCzVb/tAWFomIoOu62poVgbftOkiZjiHBSPK+c1QH nc2aonT97g1gvLYeBH6RzxWkAKS2yezmLavLni0Tdtf8svORPZ48CezUe8IU1VkkW/uC 7w== Received: from g4t3425.houston.hpe.com (g4t3425.houston.hpe.com [15.241.140.78]) by mx0b-002e3701.pphosted.com with ESMTP id 3bst7b8g9v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 19 Oct 2021 09:08:54 +0000 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g4t3425.houston.hpe.com (Postfix) with ESMTP id 3FAD992; Tue, 19 Oct 2021 09:08:54 +0000 (UTC) Received: from UB16Abner.asiapacific.hpqcorp.net (ub16abner.asiapacific.hpqcorp.net [15.119.209.229]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 306EF48; Tue, 19 Oct 2021 09:08:53 +0000 (UTC) From: "Abner Chang" To: devel@edk2.groups.io Cc: abner.chang@hpe.com, Daniel Schaefer , Sunil V L Subject: [edk2-platforms][PATCH 30/30] Silicon/RISC-V: Add PciCpuIoDxe driver Date: Tue, 19 Oct 2021 16:10:07 +0800 Message-Id: <20211019081007.31165-31-abner.chang@hpe.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211019081007.31165-1-abner.chang@hpe.com> References: <20211019081007.31165-1-abner.chang@hpe.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: L5TVtZ3J7t4i-VDXydlC_X2hekdoIare X-Proofpoint-GUID: L5TVtZ3J7t4i-VDXydlC_X2hekdoIare X-HPE-SCL: -1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-18_07,2021-10-18_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 spamscore=0 malwarescore=0 phishscore=0 suspectscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 clxscore=1015 priorityscore=1501 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2109230001 definitions=main-2110190056 Content-Transfer-Encoding: quoted-printable Add PCI CpuIo protocol to RISC-V. Signed-off-by: Abner Chang Cc: Daniel Schaefer Cc: Sunil V L --- .../RISC-V/ProcessorPkg/RiscVProcessorPkg.dsc | 1 + .../Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 47 ++ .../Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 554 ++++++++++++++++++ 3 files changed, 602 insertions(+) create mode 100644 Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciC= puIo2Dxe.inf create mode 100644 Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciC= puIo2Dxe.c diff --git a/Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dsc b/Silicon/RI= SC-V/ProcessorPkg/RiscVProcessorPkg.dsc index 3b5738957d..5c7425421b 100644 --- a/Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dsc +++ b/Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dsc @@ -105,3 +105,4 @@ Silicon/RISC-V/ProcessorPkg/Universal/CpuDxe/CpuDxe.inf=0D Silicon/RISC-V/ProcessorPkg/Universal/SmbiosDxe/RiscVSmbiosDxe.inf=0D Silicon/RISC-V/ProcessorPkg/Universal/FdtDxe/FdtDxe.inf=0D + Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.inf=0D diff --git a/Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dx= e.inf b/Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.inf new file mode 100644 index 0000000000..736143bf4c --- /dev/null +++ b/Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.inf @@ -0,0 +1,47 @@ +## @file=0D +# Produces the CPU I/O 2 Protocol by using the services of the I/O Librar= y.=0D +#=0D +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
=0D +# Copyright (c) 2016, Linaro Ltd. All rights reserved.
=0D +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D PciCpuIo2Dxe=0D + FILE_GUID =3D 4032D393-69E6-42BF-BBEA-08F3297374E8= =0D + MODULE_TYPE =3D DXE_DRIVER=0D + VERSION_STRING =3D 1.0=0D + ENTRY_POINT =3D PciCpuIo2Initialize=0D +=0D +#=0D +# The following information is for reference only and not required by the = build tools.=0D +#=0D +# VALID_ARCHITECTURES =3D RISCV64=0D +#=0D +=0D +[Sources]=0D + PciCpuIo2Dxe.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D +=0D +[LibraryClasses]=0D + UefiDriverEntryPoint=0D + BaseLib=0D + DebugLib=0D + IoLib=0D + PcdLib=0D + UefiBootServicesTableLib=0D +=0D +[Pcd]=0D + gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation=0D +=0D +[Protocols]=0D + gEfiCpuIo2ProtocolGuid ## PRODUCES=0D +=0D +[Depex]=0D + TRUE=0D diff --git a/Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dx= e.c b/Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.c new file mode 100644 index 0000000000..03e3070682 --- /dev/null +++ b/Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.c @@ -0,0 +1,554 @@ +/** @file=0D + Produces the CPU I/O 2 Protocol.=0D +=0D +Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
=0D +Copyright (c) 2016, Linaro Ltd. All rights reserved.
=0D +(C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D +=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +=0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#define MAX_IO_PORT_ADDRESS 0xFFFF=0D +=0D +//=0D +// Handle for the CPU I/O 2 Protocol=0D +//=0D +STATIC EFI_HANDLE mHandle =3D NULL;=0D +=0D +//=0D +// Lookup table for increment values based on transfer widths=0D +//=0D +STATIC CONST UINT8 mInStride[] =3D {=0D + 1, // EfiCpuIoWidthUint8=0D + 2, // EfiCpuIoWidthUint16=0D + 4, // EfiCpuIoWidthUint32=0D + 8, // EfiCpuIoWidthUint64=0D + 0, // EfiCpuIoWidthFifoUint8=0D + 0, // EfiCpuIoWidthFifoUint16=0D + 0, // EfiCpuIoWidthFifoUint32=0D + 0, // EfiCpuIoWidthFifoUint64=0D + 1, // EfiCpuIoWidthFillUint8=0D + 2, // EfiCpuIoWidthFillUint16=0D + 4, // EfiCpuIoWidthFillUint32=0D + 8 // EfiCpuIoWidthFillUint64=0D +};=0D +=0D +//=0D +// Lookup table for increment values based on transfer widths=0D +//=0D +STATIC CONST UINT8 mOutStride[] =3D {=0D + 1, // EfiCpuIoWidthUint8=0D + 2, // EfiCpuIoWidthUint16=0D + 4, // EfiCpuIoWidthUint32=0D + 8, // EfiCpuIoWidthUint64=0D + 1, // EfiCpuIoWidthFifoUint8=0D + 2, // EfiCpuIoWidthFifoUint16=0D + 4, // EfiCpuIoWidthFifoUint32=0D + 8, // EfiCpuIoWidthFifoUint64=0D + 0, // EfiCpuIoWidthFillUint8=0D + 0, // EfiCpuIoWidthFillUint16=0D + 0, // EfiCpuIoWidthFillUint32=0D + 0 // EfiCpuIoWidthFillUint64=0D +};=0D +=0D +/**=0D + Check parameters to a CPU I/O 2 Protocol service request.=0D +=0D + The I/O operations are carried out exactly as requested. The caller is r= esponsible=0D + for satisfying any alignment and I/O width restrictions that a PI System= on a=0D + platform might require. For example on some platforms, width requests of= =0D + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will=0D + be handled by the driver.=0D +=0D + @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port= operation.=0D + @param[in] Width Signifies the width of the I/O or Memory opera= tion.=0D + @param[in] Address The base address of the I/O operation.=0D + @param[in] Count The number of I/O operations to perform. The n= umber of=0D + bytes moved is Width size * Count, starting at= Address.=0D + @param[in] Buffer For read operations, the destination buffer to= store the results.=0D + For write operations, the source buffer from w= hich to write data.=0D +=0D + @retval EFI_SUCCESS The parameters for this request pass the = checks.=0D + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.=0D + @retval EFI_INVALID_PARAMETER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth.=0D + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth,=0D + and Count is not valid for this PI system= .=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +CpuIoCheckParameter (=0D + IN BOOLEAN MmioOperation,=0D + IN EFI_CPU_IO_PROTOCOL_WIDTH Width,=0D + IN UINT64 Address,=0D + IN UINTN Count,=0D + IN VOID *Buffer=0D + )=0D +{=0D + UINT64 MaxCount;=0D + UINT64 Limit;=0D +=0D + //=0D + // Check to see if Buffer is NULL=0D + //=0D + if (Buffer =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Check to see if Width is in the valid range=0D + //=0D + if ((UINT32)Width >=3D EfiCpuIoWidthMaximum) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // For FIFO type, the target address won't increase during the access,=0D + // so treat Count as 1=0D + //=0D + if (Width >=3D EfiCpuIoWidthFifoUint8 && Width <=3D EfiCpuIoWidthFifoUin= t64) {=0D + Count =3D 1;=0D + }=0D +=0D + //=0D + // Check to see if Width is in the valid range for I/O Port operations=0D + //=0D + Width =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);=0D + if (!MmioOperation && (Width =3D=3D EfiCpuIoWidthUint64)) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Check to see if Address is aligned=0D + //=0D + if ((Address & (UINT64)(mInStride[Width] - 1)) !=3D 0) {=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + //=0D + // Check to see if any address associated with this transfer exceeds the= maximum=0D + // allowed address. The maximum address implied by the parameters passe= d in is=0D + // Address + Size * Count. If the following condition is met, then the = transfer=0D + // is not supported.=0D + //=0D + // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_POR= T_ADDRESS) + 1=0D + //=0D + // Since MAX_ADDRESS can be the maximum integer value supported by the C= PU and Count=0D + // can also be the maximum integer value supported by the CPU, this rang= e=0D + // check must be adjusted to avoid all overflow conditions.=0D + //=0D + // The following form of the range check is equivalent but assumes that= =0D + // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).=0D + //=0D + Limit =3D (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);=0D + if (Count =3D=3D 0) {=0D + if (Address > Limit) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + } else {=0D + MaxCount =3D RShiftU64 (Limit, Width);=0D + if (MaxCount < (Count - 1)) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + }=0D +=0D + //=0D + // Check to see if Buffer is aligned=0D + //=0D + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != =3D 0) {=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Reads memory-mapped registers.=0D +=0D + The I/O operations are carried out exactly as requested. The caller is r= esponsible=0D + for satisfying any alignment and I/O width restrictions that a PI System= on a=0D + platform might require. For example on some platforms, width requests of= =0D + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will=0D + be handled by the driver.=0D +=0D + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32= ,=0D + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for= =0D + each of the Count operations that is performed.=0D +=0D + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,=0D + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is= =0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times on the same Address.=0D +=0D + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,=0D + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address i= s=0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times from the first element of Buffe= r.=0D +=0D + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.=0D + @param[in] Width Signifies the width of the I/O or Memory operation.= =0D + @param[in] Address The base address of the I/O operation.=0D + @param[in] Count The number of I/O operations to perform. The number= of=0D + bytes moved is Width size * Count, starting at Addr= ess.=0D + @param[out] Buffer For read operations, the destination buffer to stor= e the results.=0D + For write operations, the source buffer from which = to write data.=0D +=0D + @retval EFI_SUCCESS The data was read from or written to the = PI system.=0D + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.=0D + @retval EFI_INVALID_PARAMETER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth.=0D + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth,=0D + and Count is not valid for this PI system= .=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +CpuMemoryServiceRead (=0D + IN EFI_CPU_IO2_PROTOCOL *This,=0D + IN EFI_CPU_IO_PROTOCOL_WIDTH Width,=0D + IN UINT64 Address,=0D + IN UINTN Count,=0D + OUT VOID *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT8 InStride;=0D + UINT8 OutStride;=0D + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;=0D + UINT8 *Uint8Buffer;=0D +=0D + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + //=0D + // Select loop based on the width of the transfer=0D + //=0D + InStride =3D mInStride[Width];=0D + OutStride =3D mOutStride[Width];=0D + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);=0D + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) {=0D + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) {=0D + *Uint8Buffer =3D MmioRead8 ((UINTN)Address);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) {=0D + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) {=0D + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) {=0D + *((UINT64 *)Uint8Buffer) =3D MmioRead64 ((UINTN)Address);=0D + }=0D + }=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Writes memory-mapped registers.=0D +=0D + The I/O operations are carried out exactly as requested. The caller is r= esponsible=0D + for satisfying any alignment and I/O width restrictions that a PI System= on a=0D + platform might require. For example on some platforms, width requests of= =0D + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will=0D + be handled by the driver.=0D +=0D + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32= ,=0D + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for= =0D + each of the Count operations that is performed.=0D +=0D + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,=0D + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is= =0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times on the same Address.=0D +=0D + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,=0D + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address i= s=0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times from the first element of Buffe= r.=0D +=0D + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.=0D + @param[in] Width Signifies the width of the I/O or Memory operation.= =0D + @param[in] Address The base address of the I/O operation.=0D + @param[in] Count The number of I/O operations to perform. The number= of=0D + bytes moved is Width size * Count, starting at Addr= ess.=0D + @param[in] Buffer For read operations, the destination buffer to stor= e the results.=0D + For write operations, the source buffer from which = to write data.=0D +=0D + @retval EFI_SUCCESS The data was read from or written to the = PI system.=0D + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.=0D + @retval EFI_INVALID_PARAMETER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth.=0D + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth,=0D + and Count is not valid for this PI system= .=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +CpuMemoryServiceWrite (=0D + IN EFI_CPU_IO2_PROTOCOL *This,=0D + IN EFI_CPU_IO_PROTOCOL_WIDTH Width,=0D + IN UINT64 Address,=0D + IN UINTN Count,=0D + IN VOID *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT8 InStride;=0D + UINT8 OutStride;=0D + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;=0D + UINT8 *Uint8Buffer;=0D +=0D + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + //=0D + // Select loop based on the width of the transfer=0D + //=0D + InStride =3D mInStride[Width];=0D + OutStride =3D mOutStride[Width];=0D + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);=0D + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) {=0D + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) {=0D + MmioWrite8 ((UINTN)Address, *Uint8Buffer);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) {=0D + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) {=0D + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) {=0D + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));=0D + }=0D + }=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Reads I/O registers.=0D +=0D + The I/O operations are carried out exactly as requested. The caller is r= esponsible=0D + for satisfying any alignment and I/O width restrictions that a PI System= on a=0D + platform might require. For example on some platforms, width requests of= =0D + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will=0D + be handled by the driver.=0D +=0D + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32= ,=0D + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for= =0D + each of the Count operations that is performed.=0D +=0D + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,=0D + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is= =0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times on the same Address.=0D +=0D + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,=0D + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address i= s=0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times from the first element of Buffe= r.=0D +=0D + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.=0D + @param[in] Width Signifies the width of the I/O or Memory operation.= =0D + @param[in] Address The base address of the I/O operation.=0D + @param[in] Count The number of I/O operations to perform. The number= of=0D + bytes moved is Width size * Count, starting at Addr= ess.=0D + @param[out] Buffer For read operations, the destination buffer to stor= e the results.=0D + For write operations, the source buffer from which = to write data.=0D +=0D + @retval EFI_SUCCESS The data was read from or written to the = PI system.=0D + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.=0D + @retval EFI_INVALID_PARAMETER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth.=0D + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth,=0D + and Count is not valid for this PI system= .=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +CpuIoServiceRead (=0D + IN EFI_CPU_IO2_PROTOCOL *This,=0D + IN EFI_CPU_IO_PROTOCOL_WIDTH Width,=0D + IN UINT64 Address,=0D + IN UINTN Count,=0D + OUT VOID *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT8 InStride;=0D + UINT8 OutStride;=0D + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;=0D + UINT8 *Uint8Buffer;=0D +=0D + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + Address +=3D PcdGet64 (PcdPciIoTranslation);=0D +=0D + //=0D + // Select loop based on the width of the transfer=0D + //=0D + InStride =3D mInStride[Width];=0D + OutStride =3D mOutStride[Width];=0D + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);=0D +=0D + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) {=0D + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) {=0D + *Uint8Buffer =3D MmioRead8 ((UINTN)Address);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) {=0D + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) {=0D + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address);=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Write I/O registers.=0D +=0D + The I/O operations are carried out exactly as requested. The caller is r= esponsible=0D + for satisfying any alignment and I/O width restrictions that a PI System= on a=0D + platform might require. For example on some platforms, width requests of= =0D + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will=0D + be handled by the driver.=0D +=0D + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32= ,=0D + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for= =0D + each of the Count operations that is performed.=0D +=0D + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,=0D + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is= =0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times on the same Address.=0D +=0D + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,=0D + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address i= s=0D + incremented for each of the Count operations that is performed. The read= or=0D + write operation is performed Count times from the first element of Buffe= r.=0D +=0D + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.=0D + @param[in] Width Signifies the width of the I/O or Memory operation.= =0D + @param[in] Address The base address of the I/O operation.=0D + @param[in] Count The number of I/O operations to perform. The number= of=0D + bytes moved is Width size * Count, starting at Addr= ess.=0D + @param[in] Buffer For read operations, the destination buffer to stor= e the results.=0D + For write operations, the source buffer from which = to write data.=0D +=0D + @retval EFI_SUCCESS The data was read from or written to the = PI system.=0D + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.=0D + @retval EFI_INVALID_PARAMETER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth.=0D + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth,=0D + and Count is not valid for this PI system= .=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +CpuIoServiceWrite (=0D + IN EFI_CPU_IO2_PROTOCOL *This,=0D + IN EFI_CPU_IO_PROTOCOL_WIDTH Width,=0D + IN UINT64 Address,=0D + IN UINTN Count,=0D + IN VOID *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT8 InStride;=0D + UINT8 OutStride;=0D + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;=0D + UINT8 *Uint8Buffer;=0D +=0D + //=0D + // Make sure the parameters are valid=0D + //=0D + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + Address +=3D PcdGet64 (PcdPciIoTranslation);=0D +=0D + //=0D + // Select loop based on the width of the transfer=0D + //=0D + InStride =3D mInStride[Width];=0D + OutStride =3D mOutStride[Width];=0D + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);=0D +=0D + for (Uint8Buffer =3D (UINT8 *)Buffer; Count > 0; Address +=3D InStride, = Uint8Buffer +=3D OutStride, Count--) {=0D + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) {=0D + MmioWrite8 ((UINTN)Address, *Uint8Buffer);=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) {=0D + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));=0D + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) {=0D + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +//=0D +// CPU I/O 2 Protocol instance=0D +//=0D +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 =3D {=0D + {=0D + CpuMemoryServiceRead,=0D + CpuMemoryServiceWrite=0D + },=0D + {=0D + CpuIoServiceRead,=0D + CpuIoServiceWrite=0D + }=0D +};=0D +=0D +=0D +/**=0D + The user Entry Point for module CpuIo2Dxe. The user code starts with thi= s function.=0D +=0D + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e.=0D + @param[in] SystemTable A pointer to the EFI System Table.=0D +=0D + @retval EFI_SUCCESS The entry point is executed successfully.=0D + @retval other Some error occurs when executing this entry po= int.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PciCpuIo2Initialize (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);=0D + Status =3D gBS->InstallMultipleProtocolInterfaces (=0D + &mHandle,=0D + &gEfiCpuIo2ProtocolGuid, &mCpuIo2,=0D + NULL=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + return Status;=0D +}=0D --=20 2.31.1