From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mx.groups.io with SMTP id smtpd.web10.864.1571036252347865944 for ; Sun, 13 Oct 2019 23:57:32 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.100, mailfrom: ray.ni@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Oct 2019 23:57:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,295,1566889200"; d="scan'208";a="220018902" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga004.fm.intel.com with ESMTP; 13 Oct 2019 23:57:31 -0700 Received: from fmsmsx154.amr.corp.intel.com (10.18.116.70) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.439.0; Sun, 13 Oct 2019 23:57:30 -0700 Received: from shsmsx108.ccr.corp.intel.com (10.239.4.97) by FMSMSX154.amr.corp.intel.com (10.18.116.70) with Microsoft SMTP Server (TLS) id 14.3.439.0; Sun, 13 Oct 2019 23:57:29 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.166]) by SHSMSX108.ccr.corp.intel.com ([169.254.8.225]) with mapi id 14.03.0439.000; Mon, 14 Oct 2019 14:57:27 +0800 From: "Ni, Ray" To: "Javeed, Ashraf" , "devel@edk2.groups.io" CC: "Wang, Jian J" , "Wu, Hao A" Subject: Re: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size Thread-Topic: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size Thread-Index: AQHVcho7l4BFAB45b0GVT+j70Hksa6dZkjEA Date: Mon, 14 Oct 2019 06:57:27 +0000 Message-ID: <734D49CCEBEEF84792F5B80ED585239D5C322169@SHSMSX104.ccr.corp.intel.com> References: <20190923142051.10832-1-ashraf.javeed@intel.com> In-Reply-To: <20190923142051.10832-1-ashraf.javeed@intel.com> Accept-Language: en-US, zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: ray.ni@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Javeed, The patch is too big. I recommend you separate the patch to several small patches. The goal of th= at is to make reviewers today (like me) and future easy to understand the c= ode changes. Some potential changes that can be separated out: 1. "DEBUG_ERROR/DEBUG_INFO" 2. The change related to the PciPlatform/PciOverride invocation can also be= separated out and it can be in a patch before any changes to implement the= features. 3. The change that splits the original StartPciDevicesOnBridge() to Registe= rPciDevicesOnBridge() and StartPciRootPortsOnBridge(). This change can be s= eparated out as a patch before any changes to implement the features. Some other comments: 1. CheckPciPlatformProtocolInstall(): better to rename to IsPciPlatformAvai= lable(). "Check" doesn't tell how to interpret the return result. "Is" does= . 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform (). 3. Why the type cast is needed in below code? If it is because PciPlatform2= protocol reuses the prototype of GetPciRom defined for PciPlatform protoco= l, I suggest you define GetPciRom for PciPlatform2. Type redefinition seems= a duplication. But below type-cast is more annoyed. Status =3D mPciPlatformProtocol2->GetPciRom ( (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatf= ormProtocol2, PciIoDevice->Handle, &PlatformOpRomBuffer, &PlatformOpRomSize ); 4. Please run ECC tool and fix all coding style issue 5. I don't quite understand what *primary* PCI root port is. So I don't qui= te understand what RecordPciRootPortBridges() does. Thanks, Ray > -----Original Message----- > From: Javeed, Ashraf > Sent: Monday, September 23, 2019 10:21 PM > To: devel@edk2.groups.io > Cc: Wang, Jian J ; Wu, Hao A ; > Ni, Ray > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI > features Max_Payload_Size, Max_Read_Req_Size >=20 > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2194 >=20 > The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration > of PCI features like Max_Payload_Size and Max_Read_Req_Size. >=20 > Max_Payload_Size:- The PCI Device Control register provides this feature > register field which controls the maximum data packet (TLP) size that a > PCI device should maintain as a requester. The PCI Bus driver is required > to maintain a highest common value supported by all the PCI devices in a > PCIe hierarchy, especially in case of isochronous applications. >=20 > Max_Read_Req_Size:- The PCI Device Control register provides this feature > register field which controls the maximum memory read request size that a > PCI device should maintain as a requester. The PCI Bus driver is required > to maintain a common value, same as Max_Payload_Size, in case of > isochronous applications only; or else, it should maintain the user > requested value uniformly in a PCIe hierarchy (PCI root port and its > downstream devices). >=20 > The PCI Base Specification 4 Revision 1 contains detailed information > about these features. The EDK2 PCI Bus driver needs to enable the > configuration of these features as per the PCI Base specification. >=20 > The EDK2 PCI Bus driver also needs to take the PCI device-specific > platform policy into the consideration while programming these features; > thus the code changes to support these, is explicitly dependent on the > new PCI Platform Protocol interface definition defined in the below > record:- > https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 >=20 > Signed-off-by: Ashraf Javeed > Cc: Jian J Wang > Cc: Hao A Wu > Cc: Ray Ni > --- > MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c | 23 ++---------= --- > MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 14 ++++++++- > MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 9 +++++- > MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c | 229 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++---------------------------------------------= --- > MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c | 139 > ++++++++++++++++++++-----------------------------------------------------= --------- > MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 34 > ++++++++++++-------- > MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 1601 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 201 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 565 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 193 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c | 15 +-------- > MdeModulePkg/MdeModulePkg.dec | 10 ++++++ > 12 files changed, 2797 insertions(+), 236 deletions(-) >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c > index b020ce50ce..2503b298f4 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c > @@ -8,7 +8,7 @@ > PCI Root Bridges. So it means platform needs install PCI Root Bridge I= O > protocol for each >=20 > PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol. >=20 >=20 >=20 > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
>=20 > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
>=20 > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 >=20 >=20 > **/ >=20 > @@ -34,8 +34,6 @@ BOOLEAN gFullEnum= eration =3D TRUE; > UINT64 gAllOne =3D 0= xFFFFFFFFFFFFFFFFULL; >=20 > UINT64 gAllZero =3D 0= ; >=20 >=20 >=20 > -EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; >=20 > -EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; >=20 > EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; >=20 >=20 >=20 >=20 >=20 > @@ -266,24 +264,7 @@ PciBusDriverBindingStart ( > // If PCI Platform protocol is available, get it now. >=20 > // If the platform implements this, it must be installed before BDS ph= ase >=20 > // >=20 > - gPciPlatformProtocol =3D NULL; >=20 > - gBS->LocateProtocol ( >=20 > - &gEfiPciPlatformProtocolGuid, >=20 > - NULL, >=20 > - (VOID **) &gPciPlatformProtocol >=20 > - ); >=20 > - >=20 > - // >=20 > - // If PCI Platform protocol doesn't exist, try to Pci Override Protoco= l. >=20 > - // >=20 > - if (gPciPlatformProtocol =3D=3D NULL) { >=20 > - gPciOverrideProtocol =3D NULL; >=20 > - gBS->LocateProtocol ( >=20 > - &gEfiPciOverrideProtocolGuid, >=20 > - NULL, >=20 > - (VOID **) &gPciOverrideProtocol >=20 > - ); >=20 > - } >=20 > + GetPciPlatformProtocol (); >=20 >=20 >=20 > if (mIoMmuProtocol =3D=3D NULL) { >=20 > gBS->LocateProtocol ( >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > index 504a1b1c12..7955bf8a26 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include >=20 > #include >=20 > #include >=20 > +#include >=20 > +#include >=20 >=20 >=20 > #include >=20 > #include >=20 > @@ -79,6 +81,7 @@ typedef enum { > #include "PciPowerManagement.h" >=20 > #include "PciHotPlugSupport.h" >=20 > #include "PciLib.h" >=20 > +#include "PciFeatureSupport.h" >=20 >=20 >=20 > #define VGABASE1 0x3B0 >=20 > #define VGALIMIT1 0x3BB >=20 > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE { >=20 >=20 > BOOLEAN IsPciExp; >=20 > // >=20 > - // For SR-IOV >=20 > + // For PCI Express Capability List Structure >=20 > // >=20 > UINT8 PciExpressCapabilityOffset; >=20 > + PCI_CAPABILITY_PCIEXP PciExpStruct; >=20 > + // >=20 > + // For SR-IOV >=20 > + // >=20 > UINT32 AriCapabilityOffset; >=20 > UINT32 SrIovCapabilityOffset; >=20 > UINT32 MrIovCapabilityOffset; >=20 > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE { > // This field is used to support this case. >=20 > // >=20 > UINT16 BridgeIoAlignment; >=20 > + // >=20 > + // Other PCI features setup flags >=20 > + // >=20 > + UINT8 SetupMPS; >=20 > + UINT8 SetupMRRS; >=20 > }; >=20 >=20 >=20 > #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > index 05c22025b8..13768d7ded 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > @@ -2,7 +2,7 @@ > # The PCI bus driver will probe all PCI devices and allocate MMIO and I= O > space for these devices. >=20 > # Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable > hot plug supporting. >=20 > # >=20 > -# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. >=20 > +# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved. >=20 > # >=20 > # SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > # >=20 > @@ -57,6 +57,10 @@ > PciCommand.h >=20 > PciIo.h >=20 > PciBus.h >=20 > + PciFeatureSupport.c >=20 > + PciFeatureSupport.h >=20 > + PciPlatformSupport.c >=20 > + PciPlatformSupport.h >=20 >=20 >=20 > [Packages] >=20 > MdePkg/MdePkg.dec >=20 > @@ -91,6 +95,8 @@ > gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES >=20 > gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES >=20 > gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES >=20 > + gEfiPciPlatformProtocol2Guid ## SOMETIMES_CONSUMES >=20 > + gEfiPciOverrideProtocol2Guid ## SOMETIMES_CONSUMES >=20 >=20 >=20 > [FeaturePcd] >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## > CONSUMES >=20 > @@ -104,6 +110,7 @@ > gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport ## CONSU= MES >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport ## > CONSUMES >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration ## > SOMETIMES_CONSUMES >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures = ## > CONSUMES >=20 >=20 >=20 > [UserExtensions.TianoCore."ExtraFiles"] >=20 > PciBusDxeExtra.uni >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c > index b7832c6970..0f76ab1cd5 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle ( >=20 >=20 > if (Temp->Handle =3D=3D Controller) { >=20 >=20 >=20 > + DestroyRootBridgePciFeaturesConfigCompletionList ( Temp); >=20 > + >=20 > RemoveEntryList (CurrentLink); >=20 >=20 >=20 > DestroyPciDeviceTree (Temp); >=20 > @@ -208,8 +210,6 @@ RegisterPciDevice ( > ) >=20 > { >=20 > EFI_STATUS Status; >=20 > - VOID *PlatformOpRomBuffer; >=20 > - UINTN PlatformOpRomSize; >=20 > EFI_PCI_IO_PROTOCOL *PciIo; >=20 > UINT8 Data8; >=20 > BOOLEAN HasEfiImage; >=20 > @@ -244,49 +244,13 @@ RegisterPciDevice ( > // >=20 > // Get the OpRom provided by platform >=20 > // >=20 > - if (gPciPlatformProtocol !=3D NULL) { >=20 > - Status =3D gPciPlatformProtocol->GetPciRom ( >=20 > - gPciPlatformProtocol, >=20 > - PciIoDevice->Handle, >=20 > - &PlatformOpRomBuffer, >=20 > - &PlatformOpRomSize >=20 > - ); >=20 > - if (!EFI_ERROR (Status)) { >=20 > - PciIoDevice->EmbeddedRom =3D FALSE; >=20 > - PciIoDevice->RomSize =3D (UINT32) PlatformOpRomSize; >=20 > - PciIoDevice->PciIo.RomSize =3D PlatformOpRomSize; >=20 > - PciIoDevice->PciIo.RomImage =3D PlatformOpRomBuffer; >=20 > - // >=20 > - // For OpROM read from gPciPlatformProtocol: >=20 > - // Add the Rom Image to internal database for later PCI light > enumeration >=20 > - // >=20 > - PciRomAddImageMapping ( >=20 > - NULL, >=20 > - PciIoDevice->PciRootBridgeIo->SegmentNumber, >=20 > - PciIoDevice->BusNumber, >=20 > - PciIoDevice->DeviceNumber, >=20 > - PciIoDevice->FunctionNumber, >=20 > - PciIoDevice->PciIo.RomImage, >=20 > - PciIoDevice->PciIo.RomSize >=20 > - ); >=20 > - } >=20 > - } else if (gPciOverrideProtocol !=3D NULL) { >=20 > - Status =3D gPciOverrideProtocol->GetPciRom ( >=20 > - gPciOverrideProtocol, >=20 > - PciIoDevice->Handle, >=20 > - &PlatformOpRomBuffer, >=20 > - &PlatformOpRomSize >=20 > - ); >=20 > - if (!EFI_ERROR (Status)) { >=20 > - PciIoDevice->EmbeddedRom =3D FALSE; >=20 > - PciIoDevice->RomSize =3D (UINT32) PlatformOpRomSize; >=20 > - PciIoDevice->PciIo.RomSize =3D PlatformOpRomSize; >=20 > - PciIoDevice->PciIo.RomImage =3D PlatformOpRomBuffer; >=20 > - // >=20 > - // For OpROM read from gPciOverrideProtocol: >=20 > - // Add the Rom Image to internal database for later PCI light > enumeration >=20 > - // >=20 > - PciRomAddImageMapping ( >=20 > + Status =3D GetPlatformPciOptionRom ( Controller, PciIoDevice); >=20 > + if (!EFI_ERROR (Status)) { >=20 > + // >=20 > + // For OpROM read from the PCI Platform Protocol: >=20 > + // Add the Rom Image to internal database for later PCI light > enumeration >=20 > + // >=20 > + PciRomAddImageMapping ( >=20 > NULL, >=20 > PciIoDevice->PciRootBridgeIo->SegmentNumber, >=20 > PciIoDevice->BusNumber, >=20 > @@ -294,8 +258,7 @@ RegisterPciDevice ( > PciIoDevice->FunctionNumber, >=20 > PciIoDevice->PciIo.RomImage, >=20 > PciIoDevice->PciIo.RomSize >=20 > - ); >=20 > - } >=20 > + ); >=20 > } >=20 > } >=20 >=20 >=20 > @@ -597,7 +560,7 @@ DeRegisterPciDevice ( > } >=20 >=20 >=20 > /** >=20 > - Start to manage the PCI device on the specified root bridge or PCI-PCI > Bridge. >=20 > + Start the PCI root Ports or PCI-PCI Bridge only. >=20 >=20 >=20 > @param Controller The root bridge handle. >=20 > @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > @@ -612,7 +575,82 @@ DeRegisterPciDevice ( >=20 >=20 > **/ >=20 > EFI_STATUS >=20 > -StartPciDevicesOnBridge ( >=20 > +StartPciRootPortsOnBridge ( >=20 > + IN EFI_HANDLE Controller, >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ) >=20 > + >=20 > +{ >=20 > + PCI_IO_DEVICE *PciIoDevice; >=20 > + EFI_STATUS Status; >=20 > + LIST_ENTRY *CurrentLink; >=20 > + UINT64 Supports; >=20 > + >=20 > + PciIoDevice =3D NULL; >=20 > + CurrentLink =3D RootBridge->ChildList.ForwardLink; >=20 > + >=20 > + while (CurrentLink !=3D NULL && CurrentLink !=3D &RootBridge->ChildLis= t) { >=20 > + >=20 > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); >=20 > + >=20 > + // >=20 > + // check if the device has been assigned with required resource >=20 > + // and registered >=20 > + // >=20 > + if (!PciIoDevice->Registered && !PciIoDevice->Allocated) { >=20 > + return EFI_NOT_READY; >=20 > + } >=20 > + >=20 > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { >=20 > + Status =3D StartPciRootPortsOnBridge ( >=20 > + Controller, >=20 > + PciIoDevice >=20 > + ); >=20 > + >=20 > + PciIoDevice->PciIo.Attributes ( >=20 > + &(PciIoDevice->PciIo), >=20 > + EfiPciIoAttributeOperationSupported, >=20 > + 0, >=20 > + &Supports >=20 > + ); >=20 > + Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; >=20 > + PciIoDevice->PciIo.Attributes ( >=20 > + &(PciIoDevice->PciIo), >=20 > + EfiPciIoAttributeOperationEnable, >=20 > + Supports, >=20 > + NULL >=20 > + ); >=20 > + >=20 > + } >=20 > + >=20 > + CurrentLink =3D CurrentLink->ForwardLink; >=20 > + } >=20 > + >=20 > + if (PciIoDevice =3D=3D NULL) { >=20 > + return EFI_NOT_FOUND; >=20 > + } else { >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Register to manage the PCI device on the specified root bridge or PCI-= PCI > Bridge. >=20 > + >=20 > + @param Controller The root bridge handle. >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + @param RemainingDevicePath A pointer to the > EFI_DEVICE_PATH_PROTOCOL. >=20 > + @param NumberOfChildren Children number. >=20 > + @param ChildHandleBuffer A pointer to the child handle buffer. >=20 > + >=20 > + @retval EFI_NOT_READY Device is not allocated. >=20 > + @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge. >=20 > + @retval EFI_NOT_FOUND Can not find the specific device. >=20 > + @retval EFI_SUCCESS Success to start Pci devices on bridge. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +RegisterPciDevicesOnBridge ( >=20 > IN EFI_HANDLE Controller, >=20 > IN PCI_IO_DEVICE *RootBridge, >=20 > IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, >=20 > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge ( > EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; >=20 > EFI_STATUS Status; >=20 > LIST_ENTRY *CurrentLink; >=20 > - UINT64 Supports; >=20 >=20 >=20 > PciIoDevice =3D NULL; >=20 > CurrentLink =3D RootBridge->ChildList.ForwardLink; >=20 > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge ( > // If it is a PPB >=20 > // >=20 > if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { >=20 > - Status =3D StartPciDevicesOnBridge ( >=20 > + Status =3D RegisterPciDevicesOnBridge ( >=20 > Controller, >=20 > PciIoDevice, >=20 > CurrentDevicePath, >=20 > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge ( > ChildHandleBuffer >=20 > ); >=20 >=20 >=20 > - PciIoDevice->PciIo.Attributes ( >=20 > - &(PciIoDevice->PciIo), >=20 > - EfiPciIoAttributeOperationSupported, >=20 > - 0, >=20 > - &Supports >=20 > - ); >=20 > - Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; >=20 > - PciIoDevice->PciIo.Attributes ( >=20 > - &(PciIoDevice->PciIo), >=20 > - EfiPciIoAttributeOperationEnable, >=20 > - Supports, >=20 > - NULL >=20 > - ); >=20 > - >=20 > return Status; >=20 > } else { >=20 >=20 >=20 > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge ( > } >=20 >=20 >=20 > if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { >=20 > - Status =3D StartPciDevicesOnBridge ( >=20 > + Status =3D RegisterPciDevicesOnBridge ( >=20 > Controller, >=20 > PciIoDevice, >=20 > RemainingDevicePath, >=20 > NumberOfChildren, >=20 > ChildHandleBuffer >=20 > ); >=20 > - >=20 > - PciIoDevice->PciIo.Attributes ( >=20 > - &(PciIoDevice->PciIo), >=20 > - EfiPciIoAttributeOperationSupported, >=20 > - 0, >=20 > - &Supports >=20 > - ); >=20 > - Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; >=20 > - PciIoDevice->PciIo.Attributes ( >=20 > - &(PciIoDevice->PciIo), >=20 > - EfiPciIoAttributeOperationEnable, >=20 > - Supports, >=20 > - NULL >=20 > - ); >=20 > - >=20 > } >=20 >=20 >=20 > CurrentLink =3D CurrentLink->ForwardLink; >=20 > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge ( > } >=20 > } >=20 >=20 >=20 > +/** >=20 > + Start to manage the PCI device on the specified root bridge or PCI-PCI > Bridge. >=20 > + >=20 > + @param Controller The root bridge handle. >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + @param RemainingDevicePath A pointer to the > EFI_DEVICE_PATH_PROTOCOL. >=20 > + @param NumberOfChildren Children number. >=20 > + @param ChildHandleBuffer A pointer to the child handle buffer. >=20 > + >=20 > + @retval EFI_NOT_READY Device is not allocated. >=20 > + @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge. >=20 > + @retval EFI_NOT_FOUND Can not find the specific device. >=20 > + @retval EFI_SUCCESS Success to start Pci devices on bridge. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +StartPciDevicesOnBridge ( >=20 > + IN EFI_HANDLE Controller, >=20 > + IN PCI_IO_DEVICE *RootBridge, >=20 > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, >=20 > + IN OUT UINT8 *NumberOfChildren, >=20 > + IN OUT EFI_HANDLE *ChildHandleBuffer >=20 > + ) >=20 > + >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + // >=20 > + // first register all the PCI devices >=20 > + // >=20 > + Status =3D RegisterPciDevicesOnBridge ( >=20 > + Controller, >=20 > + RootBridge, >=20 > + RemainingDevicePath, >=20 > + NumberOfChildren, >=20 > + ChildHandleBuffer >=20 > + ); >=20 > + >=20 > + if (EFI_ERROR (Status) =3D=3D EFI_NOT_FOUND) { >=20 > + return Status; >=20 > + } else { >=20 > + if ( CheckOtherPciFeaturesPcd ()) { >=20 > + // >=20 > + // the late configuration of PCI features >=20 > + // >=20 > + Status =3D EnumerateOtherPciFeatures ( >=20 > + RootBridge >=20 > + ); >=20 > + } >=20 > + // >=20 > + // finally start those PCI bridge port devices only >=20 > + // >=20 > + return StartPciRootPortsOnBridge ( >=20 > + Controller, >=20 > + RootBridge >=20 > + ); >=20 > + } >=20 > +} >=20 > + >=20 > /** >=20 > Start to manage all the PCI devices it found previously under >=20 > the entire host bridge. >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c > index 8db1ebf8ec..0a56668380 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation ( > Status =3D RejectPciDevice (PciResNode->PciDev); >=20 > if (Status =3D=3D EFI_SUCCESS) { >=20 > DEBUG (( >=20 > - EFI_D_ERROR, >=20 > + DEBUG_ERROR, >=20 > "PciBus: [%02x|%02x|%02x] was rejected due to resource > confliction.\n", >=20 > PciResNode->PciDev->BusNumber, PciResNode->PciDev- > >DeviceNumber, PciResNode->PciDev->FunctionNumber >=20 > )); >=20 > @@ -1746,7 +1746,7 @@ NotifyPhase ( >=20 >=20 > HostBridgeHandle =3D NULL; >=20 > RootBridgeHandle =3D NULL; >=20 > - if (gPciPlatformProtocol !=3D NULL) { >=20 > + if ( CheckPciPlatformProtocolInstall()) { >=20 > // >=20 > // Get Host Bridge Handle. >=20 > // >=20 > @@ -1770,42 +1770,11 @@ NotifyPhase ( > // >=20 > // Call PlatformPci::PlatformNotify() if the protocol is present. >=20 > // >=20 > - gPciPlatformProtocol->PlatformNotify ( >=20 > - gPciPlatformProtocol, >=20 > - HostBridgeHandle, >=20 > - Phase, >=20 > - ChipsetEntry >=20 > - ); >=20 > - } else if (gPciOverrideProtocol !=3D NULL){ >=20 > - // >=20 > - // Get Host Bridge Handle. >=20 > - // >=20 > - PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle); >=20 > - >=20 > - // >=20 > - // Get the rootbridge Io protocol to find the host bridge handle >=20 > - // >=20 > - Status =3D gBS->HandleProtocol ( >=20 > - RootBridgeHandle, >=20 > - &gEfiPciRootBridgeIoProtocolGuid, >=20 > - (VOID **) &PciRootBridgeIo >=20 > - ); >=20 > - >=20 > - if (EFI_ERROR (Status)) { >=20 > - return EFI_NOT_FOUND; >=20 > - } >=20 > - >=20 > - HostBridgeHandle =3D PciRootBridgeIo->ParentHandle; >=20 > - >=20 > - // >=20 > - // Call PlatformPci::PhaseNotify() if the protocol is present. >=20 > - // >=20 > - gPciOverrideProtocol->PlatformNotify ( >=20 > - gPciOverrideProtocol, >=20 > - HostBridgeHandle, >=20 > - Phase, >=20 > - ChipsetEntry >=20 > - ); >=20 > + PciPlatformNotifyPhase ( >=20 > + HostBridgeHandle, >=20 > + Phase, >=20 > + ChipsetEntry >=20 > + ); >=20 > } >=20 >=20 >=20 > Status =3D PciResAlloc->NotifyPhase ( >=20 > @@ -1813,27 +1782,15 @@ NotifyPhase ( > Phase >=20 > ); >=20 >=20 >=20 > - if (gPciPlatformProtocol !=3D NULL) { >=20 > + if ( CheckPciPlatformProtocolInstall()) { >=20 > // >=20 > // Call PlatformPci::PlatformNotify() if the protocol is present. >=20 > // >=20 > - gPciPlatformProtocol->PlatformNotify ( >=20 > - gPciPlatformProtocol, >=20 > - HostBridgeHandle, >=20 > - Phase, >=20 > - ChipsetExit >=20 > - ); >=20 > - >=20 > - } else if (gPciOverrideProtocol !=3D NULL) { >=20 > - // >=20 > - // Call PlatformPci::PhaseNotify() if the protocol is present. >=20 > - // >=20 > - gPciOverrideProtocol->PlatformNotify ( >=20 > - gPciOverrideProtocol, >=20 > - HostBridgeHandle, >=20 > - Phase, >=20 > - ChipsetExit >=20 > - ); >=20 > + PciPlatformNotifyPhase ( >=20 > + HostBridgeHandle, >=20 > + Phase, >=20 > + ChipsetExit >=20 > + ); >=20 > } >=20 >=20 >=20 > return Status; >=20 > @@ -1914,31 +1871,16 @@ PreprocessController ( > RootBridgePciAddress.Bus =3D Bus; >=20 > RootBridgePciAddress.ExtendedRegister =3D 0; >=20 >=20 >=20 > - if (gPciPlatformProtocol !=3D NULL) { >=20 > - // >=20 > - // Call PlatformPci::PrepController() if the protocol is present. >=20 > - // >=20 > - gPciPlatformProtocol->PlatformPrepController ( >=20 > - gPciPlatformProtocol, >=20 > - HostBridgeHandle, >=20 > - RootBridgeHandle, >=20 > - RootBridgePciAddress, >=20 > - Phase, >=20 > - ChipsetEntry >=20 > - ); >=20 > - } else if (gPciOverrideProtocol !=3D NULL) { >=20 > - // >=20 > - // Call PlatformPci::PrepController() if the protocol is present. >=20 > - // >=20 > - gPciOverrideProtocol->PlatformPrepController ( >=20 > - gPciOverrideProtocol, >=20 > - HostBridgeHandle, >=20 > - RootBridgeHandle, >=20 > - RootBridgePciAddress, >=20 > - Phase, >=20 > - ChipsetEntry >=20 > - ); >=20 > - } >=20 > + // >=20 > + // Call PlatformPci::PrepController() if the protocol is present. >=20 > + // >=20 > + PciPlatformPreprocessController ( >=20 > + HostBridgeHandle, >=20 > + RootBridgeHandle, >=20 > + RootBridgePciAddress, >=20 > + Phase, >=20 > + ChipsetEntry >=20 > + ); >=20 >=20 >=20 > Status =3D PciResAlloc->PreprocessController ( >=20 > PciResAlloc, >=20 > @@ -1947,31 +1889,16 @@ PreprocessController ( > Phase >=20 > ); >=20 >=20 >=20 > - if (gPciPlatformProtocol !=3D NULL) { >=20 > - // >=20 > - // Call PlatformPci::PrepController() if the protocol is present. >=20 > - // >=20 > - gPciPlatformProtocol->PlatformPrepController ( >=20 > - gPciPlatformProtocol, >=20 > - HostBridgeHandle, >=20 > - RootBridgeHandle, >=20 > - RootBridgePciAddress, >=20 > - Phase, >=20 > - ChipsetExit >=20 > - ); >=20 > - } else if (gPciOverrideProtocol !=3D NULL) { >=20 > - // >=20 > - // Call PlatformPci::PrepController() if the protocol is present. >=20 > - // >=20 > - gPciOverrideProtocol->PlatformPrepController ( >=20 > - gPciOverrideProtocol, >=20 > - HostBridgeHandle, >=20 > - RootBridgeHandle, >=20 > - RootBridgePciAddress, >=20 > - Phase, >=20 > - ChipsetExit >=20 > - ); >=20 > - } >=20 > + // >=20 > + // Call PlatformPci::PrepController() if the protocol is present. >=20 > + // >=20 > + PciPlatformPreprocessController ( >=20 > + HostBridgeHandle, >=20 > + RootBridgeHandle, >=20 > + RootBridgePciAddress, >=20 > + Phase, >=20 > + ChipsetExit >=20 > + ); >=20 >=20 >=20 > return EFI_SUCCESS; >=20 > } >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c > index c7eafff593..2343702154 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c > @@ -230,7 +230,7 @@ PciSearchDevice ( > PciIoDevice =3D NULL; >=20 >=20 >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > "PciBus: Discovered %s @ [%02x|%02x|%02x]\n", >=20 > IS_PCI_BRIDGE (Pci) ? L"PPB" : >=20 > IS_CARDBUS_BRIDGE (Pci) ? L"P2C" : >=20 > @@ -397,7 +397,7 @@ DumpPpbPaddingResource ( >=20 >=20 > if ((Type !=3D PciBarTypeUnknown) && ((ResourceType =3D=3D > PciBarTypeUnknown) || (ResourceType =3D=3D Type))) { >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > " Padding: Type =3D %s; Alignment =3D 0x%lx;\tLength =3D 0x%lx= \n", >=20 > mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen >=20 > )); >=20 > @@ -424,7 +424,7 @@ DumpPciBars ( > } >=20 >=20 >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > " BAR[%d]: Type =3D %s; Alignment =3D 0x%lx;\tLength =3D 0x%lx;\= tOffset =3D > 0x%02x\n", >=20 > Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, > PciBarTypeMaxType)], >=20 > PciIoDevice->PciBar[Index].Alignment, PciIoDevice- > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset >=20 > @@ -437,13 +437,13 @@ DumpPciBars ( > } >=20 >=20 >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > " VFBAR[%d]: Type =3D %s; Alignment =3D 0x%lx;\tLength =3D 0x%lx;\= tOffset =3D > 0x%02x\n", >=20 > Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, > PciBarTypeMaxType)], >=20 > PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice- > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset >=20 > )); >=20 > } >=20 > - DEBUG ((EFI_D_INFO, "\n")); >=20 > + DEBUG ((DEBUG_INFO, "\n")); >=20 > } >=20 >=20 >=20 > /** >=20 > @@ -1903,7 +1903,7 @@ PciParseBar ( > // Fix the length to support some special 64 bit BAR >=20 > // >=20 > if (Value =3D=3D 0) { >=20 > - DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM6= 4 > BAR returns 0, change to 0xFFFFFFFF.\n")); >=20 > + DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM6= 4 > BAR returns 0, change to 0xFFFFFFFF.\n")); >=20 > Value =3D (UINT32) -1; >=20 > } else { >=20 > Value |=3D ((UINT32)(-1) << HighBitSet32 (Value)); >=20 > @@ -2153,7 +2153,17 @@ CreatePciIoDevice ( > NULL >=20 > ); >=20 > if (!EFI_ERROR (Status)) { >=20 > - PciIoDevice->IsPciExp =3D TRUE; >=20 > + PciIoDevice->IsPciExp =3D TRUE; >=20 > + // >=20 > + // read the PCI device's entire PCI Express Capability structure >=20 > + // >=20 > + PciIo->Pci.Read ( >=20 > + PciIo, >=20 > + EfiPciIoWidthUint8, >=20 > + PciIoDevice->PciExpressCapabilityOffset, >=20 > + sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8), >=20 > + &PciIoDevice->PciExpStruct >=20 > + ); >=20 > } >=20 >=20 >=20 > if (PcdGetBool (PcdAriSupport)) { >=20 > @@ -2206,7 +2216,7 @@ CreatePciIoDevice ( > &Data32 >=20 > ); >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n", >=20 > Bridge->BusNumber, >=20 > Bridge->DeviceNumber, >=20 > @@ -2215,7 +2225,7 @@ CreatePciIoDevice ( > } >=20 > } >=20 >=20 >=20 > - DEBUG ((EFI_D_INFO, " ARI: CapOffset =3D 0x%x\n", PciIoDevice- > >AriCapabilityOffset)); >=20 > + DEBUG ((DEBUG_INFO, " ARI: CapOffset =3D 0x%x\n", PciIoDevice- > >AriCapabilityOffset)); >=20 > } >=20 > } >=20 >=20 >=20 > @@ -2325,12 +2335,12 @@ CreatePciIoDevice ( > PciIoDevice->ReservedBusNum =3D (UINT16)(EFI_PCI_BUS_OF_RID (LastV= F) > - Bus + 1); >=20 >=20 >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > " SR-IOV: SupportedPageSize =3D 0x%x; SystemPageSize =3D 0x%x; > FirstVFOffset =3D 0x%x;\n", >=20 > SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOff= set >=20 > )); >=20 > DEBUG (( >=20 > - EFI_D_INFO, >=20 > + DEBUG_INFO, >=20 > " InitialVFs =3D 0x%x; ReservedBusNum =3D 0x%x; CapOffse= t =3D 0x%x\n", >=20 > PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevic= e- > >SrIovCapabilityOffset >=20 > )); >=20 > @@ -2345,7 +2355,7 @@ CreatePciIoDevice ( > NULL >=20 > ); >=20 > if (!EFI_ERROR (Status)) { >=20 > - DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset =3D 0x%x\n", PciIoDevice- > >MrIovCapabilityOffset)); >=20 > + DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset =3D 0x%x\n", PciIoDevice- > >MrIovCapabilityOffset)); >=20 > } >=20 > } >=20 >=20 >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > new file mode 100644 > index 0000000000..0819da6536 > --- /dev/null > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > @@ -0,0 +1,1601 @@ > +/** @file >=20 > + PCI standard feature support functions implementation for PCI Bus > module.. >=20 > + >=20 > +Copyright (c) 2019, Intel Corporation. All rights reserved.
>=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include "PciFeatureSupport.h" >=20 > + >=20 > +/** >=20 > + A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all the > primary physical >=20 > + PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance = while >=20 > + enumerating to configure the PCI features >=20 > +**/ >=20 > +PRIMARY_ROOT_PORT_NODE *mPrimaryRootPortList; >=20 > + >=20 > +/** >=20 > + A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE buffer > all the PCI >=20 > + Feature configuration Table nodes to pair against each of the > PRIMARY_ROOT_PORT_NODE >=20 > + buffer nodes. Each node of these is used to align all the PCI devices > originating >=20 > + from the PCI Root Port devices of a PCI Root Bridge instance >=20 > +**/ >=20 > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE > *mPciFeaturesConfigurationTableInstances; >=20 > + >=20 > +/** >=20 > + A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, > which stores all >=20 > + the PCI Root Bridge instances that are enumerated for the other PCI > features, >=20 > + like MaxPayloadSize & MaxReadReqSize; during the the Start() interface= of > the >=20 > + driver binding protocol. The records pointed by this pointer would be > destroyed >=20 > + when the DXE core invokes the Stop() interface. >=20 > +**/ >=20 > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST > *mPciFeaturesConfigurationCompletionList =3D NULL; >=20 > + >=20 > +/** >=20 > + Main routine to indicate platform selection of any of the other PCI fe= atures >=20 > + to be configured by this driver >=20 > + >=20 > + @retval TRUE platform has selected the other PCI features to be > configured >=20 > + FALSE platform has not selected any of the other PCI feature= s >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckOtherPciFeaturesPcd ( >=20 > + ) >=20 > +{ >=20 > + return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Main routine to indicate whether the platform has selected the > Max_Payload_Size >=20 > + PCI feature to be configured by this driver >=20 > + >=20 > + @retval TRUE platform has selected the Max_Payload_Size to be > configured >=20 > + FALSE platform has not selected this feature >=20 > +**/ >=20 > +BOOLEAN >=20 > +SetupMaxPayloadSize ( >=20 > + ) >=20 > +{ >=20 > + return (PcdGet32 ( PcdOtherPciFeatures) & > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Main routine to indicate whether the platform has selected the > Max_Read_Req_Size >=20 > + PCI feature to be configured by this driver >=20 > + >=20 > + @retval TRUE platform has selected the Max_Read_Req_Size to be > configured >=20 > + FALSE platform has not selected this feature >=20 > +**/ >=20 > +BOOLEAN >=20 > +SetupMaxReadReqSize ( >=20 > + ) >=20 > +{ >=20 > + return (PcdGet32 ( PcdOtherPciFeatures) & > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Helper routine which determines whether the given PCI Root Bridge > instance >=20 > + record already exist. This routine shall help avoid duplicate record c= reation >=20 > + in case of re-enumeration of PCI configuation features. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE for the= Root > Bridge >=20 > + @param PciFeatureConfigRecord A pointer to a pointer for type >=20 > + PCI_FEATURE_CONFIGURATION_COMPLETION_L= IST >=20 > + record, Use to return the specific rec= ord. >=20 > + >=20 > + @retval TRUE Record already exist >=20 > + FALSE Record does not exist for the given PC= I Root Bridge >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckPciFeatureConfigurationRecordExist ( >=20 > + IN PCI_IO_DEVICE *RootBridge, >=20 > + OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST > **PciFeatureConfigRecord >=20 > + ) >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp; >=20 > + >=20 > + if ( mPciFeaturesConfigurationCompletionList) { >=20 > + Link =3D &mPciFeaturesConfigurationCompletionList->RootBridgeLink; >=20 > + >=20 > + do { >=20 > + Temp =3D > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link); >=20 > + if ( Temp->RootBridgeHandle =3D=3D RootBridge->Handle) { >=20 > + *PciFeatureConfigRecord =3D Temp; >=20 > + return TRUE; >=20 > + } >=20 > + Link =3D Link->ForwardLink; >=20 > + } while (Link !=3D &mPciFeaturesConfigurationCompletionList- > >RootBridgeLink); >=20 > + } >=20 > + // >=20 > + // not found on the PCI feature configuration completion list >=20 > + // >=20 > + *PciFeatureConfigRecord =3D NULL; >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + This routine is primarily to avoid multiple configuration of PCI featu= res >=20 > + to the same PCI Root Bridge due to EDK2 core's ConnectController calls= on >=20 > + all the EFI handles. This routine also provide re-enumeration of the P= CI >=20 > + features on the same PCI Root Bridge based on the policy of > ReEnumeratePciFeatureConfiguration >=20 > + of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE for the= Root > Bridge >=20 > + >=20 > + @retval TRUE PCI Feature configuration required for= the PCI >=20 > + Root Bridge >=20 > + FALSE PCI Feature configuration is not requi= red to be >=20 > + re-enumerated for the PCI Root Bridge >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckPciFeaturesConfigurationRequired ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ) >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp; >=20 > + >=20 > + if ( mPciFeaturesConfigurationCompletionList) { >=20 > + Link =3D &mPciFeaturesConfigurationCompletionList->RootBridgeLink; >=20 > + >=20 > + do { >=20 > + Temp =3D > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link); >=20 > + if ( Temp->RootBridgeHandle =3D=3D RootBridge->Handle) { >=20 > + return Temp->ReEnumeratePciFeatureConfiguration; >=20 > + } >=20 > + Link =3D Link->ForwardLink; >=20 > + } while (Link !=3D &mPciFeaturesConfigurationCompletionList- > >RootBridgeLink); >=20 > + } >=20 > + // >=20 > + // not found on the PCI feature configuration completion list, return = as > required >=20 > + // >=20 > + return TRUE; >=20 > +} >=20 > + >=20 > +/** >=20 > + This routine finds the duplicate record if exist and assigns the re- > enumeration >=20 > + requirement flag, as passed as input. It creates new record for the PC= I > Root >=20 > + Bridge and appends the list after updating its re-enumeration flag. >=20 > + >=20 > + @param RootBridge A pointer to PCI_IO_DEVICE of the Root B= ridge >=20 > + @param ReEnumerationRequired A BOOLEAN for recording the re- > enumeration requirement >=20 > + >=20 > + @retval EFI_SUCCESS new record inserted into the list or upd= ated the >=20 > + existing record >=20 > + EFI_INVALID_PARAMETER Unexpected error as > CheckPciFeatureConfigurationRecordExist >=20 > + reports as record exist but does not ret= urn its pointer >=20 > + EFI_OUT_OF_RESOURCES Not able to create PCI features configur= atin > complete >=20 > + record for the RootBridge >=20 > +**/ >=20 > +EFI_STATUS >=20 > +AddRootBridgeInPciFeaturesConfigCompletionList ( >=20 > + IN PCI_IO_DEVICE *RootBridge, >=20 > + IN BOOLEAN ReEnumerationRequired >=20 > + ) >=20 > +{ >=20 > + PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp; >=20 > + >=20 > + if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp)) { >=20 > + // >=20 > + // this PCI Root Bridge record already exist; it may have been re- > enumerated >=20 > + // hence just update its enumeration required flag again to exit >=20 > + // >=20 > + if ( Temp) { >=20 > + Temp->ReEnumeratePciFeatureConfiguration =3D > ReEnumerationRequired; >=20 > + return EFI_SUCCESS; >=20 > + } else { >=20 > + // >=20 > + // PCI feature configuration complete record reported as exist and= no >=20 > + // record pointer returned >=20 > + // >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + } else { >=20 > + >=20 > + Temp =3D AllocateZeroPool ( sizeof > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST)); >=20 > + if ( !Temp) { >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + Temp->Signature =3D > PCI_FEATURE_CONFIGURATION_SIGNATURE; >=20 > + Temp->RootBridgeHandle =3D RootBridge->Handle; >=20 > + Temp->ReEnumeratePciFeatureConfiguration =3D ReEnumerationRequired; >=20 > + if ( mPciFeaturesConfigurationCompletionList) { >=20 > + InsertTailList ( &mPciFeaturesConfigurationCompletionList- > >RootBridgeLink, >=20 > + &Temp->RootBridgeLink); >=20 > + } else { >=20 > + // >=20 > + // init the very first node of the Root Bridge >=20 > + // >=20 > + mPciFeaturesConfigurationCompletionList =3D Temp; >=20 > + InitializeListHead ( &mPciFeaturesConfigurationCompletionList- > >RootBridgeLink); >=20 > + } >=20 > + } >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Free up memory alloted for the primary physical PCI Root ports of the = PCI > Root >=20 > + Bridge instance. Free up all the nodes of type > PRIMARY_ROOT_PORT_NODE. >=20 > +**/ >=20 > +VOID >=20 > +DestroyPrimaryRootPortNodes () >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PRIMARY_ROOT_PORT_NODE *Temp; >=20 > + >=20 > + if ( mPrimaryRootPortList) { >=20 > + Link =3D &mPrimaryRootPortList->NeighborRootPort; >=20 > + >=20 > + if ( IsListEmpty ( Link)) { >=20 > + FreePool ( mPrimaryRootPortList); >=20 > + } else { >=20 > + do { >=20 > + if ( Link->ForwardLink !=3D &mPrimaryRootPortList->NeighborRootP= ort) { >=20 > + Link =3D Link->ForwardLink; >=20 > + } >=20 > + Temp =3D PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link); >=20 > + Link =3D RemoveEntryList ( Link); >=20 > + FreePool ( Temp); >=20 > + } while ( !IsListEmpty ( Link)); >=20 > + FreePool ( mPrimaryRootPortList); >=20 > + } >=20 > + mPrimaryRootPortList =3D NULL; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Free up the memory allocated for temporarily maintaining the PCI featu= re >=20 > + configuration table for all the nodes of the primary PCI Root port. >=20 > + Free up memory alloted for > OTHER_PCI_FEATURES_CONFIGURATION_TABLE. >=20 > +**/ >=20 > +VOID >=20 > +ErasePciFeaturesConfigurationTable ( >=20 > + ) >=20 > +{ >=20 > + if ( mPciFeaturesConfigurationTableInstances) { >=20 > + FreePool ( mPciFeaturesConfigurationTableInstances); >=20 > + } >=20 > + mPciFeaturesConfigurationTableInstances =3D NULL; >=20 > +} >=20 > + >=20 > +/** >=20 > + Routine meant for initializing any global variables used. It primarily= cleans >=20 > + up the internal data structure memory allocated for the previous PCI R= oot > Bridge >=20 > + instance. This should be the first routine to call for any virtual PCI= Root >=20 > + Bridge instance. >=20 > +**/ >=20 > +VOID >=20 > +SetupPciFeaturesConfigurationDefaults () >=20 > +{ >=20 > + // >=20 > + // delete the primary root port list >=20 > + // >=20 > + if (mPrimaryRootPortList) { >=20 > + DestroyPrimaryRootPortNodes (); >=20 > + } >=20 > + >=20 > + if ( mPciFeaturesConfigurationTableInstances) { >=20 > + ErasePciFeaturesConfigurationTable (); >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Helper routine to determine whether the PCI device is a physical root = port >=20 > + recorded in the list. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE= . >=20 > + >=20 > + @retval TRUE The PCI device instance is a p= rimary >=20 > + primary physical PCI Root Port >=20 > + FALSE Not a primary physical PCI Roo= t port >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckRootBridgePrimaryPort ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PRIMARY_ROOT_PORT_NODE *Temp; >=20 > + >=20 > + if ( !mPrimaryRootPortList) { >=20 > + return FALSE; >=20 > + } >=20 > + Link =3D &mPrimaryRootPortList->NeighborRootPort; >=20 > + do { >=20 > + Temp =3D PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link); >=20 > + if ( Temp->RootBridgeHandle =3D=3D PciDevice->Parent->Handle >=20 > + && Temp->RootPortHandle =3D=3D PciDevice->Handle) { >=20 > + // >=20 > + // the given PCI device is the primary root port of the Root Bridg= e > controller >=20 > + // >=20 > + return TRUE; >=20 > + } >=20 > + Link =3D Link->ForwardLink; >=20 > + } while ( Link !=3D &mPrimaryRootPortList->NeighborRootPort); >=20 > + // >=20 > + // the given PCI device is not the primary root port of the Bridge con= troller >=20 > + // >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Main routine to determine the child PCI devices of a physical PCI brid= ge > device >=20 > + and group them under a common internal PCI features Configuration tabl= e. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE= . >=20 > + @param PciFeaturesConfigTable A pointer to a pointer to the >=20 > + OTHER_PCI_FEATURES_CONFIGURATI= ON_TABLE. >=20 > + Returns NULL in case of RCiEP = or the PCI >=20 > + device does match with any of = the physical >=20 > + Root ports, or it does not bel= ong to any >=20 > + Root port's PCU bus range (not= a child) >=20 > + >=20 > + @retval EFI_SUCCESS able to determine the PCI feat= ure >=20 > + configuration table. For RCiEP= since >=20 > + since it is not prepared. >=20 > + EFI_NOT_FOUND the PCI feature configuration = table does >=20 > + not exist as the PCI physical = Bridge device >=20 > + is not found for this device's= parent >=20 > + Root Bridge instance >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPciFeaturesConfigurationTable ( >=20 > + IN PCI_IO_DEVICE *PciDevice, >=20 > + OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE > **PciFeaturesConfigTable >=20 > + ) >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PRIMARY_ROOT_PORT_NODE *Temp; >=20 > + >=20 > + if ( !mPrimaryRootPortList) { >=20 > + *PciFeaturesConfigTable =3D NULL; >=20 > + return EFI_NOT_FOUND; >=20 > + } >=20 > + >=20 > + // >=20 > + // The PCI features configuration table is not built for RCiEP, return= NULL >=20 > + // >=20 > + if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType =3D=3D \ >=20 > + PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) > { >=20 > + *PciFeaturesConfigTable =3D NULL; >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + Link =3D &mPrimaryRootPortList->NeighborRootPort; >=20 > + do { >=20 > + Temp =3D PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link); >=20 > + if ( Temp->RootBridgeHandle =3D=3D PciDevice->Parent->Handle >=20 > + && Temp->RootPortHandle =3D=3D PciDevice->Handle) { >=20 > + // >=20 > + // the given PCI device is the primary root port of the Root Bridg= e > controller >=20 > + // >=20 > + *PciFeaturesConfigTable =3D Temp->OtherPciFeaturesConfigurationTab= le; >=20 > + return EFI_SUCCESS; >=20 > + } else { >=20 > + // >=20 > + // check this PCI device belongs to the primary root port of the r= oot > bridge >=20 > + // >=20 > + if ( PciDevice->BusNumber >=3D Temp->SecondaryBusStart >=20 > + && PciDevice->BusNumber <=3D Temp->SecondaryBusEnd) { >=20 > + *PciFeaturesConfigTable =3D Temp->OtherPciFeaturesConfigurationT= able; >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > + } >=20 > + Link =3D Link->ForwardLink; >=20 > + } while ( Link !=3D &mPrimaryRootPortList->NeighborRootPort); >=20 > + // >=20 > + // the PCI device must be RCiEP, does not belong to any primary root p= ort >=20 > + // >=20 > + *PciFeaturesConfigTable =3D NULL; >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + The helper routine to retrieve the PCI bus numbers from the PCI Bridge= or > Root >=20 > + port device. Assumes the input PCI device has the PCI Type 1 configura= tion > header. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE= . >=20 > + @param PrimaryBusNumber A pointer to return the PCI Pr= iamry >=20 > + Bus number. >=20 > + @param SecondaryBusNumber A pointer to return the PCI > Secondary >=20 > + Bus number. >=20 > + @param SubordinateBusNumber A pointer to return the PCI > Subordinate >=20 > + Bus number. >=20 > + >=20 > + @retval EFI_SUCCESS The data was read from the PCI device. >=20 > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not >=20 > + valid for the PCI configuration header o= f the PCI device. >=20 > + @retval EFI_INVALID_PARAMETER input parameters provided to the read > operation were invalid. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPciRootPortBusAssigned ( >=20 > + IN PCI_IO_DEVICE *PciDevice, >=20 > + OUT UINT8 *PrimaryBusNumber, >=20 > + OUT UINT8 *SecondaryBusNumber, >=20 > + OUT UINT8 *SubordinateBusNumber >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + UINT32 RootPortBusAssigned; >=20 > + >=20 > + Status =3D PciDevice->PciIo.Pci.Read ( >=20 > + &PciDevice->PciIo, >=20 > + EfiPciIoWidthUint32, >=20 > + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET= , >=20 > + 1, >=20 > + &RootPortBusAssigned >=20 > + ); >=20 > + if ( !EFI_ERROR(Status)) { >=20 > + if ( PrimaryBusNumber) { >=20 > + *PrimaryBusNumber =3D (UINT8) (0xFF & RootPortBusAssigned); >=20 > + } >=20 > + if ( SecondaryBusNumber) { >=20 > + *SecondaryBusNumber =3D (UINT8)(0xFF & (RootPortBusAssigned >> 8))= ; >=20 > + } >=20 > + if ( SubordinateBusNumber) { >=20 > + *SubordinateBusNumber =3D (UINT8)(0xFF & (RootPortBusAssigned >> > 16)); >=20 > + } >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + This routine determines the existance of the child PCI device for the = given >=20 > + PCI Root / Bridge Port device. Always assumes the input PCI device is = the > bridge >=20 > + or PCI-PCI Bridge device. This routine should not be used with PCI > endpoint device. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE= . >=20 > + >=20 > + @retval TRUE child device exist >=20 > + FALSE no child device >=20 > +**/ >=20 > +BOOLEAN >=20 > +IsPciRootPortEmpty ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + UINT8 SecBus, >=20 > + SubBus; >=20 > + EFI_STATUS Status; >=20 > + LIST_ENTRY *Link; >=20 > + PCI_IO_DEVICE *NextPciDevice; >=20 > + >=20 > + // >=20 > + // check secondary & suboridinate bus numbers for its endpoint device >=20 > + // existance >=20 > + // >=20 > + Status =3D GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus, > &SubBus); >=20 > + if ( !EFI_ERROR( Status)) { >=20 > + Link =3D PciDevice->ChildList.ForwardLink; >=20 > + if ( IsListEmpty ( Link)) { >=20 > + // >=20 > + // return as PCI Root port empty >=20 > + // >=20 > + DEBUG (( DEBUG_INFO, "RP empty,")); >=20 > + return TRUE; >=20 > + } >=20 > + do { >=20 > + NextPciDevice =3D PCI_IO_DEVICE_FROM_LINK ( Link); >=20 > + DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber)); >=20 > + >=20 > + if ( NextPciDevice->BusNumber >=3D SecBus >=20 > + && NextPciDevice->BusNumber <=3D SubBus) { >=20 > + >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + Link =3D Link->ForwardLink; >=20 > + } while ( Link !=3D &PciDevice->ChildList); >=20 > + } else { >=20 > + SecBus =3D SubBus =3D 0; >=20 > + DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range > assigned!!!")); >=20 > + } >=20 > + >=20 > + // >=20 > + // return as PCI Root port empty >=20 > + // >=20 > + return TRUE; >=20 > +} >=20 > + >=20 > +/** >=20 > + The main routine which process the PCI feature Max_Payload_Size as per > the >=20 > + device-specific platform policy, as well as in complaince with the PCI= Base >=20 > + specification Revision 4, that aligns the value for the entire PCI hei= rarchy >=20 > + starting from its physical PCI Root port / Bridge device. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE. >=20 > + @param PciConfigPhase for the PCI feature configuratio= n phases: >=20 > + PciFeatureGetDevicePolicy & PciF= eatureSetupPhase >=20 > + @param PciFeaturesConfigurationTable pointer to > OTHER_PCI_FEATURES_CONFIGURATION_TABLE >=20 > + >=20 > + @retval EFI_SUCCESS processing of PCI feature > Max_Payload_Size >=20 > + is successful. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +ProcessMaxPayloadSize ( >=20 > + IN PCI_IO_DEVICE *PciDevice, >=20 > + IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase, >=20 > + IN OTHER_PCI_FEATURES_CONFIGURATION_TABLE > *PciFeaturesConfigurationTable >=20 > + ) >=20 > +{ >=20 > + PCI_REG_PCIE_DEVICE_CAPABILITY PciDeviceCap; >=20 > + UINT8 MpsValue; >=20 > + >=20 > + >=20 > + PciDeviceCap.Uint32 =3D PciDevice->PciExpStruct.DeviceCapability.Uint3= 2; >=20 > + >=20 > + if ( PciConfigPhase =3D=3D PciFeatureGetDevicePolicy) { >=20 > + if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS)) >=20 > + { >=20 > + MpsValue =3D (UINT8)PciDeviceCap.Bits.MaxPayloadSize; >=20 > + // >=20 > + // no change to PCI Root ports without any endpoint device >=20 > + // >=20 > + if ( IS_PCI_BRIDGE ( &PciDevice->Pci) && > PciDeviceCap.Bits.MaxPayloadSize) { >=20 > + if ( IsPciRootPortEmpty ( PciDevice)) { >=20 > + MpsValue =3D PCIE_MAX_PAYLOAD_SIZE_128B; >=20 > + DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)")); >=20 > + } >=20 > + } >=20 > + } else { >=20 > + MpsValue =3D TranslateMpsSetupValueToPci ( PciDevice->SetupMPS); >=20 > + } >=20 > + // >=20 > + // discard device policy override request if greater than PCI device > capability >=20 > + // >=20 > + PciDevice->SetupMPS =3D MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize= , > MpsValue); >=20 > + } >=20 > + >=20 > + // >=20 > + // align the MPS of the tree to the HCF with this device >=20 > + // >=20 > + if ( PciFeaturesConfigurationTable) { >=20 > + MpsValue =3D PciFeaturesConfigurationTable->Max_Payload_Size; >=20 > + >=20 > + MpsValue =3D MIN ( PciDevice->SetupMPS, MpsValue); >=20 > + PciDevice->SetupMPS =3D MIN ( PciDevice->SetupMPS, MpsValue); >=20 > + >=20 > + if ( MpsValue !=3D PciFeaturesConfigurationTable->Max_Payload_Size) = { >=20 > + DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,", MpsValue)); >=20 > + PciFeaturesConfigurationTable->Max_Payload_Size =3D MpsValue; >=20 > + } >=20 > + } >=20 > + >=20 > + DEBUG (( DEBUG_INFO, >=20 > + "Max_Payload_Size: %d [DevCap:%d],", >=20 > + PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize >=20 > + )); >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + The main routine which process the PCI feature Max_Read_Req_Size as > per the >=20 > + device-specific platform policy, as well as in complaince with the PCI= Base >=20 > + specification Revision 4, that aligns the value for the entire PCI hei= rarchy >=20 > + starting from its physical PCI Root port / Bridge device. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE. >=20 > + @param PciConfigPhase for the PCI feature configuratio= n phases: >=20 > + PciFeatureGetDevicePolicy & PciF= eatureSetupPhase >=20 > + @param PciFeaturesConfigurationTable pointer to > OTHER_PCI_FEATURES_CONFIGURATION_TABLE >=20 > + >=20 > + @retval EFI_SUCCESS processing of PCI feature > Max_Read_Req_Size >=20 > + is successful. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +ProcessMaxReadReqSize ( >=20 > + IN PCI_IO_DEVICE *PciDevice, >=20 > + IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase, >=20 > + IN OTHER_PCI_FEATURES_CONFIGURATION_TABLE > *PciFeaturesConfigurationTable >=20 > + ) >=20 > +{ >=20 > + PCI_REG_PCIE_DEVICE_CAPABILITY PciDeviceCap; >=20 > + UINT8 MrrsValue; >=20 > + >=20 > + PciDeviceCap.Uint32 =3D PciDevice->PciExpStruct.DeviceCapability.Uint3= 2; >=20 > + >=20 > + if ( PciConfigPhase =3D=3D PciFeatureGetDevicePolicy) { >=20 > + if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS)) >=20 > + { >=20 > + // >=20 > + // The maximum read request size is not the data packet size of th= e TLP, >=20 > + // but the memory read request size, and set to the function as a > requestor >=20 > + // to not exceed this limit. >=20 > + // However, for the PCI device capable of isochronous traffic; thi= s > memory read >=20 > + // request size should not extend beyond the Max_Payload_Size. Thu= s, > in case if >=20 > + // device policy return by platform indicates to set as per device > capability >=20 > + // than set as per Max_Payload_Size configuration value >=20 > + // >=20 > + if ( SetupMaxPayloadSize()) { >=20 > + MrrsValue =3D PciDevice->SetupMPS; >=20 > + } else { >=20 > + // >=20 > + // in case this driver is not required to configure the Max_Payl= oad_Size >=20 > + // than consider programming HCF of the device capability's > Max_Payload_Size >=20 > + // in this PCI hierarchy; thus making this an implementation spe= cific > feature >=20 > + // which the platform should avoid. For better results, the plat= form > should >=20 > + // make both the Max_Payload_Size & Max_Read_Request_Size to be > configured >=20 > + // by this driver >=20 > + // >=20 > + MrrsValue =3D (UINT8)PciDeviceCap.Bits.MaxPayloadSize; >=20 > + } >=20 > + } else { >=20 > + // >=20 > + // override as per platform based device policy >=20 > + // >=20 > + MrrsValue =3D TranslateMrrsSetupValueToPci ( PciDevice->SetupMRRS)= ; >=20 > + // >=20 > + // align this device's Max_Read_Request_Size value to the entire P= CI > tree >=20 > + // >=20 > + if ( PciFeaturesConfigurationTable) { >=20 > + if ( !PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size)= { >=20 > + PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size =3D > TRUE; >=20 > + PciFeaturesConfigurationTable->Max_Read_Request_Size =3D > MrrsValue; >=20 > + } else { >=20 > + // >=20 > + // in case of another user enforced value of MRRS within the s= ame > tree, >=20 > + // pick the smallest between the locked value and this value; = to set >=20 > + // across entire PCI tree nodes >=20 > + // >=20 > + MrrsValue =3D MIN ( >=20 > + MrrsValue, >=20 > + PciFeaturesConfigurationTable->Max_Read_Request_= Size >=20 > + ); >=20 > + PciFeaturesConfigurationTable->Max_Read_Request_Size =3D > MrrsValue; >=20 > + } >=20 > + } >=20 > + } >=20 > + // >=20 > + // align this device's Max_Read_Request_Size to derived configuratio= n > value >=20 > + // >=20 > + PciDevice->SetupMRRS =3D MrrsValue; >=20 > + >=20 > + } >=20 > + >=20 > + // >=20 > + // align the Max_Read_Request_Size of the PCI tree based on 3 conditio= ns: >=20 > + // first, if user defines MRRS for any one PCI device in the tree than= align >=20 > + // all the devices in the PCI tree. >=20 > + // second, if user override is not define for this PCI tree than setup= the > MRRS >=20 > + // based on MPS value of the tree to meet the criteria for the isochro= nous >=20 > + // traffic. >=20 > + // third, if no user override, or platform firmware policy has not sel= ected >=20 > + // this PCI bus driver to configure the MPS; than configure the MRRS t= o a >=20 > + // highest common value of PCI device capability for the MPS found amo= ng > all >=20 > + // the PCI devices in this tree >=20 > + // >=20 > + if ( PciFeaturesConfigurationTable) { >=20 > + if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) { >=20 > + PciDevice->SetupMRRS =3D PciFeaturesConfigurationTable- > >Max_Read_Request_Size; >=20 > + } else { >=20 > + if ( SetupMaxPayloadSize()) { >=20 > + PciDevice->SetupMRRS =3D PciDevice->SetupMPS; >=20 > + } else { >=20 > + PciDevice->SetupMRRS =3D MIN ( >=20 > + PciDevice->SetupMRRS, >=20 > + PciFeaturesConfigurationTable->Max_Read_= Request_Size >=20 > + ); >=20 > + } >=20 > + PciFeaturesConfigurationTable->Max_Read_Request_Size =3D PciDevice= - > >SetupMRRS; >=20 > + } >=20 > + } >=20 > + DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice- > >SetupMRRS)); >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Overrides the PCI Device Control register MaxPayloadSize register fiel= d; if >=20 > + the hardware value is different than the intended value. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE instance. >=20 > + >=20 > + @retval EFI_SUCCESS The data was read from or written to the= PCI > device. >=20 > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not >=20 > + valid for the PCI configuration header o= f the PCI controller. >=20 > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +OverrideMaxPayloadSize ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + PCI_REG_PCIE_DEVICE_CONTROL PcieDev; >=20 > + UINT32 Offset; >=20 > + EFI_STATUS Status; >=20 > + >=20 > + PcieDev.Uint16 =3D 0; >=20 > + Offset =3D PciDevice->PciExpressCapabilityOffset + >=20 > + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); >=20 > + Status =3D PciDevice->PciIo.Pci.Read ( >=20 > + &PciDevice->PciIo, >=20 > + EfiPciIoWidthUint16, >=20 > + Offset, >=20 > + 1, >=20 > + &PcieDev.Uint16 >=20 > + ); >=20 > + if ( EFI_ERROR(Status)){ >=20 > + DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) > read error!", >=20 > + Offset >=20 > + )); >=20 > + return Status; >=20 > + } >=20 > + if ( PcieDev.Bits.MaxPayloadSize !=3D PciDevice->SetupMPS) { >=20 > + PcieDev.Bits.MaxPayloadSize =3D PciDevice->SetupMPS; >=20 > + DEBUG (( DEBUG_INFO, "Max_Payload_Size=3D%d,", PciDevice- > >SetupMPS)); >=20 > + >=20 > + Status =3D PciDevice->PciIo.Pci.Write ( >=20 > + &PciDevice->PciIo, >=20 > + EfiPciIoWidthUint16, >=20 > + Offset, >=20 > + 1, >=20 > + &PcieDev.Uint16 >=20 > + ); >=20 > + if ( !EFI_ERROR(Status)) { >=20 > + PciDevice->PciExpStruct.DeviceControl.Uint16 =3D PcieDev.Uint16; >=20 > + } else { >=20 > + DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) > write error!", >=20 > + Offset >=20 > + )); >=20 > + } >=20 > + } else { >=20 > + DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=3D%d,", PciDevice= - > >SetupMPS)); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Overrides the PCI Device Control register MaxPayloadSize register fiel= d; if >=20 > + the hardware value is different than the intended value. >=20 > + >=20 > + @param PciDevice A pointer to the PCI_IO_DEVICE instance. >=20 > + >=20 > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. >=20 > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not >=20 > + valid for the PCI configuration header o= f the PCI controller. >=20 > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +OverrideMaxReadReqSize ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + PCI_REG_PCIE_DEVICE_CONTROL PcieDev; >=20 > + UINT32 Offset; >=20 > + EFI_STATUS Status; >=20 > + >=20 > + PcieDev.Uint16 =3D 0; >=20 > + Offset =3D PciDevice->PciExpressCapabilityOffset + >=20 > + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); >=20 > + Status =3D PciDevice->PciIo.Pci.Read ( >=20 > + &PciDevice->PciIo, >=20 > + EfiPciIoWidthUint16, >=20 > + Offset, >=20 > + 1, >=20 > + &PcieDev.Uint16 >=20 > + ); >=20 > + if ( EFI_ERROR(Status)){ >=20 > + DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) > read error!", >=20 > + Offset >=20 > + )); >=20 > + return Status; >=20 > + } >=20 > + if ( PcieDev.Bits.MaxReadRequestSize !=3D PciDevice->SetupMRRS) { >=20 > + PcieDev.Bits.MaxReadRequestSize =3D PciDevice->SetupMRRS; >=20 > + DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice- > >SetupMRRS)); >=20 > + >=20 > + Status =3D PciDevice->PciIo.Pci.Write ( >=20 > + &PciDevice->PciIo, >=20 > + EfiPciIoWidthUint16, >=20 > + Offset, >=20 > + 1, >=20 > + &PcieDev.Uint16 >=20 > + ); >=20 > + if ( !EFI_ERROR(Status)) { >=20 > + PciDevice->PciExpStruct.DeviceControl.Uint16 =3D PcieDev.Uint16; >=20 > + } else { >=20 > + DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) > write error!", >=20 > + Offset >=20 > + )); >=20 > + } >=20 > + } else { >=20 > + DEBUG (( DEBUG_INFO, "No write of Max_Read_Request_Size=3D%d\n", > PciDevice->SetupMRRS)); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + helper routine to dump the PCIe Device Port Type >=20 > +**/ >=20 > +VOID >=20 > +DumpDevicePortType ( >=20 > + IN UINT8 DevicePortType >=20 > + ) >=20 > +{ >=20 > + switch ( DevicePortType){ >=20 > + case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT: >=20 > + DEBUG (( DEBUG_INFO, "PCIe endpoint found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT: >=20 > + DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_ROOT_PORT: >=20 > + DEBUG (( DEBUG_INFO, "PCIe Root Port found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT: >=20 > + DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT: >=20 > + DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE: >=20 > + DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE: >=20 > + DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n")); >=20 > + break; >=20 > + case > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT: >=20 > + DEBUG (( DEBUG_INFO, "RCiEP found\n")); >=20 > + break; >=20 > + case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR: >=20 > + DEBUG (( DEBUG_INFO, "RC Event Collector found\n")); >=20 > + break; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Process each PCI device as per the pltaform and device-specific polic= y. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + >=20 > + @retval EFI_SUCCESS processing each PCI feature as per polic= y > defined >=20 > + was successful. >=20 > + **/ >=20 > +EFI_STATUS >=20 > +SetupDevicePciFeatures ( >=20 > + IN PCI_IO_DEVICE *PciDevice, >=20 > + IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + PCI_REG_PCIE_CAPABILITY PcieCap; >=20 > + OTHER_PCI_FEATURES_CONFIGURATION_TABLE > *OtherPciFeaturesConfigTable; >=20 > + >=20 > + PcieCap.Uint16 =3D PciDevice->PciExpStruct.Capability.Uint16; >=20 > + DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType); >=20 > + >=20 > + OtherPciFeaturesConfigTable =3D NULL; >=20 > + Status =3D GetPciFeaturesConfigurationTable ( PciDevice, > &OtherPciFeaturesConfigTable); >=20 > + if ( EFI_ERROR( Status)) { >=20 > + DEBUG (( >=20 > + EFI_D_WARN, "No primary root port found in these root bridge > nodes!\n" >=20 > + )); >=20 > + } else if ( !OtherPciFeaturesConfigTable) { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "No PCI features config. table for this device!\n" >=20 > + )); >=20 > + } else { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "using PCI features config. table ID: %d\n", >=20 > + OtherPciFeaturesConfigTable->ID >=20 > + )); >=20 > + } >=20 > + >=20 > + if ( PciConfigPhase =3D=3D PciFeatureGetDevicePolicy) { >=20 > + Status =3D GetPciDevicePlatformPolicy ( PciDevice); >=20 > + if ( EFI_ERROR(Status)) { >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n" >=20 > + )); >=20 > + } >=20 > + } >=20 > + >=20 > + if ( SetupMaxPayloadSize ()) { >=20 > + Status =3D ProcessMaxPayloadSize ( >=20 > + PciDevice, >=20 > + PciConfigPhase, >=20 > + OtherPciFeaturesConfigTable >=20 > + ); >=20 > + } >=20 > + // >=20 > + // implementation specific rule:- the MRRS of any PCI device should be > processed >=20 > + // only after the MPS is processed for that device >=20 > + // >=20 > + if ( SetupMaxReadReqSize ()) { >=20 > + Status =3D ProcessMaxReadReqSize ( >=20 > + PciDevice, >=20 > + PciConfigPhase, >=20 > + OtherPciFeaturesConfigTable >=20 > + ); >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Traverse all the nodes from the root bridge or PCI-PCI bridge instance= , to >=20 > + configure the PCI features as per the device-specific platform policy,= and >=20 > + as per the device capability, as applicable. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + >=20 > + @retval EFI_SUCCESS Traversing all the nodes of the root bri= dge >=20 > + instances were successfull. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +SetupPciFeatures ( >=20 > + IN PCI_IO_DEVICE *RootBridge, >=20 > + IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + LIST_ENTRY *Link; >=20 > + PCI_IO_DEVICE *Device; >=20 > + >=20 > + for ( Link =3D RootBridge->ChildList.ForwardLink >=20 > + ; Link !=3D &RootBridge->ChildList >=20 > + ; Link =3D Link->ForwardLink >=20 > + ) { >=20 > + Device =3D PCI_IO_DEVICE_FROM_LINK (Link); >=20 > + if (IS_PCI_BRIDGE (&Device->Pci)) { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + if (Device->IsPciExp) { >=20 > + Status =3D SetupDevicePciFeatures ( Device, PciConfigPhase); >=20 > + } else { >=20 > + DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n")); >=20 > + // >=20 > + // PCI Bridge which does not have PCI Express Capability structu= re >=20 > + // cannot process this kind of PCI Bridge device >=20 > + // >=20 > + >=20 > + } >=20 > + >=20 > + SetupPciFeatures ( Device, PciConfigPhase); >=20 > + } else { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "::Device [%02x|%02x|%02x] -", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + if (Device->IsPciExp) { >=20 > + >=20 > + Status =3D SetupDevicePciFeatures ( Device, PciConfigPhase); >=20 > + } else { >=20 > + DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n")); >=20 > + // >=20 > + // PCI Device which does not have PCI Express Capability structu= re >=20 > + // cannot process this kind of PCI device >=20 > + // >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Program the PCI device, to override the PCI features as per the policy= , >=20 > + resolved from previous traverse. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + >=20 > + @retval EFI_SUCCESS The other PCI features configuration dur= ing > enumeration >=20 > + of all the nodes of the PCI root bridge = instance were >=20 > + programmed in PCI-compliance pattern alo= ng with the >=20 > + device-specific policy, as applicable. >=20 > + @retval EFI_UNSUPPORTED One of the override operation maong the > nodes of >=20 > + the PCI hierarchy resulted in a incompat= ible address >=20 > + range. >=20 > + @retval EFI_INVALID_PARAMETER The override operation is performed > with invalid input >=20 > + parameters. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +ProgramDevicePciFeatures ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + if ( SetupMaxPayloadSize ()) { >=20 > + Status =3D OverrideMaxPayloadSize (PciDevice); >=20 > + } >=20 > + if ( SetupMaxReadReqSize ()) { >=20 > + Status =3D OverrideMaxReadReqSize (PciDevice); >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Program all the nodes of the specified root bridge or PCI-PCI Bridge, = to >=20 > + override the PCI features. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + >=20 > + @retval EFI_SUCCESS The other PCI features configuration dur= ing > enumeration >=20 > + of all the nodes of the PCI root bridge = instance were >=20 > + programmed in PCI-compliance pattern alo= ng with the >=20 > + device-specific policy, as applicable. >=20 > + @retval EFI_UNSUPPORTED One of the override operation maong the > nodes of >=20 > + the PCI hierarchy resulted in a incompat= ible address >=20 > + range. >=20 > + @retval EFI_INVALID_PARAMETER The override operation is performed > with invalid input >=20 > + parameters. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +ProgramPciFeatures ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + LIST_ENTRY *Link; >=20 > + PCI_IO_DEVICE *Device; >=20 > + >=20 > + for ( Link =3D RootBridge->ChildList.ForwardLink >=20 > + ; Link !=3D &RootBridge->ChildList >=20 > + ; Link =3D Link->ForwardLink >=20 > + ) { >=20 > + Device =3D PCI_IO_DEVICE_FROM_LINK (Link); >=20 > + if (IS_PCI_BRIDGE (&Device->Pci)) { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + if (Device->IsPciExp) { >=20 > + DEBUG (( DEBUG_INFO, "ready to override!\n")); >=20 > + >=20 > + Status =3D ProgramDevicePciFeatures ( Device); >=20 > + } else { >=20 > + DEBUG (( DEBUG_INFO, "skipped!\n")); >=20 > + // >=20 > + // PCI Bridge which does not have PCI Express Capability structu= re >=20 > + // cannot process this kind of PCI Bridge device >=20 > + // >=20 > + >=20 > + } >=20 > + >=20 > + Status =3D ProgramPciFeatures ( Device); >=20 > + } else { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "::Device [%02x|%02x|%02x] -", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + if (Device->IsPciExp) { >=20 > + DEBUG (( DEBUG_INFO, "ready to override!\n")); >=20 > + >=20 > + Status =3D ProgramDevicePciFeatures ( Device); >=20 > + } else { >=20 > + DEBUG (( DEBUG_INFO, "skipped!\n")); >=20 > + // >=20 > + // PCI Device which does not have PCI Express Capability structu= re >=20 > + // cannot process this kind of PCI device >=20 > + // >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Create a node of type PRIMARY_ROOT_PORT_NODE for the given PCI > device, and >=20 > + assigns EFI handles of its Root Bridge and its own, along with its PCI= Bus >=20 > + range for the secondary and subordinate bus range. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE for its PCI= Root > Bridge >=20 > + @param Device A pointer to the PCI_IO_DEVICE for the PCI > controller >=20 > + @param RootPortSecBus PCI controller's Secondary Bus number >=20 > + @param RootPortSubBus PCI controller's Subordinate Bus number >=20 > + @param PrimaryRootPortNode A pointer to the > PRIMARY_ROOT_PORT_NODE to return >=20 > + the newly created node for the PCI control= ler. In >=20 > + case of error nothing is return in this. >=20 > + >=20 > + @retval EFI_SUCCESS new node of PRIMARY_ROOT_PORT_NODE is > returned for >=20 > + the PCI controller >=20 > + EFI_OUT_OF_RESOURCES unable to create the node for the PCI > controller >=20 > + EFI_INVALID_PARAMETER unable to store the node as the input > buffer is >=20 > + not empty (*PrimaryRootPortNode) >=20 > +**/ >=20 > +EFI_STATUS >=20 > +CreatePrimaryPciRootPortNode ( >=20 > + IN PCI_IO_DEVICE *RootBridge, >=20 > + IN PCI_IO_DEVICE *Device, >=20 > + IN UINT8 RootPortSecBus, >=20 > + IN UINT8 RootPortSubBus, >=20 > + OUT PRIMARY_ROOT_PORT_NODE **PrimaryRootPortNode >=20 > + ) >=20 > +{ >=20 > + PRIMARY_ROOT_PORT_NODE *RootPortNode =3D NULL; >=20 > + >=20 > + if ( !*PrimaryRootPortNode) { >=20 > + RootPortNode =3D AllocateZeroPool ( sizeof > (PRIMARY_ROOT_PORT_NODE)); >=20 > + if ( RootPortNode =3D=3D NULL) { >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + RootPortNode->Signature =3D PCI_ROOT_PORT_SIGNATURE; >=20 > + RootPortNode->RootBridgeHandle =3D RootBridge->Handle; >=20 > + RootPortNode->RootPortHandle =3D Device->Handle; >=20 > + RootPortNode->SecondaryBusStart =3D RootPortSecBus; >=20 > + RootPortNode->SecondaryBusEnd =3D RootPortSubBus; >=20 > + InitializeListHead ( &RootPortNode->NeighborRootPort); >=20 > + *PrimaryRootPortNode =3D RootPortNode; >=20 > + return EFI_SUCCESS; >=20 > + } else { >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Checks to report whether the input PCI controller's secondary / > subordinate >=20 > + bus numbers are within the recorded list of other PCI controllers (roo= t > ports). >=20 > + >=20 > + @param RootPortNode A pointer to the first node of > PRIMARY_ROOT_PORT_NODE >=20 > + @param RootPortSecBus PCI secondary bus number of the PCI controll= er > found >=20 > + @param RootPortSubBus PCI subordinate bus number of the PCI Root > Port found >=20 > + >=20 > + @retval TRUE A child PCI Root port found >=20 > + FALSE A new PCI controller found >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckChildRootPort ( >=20 > + IN PRIMARY_ROOT_PORT_NODE *RootPortNode, >=20 > + IN UINT8 RootPortSecBus, >=20 > + IN UINT8 RootPortSubBus >=20 > +) >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PRIMARY_ROOT_PORT_NODE *Temp; >=20 > + >=20 > + if ( !RootPortNode) { >=20 > + return FALSE; >=20 > + } >=20 > + Link =3D &RootPortNode->NeighborRootPort; >=20 > + do { >=20 > + Temp =3D PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link); >=20 > + if ( RootPortSecBus >=3D Temp->SecondaryBusStart >=20 > + && RootPortSubBus <=3D Temp->SecondaryBusEnd) { >=20 > + // >=20 > + // given root port's secondary & subordinate within its primary po= rts >=20 > + // hence return as child port >=20 > + // >=20 > + return TRUE; >=20 > + } >=20 > + Link =3D Link->ForwardLink; >=20 > + } while (Link !=3D &RootPortNode->NeighborRootPort); >=20 > + // >=20 > + // the given root port's secondary / subordinate bus numbers do not > belong to >=20 > + // any existing primary root port's bus range hence consider another > primary >=20 > + // root port of the root bridge controller >=20 > + // >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Create the vector of PCI Feature configuration table as per the number= of >=20 > + the PCI Root Ports given, assigns default value to the PCI features > supported >=20 > + and assign its address to the global variable > "mPciFeaturesConfigurationTableInstances". >=20 > + >=20 > + @param NumberOfRootPorts An input arguement of UINTN to indicate > number of >=20 > + primary PCI physical Root Bridge devices f= ound >=20 > + >=20 > + @retval EFI_OUT_OF_RESOURCES unable to allocate buffer to store PCI > feature >=20 > + configuration table for all the physical= PCI root >=20 > + ports given >=20 > + EFI_SUCCESS PCI Feature COnfiguration table created = for all >=20 > + the PCI Rooot ports reported >=20 > + */ >=20 > +EFI_STATUS >=20 > +CreatePciFeaturesConfigurationTableInstances ( >=20 > + IN UINTN NumberOfRootPorts >=20 > + ) >=20 > +{ >=20 > + OTHER_PCI_FEATURES_CONFIGURATION_TABLE > *PciRootBridgePortFeatures =3D NULL; >=20 > + UINTN Instances; >=20 > + >=20 > + PciRootBridgePortFeatures =3D AllocateZeroPool ( >=20 > + sizeof ( OTHER_PCI_FEATURES_CONFIGURATIO= N_TABLE) * > NumberOfRootPorts >=20 > + ); >=20 > + if ( !PciRootBridgePortFeatures) { >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + >=20 > + for ( Instances =3D 0; Instances < NumberOfRootPorts; Instances++) { >=20 > + PciRootBridgePortFeatures [Instances].ID =3D Inst= ances + 1; >=20 > + PciRootBridgePortFeatures [Instances].Max_Payload_Size =3D > PCIE_MAX_PAYLOAD_SIZE_4096B; >=20 > + PciRootBridgePortFeatures [Instances].Max_Read_Request_Size =3D > PCIE_MAX_READ_REQ_SIZE_4096B; >=20 > + PciRootBridgePortFeatures [Instances].Lock_Max_Read_Request_Size =3D > FALSE; >=20 > + } >=20 > + mPciFeaturesConfigurationTableInstances =3D PciRootBridgePortFeatures; >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + This routine pairs the each PCI Root Port node with one of the PCI Fea= ture >=20 > + Configuration Table node. Each physical PCI Root Port has its own PCI > feature >=20 > + configuration table which will used for aligning all its downstream > components. >=20 > + >=20 > + @param NumberOfRootPorts inputs the number of physical PCI root > ports >=20 > + found on the Root bridge instance >=20 > + >=20 > + @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is > vacant when >=20 > + there is one or more PCI Root port indic= ated as per >=20 > + input parameter >=20 > + EFI_UNSUPPORTED The PCI Root Port nodes not paired equal= ly with >=20 > + the PCI Configuration Table nodes >=20 > + EFI_SUCCESS each PCI feature configuration node is p= aired > equally >=20 > + with each PCI Root port in the list >=20 > +**/ >=20 > +EFI_STATUS >=20 > +AssignPciFeaturesConfigurationTable ( >=20 > + IN UINTN NumberOfRootPorts >=20 > + ) >=20 > +{ >=20 > + UINTN Instances; >=20 > + LIST_ENTRY *Link; >=20 > + PRIMARY_ROOT_PORT_NODE *Temp; >=20 > + >=20 > + if ( !mPrimaryRootPortList >=20 > + && NumberOfRootPorts) { >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, >=20 > + "Critical error! no internal table setup for %d PCI Root ports \= n", >=20 > + NumberOfRootPorts >=20 > + )); >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + if ( NumberOfRootPorts) { >=20 > + Link =3D &mPrimaryRootPortList->NeighborRootPort; >=20 > + for ( Instances =3D 0 >=20 > + ; (Instances < NumberOfRootPorts) >=20 > + ; Instances++ >=20 > + ) { >=20 > + Temp =3D PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link); >=20 > + Temp->OtherPciFeaturesConfigurationTable =3D > &mPciFeaturesConfigurationTableInstances [Instances]; >=20 > + DEBUG (( >=20 > + DEBUG_INFO, >=20 > + "Assigned to %dth primary root port\n", >=20 > + Instances >=20 > + )); >=20 > + >=20 > + Link =3D Link->ForwardLink; >=20 > + } >=20 > + if ( Link !=3D &mPrimaryRootPortList->NeighborRootPort) { >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, >=20 > + "Error!! PCI Root Port list is not properly matched with Confi= g., Table > list \n" >=20 > + )); >=20 > + return EFI_UNSUPPORTED; >=20 > + } >=20 > + } >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Prepare each PCI Controller (Root Port) with its own PCI Feature > configuration >=20 > + table node that can be used for tracking to align all PCI nodes in its > hierarchy. >=20 > + >=20 > + @param PrimaryRootPorts A pointer to PRIMARY_ROOT_PORT_NODE >=20 > + @param NumberOfRootPorts Total number of pysical primary PCI Root > ports >=20 > + >=20 > + @retval EFI_OUT_OF_RESOURCES unable to allocate buffer to store PCI > feature >=20 > + configuration table for all the physical= PCI root >=20 > + ports given >=20 > + EFI_INVALID_PARAMETER if the primary PCI root ports list is va= cant > when >=20 > + there is one or more PCI Root port indic= ated as per >=20 > + input parameter >=20 > + EFI_UNSUPPORTED The PCI Root Port nodes not paired equal= ly with >=20 > + the PCI Configuration Table nodes >=20 > + EFI_SUCCESS each PCI feature configuration node is p= aired > equally >=20 > + with each PCI Root port in the list >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PreparePciControllerConfigurationTable ( >=20 > + IN PRIMARY_ROOT_PORT_NODE *PrimaryRootPorts, >=20 > + IN UINTN NumberOfRootPorts >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + mPrimaryRootPortList =3D PrimaryRootPorts; >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "Number of primary Root Ports found on this bridge > =3D %d\n", >=20 > + NumberOfRootPorts >=20 > + )); >=20 > + >=20 > + Status =3D CreatePciFeaturesConfigurationTableInstances > ( NumberOfRootPorts); >=20 > + if ( EFI_ERROR(Status)) { >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, "Unexpected memory node creation error for PCI > features!\n" >=20 > + )); >=20 > + } else { >=20 > + // >=20 > + // align the primary root port nodes list with the PCI Feature confi= guration >=20 > + // table. Note that the PCI Feature configuration table is not maint= ain for >=20 > + // the RCiEP devices >=20 > + // >=20 > + Status =3D AssignPciFeaturesConfigurationTable ( NumberOfRootPorts); >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Scan all the nodes of the RootBridge to identify and create a separate= list >=20 > + of all primary physical PCI root ports and link each with its own inst= ance of >=20 > + the PCI Feature Configuration Table. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE of the PCI Root > Bridge >=20 > + >=20 > + @retval EFI_OUT_OF_RESOURCES unable to allocate buffer to store PCI > feature >=20 > + configuration table for all the physical= PCI root >=20 > + ports given >=20 > + EFI_NOT_FOUND No PCI Bridge device found >=20 > + EFI_SUCCESS PCI Feature COnfiguration table created = for all >=20 > + the PCI Rooot ports found >=20 > + EFI_INVALID_PARAMETER invalid parameter passed to the routine > which >=20 > + creates the PCI controller node for the = primary >=20 > + Root post list >=20 > +**/ >=20 > +EFI_STATUS >=20 > +RecordPciRootPortBridges ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status =3D EFI_NOT_FOUND; >=20 > + LIST_ENTRY *Link; >=20 > + PCI_IO_DEVICE *Device; >=20 > + UINTN NumberOfRootPorts; >=20 > + PRIMARY_ROOT_PORT_NODE *PrimaryRootPorts, >=20 > + *TempNode; >=20 > + UINT8 RootPortSecBus, >=20 > + RootPortSubBus; >=20 > + >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "<<********** RecordPciRootPortBridges -start > *************>>\n" >=20 > + )); >=20 > + NumberOfRootPorts =3D 0; >=20 > + PrimaryRootPorts =3D NULL; >=20 > + for ( Link =3D RootBridge->ChildList.ForwardLink >=20 > + ; Link !=3D &RootBridge->ChildList >=20 > + ; Link =3D Link->ForwardLink >=20 > + ) { >=20 > + Device =3D PCI_IO_DEVICE_FROM_LINK (Link); >=20 > + if (IS_PCI_BRIDGE (&Device->Pci)) { >=20 > + Status =3D GetPciRootPortBusAssigned ( >=20 > + Device, >=20 > + NULL, >=20 > + &RootPortSecBus, >=20 > + &RootPortSubBus >=20 > + ); >=20 > + if ( !EFI_ERROR(Status)) { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=3D0x%x, > SubBus=3D0x%x\n", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber, >=20 > + RootPortSecBus, RootPortSubBus >=20 > + )); >=20 > + } else { >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, "Unexpected read error [0x%lx]::Device > [%02x|%02x|%02x]\n", >=20 > + Status, Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + RootPortSecBus =3D RootPortSubBus =3D 0; >=20 > + continue; >=20 > + } >=20 > + >=20 > + if ( !PrimaryRootPorts) { >=20 > + NumberOfRootPorts++; >=20 > + Status =3D CreatePrimaryPciRootPortNode ( >=20 > + RootBridge, >=20 > + Device, >=20 > + RootPortSecBus, >=20 > + RootPortSubBus, >=20 > + &PrimaryRootPorts >=20 > + ); >=20 > + if ( EFI_ERROR(Status)) { >=20 > + // >=20 > + // abort mission to scan for all primary roots ports of a brid= ge >=20 > + // controller if error encountered for very first PCI primary = root port >=20 > + // >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Devi= ce > [%02x|%02x|%02x]\n", >=20 > + Status, Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + return Status; >=20 > + } >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "first primary root port found::Device > [%02x|%02x|%02x]\n", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + } else { >=20 > + if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus, > RootPortSubBus)) { >=20 > + NumberOfRootPorts++; >=20 > + TempNode =3D NULL; >=20 > + Status =3D CreatePrimaryPciRootPortNode ( >=20 > + RootBridge, >=20 > + Device, >=20 > + RootPortSecBus, >=20 > + RootPortSubBus, >=20 > + &TempNode >=20 > + ); >=20 > + if ( !EFI_ERROR(Status)) { >=20 > + // >=20 > + // another primary root port found on the same bridge contro= ller >=20 > + // insert in the node list >=20 > + // >=20 > + InsertTailList ( &PrimaryRootPorts->NeighborRootPort, &TempN= ode- > >NeighborRootPort); >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "next primary root port found::Device > [%02x|%02x|%02x]\n", >=20 > + Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + } else { >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, "Unexpected node creation error [0x%lx]::De= vice > [%02x|%02x|%02x]\n", >=20 > + Status, Device->BusNumber, Device->DeviceNumber, Device- > >FunctionNumber >=20 > + )); >=20 > + } >=20 > + } >=20 > + } >=20 > + } >=20 > + } >=20 > + // >=20 > + // prepare the PCI root port and its feature configuration table list >=20 > + // >=20 > + if ( NumberOfRootPorts) { >=20 > + Status =3D PreparePciControllerConfigurationTable ( >=20 > + PrimaryRootPorts, >=20 > + NumberOfRootPorts >=20 > + ); >=20 > + >=20 > + } else { >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "No PCI Root port found on this bridge!\n" >=20 > + )); >=20 > + } >=20 > + >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "<<********** RecordPciRootPortBridges - end > **********>>\n" >=20 > + )); >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge= , to >=20 > + configure the other PCI features. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + >=20 > + @retval EFI_SUCCESS The other PCI features configuration dur= ing > enumeration >=20 > + of all the nodes of the PCI root bridge = instance were >=20 > + programmed in PCI-compliance pattern alo= ng with the >=20 > + device-specific policy, as applicable. >=20 > + @retval EFI_UNSUPPORTED One of the override operation maong the > nodes of >=20 > + the PCI hierarchy resulted in a incompat= ible address >=20 > + range. >=20 > + @retval EFI_INVALID_PARAMETER The override operation is performed > with invalid input >=20 > + parameters. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EnumerateOtherPciFeatures ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + CHAR16 *Str; >=20 > + UINTN OtherPciFeatureConfigPhase; >=20 > + >=20 > + // >=20 > + // check on PCI features configuration is complete and re-enumeration = is > required >=20 > + // >=20 > + if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) { >=20 > + return EFI_ALREADY_STARTED; >=20 > + } >=20 > + >=20 > + Str =3D ConvertDevicePathToText ( >=20 > + DevicePathFromHandle (RootBridge->Handle), >=20 > + FALSE, >=20 > + FALSE >=20 > + ); >=20 > + DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n", > Str !=3D NULL ? Str : L"")); >=20 > + >=20 > + for ( OtherPciFeatureConfigPhase =3D PciFeatureRootBridgeScan >=20 > + ; OtherPciFeatureConfigPhase <=3D PciFeatureConfigurationComplete >=20 > + ; OtherPciFeatureConfigPhase++ >=20 > + ) { >=20 > + switch ( OtherPciFeatureConfigPhase){ >=20 > + case PciFeatureRootBridgeScan: >=20 > + SetupPciFeaturesConfigurationDefaults (); >=20 > + // >=20 > + //first scan the entire root bridge heirarchy for the primary PC= I root > ports >=20 > + // >=20 > + RecordPciRootPortBridges ( RootBridge); >=20 > + break; >=20 > + >=20 > + case PciFeatureGetDevicePolicy: >=20 > + case PciFeatureSetupPhase: >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "<<********** SetupPciFeatures - start > **********>>\n" >=20 > + )); >=20 > + // >=20 > + // enumerate the other PCI features >=20 > + // >=20 > + Status =3D SetupPciFeatures ( RootBridge, OtherPciFeatureConfigP= hase); >=20 > + >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "<<********** SetupPciFeatures - end > **********>>\n" >=20 > + )); >=20 > + break; >=20 > + >=20 > + case PciFeatureConfigurationPhase: >=20 > + // >=20 > + // override the PCI features as per enumeration phase >=20 > + // >=20 > + DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n"= , > Str !=3D NULL ? Str : L"")); >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "<<********** ProgramPciFeatures - start > **********>>\n" >=20 > + )); >=20 > + Status =3D ProgramPciFeatures ( RootBridge); >=20 > + DEBUG (( >=20 > + DEBUG_INFO, "<<********** ProgramPciFeatures - end > **********>>\n" >=20 > + )); >=20 > + break; >=20 > + >=20 > + case PciFeatureConfigurationComplete: >=20 > + // >=20 > + // clean up the temporary resource nodes created for this root b= ridge >=20 > + // >=20 > + DestroyPrimaryRootPortNodes (); >=20 > + >=20 > + ErasePciFeaturesConfigurationTable (); >=20 > + } >=20 > + } >=20 > + >=20 > + if (Str !=3D NULL) { >=20 > + FreePool (Str); >=20 > + } >=20 > + // >=20 > + // mark this root bridge as PCI features configuration complete, and n= o > new >=20 > + // enumeration is required >=20 > + // >=20 > + AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge, FALSE); >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + This routine is invoked from the Stop () interface for the EFI handle = of the >=20 > + RootBridge. Free up its node of type > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE >=20 > +**/ >=20 > +VOID >=20 > +DestroyRootBridgePciFeaturesConfigCompletionList ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ) >=20 > +{ >=20 > + LIST_ENTRY *Link; >=20 > + PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp; >=20 > + >=20 > + if ( mPciFeaturesConfigurationCompletionList) { >=20 > + Link =3D &mPciFeaturesConfigurationCompletionList->RootBridgeLink; >=20 > + >=20 > + do { >=20 > + Temp =3D > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link); >=20 > + if ( Temp->RootBridgeHandle =3D=3D RootBridge->Handle) { >=20 > + RemoveEntryList ( Link); >=20 > + FreePool ( Temp); >=20 > + return; >=20 > + } >=20 > + Link =3D Link->ForwardLink; >=20 > + } while (Link !=3D &mPciFeaturesConfigurationCompletionList- > >RootBridgeLink); >=20 > + } >=20 > + // >=20 > + // not found on the PCI feature configuration completion list, return >=20 > + // >=20 > + return; >=20 > +} >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h > new file mode 100644 > index 0000000000..9f225fa993 > --- /dev/null > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h > @@ -0,0 +1,201 @@ > +/** @file >=20 > + PCI standard feature support functions implementation for PCI Bus > module.. >=20 > + >=20 > +Copyright (c) 2019, Intel Corporation. All rights reserved.
>=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_ >=20 > +#define _EFI_PCI_FEATURES_SUPPORT_H_ >=20 > + >=20 > +#include "PciBus.h" >=20 > +#include "PciPlatformSupport.h" >=20 > + >=20 > +// >=20 > +// Macro definitions for the PCI Features support PCD >=20 > +// >=20 > +#define PCI_FEATURE_SUPPORT_FLAG_MPS BIT0 >=20 > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1 >=20 > + >=20 > +// >=20 > +// defines the data structure to hold the details of the PCI Root port d= evices >=20 > +// >=20 > +typedef struct _PRIMARY_ROOT_PORT_NODE > PRIMARY_ROOT_PORT_NODE; >=20 > + >=20 > +// >=20 > +// defines the data structure to hold the configuration data for the oth= er > PCI >=20 > +// features >=20 > +// >=20 > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE > OTHER_PCI_FEATURES_CONFIGURATION_TABLE; >=20 > + >=20 > +// >=20 > +// Defines for the PCI features configuration completion and re- > enumeration list >=20 > +// >=20 > +typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST; >=20 > + >=20 > +// >=20 > +// Signature value for the PCI Root Port node >=20 > +// >=20 > +#define PCI_ROOT_PORT_SIGNATURE SIGNATURE_32 ('p', 'c', 'i= ', 'p') >=20 > + >=20 > +// >=20 > +// Definitions of the PCI Root Port data structure members >=20 > +// >=20 > +struct _PRIMARY_ROOT_PORT_NODE { >=20 > + // >=20 > + // Signature header >=20 > + // >=20 > + UINT32 Signature; >=20 > + // >=20 > + // linked list pointers to next node >=20 > + // >=20 > + LIST_ENTRY NeighborRootPort; >=20 > + // >=20 > + // EFI handle of the parent Root Bridge instance >=20 > + // >=20 > + EFI_HANDLE RootBridgeHandle; >=20 > + // >=20 > + // EFI handle of the PCI controller >=20 > + // >=20 > + EFI_HANDLE RootPortHandle; >=20 > + // >=20 > + // PCI Secondary bus value of the PCI controller >=20 > + // >=20 > + UINT8 SecondaryBusStart; >=20 > + // >=20 > + // PCI Subordinate bus value of the PCI controller >=20 > + // >=20 > + UINT8 SecondaryBusEnd; >=20 > + // >=20 > + // pointer to the corresponding PCI feature configuration Table node >=20 > + // >=20 > + OTHER_PCI_FEATURES_CONFIGURATION_TABLE > *OtherPciFeaturesConfigurationTable; >=20 > +}; >=20 > + >=20 > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \ >=20 > + CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort, > PCI_ROOT_PORT_SIGNATURE) >=20 > + >=20 > +// >=20 > +// Definition of the PCI Feature configuration Table members >=20 > +// >=20 > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE { >=20 > + // >=20 > + // Configuration Table ID >=20 > + // >=20 > + UINTN ID; >=20 > + // >=20 > + // to configure the PCI feature Maximum payload size to maintain the d= ata > packet >=20 > + // size among all the PCI devices in the PCI hierarchy >=20 > + // >=20 > + UINT8 Max_Payload_Size; >=20 > + // >=20 > + // to configure the PCI feature maximum read request size to maintain = the > memory >=20 > + // requester size among all the PCI devices in the PCI hierarchy >=20 > + // >=20 > + UINT8 Max_Read_Request_Size; >=20 > + // >=20 > + // lock the Max_Read_Request_Size for the entire PCI tree of a root po= rt >=20 > + // >=20 > + BOOLEAN Lock_Max_Read_Request_Size; >=20 > +}; >=20 > + >=20 > + >=20 > +// >=20 > +// PCI feature configuration node signature value >=20 > +// >=20 > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE > SIGNATURE_32 ('p', 'c', 'i', 'f') >=20 > + >=20 > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST { >=20 > + // >=20 > + // Signature header >=20 > + // >=20 > + UINT32 Signature; >=20 > + // >=20 > + // link to next Root Bridge whose PCI Feature configuration is complet= e >=20 > + // >=20 > + LIST_ENTRY RootBridgeLink; >=20 > + // >=20 > + // EFI handle of the Root Bridge whose PCI feature configuration is > complete >=20 > + // >=20 > + EFI_HANDLE RootBridgeHandle; >=20 > + // >=20 > + // indication for complete re-enumeration of the PCI feature configura= tion >=20 > + // >=20 > + BOOLEAN ReEnumeratePciFeatureConfigu= ration; >=20 > +}; >=20 > + >=20 > +#define > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \ >=20 > + CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE) >=20 > + >=20 > +// >=20 > +// Declaration of the internal sub-phases within the PCI Feature > enumeration >=20 > +// >=20 > +typedef enum { >=20 > + // >=20 > + // initial phase in configuring the other PCI features to record the p= rimary >=20 > + // root ports >=20 > + // >=20 > + PciFeatureRootBridgeScan, >=20 > + // >=20 > + // get the PCI device-specific platform policies and align with device > capabilities >=20 > + // >=20 > + PciFeatureGetDevicePolicy, >=20 > + // >=20 > + // align all PCI nodes in the PCI heirarchical tree >=20 > + // >=20 > + PciFeatureSetupPhase, >=20 > + // >=20 > + // finally override to complete configuration of the PCI feature >=20 > + // >=20 > + PciFeatureConfigurationPhase, >=20 > + // >=20 > + // PCI feature configuration complete >=20 > + // >=20 > + PciFeatureConfigurationComplete >=20 > + >=20 > +}PCI_FEATURE_CONFIGURATION_PHASE; >=20 > + >=20 > +/** >=20 > + Main routine to indicate platform selection of any of the other PCI fe= atures >=20 > + to be configured by this driver >=20 > + >=20 > + @retval TRUE platform has selected the other PCI features to be > configured >=20 > + FALSE platform has not selected any of the other PCI feature= s >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckOtherPciFeaturesPcd ( >=20 > + ); >=20 > + >=20 > +/** >=20 > + Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge= , to >=20 > + configure the other PCI features. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE. >=20 > + >=20 > + @retval EFI_SUCCESS The other PCI features configuration dur= ing > enumeration >=20 > + of all the nodes of the PCI root bridge = instance were >=20 > + programmed in PCI-compliance pattern alo= ng with the >=20 > + device-specific policy, as applicable. >=20 > + @retval EFI_UNSUPPORTED One of the override operation maong the > nodes of >=20 > + the PCI hierarchy resulted in a incompat= ible address >=20 > + range. >=20 > + @retval EFI_INVALID_PARAMETER The override operation is performed > with invalid input >=20 > + parameters. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EnumerateOtherPciFeatures ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ); >=20 > + >=20 > +/** >=20 > + This routine is invoked from the Stop () interface for the EFI handle = of the >=20 > + RootBridge. Free up its node of type > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST. >=20 > + >=20 > + @param RootBridge A pointer to the PCI_IO_DEVICE >=20 > +**/ >=20 > +VOID >=20 > +DestroyRootBridgePciFeaturesConfigCompletionList ( >=20 > + IN PCI_IO_DEVICE *RootBridge >=20 > + ); >=20 > +#endif >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > new file mode 100644 > index 0000000000..d94037d69a > --- /dev/null > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > @@ -0,0 +1,565 @@ > +/** @file >=20 > + This file encapsulate the usage of PCI Platform Protocol >=20 > + >=20 > + This file define the necessary hooks used to obtain the platform >=20 > + level data and policies which could be used in the PCI Enumeration pha= ses >=20 > + >=20 > +Copyright (c) 2019, Intel Corporation. All rights reserved.
>=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include "PciPlatformSupport.h" >=20 > + >=20 > +EFI_PCI_PLATFORM_PROTOCOL *mPciPlatformProtocol; >=20 > +EFI_PCI_OVERRIDE_PROTOCOL *mPciOverrideProtocol; >=20 > + >=20 > +EFI_PCI_PLATFORM_PROTOCOL2 *mPciPlatformProtocol2; >=20 > +EFI_PCI_OVERRIDE_PROTOCOL2 *mPciOverrideProtocol2; >=20 > + >=20 > + >=20 > +/** >=20 > + This function retrieves the PCI Platform Protocol published by platfor= m > driver >=20 > + >=20 > +**/ >=20 > +VOID >=20 > +GetPciPlatformProtocol ( >=20 > + ) >=20 > +{ >=20 > + mPciPlatformProtocol2 =3D NULL; >=20 > + gBS->LocateProtocol ( >=20 > + &gEfiPciPlatformProtocol2Guid, >=20 > + NULL, >=20 > + (VOID **) &mPciPlatformProtocol2 >=20 > + ); >=20 > + >=20 > + // >=20 > + // If PCI Platform protocol doesn't exist, try to get Pci Override Pro= tocol. >=20 > + // >=20 > + if (mPciPlatformProtocol2 =3D=3D NULL) { >=20 > + mPciOverrideProtocol2 =3D NULL; >=20 > + gBS->LocateProtocol ( >=20 > + &gEfiPciOverrideProtocol2Guid, >=20 > + NULL, >=20 > + (VOID **) &mPciOverrideProtocol2 >=20 > + ); >=20 > + } >=20 > + // >=20 > + // fetch the old PCI Platform Protocols if new are not installed >=20 > + // >=20 > + if (mPciOverrideProtocol2 =3D=3D NULL) { >=20 > + >=20 > + mPciPlatformProtocol =3D NULL; >=20 > + gBS->LocateProtocol ( >=20 > + &gEfiPciPlatformProtocolGuid, >=20 > + NULL, >=20 > + (VOID **) &mPciPlatformProtocol >=20 > + ); >=20 > + >=20 > + // >=20 > + // If PCI Platform protocol doesn't exist, try to get Pci Override = Protocol. >=20 > + // >=20 > + if (mPciPlatformProtocol =3D=3D NULL) { >=20 > + mPciOverrideProtocol =3D NULL; >=20 > + gBS->LocateProtocol ( >=20 > + &gEfiPciOverrideProtocolGuid, >=20 > + NULL, >=20 > + (VOID **) &mPciOverrideProtocol >=20 > + ); >=20 > + } >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + This function indicates the presence of PCI Platform driver >=20 > + @retval TRUE or FALSE >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckPciPlatformProtocolInstall ( >=20 > + ) >=20 > +{ >=20 > + if (mPciPlatformProtocol2 !=3D NULL) { >=20 > + return TRUE; >=20 > + } else if (mPciOverrideProtocol2 !=3D NULL) { >=20 > + return TRUE; >=20 > + } else { >=20 > + if (mPciPlatformProtocol !=3D NULL) { >=20 > + return TRUE; >=20 > + } else if (mPciOverrideProtocol !=3D NULL){ >=20 > + return TRUE; >=20 > + } >=20 > + } >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Provides the hooks from the PCI bus driver to every PCI controller > (device/function) at various >=20 > + stages of the PCI enumeration process that allow the host bridge drive= r to > preinitialize individual >=20 > + PCI controllers before enumeration. >=20 > + >=20 > + This function is called during the PCI enumeration process. No specifi= c > action is expected from this >=20 > + member function. It allows the host bridge driver to preinitialize ind= ividual > PCI controllers before >=20 > + enumeration. >=20 > + >=20 > + @param[in] HostBridgeHandle The associated PCI host bridge handle. >=20 > + @param[in] RootBridgeHandle The associated PCI root bridge handle. >=20 > + @param[in] RootBridgePciAddress The address of the PCI device on the > PCI bus. >=20 > + @param[in] Phase The phase of the PCI controller enumeration. >=20 > + @param[in] ExecPhase Defines the execution phase of the PCI chips= et > driver. >=20 > + >=20 > + @retval Status returns the status from the PCI Platform pro= tocol as is >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PciPlatformPreprocessController ( >=20 > + IN EFI_HANDLE HostBridgeHandle, >=20 > + IN EFI_HANDLE RootBridgeHandle, >=20 > + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS > RootBridgePciAddress, >=20 > + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase, >=20 > + IN EFI_PCI_EXECUTION_PHASE ExecPhase >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + if (mPciPlatformProtocol2 !=3D NULL) { >=20 > + // >=20 > + // Call PlatformPci::PrepController() if the protocol is present. >=20 > + // >=20 > + Status =3D mPciPlatformProtocol2->PlatformPrepController ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2, >=20 > + HostBridgeHandle, >=20 > + RootBridgeHandle, >=20 > + RootBridgePciAddress, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else if (mPciOverrideProtocol2 !=3D NULL) { >=20 > + // >=20 > + // Call PlatformPci::PrepController() if the protocol is present. >=20 > + // >=20 > + Status =3D mPciOverrideProtocol2->PlatformPrepController ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2, >=20 > + HostBridgeHandle, >=20 > + RootBridgeHandle, >=20 > + RootBridgePciAddress, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else { >=20 > + if (mPciPlatformProtocol !=3D NULL) { >=20 > + // >=20 > + // Call PlatformPci::PrepController() if the protocol is present. >=20 > + // >=20 > + Status =3D mPciPlatformProtocol->PlatformPrepController ( >=20 > + mPciPlatformProtocol, >=20 > + HostBridgeHandle, >=20 > + RootBridgeHandle, >=20 > + RootBridgePciAddress, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else if (mPciOverrideProtocol !=3D NULL) { >=20 > + // >=20 > + // Call PlatformPci::PrepController() if the protocol is present. >=20 > + // >=20 > + Status =3D mPciOverrideProtocol->PlatformPrepController ( >=20 > + mPciOverrideProtocol, >=20 > + HostBridgeHandle, >=20 > + RootBridgeHandle, >=20 > + RootBridgePciAddress, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else { >=20 > + // >=20 > + // return PCI Platform Protocol not found >=20 > + // >=20 > + return EFI_NOT_FOUND; >=20 > + } >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + This function notifies the PCI Platform driver about the PCI host brid= ge > resource >=20 > + allocation phase and PCI execution phase. >=20 > + >=20 > + @param[in] HostBridge The handle of the host bridge controller. >=20 > + @param[in] Phase The phase of the PCI bus enumeration. >=20 > + @param[in] ExecPhase Defines the execution phase of the PCI chip= set > driver. >=20 > + @retval Status returns the status from the PCI Platform p= rotocol as > is >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PciPlatformNotifyPhase ( >=20 > + IN EFI_HANDLE HostBridgeHandle, >=20 > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase, >=20 > + IN EFI_PCI_EXECUTION_PHASE ExecPhase >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + if ( mPciPlatformProtocol2 !=3D NULL) { >=20 > + Status =3D mPciPlatformProtocol2->PlatformNotify ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2, >=20 > + HostBridgeHandle, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else if ( mPciOverrideProtocol2 !=3D NULL) { >=20 > + Status =3D mPciOverrideProtocol2->PlatformNotify ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2, >=20 > + HostBridgeHandle, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else { >=20 > + >=20 > + if ( mPciPlatformProtocol !=3D NULL) { >=20 > + Status =3D mPciPlatformProtocol->PlatformNotify ( >=20 > + mPciPlatformProtocol, >=20 > + HostBridgeHandle, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else if ( mPciOverrideProtocol !=3D NULL){ >=20 > + Status =3D mPciOverrideProtocol->PlatformNotify ( >=20 > + mPciOverrideProtocol, >=20 > + HostBridgeHandle, >=20 > + Phase, >=20 > + ExecPhase >=20 > + ); >=20 > + } else { >=20 > + // >=20 > + // return PCI Platform Protocol not found >=20 > + // >=20 > + return EFI_NOT_FOUND; >=20 > + } >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + This function retrieves the PCI platform policy. >=20 > + >=20 > + @param PciPolicy pointer to the legacy EFI_PCI_PLATFORM_POLICY >=20 > + @retval Status returns the status from the PCI Platform protoco= l as is >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PciGetPlatformPolicy ( >=20 > + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + if ( mPciPlatformProtocol2 !=3D NULL) { >=20 > + Status =3D mPciPlatformProtocol2->GetPlatformPolicy ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2, >=20 > + PciPolicy >=20 > + ); >=20 > + } else if ( mPciOverrideProtocol2 !=3D NULL) { >=20 > + Status =3D mPciOverrideProtocol2->GetPlatformPolicy ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2, >=20 > + PciPolicy >=20 > + ); >=20 > + } else { >=20 > + if ( mPciPlatformProtocol !=3D NULL) { >=20 > + Status =3D mPciPlatformProtocol->GetPlatformPolicy ( >=20 > + mPciPlatformProtocol, >=20 > + PciPolicy >=20 > + ); >=20 > + } >=20 > + >=20 > + if ( mPciOverrideProtocol !=3D NULL) { >=20 > + Status =3D mPciOverrideProtocol->GetPlatformPolicy ( >=20 > + mPciOverrideProtocol, >=20 > + PciPolicy >=20 > + ); >=20 > + } else { >=20 > + // >=20 > + // return PCI Platform Protocol not found >=20 > + // >=20 > + return EFI_NOT_FOUND; >=20 > + } >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + This function retrieves the Option ROM image and size from the Platfor= m. >=20 > + >=20 > + It uses the PCI_IO_DEVICE internal fields are used to store OpROM > image/size >=20 > + >=20 > + @param Controller An EFI handle for the PCI bus controller. >=20 > + @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to = be > registered. >=20 > + >=20 > + @retval EFI_SUCCESS The option ROM was available for this d= evice > and loaded into memory. >=20 > + @retval EFI_NOT_FOUND No option ROM was available for this de= vice. >=20 > + @retval EFI_OUT_OF_RESOURCES No memory was available to load the > option ROM. >=20 > + @retval EFI_DEVICE_ERROR An error occurred in obtaining the opti= on > ROM. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPlatformPciOptionRom ( >=20 > + IN EFI_HANDLE Controller, >=20 > + IN PCI_IO_DEVICE *PciIoDevice >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + VOID *PlatformOpRomBuffer; >=20 > + UINTN PlatformOpRomSize; >=20 > + >=20 > + if (mPciPlatformProtocol2 !=3D NULL) { >=20 > + Status =3D mPciPlatformProtocol2->GetPciRom ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2, >=20 > + PciIoDevice->Handle, >=20 > + &PlatformOpRomBuffer, >=20 > + &PlatformOpRomSize >=20 > + ); >=20 > + } else if (mPciOverrideProtocol2 !=3D NULL) { >=20 > + Status =3D mPciOverrideProtocol2->GetPciRom ( >=20 > + > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2, >=20 > + PciIoDevice->Handle, >=20 > + &PlatformOpRomBuffer, >=20 > + &PlatformOpRomSize >=20 > + ); >=20 > + } else { >=20 > + if (mPciPlatformProtocol !=3D NULL) { >=20 > + Status =3D mPciPlatformProtocol->GetPciRom ( >=20 > + mPciPlatformProtocol, >=20 > + PciIoDevice->Handle, >=20 > + &PlatformOpRomBuffer, >=20 > + &PlatformOpRomSize >=20 > + ); >=20 > + } else if (mPciOverrideProtocol !=3D NULL) { >=20 > + Status =3D mPciOverrideProtocol->GetPciRom ( >=20 > + mPciOverrideProtocol, >=20 > + PciIoDevice->Handle, >=20 > + &PlatformOpRomBuffer, >=20 > + &PlatformOpRomSize >=20 > + ); >=20 > + } else { >=20 > + // >=20 > + // return PCI Platform Protocol not found >=20 > + // >=20 > + return EFI_NOT_FOUND; >=20 > + } >=20 > + } >=20 > + >=20 > + if (!EFI_ERROR (Status)) { >=20 > + PciIoDevice->EmbeddedRom =3D FALSE; >=20 > + PciIoDevice->RomSize =3D (UINT32)PlatformOpRomSize; >=20 > + PciIoDevice->PciIo.RomSize =3D PlatformOpRomSize; >=20 > + PciIoDevice->PciIo.RomImage =3D PlatformOpRomBuffer; >=20 > + } >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Helper routine to indicate whether the given PCI device specific polic= y > value >=20 > + dictates to override the Max_Payload_Size to a particular value, or se= t as > per >=20 > + device capability. >=20 > + >=20 > + @param MPS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_PAYLOAD_SIZE >=20 > + >=20 > + @retval TRUE Setup Max_Payload_Size as per device capability >=20 > + FALSE override as per device-specific platform policy >=20 > +**/ >=20 > +BOOLEAN >=20 > +SetupMpsAsPerDeviceCapability ( >=20 > + IN UINT8 MPS >=20 > +) >=20 > +{ >=20 > + if ( MPS =3D=3D EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) { >=20 > + return TRUE; >=20 > + } else { >=20 > + return FALSE; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Helper routine to indicate whether the given PCI device specific polic= y > value >=20 > + dictates to override the Max_Read_Req_Size to a particular value, or s= et as > per >=20 > + device capability. >=20 > + >=20 > + @param MRRS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_READ_REQ_SIZE >=20 > + >=20 > + @retval TRUE Setup Max_Read_Req_Size as per device capability >=20 > + FALSE override as per device-specific platform policy >=20 > +**/ >=20 > +BOOLEAN >=20 > +SetupMrrsAsPerDeviceCapability ( >=20 > + IN UINT8 MRRS >=20 > +) >=20 > +{ >=20 > + if ( MRRS =3D=3D EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) { >=20 > + return TRUE; >=20 > + } else { >=20 > + return FALSE; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Routine to translate the given device-specific platform policy from ty= pe >=20 > + EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base > Specification >=20 > + Revision 4.0; for the PCI feature Max_Payload_Size. >=20 > + >=20 > + @param MPS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_PAYLOAD_SIZE >=20 > + >=20 > + @retval Range values for the Max_Payload_Size as defined in th= e PCI >=20 > + Base Specification 4.0 >=20 > +**/ >=20 > +UINT8 >=20 > +TranslateMpsSetupValueToPci ( >=20 > + IN UINT8 MPS >=20 > +) >=20 > +{ >=20 > + switch (MPS) { >=20 > + case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_128B; >=20 > + case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_256B; >=20 > + case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_512B; >=20 > + case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_1024B; >=20 > + case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_2048B; >=20 > + case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_4096B; >=20 > + default: >=20 > + return PCIE_MAX_PAYLOAD_SIZE_128B; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Routine to translate the given device-specific platform policy from ty= pe >=20 > + EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI > Base Specification >=20 > + Revision 4.0; for the PCI feature Max_Read_Req_Size. >=20 > + >=20 > + @param MRRS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_READ_REQ_SIZE >=20 > + >=20 > + @retval Range values for the Max_Read_Req_Size as defined in t= he > PCI >=20 > + Base Specification 4.0 >=20 > +**/ >=20 > +UINT8 >=20 > +TranslateMrrsSetupValueToPci ( >=20 > + IN UINT8 MRRS >=20 > +) >=20 > +{ >=20 > + switch (MRRS) { >=20 > + case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B: >=20 > + return PCIE_MAX_READ_REQ_SIZE_128B; >=20 > + case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B: >=20 > + return PCIE_MAX_READ_REQ_SIZE_256B; >=20 > + case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B: >=20 > + return PCIE_MAX_READ_REQ_SIZE_512B; >=20 > + case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B: >=20 > + return PCIE_MAX_READ_REQ_SIZE_1024B; >=20 > + case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B: >=20 > + return PCIE_MAX_READ_REQ_SIZE_2048B; >=20 > + case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B: >=20 > + return PCIE_MAX_READ_REQ_SIZE_4096B; >=20 > + default: >=20 > + return PCIE_MAX_READ_REQ_SIZE_128B; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Generic routine to setup the PCI features as per its predetermined > defaults. >=20 > +**/ >=20 > +VOID >=20 > +SetupDefaultsDevicePlatformPolicy ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + PciDevice->SetupMPS =3D EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO; >=20 > + PciDevice->SetupMRRS =3D EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO; >=20 > +} >=20 > + >=20 > +/** >=20 > + Intermediate routine to either get the PCI device specific platform po= licies >=20 > + through the PCI Platform Protocol, or its alias the PCI Override Proto= col. >=20 > + >=20 > + @param PciIoDevice A pointer to PCI_IO_DEVICE >=20 > + @param PciPlatformProtocol A pointer to > EFI_PCI_PLATFORM_PROTOCOL2 >=20 > + >=20 > + @retval EFI_STATUS The direct status from the PCI Platform Pr= otocol >=20 > + @retval EFI_SUCCESS if on returning predetermined PCI features > defaults, >=20 > + for the case when protocol returns as EFI_= UNSUPPORTED >=20 > + to indicate PCI device exist and it has no= platform >=20 > + policy defined. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPciDevicePlatformPolicyEx ( >=20 > + IN PCI_IO_DEVICE *PciIoDevice, >=20 > + IN EFI_PCI_PLATFORM_PROTOCOL2 *PciPlatformProtocol >=20 > + ) >=20 > +{ >=20 > + EFI_PCI_PLATFORM_EXTENDED_POLICY PciPlatformExtendedPolicy; >=20 > + EFI_STATUS Status; >=20 > + >=20 > + ZeroMem ( &PciPlatformExtendedPolicy, sizeof > (EFI_PCI_PLATFORM_EXTENDED_POLICY)); >=20 > + Status =3D PciPlatformProtocol->GetDevicePolicy ( >=20 > + PciPlatformProtocol, >=20 > + PciIoDevice->Handle, >=20 > + &PciPlatformExtendedPolicy >=20 > + ); >=20 > + // >=20 > + // platform chipset policies are returned for this PCI device >=20 > + // >=20 > + if (!EFI_ERROR(Status)) { >=20 > + PciIoDevice->SetupMPS =3D PciPlatformExtendedPolicy.DeviceCtlMPS; >=20 > + PciIoDevice->SetupMRRS =3D PciPlatformExtendedPolicy.DeviceCtlMRRS; >=20 > + } >=20 > + // >=20 > + // platform chipset policies are not provided for this PCI device >=20 > + // >=20 > + if (EFI_ERROR(Status) =3D=3D EFI_UNSUPPORTED) { >=20 > + // >=20 > + // let the enumeration happen as per the PCI standard way >=20 > + // >=20 > + SetupDefaultsDevicePlatformPolicy ( PciIoDevice); >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Gets the PCI device-specific platform policy from the PCI Platform Pro= tocol. >=20 > + If no PCI Platform protocol is published than setup the PCI feature to > predetermined >=20 > + defaults, in order to align all the PCI devices in the PCI hierarchy, = as > applicable. >=20 > + >=20 > + @param PciDevice A pointer to PCI_IO_DEVICE >=20 > + >=20 > + @retval EFI_STATUS The direct status from the PCI Platform Protocol >=20 > + @retval EFI_SUCCESS On return of predetermined PCI features defaults= , > for >=20 > + the case when protocol returns as EFI_UNSUPPORTE= D to >=20 > + indicate PCI device exist and it has no platform= policy >=20 > + defined. Also, on returns when no PCI Platform P= rotocol >=20 > + exist. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPciDevicePlatformPolicy ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ) >=20 > +{ >=20 > + if ( mPciPlatformProtocol2 !=3D NULL) { >=20 > + return GetPciDevicePlatformPolicyEx ( PciDevice, mPciPlatformProtoco= l2); >=20 > + } else if (mPciOverrideProtocol2 !=3D NULL) { >=20 > + return GetPciDevicePlatformPolicyEx ( PciDevice, mPciOverrideProtoco= l2); >=20 > + } else { >=20 > + // >=20 > + // new PCI Platform Protocol 2 is not installed; let the enumeration > happen >=20 > + // as per PCI standard way >=20 > + // >=20 > + SetupDefaultsDevicePlatformPolicy ( PciDevice); >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > +} >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h > new file mode 100644 > index 0000000000..d54e46b950 > --- /dev/null > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h > @@ -0,0 +1,193 @@ > +/** @file >=20 > + This file encapsulate the usage of PCI Platform Protocol >=20 > + >=20 > + This file define the necessary hooks used to obtain the platform >=20 > + level data and policies which could be used in the PCI Enumeration pha= ses >=20 > + >=20 > +Copyright (c) 2019, Intel Corporation. All rights reserved.
>=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > + >=20 > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_ >=20 > +#define _EFI_PCI_PLATFORM_SUPPORT_H_ >=20 > + >=20 > +#include "PciBus.h" >=20 > + >=20 > +/** >=20 > + This function retrieves the PCI Platform Protocol published by platfor= m > driver >=20 > + >=20 > +**/ >=20 > +VOID >=20 > +GetPciPlatformProtocol ( >=20 > + ); >=20 > + >=20 > +/** >=20 > + This function indicates the presence of PCI Platform driver >=20 > + @retval TRUE or FALSE >=20 > +**/ >=20 > +BOOLEAN >=20 > +CheckPciPlatformProtocolInstall ( >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + Provides the hooks from the PCI bus driver to every PCI controller > (device/function) at various >=20 > + stages of the PCI enumeration process that allow the host bridge drive= r to > preinitialize individual >=20 > + PCI controllers before enumeration. >=20 > + >=20 > + This function is called during the PCI enumeration process. No specifi= c > action is expected from this >=20 > + member function. It allows the host bridge driver to preinitialize ind= ividual > PCI controllers before >=20 > + enumeration. >=20 > + >=20 > + @param[in] HostBridgeHandle The associated PCI host bridge handle. >=20 > + @param[in] RootBridgeHandle The associated PCI root bridge handle. >=20 > + @param[in] RootBridgePciAddress The address of the PCI device on the > PCI bus. >=20 > + @param[in] Phase The phase of the PCI controller enumeration. >=20 > + @param[in] ExecPhase Defines the execution phase of the PCI chips= et > driver. >=20 > + >=20 > + @retval Status returns the status from the PCI Platform pro= tocol as is >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PciPlatformPreprocessController ( >=20 > + IN EFI_HANDLE HostBridgeHandle, >=20 > + IN EFI_HANDLE RootBridgeHandle, >=20 > + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS > RootBridgePciAddress, >=20 > + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase, >=20 > + IN EFI_PCI_EXECUTION_PHASE ExecPhase >=20 > + ); >=20 > + >=20 > +/** >=20 > + This function notifies the PCI Platform driver about the PCI host brid= ge > resource >=20 > + allocation phase and PCI execution phase. >=20 > + >=20 > + @param[in] HostBridge The handle of the host bridge controller. >=20 > + @param[in] Phase The phase of the PCI bus enumeration. >=20 > + @param[in] ExecPhase Defines the execution phase of the PCI chip= set > driver. >=20 > + @retval Status returns the status from the PCI Platform p= rotocol as > is >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PciPlatformNotifyPhase ( >=20 > + IN EFI_HANDLE HostBridgeHandle, >=20 > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase, >=20 > + IN EFI_PCI_EXECUTION_PHASE ExecPhase >=20 > + ); >=20 > + >=20 > +/** >=20 > + This function retrieves the PCI platform policy. >=20 > + >=20 > + @param PciPolicy pointer to the legacy EFI_PCI_PLATFORM_POLICY >=20 > + @retval Status returns the status from the PCI Platform protoco= l as is >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +PciGetPlatformPolicy ( >=20 > + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy >=20 > + ); >=20 > + >=20 > +/** >=20 > + This function retrieves the Option ROM image and size from the Platfor= m. >=20 > + >=20 > + It uses the PCI_IO_DEVICE internal fields are used to store OpROM > image/size >=20 > + >=20 > + @param Controller An EFI handle for the PCI bus controller. >=20 > + @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to = be > registered. >=20 > + >=20 > + @retval EFI_SUCCESS The option ROM was available for this d= evice > and loaded into memory. >=20 > + @retval EFI_NOT_FOUND No option ROM was available for this de= vice. >=20 > + @retval EFI_OUT_OF_RESOURCES No memory was available to load the > option ROM. >=20 > + @retval EFI_DEVICE_ERROR An error occurred in obtaining the opti= on > ROM. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPlatformPciOptionRom ( >=20 > + IN EFI_HANDLE Controller, >=20 > + IN PCI_IO_DEVICE *PciIoDevice >=20 > + ); >=20 > + >=20 > +/** >=20 > + Gets the PCI device-specific platform policy from the PCI Platform Pro= tocol. >=20 > + If no PCI Platform protocol is published than setup the PCI feature to > predetermined >=20 > + defaults, in order to align all the PCI devices in the PCI hierarchy, = as > applicable. >=20 > + >=20 > + @param PciDevice A pointer to PCI_IO_DEVICE >=20 > + >=20 > + @retval EFI_STATUS The direct status from the PCI Platform Protocol >=20 > + @retval EFI_SUCCESS On return of predetermined PCI features defaults= , > for >=20 > + the case when protocol returns as EFI_UNSUPPORTE= D to >=20 > + indicate PCI device exist and it has no platform= policy >=20 > + defined. Also, on returns when no PCI Platform P= rotocol >=20 > + exist. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +GetPciDevicePlatformPolicy ( >=20 > + IN PCI_IO_DEVICE *PciDevice >=20 > + ); >=20 > + >=20 > +/** >=20 > + Helper routine to indicate whether the given PCI device specific polic= y > value >=20 > + dictates to override the Max_Payload_Size to a particular value, or se= t as > per >=20 > + device capability. >=20 > + >=20 > + @param MPS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_PAYLOAD_SIZE >=20 > + >=20 > + @retval TRUE Setup Max_Payload_Size as per device capability >=20 > + FALSE override as per device-specific platform policy >=20 > +**/ >=20 > +BOOLEAN >=20 > +SetupMpsAsPerDeviceCapability ( >=20 > + IN UINT8 MPS >=20 > +); >=20 > + >=20 > +/** >=20 > + Helper routine to indicate whether the given PCI device specific polic= y > value >=20 > + dictates to override the Max_Read_Req_Size to a particular value, or s= et as > per >=20 > + device capability. >=20 > + >=20 > + @param MRRS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_READ_REQ_SIZE >=20 > + >=20 > + @retval TRUE Setup Max_Read_Req_Size as per device capability >=20 > + FALSE override as per device-specific platform policy >=20 > +**/ >=20 > +BOOLEAN >=20 > +SetupMrrsAsPerDeviceCapability ( >=20 > + IN UINT8 MRRS >=20 > +); >=20 > + >=20 > +/** >=20 > + Routine to translate the given device-specific platform policy from ty= pe >=20 > + EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base > Specification >=20 > + Revision 4.0; for the PCI feature Max_Payload_Size. >=20 > + >=20 > + @param MPS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_PAYLOAD_SIZE >=20 > + >=20 > + @retval Range values for the Max_Payload_Size as defined in th= e PCI >=20 > + Base Specification 4.0 >=20 > +**/ >=20 > +UINT8 >=20 > +TranslateMpsSetupValueToPci ( >=20 > + IN UINT8 MPS >=20 > +); >=20 > + >=20 > +/** >=20 > + Routine to translate the given device-specific platform policy from ty= pe >=20 > + EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI > Base Specification >=20 > + Revision 4.0; for the PCI feature Max_Read_Req_Size. >=20 > + >=20 > + @param MRRS Input device-specific policy should be in terms of typ= e >=20 > + EFI_PCI_CONF_MAX_READ_REQ_SIZE >=20 > + >=20 > + @retval Range values for the Max_Read_Req_Size as defined in t= he > PCI >=20 > + Base Specification 4.0 >=20 > +**/ >=20 > +UINT8 >=20 > +TranslateMrrsSetupValueToPci ( >=20 > + IN UINT8 MRRS >=20 > +); >=20 > +#endif >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c > index 4969ee0f64..755423f77b 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c > @@ -198,20 +198,7 @@ CalculateApertureIo16 ( > // >=20 > Status =3D EFI_NOT_FOUND; >=20 > PciPolicy =3D 0; >=20 > - if (gPciPlatformProtocol !=3D NULL) { >=20 > - Status =3D gPciPlatformProtocol->GetPlatformPolicy ( >=20 > - gPciPlatformProtocol, >=20 > - &PciPolicy >=20 > - ); >=20 > - } >=20 > - >=20 > - if (EFI_ERROR (Status) && gPciOverrideProtocol !=3D NULL) { >=20 > - Status =3D gPciOverrideProtocol->GetPlatformPolicy ( >=20 > - gPciOverrideProtocol, >=20 > - &PciPolicy >=20 > - ); >=20 > - } >=20 > - >=20 > + Status =3D PciGetPlatformPolicy ( &PciPolicy); >=20 > if (!EFI_ERROR (Status)) { >=20 > if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) !=3D 0) { >=20 > mReserveIsaAliases =3D TRUE; >=20 > diff --git a/MdeModulePkg/MdeModulePkg.dec > b/MdeModulePkg/MdeModulePkg.dec > index 17beb45235..7bcbe5a3ea 100644 > --- a/MdeModulePkg/MdeModulePkg.dec > +++ b/MdeModulePkg/MdeModulePkg.dec > @@ -1026,6 +1026,16 @@ > # @Prompt Enable UEFI Stack Guard. >=20 >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0 > x30001055 >=20 >=20 >=20 > + ## This PCD is to indicate the PCI Bus driver to setup other new PCI > features. >=20 > + # Each PCI feature is represented by its mask bit position and it con= figures >=20 > + # if that bit is set. >=20 > + # >=20 > + # Bit 0 - if set, the PCI Bus driver programs the device's > Max_Payload_Size.
>=20 > + # Bit 1 - if set, the PCI Bus driver programs the device's > Max_Read_Req_Size.
>=20 > + # Bit 2 to 31 - Reserved for future use by the PCI Bus driver.
>=20 > + # @Prompt The UEFI PCU Bus driver enables the new set of other PCI > Features. >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN > T32|0x30001056 >=20 > + >=20 > [PcdsFixedAtBuild, PcdsPatchableInModule] >=20 > ## Dynamic type PCD can be registered callback function for Pcd settin= g > action. >=20 > # PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum > number of callback function >=20 > -- > 2.21.0.windows.1