From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (EUR05-AM6-obe.outbound.protection.outlook.com [40.107.22.64]) by mx.groups.io with SMTP id smtpd.web12.46724.1590482347679859327 for ; Tue, 26 May 2020 01:39:08 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@nxp1.onmicrosoft.com header.s=selector2-nxp1-onmicrosoft-com header.b=RvaaCOXa; spf=pass (domain: oss.nxp.com, ip: 40.107.22.64, mailfrom: wasim.khan@oss.nxp.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=IJfuDbL8A07kwX5NB37jdRZWHlOQlRZ/up4H4PvW2o9m1qDw+BLT9/ZBn3lnsS54Z3wD6DMFDYjt5a7dFdp3sjF/8bDVZjzjJWYyr1i+uBYvh84PMH+oaNNZ7eFioFZsRT3HRS2MGVxzuz6vpUeDfRgkGPRJptdC8jfGLCIwJqJ78+3foNdxLPy7Ju2yZ6aajRG6ZLYFZzoh3vhP3h8gjjwYcVKdZxqH1JVgWGEE6SrutL7JfYCoivB0CfZ1st4QTqA1WWnekhIqX3JUBrda0CkMSrzd5DIIM68m7l0ATxF4br1oVGKiKP/gXjOyZiVzH1zoWOuAozF4GwNQ6zvzSg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+WSw721+oiR+Ukvlr8ZKTGUVFVNJa2FszB+b3H6CzZc=; b=DKaI0i2eHf1qjH0J8QITb5ibCyQswlyw4oCq3iMHLqUhafOp2Zh1MYiMMqy1p6HYBG370FdzOqou7nrPbwrt+rTFwHLCp8kabpAzySQ9trxAO+tvE+oUCoj/x7BRNnnsDvIcSySjp9CIGZ9sUR5zDkehbbS+DHYDRrUsIvLCMkHFs9FXwuGibsFfV6uZs9ko0wdx8qVYrxEnPD2Lg+pHLNecpGUlLqnNevg6vcEZX+CVPmkjl2bBmVwYRSwikRZtOCi4u0ag+1L3iBcmuBkJQ3N9pu5qyA+VdgcNQslow4dYVZdM4kwoHg20nSUeLfrvVPDNaiPWZyRGcBcwtV2kzA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+WSw721+oiR+Ukvlr8ZKTGUVFVNJa2FszB+b3H6CzZc=; b=RvaaCOXaThNuLJ+LRRW+v7quUVszAylgj+xQ0t+VbeLyAayoYkkw42Ee295aXy3D2HVpfsP0mag4IdPmgykmn64AULw1dxfQrvPssX7LJYAqrKushslm4nBlSS4jVaK67WVKEq1ErydNyDMlXFUNtKAXu567g6SAxS5gpltgSaQ= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=oss.nxp.com; Received: from VE1PR04MB6702.eurprd04.prod.outlook.com (2603:10a6:803:123::13) by VE1PR04MB6367.eurprd04.prod.outlook.com (2603:10a6:803:11a::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3021.27; Tue, 26 May 2020 08:39:05 +0000 Received: from VE1PR04MB6702.eurprd04.prod.outlook.com ([fe80::81c4:97a6:7592:f225]) by VE1PR04MB6702.eurprd04.prod.outlook.com ([fe80::81c4:97a6:7592:f225%7]) with mapi id 15.20.3021.029; Tue, 26 May 2020 08:39:05 +0000 From: Wasim Khan To: devel@edk2.groups.io, meenakshi.aggarwal@nxp.com, vabhav.sharma@nxp.com, V.Sethi@nxp.com, ard.biesheuvel@arm.com, leif@nuviainc.com, jon@solid-run.com CC: Wasim Khan Subject: [PATCH edk2-platforms v2 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver Date: Tue, 26 May 2020 14:07:18 +0530 Message-ID: <1590482241-13132-14-git-send-email-wasim.khan@oss.nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1590482241-13132-1-git-send-email-wasim.khan@oss.nxp.com> References: <1590482241-13132-1-git-send-email-wasim.khan@oss.nxp.com> X-ClientProxiedBy: BM1PR0101CA0015.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00:18::25) To VE1PR04MB6702.eurprd04.prod.outlook.com (2603:10a6:803:123::13) Return-Path: wasim.khan@oss.nxp.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from wasimk-VirtualBox.nxp.com (171.79.147.152) by BM1PR0101CA0015.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00:18::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.3021.23 via Frontend Transport; Tue, 26 May 2020 08:39:01 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [171.79.147.152] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 7a74588e-d34c-4ee8-3161-08d801503f40 X-MS-TrafficTypeDiagnostic: VE1PR04MB6367: X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-Forefront-PRVS: 041517DFAB X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PFDDcj7YoBauG/QOYjVORxl506xon2S/thPqQIuvU+OWZ9rH4FcCHHtLQw1+q2jNPrhXLTwsdm6kunqItyofsxwEA0ClSq2KQ8CZ9rjk6cJcNKeNOvpX0DUuMw4jwD/dpMV+afLsN+CC4zac20I5PRgJLkmHSWIIXzrQ1Nyevf5kQe9SCdD2LtG9xSfBROuOPEUXqm+7O0+F8r/5C5y8Ut6eNApYMO/YcLDvZAhMY0KRSCWXk3yEKFDdXq8+uHn1CuGyTsUbvQQ1gBgp3UGALeKoXhin67mSt1qiT/40cAZEKmCiUC8Jv1WtJWf4dMcI83b2omDiUYtrr03mvn0fLIOQbYy3aEqK3Gj0j6raF7jrpZ6dCv63nR3SBmTNv4Lv X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VE1PR04MB6702.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(376002)(396003)(346002)(39860400002)(366004)(136003)(478600001)(6666004)(30864003)(66946007)(86362001)(956004)(66476007)(44832011)(5660300002)(19627235002)(66556008)(316002)(2616005)(8936002)(2906002)(8676002)(6506007)(4326008)(16526019)(6486002)(52116002)(26005)(186003)(6512007)(44824005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: lxi0F6d1XfAlx3ARcA0zN2vgubLos/fpvWzOuZW+yp9tA/wswpLS7uINgDFtbnA0t9ZTtRnZiO0qW910YhnnjaYT37aMDnU9wH/qS4i7xhMuwG+Xwf/guVyqJHDKVWrYMENFIyetCblckG1Xy4zlckPLcrKClCwbhI0M6xZclkaMHPfsOzmMtrAW0CLI3L3u8KTYT3xUzpXzT/fTl7y1KaRGzv459YcKXbwggn12UOpKFdcfUS6c1s3cQ9pFd6/1QlhG+Di5+zsdSPWzBsPv+ntc5hUuI4oefM5sLq0B3sUxA84JtbdEDOre89UeF2mNe0P/CNym1hz2ToFlTts78ehHXnTRnG3mMcvz3hvxuD3/lvW5u9lRk6KDOU/gbayXL/FQ01WIPJIWDLk7s3iVXqHbftyKcVmmYiTKnIqzAHI/Bpb9OA8YN7srImLzz3km8gum7LFlVnu56tPBsaEylor/GNTwO1+QPIFHg64Xmys= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7a74588e-d34c-4ee8-3161-08d801503f40 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 May 2020 08:39:05.2093 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: VbNFNv2RLVOBOc8ytqrWetm1GJGrdZlMOf98fQZX7ZUOthGxm0ui1+Ic8P9lTKfpqrCMlKZqUpUFUXjN5xnI7A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR04MB6367 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Wasim Khan NXP SoC has multiple PCIe RCs and 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 different RCs for IO access. Signed-off-by: Wasim Khan Reviewed-by: Ard Biesheuvel --- Notes: V2: - No change Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 40 ++ Silicon/NXP/Include/Pcie.h | 19 + Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 628 ++++++++++++++++++= ++ 3 files changed, 687 insertions(+) diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf b/Silicon/NX= P/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf new file mode 100755 index 000000000000..0ee470e41d5e --- /dev/null +++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf @@ -0,0 +1,40 @@ +## @file +# Produces the CPU I/O 2 Protocol by using the services of the I/O Librar= y. +# +# Copyright 2018, 2020 NXP +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D PciCpuIo2Dxe + FILE_GUID =3D 7bff18d7-9aae-434b-9c06-f10a7e157eac + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PciCpuIo2Initialize + +[Sources] + PciCpuIo2Dxe.c + +[Packages] + MdePkg/MdePkg.dec + Silicon/NXP/NxpQoriqLs.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Pcd] + gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr + gNxpQoriqLsTokenSpaceGuid.PcdNumPciController + +[Protocols] + gEfiCpuIo2ProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h index 210e4c3cf5e7..14cf385df7eb 100755 --- a/Silicon/NXP/Include/Pcie.h +++ b/Silicon/NXP/Include/Pcie.h @@ -42,6 +42,25 @@ #define PCI_SEG0_PHY_MEM64_BASE PCI_SEG0_MMIO_MEMBASE + SEG_MEM64_BASE #define PCI_MMIO64_WIN_SIZE SIZE_16GB #define PCI_SEG0_PHY_IO_BASE PCI_SEG0_MMIO_MEMBASE + SEG_IO_BASE +#define PCI_SEG0_PORTIO_MIN 0x0 +#define PCI_SEG0_PORTIO_MAX 0xffff +#define PCI_SEG0_PORTIO_OFFSET 0x0 +#define PCI_SEG1_PORTIO_MIN 0x0 +#define PCI_SEG1_PORTIO_MAX 0xffff +#define PCI_SEG1_PORTIO_OFFSET 0x10000 +#define PCI_SEG2_PORTIO_MIN 0x0 +#define PCI_SEG2_PORTIO_MAX 0xffff +#define PCI_SEG2_PORTIO_OFFSET 0x20000 +#define PCI_SEG3_PORTIO_MIN 0x0 +#define PCI_SEG3_PORTIO_MAX 0xffff +#define PCI_SEG3_PORTIO_OFFSET 0x30000 +#define PCI_SEG4_PORTIO_MIN 0x0 +#define PCI_SEG4_PORTIO_MAX 0xffff +#define PCI_SEG4_PORTIO_OFFSET 0x40000 +#define PCI_SEG5_PORTIO_MIN 0x0 +#define PCI_SEG5_PORTIO_MAX 0xffff +#define PCI_SEG5_PORTIO_OFFSET 0x50000 +#define PCI_SEG_PORTIO_LIMIT PCI_SEG5_PORTIO_MAX + PCI_SEG5_PORTIO_OF= FSET =20 // PCIe Controller configuration #define NUM_PCIE_CONTROLLER FixedPcdGet32 (PcdNumPciController) diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c b/Silicon/NXP/= Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c new file mode 100755 index 000000000000..17db44a8b510 --- /dev/null +++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c @@ -0,0 +1,628 @@ +/** @file + Produces the CPU I/O 2 Protocol. + + Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2016, Linaro Ltd. All rights reserved.
+ Copyright 2018-2020 NXP + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_IO_PORT_ADDRESS PCI_SEG_PORTIO_LIMIT + +// +// Handle for the CPU I/O 2 Protocol +// +STATIC EFI_HANDLE mHandle =3D NULL; + +// +// Lookup table for increment values based on transfer widths +// +STATIC CONST UINT8 mInStride[] =3D { + 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[] =3D { + 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 r= esponsible + 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. + + @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 opera= tion. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The n= umber 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 w= hich 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 W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system= . + +**/ +STATIC +EFI_STATUS +CpuIoCheckParameter ( + IN BOOLEAN MmioOperation, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT64 MaxCount; + UINT64 Limit; + + // + // Check to see if Buffer is NULL + // + if (Buffer =3D=3D NULL) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Width is in the valid range + // + if ((UINT32)Width >=3D EfiCpuIoWidthMaximum) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // For FIFO type, the target address won't increase during the access, + // so treat Count as 1 + // + if (Width >=3D EfiCpuIoWidthFifoUint8 && Width <=3D EfiCpuIoWidthFifoUin= t64) { + Count =3D 1; + } + + // + // Check to see if Width is in the valid range for I/O Port operations + // + Width =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + if (!MmioOperation && (Width =3D=3D EfiCpuIoWidthUint64)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Address is aligned + // + if ((Address & (UINT64)(mInStride[Width] - 1)) !=3D 0) { + ASSERT (FALSE); + 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 passe= d 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_POR= T_ADDRESS) + 1 + // + // Since MAX_ADDRESS can be the maximum integer value supported by the C= PU and Count + // can also be the maximum integer value supported by the CPU, this rang= e + // check must be adjusted to avoid all oveflow conditions. + // + Limit =3D (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); + if (Count =3D=3D 0) { + if (Address > Limit) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + } else { + MaxCount =3D RShiftU64 (Limit, Width); + if (MaxCount < (Count - 1)) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + } + + // + // Check to see if Buffer is aligned + // + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != =3D 0) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Reads memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + 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. + + 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 i= s + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @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 Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e 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 W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system= . + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + *Uint8Buffer =3D MmioRead8 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) { + *((UINT64 *)Uint8Buffer) =3D MmioRead64 ((UINTN)Address); + } + } + return EFI_SUCCESS; +} + +/** + Writes memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + 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. + + 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 i= s + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @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 Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e 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 W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system= . + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) { + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + } + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +TranslateIoAddress ( + IN OUT UINT64 *Address + ) +{ + UINT64 Start; + UINT64 End; + UINT64 Shift; + UINT64 SegIoHostAddressBase; + + SegIoHostAddressBase =3D PCI_SEG0_PHY_IO_BASE; + Start =3D PCI_SEG0_PORTIO_MIN + PCI_SEG0_PORTIO_OFFSET; + End =3D PCI_SEG0_PORTIO_MAX + PCI_SEG0_PORTIO_OFFSET; + Shift =3D SegIoHostAddressBase - PCI_SEG0_PORTIO_OFFSET; + + if (*Address >=3D Start && *Address <=3D End) { + *Address +=3D Shift; + return EFI_SUCCESS; + } + + Start =3D PCI_SEG1_PORTIO_MIN + PCI_SEG1_PORTIO_OFFSET; + End =3D PCI_SEG1_PORTIO_MAX + PCI_SEG1_PORTIO_OFFSET; + Shift =3D (SegIoHostAddressBase + (PCI_BASE_DIFF * 1)) - PCI_SEG1_PORTIO= _OFFSET; + + if (*Address >=3D Start && *Address <=3D End) { + *Address +=3D Shift; + return EFI_SUCCESS; + } + + Start =3D PCI_SEG2_PORTIO_MIN + PCI_SEG2_PORTIO_OFFSET; + End =3D PCI_SEG2_PORTIO_MAX + PCI_SEG2_PORTIO_OFFSET; + Shift =3D (SegIoHostAddressBase + (PCI_BASE_DIFF * 2)) - PCI_SEG2_PORTIO= _OFFSET; + + if (*Address >=3D Start && *Address <=3D End) { + *Address +=3D Shift; + return EFI_SUCCESS; + } + + Start =3D PCI_SEG3_PORTIO_MIN + PCI_SEG3_PORTIO_OFFSET; + End =3D PCI_SEG3_PORTIO_MAX + PCI_SEG3_PORTIO_OFFSET; + Shift =3D (SegIoHostAddressBase + (PCI_BASE_DIFF * 3)) - PCI_SEG3_PORTIO= _OFFSET; + + if (*Address >=3D Start && *Address <=3D End) { + *Address +=3D Shift; + return EFI_SUCCESS; + } + + Start =3D PCI_SEG4_PORTIO_MIN + PCI_SEG4_PORTIO_OFFSET; + End =3D PCI_SEG4_PORTIO_MAX + PCI_SEG4_PORTIO_OFFSET; + Shift =3D (SegIoHostAddressBase + (PCI_BASE_DIFF * 4)) - PCI_SEG4_PORTIO= _OFFSET; + + if (*Address >=3D Start && *Address <=3D End) { + *Address +=3D Shift; + return EFI_SUCCESS; + } + + Start =3D PCI_SEG5_PORTIO_MIN + PCI_SEG5_PORTIO_OFFSET; + End =3D PCI_SEG5_PORTIO_MAX + PCI_SEG5_PORTIO_OFFSET; + Shift =3D (SegIoHostAddressBase + (PCI_BASE_DIFF * 5)) - PCI_SEG5_PORTIO= _OFFSET; + + if (*Address >=3D Start && *Address <=3D End) { + *Address +=3D Shift; + return EFI_SUCCESS; + } + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; +} + +/** + Reads I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + 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. + + 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 i= s + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @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 Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e 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 W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system= . + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D TranslateIoAddress (&Address); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + + for (Uint8Buffer =3D Buffer; Count > 0; + Address +=3D InStride, Uint8Buffer +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + *Uint8Buffer =3D MmioRead8 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address); + } + } + + return EFI_SUCCESS; +} + +/** + Write I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + 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. + + 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 i= s + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @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 Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e 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 W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system= . + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + // + // Make sure the parameters are valid + // + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D TranslateIoAddress (&Address); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + + for (Uint8Buffer =3D (UINT8 *)Buffer; Count > 0; + Address +=3D InStride, Uint8Buffer +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } + } + + return EFI_SUCCESS; +} + +// +// CPU I/O 2 Protocol instance +// +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 =3D { + { + CpuMemoryServiceRead, + CpuMemoryServiceWrite + }, + { + CpuIoServiceRead, + CpuIoServiceWrite + } +}; + + +/** + The user Entry Point for module CpuIo2Dxe. The user code starts with thi= s function. + + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. + @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 po= int. + +**/ +EFI_STATUS +EFIAPI +PciCpuIo2Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiCpuIo2ProtocolGuid, &mCpuIo2, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} --=20 2.7.4