From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.3530.1665720098290912304 for ; Thu, 13 Oct 2022 21:01:38 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Bx32sZ30hjMt8tAA--.26776S11; Fri, 14 Oct 2022 12:01:36 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, kraxel@redhat.com, ardb@kernel.org, maobibo@loongson.cn Subject: [edk2-platforms][PATCH V3 09/16] Platform/Loongson: Add PciCpuIoDxe driver. Date: Fri, 14 Oct 2022 12:01:22 +0800 Message-Id: <9551a19cab745a067522a1153fa42ab09e68045b.1665719826.git.lixianglai@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8Bx32sZ30hjMt8tAA--.26776S11 X-Coremail-Antispam: 1UD129KBjvAXoWfur1rKrWfZr18CFWruF17ZFb_yoW5Zr48Wo W093yIvws8tw1rGrZ8C3sYya17XFnrWFsaqF4rAF1UWa1qqrn5Ka4rX3WUGryrt3yDuFWD Ja4UX3yxJrsYqa4fn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Content-Transfer-Encoding: quoted-printable Add PCI CpuIo protocol.there is no fix translation offset between I/O port accesses and MMIO accesses. Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOL to add the translation for IO access. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 548 ++++++++++++++++++ .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h | 219 +++++++ .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 40 ++ 3 files changed, 807 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo= 2Dxe.c new file mode 100644 index 0000000000..f5154eea7a --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c @@ -0,0 +1,548 @@ +/** @file=0D + Produces the CPU I/O 2 Protocol.=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=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 +#include "PciCpuIo2Dxe.h"=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 +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)=0D + && (Width <=3D EfiCpuIoWidthFifoUint64))=0D + {=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)=0D + && (Width =3D=3D EfiCpuIoWidthUint64))=0D + {=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 +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 + 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 +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 +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 + 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 +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 diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo= 2Dxe.h new file mode 100644 index 0000000000..a3f8cf7cbb --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h @@ -0,0 +1,219 @@ +/** @file=0D + Internal include file for the CPU I/O 2 Protocol.=0D +=0D +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef PCI_CPU_IO2_DXE_H_=0D +#define PCI_CPU_IO2_DXE_H_=0D +=0D +//#include =0D +//=0D +//#include =0D +//=0D +//#include =0D +//#include =0D +//#include =0D +//#include =0D +=0D +#define MAX_IO_PORT_ADDRESS 0xFFFF=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 +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 +/**=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 +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 +/**=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 +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 +/**=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 +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 +#endif=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.inf new file mode 100644 index 0000000000..9fb7160ae7 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.= inf @@ -0,0 +1,40 @@ +## @file=0D +# Produces the CPU I/O 2 Protocol by using the services of the I/O Librar= y.=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
=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 168D1A6E-F4A5-448A-9E95-795661BB3067= =0D + MODULE_TYPE =3D DXE_DRIVER=0D + VERSION_STRING =3D 1.0=0D + ENTRY_POINT =3D PciCpuIo2Initialize=0D +=0D +[Sources]=0D + PciCpuIo2Dxe.c=0D +=0D +[Packages]=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=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 --=20 2.31.1