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.web08.3551.1668157963687024175 for ; Fri, 11 Nov 2022 01:12:44 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8CxjdoKEm5jlRMGAA--.18816S3; Fri, 11 Nov 2022 17:12:42 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxFlcAEm5jXc0QAA--.27651S11; Fri, 11 Nov 2022 17:12:41 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: Bibo Mao , Chao Li , Leif Lindholm , Liming Gao , Michael D Kinney Subject: [edk2-platforms][PATCH V5 09/15] Platform/Loongson: Add PciCpuIoDxe driver. Date: Fri, 11 Nov 2022 17:12:24 +0800 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxFlcAEm5jXc0QAA--.27651S11 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWfXrW3tF13CrW8Cw13AFyftFb_yoW5Zr43Ao W093yIvws8Jw1rGrZ5C3sYya17XFnrWFsaqF4rAF1UWa1qqrn8Ka4rX3WUG34rt3yDuFWD Ja4UX3yxJrsYqa4fn29KB7ZKAUJUUUU7529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUym1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64 kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY 1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6x kF7I0E14v26F4UJVW0owAaw2AFwI0_Jrv_JF1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAq jxCEc2xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E74AGY7Cv6c x26rWlOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxAIw28IcxkI7VAKI48J MxAIw28IcVCjz48v1sIEY20_WwCFx2IqxVCFs4IE7xkEbVWUJVW8JwCFI7km07C267AKxV WUAVWUtwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF 67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW5JVW7JwCI42 IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF 0xvEx4A2jsIE14v26r4UJVWxJr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIda VFxhVjvjDU0xZFpf9x0zRByIUUUUUU= Content-Transfer-Encoding: quoted-printable Add PCI CpuIo protocol.there is no fix translation=0D offset between I/O port accesses and MMIO accesses.=0D Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOL=0D to add the translation for IO access.=0D =0D REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054=0D =0D Cc: Bibo Mao =0D Cc: Chao Li =0D Cc: Leif Lindholm =0D Cc: Liming Gao =0D Cc: Michael D Kinney =0D Signed-off-by: xianglai li =0D ---=0D .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 538 ++++++++++++++++++=0D .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h | 207 +++++++=0D .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 44 ++=0D 3 files changed, 789 insertions(+)=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.c=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.h=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.inf=0D =0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo= 2Dxe.c=0D new file mode 100644=0D index 0000000000..25417ff101=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.= c=0D @@ -0,0 +1,538 @@=0D +/** @file=0D + Produces the CPU I/O 2 Protocol.=0D +=0D + Copyright (c) 2022 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 +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 +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 +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 +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 + 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 +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 + 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 + 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 +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 + return Status;=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo= 2Dxe.h=0D new file mode 100644=0D index 0000000000..2489429df7=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.= h=0D @@ -0,0 +1,207 @@=0D +/** @file=0D + Internal include file for the CPU I/O 2 Protocol.=0D +=0D + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=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 +#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 +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 +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 +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 +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 // PCI_CPU_IO2_DXE_H_=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.inf=0D new file mode 100644=0D index 0000000000..a8a14cddd2=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.= inf=0D @@ -0,0 +1,44 @@=0D +## @file=0D +# Produces the CPU I/O 2 Protocol by using the services of the I/O Librar= y.=0D +#=0D +# Copyright (c) 2022 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 +#=0D +# VALID_ARCHITECTURES =3D LOONGARCH64=0D +#=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 -- =0D 2.31.1=0D =0D