Thanks,
Chao
--------
Add PCI CpuIo protocol.there is no fix translationoffset between I/O port accesses and MMIO accesses.Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOLto add the translation for IO access.REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054Cc: Bibo Mao <maobibo@loongson.cn>Cc: Chao Li <lichao@loongson.cn>Cc: Leif Lindholm <quic_llindhol@quicinc.com>Cc: Liming Gao <gaoliming@byosoft.com.cn>Cc: Michael D Kinney <michael.d.kinney@intel.com>Signed-off-by: xianglai li <lixianglai@loongson.cn>---.../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 538 ++++++++++++++++++.../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h | 207 +++++++.../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 44 ++3 files changed, 789 insertions(+)create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.ccreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.hcreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.infdiff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.cnew file mode 100644index 0000000000..25417ff101--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c@@ -0,0 +1,538 @@+/** @file+ Produces the CPU I/O 2 Protocol.++ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>++ SPDX-License-Identifier: BSD-2-Clause-Patent++**/++#include <PiDxe.h>++#include <Protocol/CpuIo2.h>++#include <Library/BaseLib.h>+#include <Library/DebugLib.h>+#include <Library/IoLib.h>+#include <Library/PcdLib.h>+#include <Library/UefiBootServicesTableLib.h>+#include "PciCpuIo2Dxe.h"++//+// Handle for the CPU I/O 2 Protocol+//+STATIC EFI_HANDLE mHandle = NULL;++//+// 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.+**/+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 overflow 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.+**/+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.+**/+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.+**/+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;+ }+ Address += PcdGet64 (PcdPciIoTranslation);++ //+ // 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);+ }+ }+ 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.+**/+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;+ }++ Address += PcdGet64 (PcdPciIoTranslation);++ //+ // 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 = (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+PciCpuIo2Initialize (+ IN EFI_HANDLE ImageHandle,+ IN EFI_SYSTEM_TABLE *SystemTable+ )+{+ EFI_STATUS Status;++ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);+ Status = gBS->InstallMultipleProtocolInterfaces (+ &mHandle,+ &gEfiCpuIo2ProtocolGuid, &mCpuIo2,+ NULL+ );+ ASSERT_EFI_ERROR (Status);+ return Status;+}diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.hnew file mode 100644index 0000000000..2489429df7--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h@@ -0,0 +1,207 @@+/** @file+ Internal include file for the CPU I/O 2 Protocol.++ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>++ SPDX-License-Identifier: BSD-2-Clause-Patent++**/++#ifndef PCI_CPU_IO2_DXE_H_+#define PCI_CPU_IO2_DXE_H_++#define MAX_IO_PORT_ADDRESS 0xFFFF++/**+ 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.+**/+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+ );++/**+ 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.+**/+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+ );++/**+ 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.+**/+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+ );++/**+ 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.+**/+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+ );++#endif // PCI_CPU_IO2_DXE_H_diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.infnew file mode 100644index 0000000000..a8a14cddd2--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf@@ -0,0 +1,44 @@+## @file+# Produces the CPU I/O 2 Protocol by using the services of the I/O Library.+#+# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>+#+# SPDX-License-Identifier: BSD-2-Clause-Patent+#+##++[Defines]+ INF_VERSION = 0x00010005+ BASE_NAME = PciCpuIo2Dxe+ FILE_GUID = 168D1A6E-F4A5-448A-9E95-795661BB3067+ MODULE_TYPE = DXE_DRIVER+ VERSION_STRING = 1.0+ ENTRY_POINT = PciCpuIo2Initialize++#+# VALID_ARCHITECTURES = LOONGARCH64+#++[Sources]+ PciCpuIo2Dxe.c++[Packages]+ Platform/Loongson/LoongArchQemuPkg/Loongson.dec+ MdePkg/MdePkg.dec++[LibraryClasses]+ UefiDriverEntryPoint+ BaseLib+ DebugLib+ IoLib+ PcdLib+ UefiBootServicesTableLib++[Pcd]+ gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation++[Protocols]+ gEfiCpuIo2ProtocolGuid ## PRODUCES++[Depex]+ TRUE--2.31.1