From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (NAM12-BN8-obe.outbound.protection.outlook.com [40.107.237.101]) by mx.groups.io with SMTP id smtpd.web11.5275.1635932420149395988 for ; Wed, 03 Nov 2021 02:40:20 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=QlzbOb8M; spf=pass (domain: os.amperecomputing.com, ip: 40.107.237.101, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Iq4KL5oCIshfFw4hOIdOFl8pR5esuzveQFZpa7CzGccOgdBI13IOmhjSlWEHJ+wkrp1evYewqSzC4zxeJjWK0SDSVsSOowtKp6zykRZ7qhNSOB0k/S80/aASCNdvmxRkcWldUviFlaDlvrYZMGEUVsf4iH5Gzm9cu/WUglh0xa37r9nf27a4jfY92u18X928bujrE8X39l94UCgfO1uaXAv7o+52idc7kNTk36NWLM68IsB5Pmciuh6nP0SxJ38/rXilh8PaFsphu2gtuUc4EWyILnJNDFs9fGSd5xemRKKmeKMG8LuGRXY0rJRvXKjDfCLn3arMrePvM5HscXnyRg== 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=7pLaGkq6ysFo3GVa0N6iInKMCdgTj1tsW5rxT482mGY=; b=ORm3B8xit0aD6cKNFODYsICIVxjzxi7JCpRjDvxjq9sIEts8DYF2h8u1fa6JQ3CYgatqSlxrYEYP4yZSBqlDK06IF9LUmwC1Fs/Jrs95VA0g7Achbxjiqlr87w/tG9+cj3yYsOh9PSMzTO90nun5doN8yMSWLO+1rVRE4kFuUSybN5/t3dX51a9M6skFQQtMzBoSKI1qCYSQnG2eR7wesk6YEzLBPbA+e+6CmhrgqCQydxnra3YaNCUHi2AfQ48e9CBRF0E6qTAIzSyfOInRCgFJneiSfR/3glxMj/ZEcEk8R5wGNApUS+AhOW1SCGcXMKTLCxok+DquQNerGn5z/w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7pLaGkq6ysFo3GVa0N6iInKMCdgTj1tsW5rxT482mGY=; b=QlzbOb8MMrX0/qHay4Hnrb6juCiRfiLvPIi/a3gQHl73KoX9VnePzqD2BA5AfsqP2TMFjsnn9iP2HTTnUmv8fyjRf/1JkW3xT4S3efHy0Hif0N521bs09DInSp5qsJzuJlAwmdhBgkyXt+EcSuea3EboY+OzrBE05N+FOsZD0Ls= Authentication-Results: nuviainc.com; dkim=none (message not signed) header.d=none;nuviainc.com; dmarc=none action=none header.from=os.amperecomputing.com; Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by PH0PR01MB7333.prod.exchangelabs.com (2603:10b6:510:dd::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.11; Wed, 3 Nov 2021 09:40:17 +0000 Received: from PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee]) by PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee%5]) with mapi id 15.20.4669.011; Wed, 3 Nov 2021 09:40:17 +0000 Message-ID: Date: Wed, 3 Nov 2021 16:35:03 +0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.2.1 Subject: Re: [edk2-platforms][PATCH v4 16/31] AmpereAltraPkg: Add PciSegmentLib library instance To: Leif Lindholm Cc: devel@edk2.groups.io, patches@amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone References: <20211022061809.31087-1-nhi@os.amperecomputing.com> <20211022061809.31087-17-nhi@os.amperecomputing.com> <20211026125337.2r3yapa5uuimtc7o@leviathan> From: "Nhi Pham" In-Reply-To: <20211026125337.2r3yapa5uuimtc7o@leviathan> X-ClientProxiedBy: HKAPR03CA0003.apcprd03.prod.outlook.com (2603:1096:203:c8::8) To PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 Received: from [192.168.1.3] (113.188.173.157) by HKAPR03CA0003.apcprd03.prod.outlook.com (2603:1096:203:c8::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.6 via Frontend Transport; Wed, 3 Nov 2021 09:40:13 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 3b370367-450a-4914-b40f-08d99eadf1b1 X-MS-TrafficTypeDiagnostic: PH0PR01MB7333: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: BwcFBDVmguK5yOI+1HJQpZBpra1ni6WFJkNp0VF9RsJoBe+pnNZGN7XUREDDI4xaji/A8rE2CNK/nfu3B3sCPWcT4GYEkE1GFiO9+6loBxP+YX+l9xQDnpCp8t8MkrGz3+GlDB2gA/m2y8243JaKWox7BPRf+Mt2dTfbL1Oj8LHq2j8sJ0GVc/Wd0vL1CBjMyZWLr98HoLwzSJKoL1S2JQHBbdsH44OtQyRw3Mt+ii83WnHpuVpEcJizs8Frnp3NZ+ok/3H8mVllScbA0rQmoA6W3u6XV0jhlHk59c4boyKIdX3rmOrPA2C5Cyppa+1DwKV0f272ZcNzvCe1ANiMApiVX9usuYwhN0gLenDRVVWmFpfNqlvVEZGoGznrIYbIEmivWHIzs6L1SgojgEXsYAoNVxMZkv8YzrA96g05emUVSugWYG9Obt8G8Yr2uVg4CnBEXPvfSPQYY03HtlspwDsRjI+d5KZZuBlLWm3C8pCvPix2kqAZ+/LyCk8moD0iHbisX4TAqUM3notLh+YsDgDmBnpJG+ynPrK+fz60y2QHGMU0zscQgOiywFnpfTIivdKz1VCaCqclImcfc/ihcycDGusnp+D9wIQh8GNkiqHQtA5yP2qa3TOCjlPmZd8aT0QVO/Q+u1cGRmXS1x+2zfvvhQDaTEnszWxzVS1fMZLRNVyV7nQzF/0Cs3fZwhoInWAs9en7B/YuVvkOqr1r1GhtsEOsTuj6lN0nLYspFyi+9gyyKGMMk1gJOSEY9vfunJoSVrh6pQvX5YApSWnwCTvzCliS4n2J3pZCY+tPN+s= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR01MB7287.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(6666004)(30864003)(38350700002)(66946007)(2906002)(2616005)(86362001)(38100700002)(52116002)(6486002)(53546011)(16576012)(186003)(54906003)(8676002)(5660300002)(508600001)(316002)(31696002)(83380400001)(66476007)(31686004)(66556008)(26005)(6916009)(19627235002)(4326008)(956004)(8936002)(9186005)(45980500001)(43740500002)(579004)(559001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?bHZ2akRDN3I5bzhGWmlPU0lnVmR2Qjhkb3dpdStEZE1CWnp2NmlwRjJSQVdN?= =?utf-8?B?c3hsRTh6eEJtVEU5d2RqVkVhT0RxMk5HSjB2TlEzTzRHNEJuVUxjRjNndkw5?= =?utf-8?B?ODFmOThCTzNjSG1mL0s4STNwSDFvUUF0MmxwY3B6bUdubWw3S0lHVUdrc0pK?= =?utf-8?B?M1FuRk1zdENGdmJ3Sko1MzhIcmVrd3hPVkRNS2d1WVFVbktCekhDVjIzUmFX?= =?utf-8?B?WVRsRnRjWWlVK1JidXdlbk5DOE05QWxSWnNqTDAvUmNzbGQ0YjY4ZjJaemha?= =?utf-8?B?Y0p2VXByYXZtUzZBRUg4REQ5N3NSZWhLWmVNNWMveExGUTI5VXpVZE12akFL?= =?utf-8?B?L1JNWUUzN0ZRckZqMWgzZENOc1FOUUhWN3puYVBkaXpZakUybFo2VklZLzlV?= =?utf-8?B?OXd5OE5KckhwRUZqSjZIWkNTd3E0MTJyS09VR3IweGNVOWZhV0NyU2x4emlM?= =?utf-8?B?bTRubFhmd0toeXhmSk9oYnUzZlBxU2k0cTZ3K3UxOVRZZXJZWitaZDRvdWZ6?= =?utf-8?B?YXlBRnREVE9PMHRzUnliT2Y2cmhoNHBWdzFjb1RRL293alVvV2s3UDVwNkVK?= =?utf-8?B?NmkvaXczQUJ5RFhCZ3JTRXNjTFVVTFZhSFoxZnNwcTB0NTJDd3NvVWxDcGF2?= =?utf-8?B?NDQxYU5uVlpJMWlvUnYvZ1BBdmtVdHRoZ09mNHBoamxjMkRYdE5aU01vV3hI?= =?utf-8?B?VXVJS09PS0huSDF5QkJKb2V0VGQ2UjlOY0FtRDZ3UWZDZXM0bFFacGliR3M5?= =?utf-8?B?cWpubWZFbHJYNEw3ZFUxdVpRWkV5WEt0U3pnR3Z5WVlSWmpmUXYyZU1mV3Bz?= =?utf-8?B?d1RRTGlBQlYrL25PMGR5NE1acWM2VlJlUDI1clEvNG9DTmd4bUo0T0EvNnpq?= =?utf-8?B?VnZXYnZQbnhKWUVodWJ3WkdpaUk1U091emVZVHhRM1dNbVIyOVhpT3dETXZm?= =?utf-8?B?NlFYVUFUSDVQK0haM09rcis0SEljS3pvRUxqTnRzOHNyeTFjeGo3aXc5am1F?= =?utf-8?B?UDZFUlFsazdtM2ZaaFJlbDNDb0tGWVJBOVdnbm05NVFrbEZBNGVCbmZIZzFY?= =?utf-8?B?UlRJQkhQTUlENHlFS0VaMjhHMm5zVnhZc2lZWGhPT0duQkhWUzdHQ08vZnJq?= =?utf-8?B?cGsrYzRtYW1uUDJDTzUyc1FONnh2M1F4aXl3SjFQUDJpK3ZiR25xMGRvbTd0?= =?utf-8?B?MWZBRUc3Wjg1YlJQU2VXcm9hWGQ5b3o3eWo5d2taTHlJQ0RIL0t0MU8vSjVS?= =?utf-8?B?bmZmWEJpVjkwYWhsaEk3SFBnbnZNS0ZFZ3Y5MTQ4OEFMcENOZ1UyNEVQdEN0?= =?utf-8?B?b3JlVkhwYnhya3VBZEJ2dWRVQ2RvdmZRZDI0S3FTMW4zSjNSVlIvOGs1S3lm?= =?utf-8?B?YnFydlVyelNqWlBUUDhUa0FJcDlqY1dxeHFpTEpuMmYzdG5ERzhOdVo2T0Ja?= =?utf-8?B?cU9ncVZwR05aUjRKVW5leW9wZmovOE1nMDBkOUZFeW1qR0NzR25iZkxsV2tu?= =?utf-8?B?eGJlSzR4SUVQbUJFTnlkbGZHSXRHMFF5V3RMc1JSdWxlTU92ekhRTTRvZlVH?= =?utf-8?B?d2c0N1dnSVRkMThHUlFLQ3IrbVVyN1YyM2NXQjJGUVRtTnl5VXhXN2tqYjVJ?= =?utf-8?B?V2grNDhtbmE2TUYxWXdHSlRzNVJHVTBpeUtXcXd3SnpORjFPR0poN3Z0UWpy?= =?utf-8?B?UFZtNzYwK21WM0tRUlFFbVZsRWhiaGZqVDRHRnRuZm15dDRPcGc1NFRQSXZW?= =?utf-8?B?UkZqNlJqMFRYaU1ydGkvNXZmd2xhTXJTTzdRTmxaS293RFNyTUZYVjRVTXFj?= =?utf-8?B?R0Q5L1N6UnNEUGNoczdlWU9FQkVwSU53T0pMdXo1Wml1bjRtd2dOR3c1SlJv?= =?utf-8?B?Zkw0YytxcENHcnltY0R5eVJUWDhHbXliekhyRVhScEpTT1R5VnhTSXFHakFP?= =?utf-8?B?Y2E2RVowYVF3bm5YS1hEVGJRVm80MzlOZ3Z1TGhOMVloUGwzbTdsNkgwcitD?= =?utf-8?B?NERRMFJxcldBY0QvdjBzYVNBaXpESDRhN3lKT1NZYXJ4Qy8zNGdNSFdKSGNS?= =?utf-8?B?aVh5ZEs1V1pGdFpaRVRVWEcwVjAyS2NxSjd6QzNja09ocHhUaHJ2cmRlSTVK?= =?utf-8?B?WC9kN1pyVzkwQi80bWpQR2lwR2FqTEFCN0g3YXJ2em5EdFlBcEJsR2U1NUN2?= =?utf-8?B?bFlFa2trbWpWdlhwVFRhM3FSVjYwWm9qTHNEeFVSZmdQdm50eHJUdnRLa1Bh?= =?utf-8?Q?oNnnDpXUVW/bk1Z+Q+FuZZWS6vNyfZn9ATmsUp00l8=3D?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3b370367-450a-4914-b40f-08d99eadf1b1 X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Nov 2021 09:40:17.6836 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: z8drwTouoO+BEIU5oOHScK98qgrD+O7XxB8ueK3xyzni7CQRcQIO0ce12LpOKG8mkclDuTTXrEAUbhiKcGrnm6hPYFatw/3u1EivSJuK53M= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB7333 Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Thanks, Leif. Will fix all of them. Best regards, Nhi On 26/10/2021 19:53, Leif Lindholm wrote: > On Fri, Oct 22, 2021 at 13:17:54 +0700, Nhi Pham wrote: >> From: Vu Nguyen >> >> Provides functions to handle the PCIe configuration requests. The target >> Root Complex is selected based on the segment number parsed from the input >> address. >> >> Cc: Thang Nguyen >> Cc: Chuong Tran >> Cc: Phong Vo >> Cc: Leif Lindholm >> Cc: Michael D Kinney >> Cc: Ard Biesheuvel >> Cc: Nate DeSimone >> >> Signed-off-by: Nhi Pham >> --- >> Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 1 + >> Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf | 32 + >> Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c | 1573 ++++++++++++++++++++ >> 3 files changed, 1606 insertions(+) >> >> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> index 3b576df24073..1dee436f97b4 100644 >> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> @@ -226,6 +226,7 @@ [LibraryClasses.common.DXE_DRIVER] >> PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf >> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf >> PciHostBridgeLib|Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf >> + PciSegmentLib|Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf >> >> [LibraryClasses.common.UEFI_APPLICATION] >> UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf >> new file mode 100644 >> index 000000000000..ca564997e609 >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf >> @@ -0,0 +1,32 @@ >> +## @file >> +# >> +# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
>> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +## >> + >> +[Defines] >> + INF_VERSION = 0x0001001B >> + BASE_NAME = PciSegmentLibPci >> + FILE_GUID = 0AF5E76D-D31E-492B-AE69-A7B441FF62D9 >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = PciSegmentLib >> + >> +[Sources] >> + PciSegmentLib.c >> + >> +[Packages] >> + MdeModulePkg/MdeModulePkg.dec >> + MdePkg/MdePkg.dec >> + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> + >> +[LibraryClasses] >> + BaseLib >> + DebugLib >> + HobLib >> + IoLib >> + >> +[Guids] >> + gRootComplexInfoHobGuid >> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c >> new file mode 100644 >> index 000000000000..854f50f953be >> --- /dev/null >> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c >> @@ -0,0 +1,1573 @@ >> +/** @file >> + >> + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#include >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include >> + >> +#define GET_SEG_NUM(Address) (((Address) >> 32) & 0xFFFF) >> +#define GET_BUS_NUM(Address) (((Address) >> 20) & 0x7F) >> +#define GET_DEV_NUM(Address) (((Address) >> 15) & 0x1F) >> +#define GET_FUNC_NUM(Address) (((Address) >> 12) & 0x07) >> +#define GET_REG_NUM(Address) ((Address) & 0xFFF) >> + >> +/** >> + 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) >> + >> +/** >> + Convert the PCI Segment library address to PCI library address. >> + >> + @param A The address to convert. >> +**/ >> +#define PCI_SEGMENT_TO_PCI_ADDRESS(A) ((UINTN)(UINT32)A) >> + >> +/** >> + Get the MCFG Base from input Address. >> +**/ >> +UINTN >> +GetMmcfgBase ( >> + IN UINTN Address >> + ) >> +{ >> + AC01_ROOT_COMPLEX *RootComplexList; >> + UINTN Idx; >> + VOID *Hob; >> + >> + Hob = GetFirstGuidHob (&gRootComplexInfoHobGuid); >> + if (Hob == NULL) { >> + return 0; >> + } >> + >> + RootComplexList = (AC01_ROOT_COMPLEX *)GET_GUID_HOB_DATA (Hob); >> + >> + for (Idx = 0; Idx < AC01_PCIE_MAX_ROOT_COMPLEX; Idx++) { >> + if (RootComplexList[Idx].Logical == GET_SEG_NUM (Address)) { >> + return RootComplexList[Idx].MmcfgBase; >> + } >> + } >> + >> + return 0; >> +} >> + >> +/** >> + Register a PCI device so PCI configuration registers may be accessed after >> + SetVirtualAddressMap(). >> + >> + If any reserved bits in Address are set, then ASSERT(). >> + >> + @param Address The address that encodes the PCI Bus, Device, Function and >> + Register. >> + >> + @retval RETURN_SUCCESS The PCI device was registered for runtime access. >> + @retval RETURN_UNSUPPORTED An attempt was made to call this function >> + after ExitBootServices(). >> + @retval RETURN_UNSUPPORTED The resources required to access the PCI device >> + at runtime could not be mapped. >> + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to >> + complete the registration. >> + >> +**/ >> +RETURN_STATUS >> +EFIAPI >> +PciSegmentRegisterForRuntimeAccess ( >> + IN UINTN Address >> + ) >> +{ >> + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); >> + return RETURN_UNSUPPORTED; >> +} >> + >> +/** >> + 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 Address that encodes the PCI Segment, Bus, Device, Function, and Register. >> + >> + @return The 8-bit PCI configuration register specified by Address. >> + >> +**/ >> +UINT8 >> +EFIAPI >> +PciSegmentRead8 ( >> + IN UINT64 Address >> + ) >> +{ >> + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); >> + >> + UINTN CfgBase; >> + UINT8 Value; >> + >> + CfgBase = GetMmcfgBase (Address) + (Address & 0x0FFFFFFF); >> + >> + UINT64 AlignedAddr = CfgBase & ~0x3; >> + UINT32 Val32 = MmioRead32 (AlignedAddr); >> + switch (CfgBase & 0x3) { >> + case 3: >> + Value = Val32 >> 24; >> + break; >> + >> + case 2: >> + Value = Val32 >> 16; >> + break; >> + >> + case 1: >> + Value = Val32 >> 8; >> + break; >> + >> + case 0: >> + default: >> + Value = Val32; >> + break; >> + } >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG RD8: 0x%p value: 0x%02X (0x%08llX 0x%08X)\n", >> + CfgBase, >> + Value, >> + AlignedAddr, >> + Val32 >> + )); >> + >> + return Value; >> +} >> + >> +/** >> + Writes an 8-bit PCI configuration register. >> + >> + Writes the 8-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(). >> + >> + @param Address 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 >> + ) >> +{ >> + UINT32 Val32; >> + UINT64 AlignedAddr; >> + UINTN CfgBase; >> + >> + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); >> + >> + CfgBase = GetMmcfgBase (Address) + (Address & 0x0FFFFFFF); >> + >> + AlignedAddr = CfgBase & ~0x3; >> + Val32 = MmioRead32 (AlignedAddr); >> + >> + switch (CfgBase & 0x3) { >> + case 0: >> + Val32 &= ~0xFF; >> + Val32 |= Value; >> + break; >> + >> + case 1: >> + Val32 &= ~0xFF00; >> + Val32 |= (UINT32)Value << 8; >> + break; >> + >> + case 2: >> + Val32 &= ~0xFF0000; >> + Val32 |= (UINT32)Value << 16; >> + break; >> + >> + case 3: >> + default: >> + Val32 &= ~0xFF000000; >> + Val32 |= (UINT32)Value << 24; >> + break; >> + } >> + MmioWrite32 (AlignedAddr, Val32); >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG WR8: 0x%p value: 0x%04X (0x%08llX 0x%08X)\n", >> + CfgBase, >> + Value, >> + AlignedAddr, >> + MmioRead32 ((UINT64)AlignedAddr) >> + )); >> + >> + return 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 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 (PCI_SEGMENT_TO_PCI_ADDRESS (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 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 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 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 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 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 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 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 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 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 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); >> + >> + UINTN CfgBase; >> + UINT16 Value; >> + >> + CfgBase = GetMmcfgBase (Address) + (Address & 0x0FFFFFFE); >> + UINT64 AlignedAddr = CfgBase & ~0x3; >> + UINT32 RegC, Reg18; >> + UINT8 MfHt, Primary = 0, Sec = 0, Sub = 0; > MfHt is not a proper CamelCase name. > >> + UINT32 Val32; >> + >> + if ((GET_BUS_NUM (CfgBase) > 0) && (GET_DEV_NUM (CfgBase) > 0) && (GET_REG_NUM (CfgBase) == 0)) { >> + Value = MmioRead32 (CfgBase); >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG16 RD: B%X|D%X 0x%p value: 0x%08X\n", >> + GET_BUS_NUM (CfgBase), >> + GET_DEV_NUM (CfgBase), >> + CfgBase, >> + Value >> + )); >> + >> + if (Value != 0xffff) { >> + RegC = MmioRead32 (CfgBase + 0xC); >> + DEBUG ((DEBUG_INFO, " Peek PCIE MfHt RD: 0x%p value: 0x%08X\n", CfgBase + 0xc, RegC)); >> + MfHt = RegC >> 16; >> + DEBUG ((DEBUG_INFO, " Peek RD8 MfHt=0x%02X\n", MfHt)); >> + >> + if ((MfHt & 0x7F)!= 0) { /* Type 1 header */ >> + Reg18 = MmioRead32 (CfgBase + 0x18); >> + Primary = Reg18; Sec = Reg18 >> 8; Sub = Reg18 >> 16; >> + DEBUG (( >> + DEBUG_INFO, >> + " Bus Peek PCIE Sub:%01X Sec:%01X Primary:%01X RD: 0x%p value: 0x%08X\n", >> + Sub, >> + Sec, >> + Primary, >> + CfgBase + 0x18, >> + Reg18 >> + )); >> + } >> + >> + if ((MfHt == 0) || (Primary != 0)) { /* QS RPs Primary Bus is 0b */ >> + Value = 0xffff; >> + DEBUG (( >> + DEBUG_INFO, >> + " Skip RD16 B%X|D%X PCIE CFG RD: 0x%p return 0xffff\n", >> + GET_BUS_NUM (CfgBase), >> + GET_DEV_NUM (CfgBase), >> + CfgBase >> + )); >> + return 0; >> + } >> + } >> + } >> + >> + Val32 = MmioRead32 (AlignedAddr); >> + switch (CfgBase & 0x3) { >> + case 2: >> + Value = Val32 >> 16; >> + break; >> + >> + case 0: >> + default: >> + Value = Val32; >> + break; >> + } >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG RD16: 0x%p value: 0x%04X (0x%08llX 0x%08X)\n", >> + CfgBase, >> + Value, >> + AlignedAddr, >> + Val32 >> + )); >> + >> + if (GET_REG_NUM (Address) == 0xAE && Value == 0xFFFF) { >> + DEBUG ((DEBUG_ERROR, "PANIC due to PCIE link issue - Addr 0x%llx\n", Address)); >> + // Loop forever waiting for failsafe/watch dog time out >> + CpuDeadLoop (); >> + } >> + >> + return Value; >> +} >> + >> +/** >> + 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 Address that encodes the PCI Segment, Bus, Device, Function, and Register. >> + @param Value The value to write. >> + >> + @return The parameter of Value. >> + >> +**/ >> +UINT16 >> +EFIAPI >> +PciSegmentWrite16 ( >> + IN UINT64 Address, >> + IN UINT16 Value >> + ) >> +{ >> + UINT32 Val32; >> + UINT64 AlignedAddr; >> + UINTN CfgBase; >> + >> + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); >> + >> + CfgBase = GetMmcfgBase (Address) + (Address & 0x0FFFFFFE); >> + >> + AlignedAddr = CfgBase & ~0x3; >> + Val32 = MmioRead32 (AlignedAddr); >> + >> + switch (CfgBase & 0x3) { >> + case 2: >> + Val32 &= ~0xFFFF0000; >> + Val32 |= (UINT32)Value << 16; >> + break; >> + >> + case 0: >> + default: >> + Val32 &= ~0xFFFF; >> + Val32 |= Value; >> + break; >> + } >> + MmioWrite32 (AlignedAddr, Val32); >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG WR16: 0x%p value: 0x%04X (0x%08llX 0x%08X)\n", >> + CfgBase, >> + Value, >> + AlignedAddr, >> + MmioRead32 (AlignedAddr) >> + )); >> + >> + return 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 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 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 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 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 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 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 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 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 a bit field in a 16-bit PCI configuration, performs a bitwise OR, 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 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 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 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 register, performs a bitwise >> + AND, writes the result back to the bit field in the 16-bit register. >> + >> + 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 >> + 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 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 AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). >> + >> + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. >> + @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. >> + >> + @return The value written back 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 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 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 >> + ) >> +{ >> + UINT32 RegC, Reg18; >> + UINT32 Value; >> + UINT8 MfHt, Ht, Primary = 0, Sec = 0, Sub = 0; > And neither is Ht. > > / > Leif > >> + UINTN CfgBase; >> + >> + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); >> + >> + CfgBase = GetMmcfgBase (Address) + (Address & 0x0FFFFFFC); >> + >> + if ((GET_BUS_NUM (CfgBase) > 0) && (GET_DEV_NUM (CfgBase) > 0) && (GET_REG_NUM (CfgBase) == 0)) { >> + Value = MmioRead32 (CfgBase); >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG RD32: B%X|D%X 0x%p value: 0x%08X\n", >> + GET_BUS_NUM (CfgBase), >> + GET_DEV_NUM (CfgBase), >> + CfgBase, >> + Value >> + )); >> + >> + if (Value != 0xffffffff) { >> + RegC = MmioRead32 (CfgBase + 0xC); >> + DEBUG ((DEBUG_INFO, "Peek PCIE MfHt RD32: 0x%p value: 0x%08X\n", CfgBase + 0xc, RegC)); >> + MfHt = RegC >> 16; >> + DEBUG ((DEBUG_INFO, " Peek RD8 MfHt=0x%02X\n", MfHt)); >> + >> + Ht = MfHt & 0x7F; >> + if (Ht != 0) { /* Type 1 header */ >> + Reg18 = MmioRead32 (CfgBase + 0x18); >> + Primary = Reg18; Sec = Reg18 >> 8; Sub = Reg18 >> 16; >> + DEBUG (( >> + DEBUG_INFO, >> + " Bus Peek PCIE Sub:%01X Sec:%01X Primary:%01X RD32: 0x%p value: 0x%08X\n", >> + Sub, >> + Sec, >> + Primary, >> + CfgBase + 0x18, >> + Reg18 >> + )); >> + } >> + if ((Ht == 0) || (Primary != 0)) { /* Ampere Altra RPs Primary Bus is 0b */ >> + Value = 0xffffffff; >> + DEBUG (( >> + DEBUG_INFO, >> + " Skip RD32 B%X|D%X PCIE CFG RD32: 0x%p return 0xffffffff\n", >> + GET_BUS_NUM (CfgBase), >> + GET_DEV_NUM (CfgBase), >> + CfgBase >> + )); >> + } >> + } >> + } else { >> + Value = MmioRead32 (CfgBase); >> + } >> + >> + DEBUG ((DEBUG_INFO, "PCIE CFG RD32: 0x%p value: 0x%08X\n", CfgBase, Value)); >> + >> + return Value; >> +} >> + >> +/** >> + 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 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); >> + >> + UINTN CfgBase; >> + >> + CfgBase = GetMmcfgBase (Address) + (Address & 0x0FFFFFFC); >> + MmioWrite32 (CfgBase, Value); >> + DEBUG (( >> + DEBUG_INFO, >> + "PCIE CFG WR32: 0x%p value: 0x%08X (0x%08X)\n", >> + CfgBase, >> + Value, >> + MmioRead32 (CfgBase) >> + )); >> + >> + return 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 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 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 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 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 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 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 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 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 Address that encodes the PCI Segment, Bus, Device, Function, and Register. >> + @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 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 StartAddress 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 Starting address that encodes the PCI Segment, Bus, Device, >> + Function and Register. >> + @param Size Size in bytes of the transfer. >> + @param Buffer 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) <= SIZE_4KB); >> + >> + 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 StartAddress 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 Starting address that encodes the PCI Segment, Bus, Device, >> + Function and Register. >> + @param Size Size in bytes of the transfer. >> + @param Buffer 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) <= SIZE_4KB); >> + >> + if (Size == 0) { >> + return Size; >> + } >> + >> + 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; >> +} >> -- >> 2.17.1 >>