From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (EUR05-VI1-obe.outbound.protection.outlook.com [40.107.21.82]) by mx.groups.io with SMTP id smtpd.web12.3382.1590102228073883686 for ; Thu, 21 May 2020 16:03:48 -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=GxkJ1dJ5; spf=pass (domain: oss.nxp.com, ip: 40.107.21.82, mailfrom: wasim.khan@oss.nxp.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ICv1EZ4+wZLtG3mBPauKX2/TElNYwH8AFsxSVWqhJBP2pDuqDw11u+hqRL1dQBu8Z47UfDztAG37cKNrW67SopZVePtDdEd/aXibp15pDVS1tIqgvNMIRGZVG8zgn8hzITP+/qi0lCLltc+IVT7kREYwKvkWQ3VACQS+yXI0s5txgRvfuTXiLDmnDNa8BavhIULeuJY8Xim8PZXMlz4O3glyW3tE/d59bVAjBr7Fl3gsHJ18tEDfO4216adcK4OQqOkwTEP8lrRJEg6uTbE0dZ8sHOdRhMij8xjTGuctifLvQTRyxWWR4ov+d0q38a6e93hKMDRCo8tXcm2kqnKJJA== 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=b1Dt2RxUknRS6RRtXkm9MTxlutL/3/+h8UZ9rhVBG+I=; b=NG6udPTnb2S8IJUGs/XGgdz5TU+CSTiTzemcvGIwD/VlABXX/7LrmuAPREJjPvOkPUe0/vqH+1gJLcv4vrH/wYQidCOwPgMc/Bc+cUgnC6VC9EkZtszt2XksOMp6d8jXWKmK0MBpeyxdwJBIsVcOBaBsWO+/ldUDHXJi6/dlak/CgcbPcqLZBpj1Pea082LKT6N31R0F6pifh6P6AnEIU5mrQ9M99GVS9CT/yDgdcHz0x+fU/VgDVwiCEkPy4r8d+34JbxDa2KQm9/vdRctjXUvJ07uWZvq1zmT+5Jhd47cGcxuFuphXxI4b6vnyr5XHyV/046kXbX5Hqs8kxhE8AQ== 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=b1Dt2RxUknRS6RRtXkm9MTxlutL/3/+h8UZ9rhVBG+I=; b=GxkJ1dJ5doakjvUQOv84peub/X2eglVmpSHAK5dgfS1jcbd8gStEr6xg+Y5qJT/0x86w/cdVxe0FrDPW68Lp2Aw1F9ncLBb4jg/xy7yEUrkLfG0pEiFg8PAb+hk2sdwkFfHnstF8KhX7LXaH6pa/Kjn3XiQhl+bwToEOeAV5R/c= 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 VE1PR04MB6381.eurprd04.prod.outlook.com (2603:10a6:803:119::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3021.27; Thu, 21 May 2020 23:03:45 +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.020; Thu, 21 May 2020 23:03:45 +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 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver Date: Fri, 22 May 2020 04:32:16 +0530 Message-ID: <1590102139-16588-14-git-send-email-wasim.khan@oss.nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1590102139-16588-1-git-send-email-wasim.khan@oss.nxp.com> References: <1590102139-16588-1-git-send-email-wasim.khan@oss.nxp.com> X-ClientProxiedBy: PN1PR01CA0071.INDPRD01.PROD.OUTLOOK.COM (2603:1096:c00:1::11) 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 (157.47.200.219) by PN1PR01CA0071.INDPRD01.PROD.OUTLOOK.COM (2603:1096:c00:1::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.3021.23 via Frontend Transport; Thu, 21 May 2020 23:03:42 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [157.47.200.219] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 91636630-4ba5-4611-f4db-08d7fddb3683 X-MS-TrafficTypeDiagnostic: VE1PR04MB6381: 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: 041032FF37 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: I+IWGU2A2QVs23gj7Y5jssgcNhQn0wTwkrF3uZSQio8vaGYIcbJ7hp7C097C0TFj4gQf4GXfuNFnVKlfdk7RBsUAmomryuA1mfZbgS58PmWXexXz/jxNbAzny1ufzWN8U0QQFzP1SLTA2s8s238Zr9MHMrsfPXYev2IZkQhoruqTmaKJIfrURXLk3DrDmgHN5+HqntJPRT5hwjW47sSRUuRQ4eAjdLpxEgo/n4KNjWtXoG1fnRd8l2UGVn4aEUDvRAXBfvr1Fb0PL28DwXIIuNY/yEK609h5KKZUdmEM+xfoJWwQ1et69WDZQZq0eQJIsztxG4B2Jyu1M7Pz+TVp/rLau+wKFl7xXLrbQsE/nwlTTo97t98L5YWRNqjZYcyl 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)(346002)(376002)(136003)(366004)(396003)(39860400002)(6506007)(52116002)(66476007)(2616005)(956004)(44832011)(66946007)(8936002)(8676002)(4326008)(316002)(478600001)(2906002)(16526019)(186003)(66556008)(86362001)(6512007)(19627235002)(5660300002)(6666004)(6486002)(30864003)(26005)(44824005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: SZTmpKZtpgJ9Bwcmi4FrsYdMHtcRJLJfE31tsmahYZsg8MBX1XXodyO/UUBnwzqMcYmek0+t+rPGs79VfMpywLfVeHH+PZIp91R+YFxL1gE39janPgQktiL1ImbzQH1oabFG1ggJB/czl3/+UbgUiBiFvjELjxZ0PtzybwV53X87cKdhhdVOu8/6jeHq5NN6OwLVVgEeY1X49RCpL67WpFxKexVWEDeabsK8eoWwAt2dYZdUjXWm4ZYpzy+n5ZYniq/OmaWyCQulXt98B906Ql2rVz+oBfKc6QcrKaQQGnjLbLl/CzWC8tadWTZdHb78b9i+R6HXeoBQ66e6fcv1BIBj9NVso/geygP8tD4i+N/edQR0QZvCQ1SXH9SyLo4gaVZcHcbsFfOGA2MX5P8tM/+o667jJeeOGjohE2/RpfGINYA0G26Bz7oQwamwVyb05AMe7S1+HG2DR9gF1Rb2uzg8cZPf6kTaqd7/H9RULEs= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 91636630-4ba5-4611-f4db-08d7fddb3683 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 May 2020 23:03:45.2895 (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: CEoZ/hn5OadUoCHNODLGsp7S8/guH6t1U7kcbzHUpuXEjz1L6JTEDpN3ZzuK6WUEgqRjUi6qlMkyLDWWGUbU7Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR04MB6381 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 --- 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(+) create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c 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 bc35570f79bc..b561d0e3ba11 100755 --- a/Silicon/NXP/Include/Pcie.h +++ b/Silicon/NXP/Include/Pcie.h @@ -39,6 +39,25 @@ #define PCI_SEG0_PHY_MEM_BASE PCI_SEG0_MMIO_MEMBASE + SEG_MEM_BASE #define PCI_SEG0_PHY_MEM64_BASE PCI_SEG0_MMIO_MEMBASE + SEG_MEM64_BASE #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