From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR03-AM5-obe.outbound.protection.outlook.com (EUR03-AM5-obe.outbound.protection.outlook.com [40.107.3.84]) by mx.groups.io with SMTP id smtpd.web12.10586.1637670461986604070 for ; Tue, 23 Nov 2021 04:27:43 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@armh.onmicrosoft.com header.s=selector2-armh-onmicrosoft-com header.b=IiDcRbUm; spf=pass (domain: arm.com, ip: 40.107.3.84, mailfrom: khasim.mohammed@arm.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kIYWtCXwjdu3/pAMs9HnFptcrq75PGQ07OR3Tb2BCl4=; b=IiDcRbUmbRxU23BI63R2sUwnPcXrWYPWmEboPoMZY6r14CqPr7MDMvBAHtmAT7owCiD0QfEQ4pDRyll/Onfy2nAE1XvxqF8hG8osrbqXoR1jqdfk3cdt2qnBWOj5OHnC6hrZ6YQanSo3DlC4qz1djndNA8xdYyWl5C6PFpUmz5A= Received: from DU2PR04CA0206.eurprd04.prod.outlook.com (2603:10a6:10:28d::31) by AS8PR08MB6614.eurprd08.prod.outlook.com (2603:10a6:20b:338::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.22; Tue, 23 Nov 2021 12:27:36 +0000 Received: from DB5EUR03FT052.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:28d:cafe::5d) by DU2PR04CA0206.outlook.office365.com (2603:10a6:10:28d::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4734.19 via Frontend Transport; Tue, 23 Nov 2021 12:27:36 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DB5EUR03FT052.mail.protection.outlook.com (10.152.21.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.19 via Frontend Transport; Tue, 23 Nov 2021 12:27:36 +0000 Received: ("Tessian outbound 157533e214a9:v110"); Tue, 23 Nov 2021 12:27:36 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 20b8163157a0cd78 X-CR-MTA-TID: 64aa7808 Received: from 08672cbdc00e.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id E18F17DC-99B4-495E-90D4-59BE892AAED3.1; Tue, 23 Nov 2021 12:27:20 +0000 Received: from EUR04-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 08672cbdc00e.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Tue, 23 Nov 2021 12:27:20 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=AMPvkfUxm48kHauNBwn9hiVB6LeBV1rMyri8K/EmWJy5ZZQOqrfoPxyTUxFnA84D4OZPev0TQpsopL6a5Op+dcgrWpt5a706utmQpXnu8dN7sel4z1kjHKLb/lBRSssZUq/FyGNfPowQum/4luCvUnxG+Qc2M1T0ceuODuTAP6d4VtCNkr4TL1dRQmaLpSSo8N3lakV1cJM/f8Pb9BkCxdmWUnjFH/NNOtrhxJ4O+JuLmu19qcFKkyDqMjA7+7zS0extqpFjVz1okhkK1fhboQp1dOpzr3CkiGfOQV0QDFq+8THHVRDpP4xBdoLGHcUYjOUp006J2wMt/f49jKe90A== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=kIYWtCXwjdu3/pAMs9HnFptcrq75PGQ07OR3Tb2BCl4=; b=f2fPixxiWRg3mAP3B6v6wio8vPpbQLETvnRmXE4AD0pHzbDISihH+YST4XBHuBKTvna266vT7ZP+IQxBFt2OlXtJq4NPpO9SBvdp/e8jVdHGFINkLmoZMZs7hglT22RWk6/zHaJsbsCNVnUm3pAlDKUKF8Blww4lm722djZxpBkzsHkY0Gea6rx7iYWN0hFgXTV4fj8Uz+pZJ5JdE4BBoQKAzEe3pkOxsbe1BF1NNGWNrkjOcvvwmvc+XtC4RAA59q/JnkKAkkayc+pNi6ltpzlBWZIJB75GIPYNoqc6G5+PmhdYs0U29JVbYzWcuC8BMvEo6IIhG+g4mqSKS0HLMA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kIYWtCXwjdu3/pAMs9HnFptcrq75PGQ07OR3Tb2BCl4=; b=IiDcRbUmbRxU23BI63R2sUwnPcXrWYPWmEboPoMZY6r14CqPr7MDMvBAHtmAT7owCiD0QfEQ4pDRyll/Onfy2nAE1XvxqF8hG8osrbqXoR1jqdfk3cdt2qnBWOj5OHnC6hrZ6YQanSo3DlC4qz1djndNA8xdYyWl5C6PFpUmz5A= Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from PA4PR08MB5902.eurprd08.prod.outlook.com (2603:10a6:102:e0::10) by PA4PR08MB6176.eurprd08.prod.outlook.com (2603:10a6:102:ea::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.22; Tue, 23 Nov 2021 12:27:15 +0000 Received: from PA4PR08MB5902.eurprd08.prod.outlook.com ([fe80::64a1:69a1:148d:9fa]) by PA4PR08MB5902.eurprd08.prod.outlook.com ([fe80::64a1:69a1:148d:9fa%7]) with mapi id 15.20.4713.025; Tue, 23 Nov 2021 12:27:15 +0000 From: "Khasim Mohammed" To: devel@edk2.groups.io Cc: nd@arm.com, Khasim Syed Mohammed Subject: [PATCH v2 2/3] Silicon/ARM/NeoverseN1Soc: Port PCI Segment Library Date: Tue, 23 Nov 2021 17:56:54 +0530 Message-Id: <20211123122655.9516-3-khasim.mohammed@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211123122655.9516-1-khasim.mohammed@arm.com> References: <20211123122655.9516-1-khasim.mohammed@arm.com> X-ClientProxiedBy: BM1PR01CA0102.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00::18) To PA4PR08MB5902.eurprd08.prod.outlook.com (2603:10a6:102:e0::10) MIME-Version: 1.0 Received: from e116623.arm.com (217.140.105.55) by BM1PR01CA0102.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.21 via Frontend Transport; Tue, 23 Nov 2021 12:27:13 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: fe178cd0-40fd-42a6-46ed-08d9ae7ca1f5 X-MS-TrafficTypeDiagnostic: PA4PR08MB6176:|AS8PR08MB6614: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:8273;OLM:8273; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: x8Y+K5kJskbYP6cv2MmZZRslUjsKpfwhJo46ND4FDJKDWcwuP7mOwy6IOXm5OSAU1pzvlNSdEFahsN1lgeUis+LUZKT/MR1haNt4Ry7FfLds8lYei3Cqvx2y5C6NVfRobUzhlYzziItoc1JAbp32yNlaSC0bJ5Daj/Ij/YnUyloPlbePUASsjK0wYJ88jww3UXyJ9yv5gn5m/heOMoMYkyksxvK48CWTBSl1Af+XY+Hjd2FG1FsCXTgPMxBlC1hovdOSiiv8jNAf3wxYxGM0UPqMi60x20gjbNlXiKEFZ9+O46kuTSm6PABG4RkvoohOxJlxTpr3ZJs8BKpnAnNnYDfl0AVAOgEqrZNgA7rbI9c3tij1eH4ztel2fFXyrLR51A4ZFvWCPwS6+5uOtMwpQnTl9QlP7jLSDypRV3spE1fvBV5tyHK77yUNn6Iy1HNj4NLXaU6idMS5Nkkn7ds9ipJbHzVLY2Z2MsI626AMI+4zbrXlhJQ9w2mVA4OqRiPxUBCRns/nmREpJg3yJmXJVrW3u+5ivuTz+59f4WtUnrUeC/gTBJl0F7rV30Y3veoCQjj1hYNwCQvIOX/G9iYmqDSdAkumH+9UlH1s3/mTwghZwiO9s0FexCnhlgpunlWPXscD30I+Jp+IerB0lqPdgT0WdBSbM5W9vxyUZG7SZfFZ8PutG2kPWkTrDJq2QXSYEYx9KJ9fYE5ym0qCJB6yQA== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PA4PR08MB5902.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(52116002)(7696005)(2906002)(6666004)(4326008)(66476007)(38100700002)(38350700002)(66946007)(30864003)(66556008)(8676002)(6486002)(19627235002)(186003)(508600001)(1076003)(956004)(8936002)(6916009)(2616005)(5660300002)(86362001)(83380400001)(316002)(36756003)(26005)(579004)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB6176 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Return-Path: Khasim.Mohammed@arm.com X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT052.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 2b5daa9f-92ad-4445-892e-08d9ae7c94c6 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: us4boyyjn9sXtk/BgBBD/1NzTX4dof9/i8IMwnl1DzvTWlH66aRmDkZpbf3TXL3mrPjXvMJmofcR30pUxuTA25rUpPKJneocCU5tsyjjClDHYdTAkRiumTxhXHwEZUCbVDyvMY4fO/2gO25jusKITQ6S6UYzhuYkXBph5C11YnFL/u0vjr105tBvdUC0y2pZLp9B6h/1sPqG3bRHnwVIFCcfbAFbWtGx2MtBcOpyuLkhKKhc7i4DwrTWh0gxcSOgGVgCMbmht/c/JK6XqfTqvNUWlCRGnHVjWc6t0gdOcn1zfQZt37wK+AOCqSMIfaYEO2hHrdZ7WDvzPOx3zNPwrUfI1ljhjFHKvWYGAFPK//OiHRKoON4MW7ZYqvdDlj46+sGJgjJrV5he2kBE0IyP4e2utqOpzb/+Sa7r+wYqdiCRFeP16AyP0pqh3+uZHa+xTG1Tdb22ZiXscNWg/JzcvmOtT8sOtZGv3IVaMEEmU1BG9uOZzpOoqNaHl4TJDSQDYAFL86yW7x2IM99xDdYx9K+q9H/OL5EYi9JDiPyUf7zYBZVzSLWj9OxMWn9N0X3WzMSu8SUG33G+9xz7xeUTW3fqGSgIEajCUvTTH3dBDKQhMZyLy65W+dLOQIh/VJnkwmXQJtwJxwZUdLoXyG604C2V5Lfp9FQoHGIAei9IckgFicd7ckS3pVrd3VmiOxb2yWUjHoh+7+RHDvp7FL/GaQ== X-Forefront-Antispam-Report: CIP:63.35.35.123;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:64aa7808-outbound-1.mta.getcheckrecipient.com;PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com;CAT:NONE;SFS:(4636009)(36840700001)(46966006)(956004)(2616005)(81166007)(30864003)(356005)(19627235002)(70586007)(8676002)(186003)(7696005)(6916009)(6486002)(1076003)(2906002)(336012)(6666004)(5660300002)(26005)(36860700001)(508600001)(47076005)(4326008)(8936002)(82310400004)(83380400001)(36756003)(70206006)(86362001)(316002)(559001)(579004);DIR:OUT;SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Nov 2021 12:27:36.5919 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: fe178cd0-40fd-42a6-46ed-08d9ae7ca1f5 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d;Ip=[63.35.35.123];Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: DB5EUR03FT052.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB6614 Content-Type: text/plain The BasePCISegment Library in MdePkg doesn't allow configuring multiple segments required for PCIe and CCIX root port enumeration. Therefore, a custom PCI Segment library is adapted from SynQuacerPciSegmentLib and ported for N1Sdp. Change-Id: I0a124b0ea2fb7a8ee652de2d66b977d848c509b4 Signed-off-by: Khasim Syed Mohammed --- .../Library/PciSegmentLib/PciSegmentLib.c | 1425 +++++++++++++++++ .../Library/PciSegmentLib/PciSegmentLib.inf | 35 + 2 files changed, 1460 insertions(+) create mode 100644 Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.c create mode 100644 Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.inf diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.c new file mode 100644 index 0000000000..dbf00e1f14 --- /dev/null +++ b/Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.c @@ -0,0 +1,1425 @@ +/** @file + PCI Segment Library for N1SDP SoC with multiple RCs + + Having two distinct root complexes is not supported by the standard + set of PciLib/PciExpressLib/PciSegmentLib, this PciSegmentLib + reimplements the functionality to support multiple root ports on + different segment numbers. + + Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2021, ARM Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef enum { + PciCfgWidthUint8 = 0, + PciCfgWidthUint16, + PciCfgWidthUint32, + PciCfgWidthMax +} PCI_CFG_WIDTH; + +/** + Assert the validity of a PCI Segment address. + A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63 + + @param A The address to validate. + @param M Additional bits to assert to be zero. +**/ +#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \ + ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0) + +/** + Function to return PCIe Physical Address for different RCs. + If address is invalid, then ASSERT(). + + @param Address Address passed from bus layer. + + @return Return PCIe base address. + +**/ +STATIC +UINT64 +PciSegmentLibGetConfigBase ( + IN UINT64 Address + ) +{ + switch ((UINT16)(Address >> 32)) { + case 0: + return FixedPcdGet32 (PcdPcieExpressBaseAddress); + case 1: + return FixedPcdGet32 (PcdCcixExpressBaseAddress); + default: + ASSERT (FALSE); + } + return 0; +} + +/** + Internal worker function to read a PCI configuration register. + + @param Address The address that encodes the PCI Bus, Device, Function + and Register. + @param Width The width of data to read + + @return The value read from the PCI configuration register. +**/ +STATIC +UINT32 +PciSegmentLibReadWorker ( + IN UINT64 Address, + IN PCI_CFG_WIDTH Width + ) +{ + UINT64 Base; + + Base = PciSegmentLibGetConfigBase (Address); + + switch (Width) { + case PciCfgWidthUint8: + return PciRead8 (Base + (UINT32)Address); + case PciCfgWidthUint16: + return PciRead16 (Base + (UINT32)Address); + case PciCfgWidthUint32: + return PciRead32 (Base + (UINT32)Address); + default: + ASSERT (FALSE); + } + return 0; +} + +/** + Internal worker function to write to a PCI configuration register. + + @param Address The address that encodes the PCI Bus, Device, Function + and Register. + @param Width The width of data to write + @param Data The value to write. + + @return The value written to the PCI configuration register. +**/ +STATIC +UINT32 +PciSegmentLibWriteWorker ( + IN UINT64 Address, + IN PCI_CFG_WIDTH Width, + IN UINT32 Data + ) +{ + UINT64 Base; + + Base = PciSegmentLibGetConfigBase (Address); + + switch (Width) { + case PciCfgWidthUint8: + PciWrite8 (Base + (UINT32)Address, Data); + break; + case PciCfgWidthUint16: + PciWrite16 (Base + (UINT32)Address, Data); + break; + case PciCfgWidthUint32: + PciWrite32 (Base + (UINT32)Address, Data); + break; + default: + ASSERT (FALSE); + } + + return Data; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, + Device, Function and Register. + + @return The 8-bit PCI configuration register specified by the Address. +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return (UINT8) PciSegmentLibReadWorker (Address, PciCfgWidthUint8); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit Value in the PCI configuration register specified by the + Address. This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, + Device, Function, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return (UINT8) PciSegmentLibWriteWorker (Address, PciCfgWidthUint8, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, + (UINT8) (PciSegmentRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by + AndData, and writes the result to the 8-bit PCI configuration register + specified by Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 (Address, + (UINT8) (PciSegmentRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with + an 8-bit value, followed by a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified + by AndData, performs a bitwise OR between the result of the AND operation + and the value specified by OrData, and writes the result to the 8-bit + PCI configuration register specified by Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, + (UINT8) ((PciSegmentRead8 (Address) & AndData) + | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit + and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciSegmentWrite8 (Address, + BitFieldWrite8 (PciSegmentRead8 (Address), + StartBit, + EndBit, + Value)); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, + BitFieldOr8 (PciSegmentRead8 (Address), + StartBit, + EndBit, + OrData)); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 (Address, + BitFieldAnd8 (PciSegmentRead8 (Address), + StartBit, + EndBit, + AndData)); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit + and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit + and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, + BitFieldAndThenOr8 (PciSegmentRead8 (Address), + StartBit, + EndBit, + AndData, + OrData)); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return (UINT16) PciSegmentLibReadWorker (Address, PciCfgWidthUint16); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param Value The value to write. + + @return The Value written is returned. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return (UINT16) PciSegmentLibWriteWorker (Address, PciCfgWidthUint16, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, + (UINT16) (PciSegmentRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified + by AndData, and writes the result to the 16-bit PCI configuration register + specified by the Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 (Address, + (UINT16) (PciSegmentRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by + AndData, performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by the Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, + (UINT16) ((PciSegmentRead16 (Address) & AndData) + | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciSegmentWrite16 (Address, + BitFieldWrite16 (PciSegmentRead16 (Address), + StartBit, + EndBit, + Value)); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified + by OrData, and writes the result to the 16-bit PCI configuration register + specified by the Address. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, + BitFieldOr16 (PciSegmentRead16 (Address), + StartBit, + EndBit, + OrData)); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, + and writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by the Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is + bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI + configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 (Address, + BitFieldAnd16 (PciSegmentRead16 (Address), + StartBit, + EndBit, + AndData)); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, + BitFieldAndThenOr16 (PciSegmentRead16 (Address), + StartBit, + EndBit, + AndData, + OrData)); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, + Device, Function and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return PciSegmentLibReadWorker (Address, PciCfgWidthUint32); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return PciSegmentLibWriteWorker (Address, PciCfgWidthUint32, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a + 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified + by OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified + by AndData, and writes the result to the 32-bit PCI configuration register + specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, + Device, Function and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with + a 32-bit value, followed by a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified + by AndData, performs a bitwise OR between the result of the AND operation + and the value specified by OrData, and writes the result to the 32-bit + PCI configuration register specified by Address. + + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations + are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, + (PciSegmentRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit + and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciSegmentWrite32 (Address, + BitFieldWrite32 (PciSegmentRead32 (Address), + StartBit, + EndBit, + Value)); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, + BitFieldOr32 (PciSegmentRead32 (Address), + StartBit, + EndBit, + OrData)); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified + by AndData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register + is returned. This function must guarantee that all PCI read and write + operations are serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and + EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 (Address, + BitFieldAnd32 (PciSegmentRead32 (Address), + StartBit, + EndBit, + AndData)); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit + and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit + and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAndThenOr32 (PciSegmentRead32 (Address), + StartBit, + EndBit, + AndData, + OrData)); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Segment, Bus, + Device, Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // Save Size for return + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // Read a byte if StartAddress is byte aligned + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // Read a word if StartAddress is word aligned + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // Read as many double words as possible + WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // Read the last remaining word if exist + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // Read the last remaining byte if exist + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + } + + return ReturnValue; +} + + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Segment, Bus, + Device, Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // Save Size for return + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // Write a byte if StartAddress is byte aligned + PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // Write a word if StartAddress is word aligned + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // Write as many double words as possible + PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // Write the last remaining word if exist + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // Write the last remaining byte if exist + PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.inf new file mode 100644 index 0000000000..fdeb2eb5ad --- /dev/null +++ b/Silicon/ARM/NeoverseN1Soc/Library/PciSegmentLib/PciSegmentLib.inf @@ -0,0 +1,35 @@ +## @file +# PCI Segment Library for N1Sdp SoC with multiple RCs +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2021, ARM Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = PciSegmentLib + FILE_GUID = b5ecc9c3-6b30-4f72-8a06-889b4ea8427e + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentLib + +[Sources] + PciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + Platform/ARM/N1Sdp/N1SdpPlatform.dec + Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + PciLib + +[FixedPcd] + gArmNeoverseN1SocTokenSpaceGuid.PcdCcixExpressBaseAddress + gArmNeoverseN1SocTokenSpaceGuid.PcdPcieExpressBaseAddress -- 2.17.1