From nobody Fri Dec 27 02:40:16 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 15036514661351015.4010865061304; Fri, 25 Aug 2017 01:57:46 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 9D48A21D1E2DF; Fri, 25 Aug 2017 01:54:59 -0700 (PDT) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 381CD21D1E2E9 for ; Fri, 25 Aug 2017 01:54:56 -0700 (PDT) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Aug 2017 01:57:31 -0700 Received: from ray-dev.ccr.corp.intel.com ([10.239.9.2]) by orsmga004.jf.intel.com with ESMTP; 25 Aug 2017 01:57:30 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,424,1498546800"; d="scan'208";a="122500782" From: Ruiyu Ni To: edk2-devel@lists.01.org Date: Fri, 25 Aug 2017 16:57:22 +0800 Message-Id: <20170825085723.396044-5-ruiyu.ni@intel.com> X-Mailer: git-send-email 2.12.2.windows.2 In-Reply-To: <20170825085723.396044-1-ruiyu.ni@intel.com> References: <20170825085723.396044-1-ruiyu.ni@intel.com> Subject: [edk2] [PATCH v2 4/5] MdePkg/PciSegmentLib: Add instances that consumes PciSegmentInfoLib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Liming Gao MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The patch adds two PciSegmentLib instances that consumes PciSegmentInfoLib to provide multiple segments PCI configuration access. BasePciSegmentLibSegmentInfo instance is a BASE library. DxeRuntimePciSegmentLibSegmentInfo instance is to be linked with runtime drivers to provide not only boot time but also runtime PCI configuration access. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni Cc: Liming Gao --- .../PciSegmentLibSegmentInfo/BasePciSegmentLib.c | 71 + .../BasePciSegmentLibSegmentInfo.inf | 46 + .../BasePciSegmentLibSegmentInfo.uni | 21 + .../DxeRuntimePciSegmentLib.c | 321 +++++ .../DxeRuntimePciSegmentLibSegmentInfo.inf | 55 + .../DxeRuntimePciSegmentLibSegmentInfo.uni | 21 + .../PciSegmentLibSegmentInfo/PciSegmentLibCommon.c | 1375 ++++++++++++++++= ++++ .../PciSegmentLibSegmentInfo/PciSegmentLibCommon.h | 57 + MdePkg/MdePkg.dsc | 2 + 9 files changed, 1969 insertions(+) create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentL= ib.c create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentL= ibSegmentInfo.inf create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentL= ibSegmentInfo.uni create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSe= gmentLib.c create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSe= gmentLibSegmentInfo.inf create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSe= gmentLibSegmentInfo.uni create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCo= mmon.c create mode 100644 MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCo= mmon.h diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c b/= MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c new file mode 100644 index 0000000000..e71624d4ba --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c @@ -0,0 +1,71 @@ +/** @file + Instance of Base PCI Segment Library that support multi-segment PCI conf= iguration access. + + PCI Segment Library that consumes segment information provided by PciSeg= mentInfoLib to + support multi-segment PCI configuration access through enhanced configu= ration access mechanism. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "PciSegmentLibCommon.h" + +/** + Return the virtual address for the physical address. + + @param Address The physical address. + + @retval The virtual address. +**/ +UINTN +PciSegmentLibVirtualAddress ( + IN UINTN Address + ) +{ + return Address; +} + +/** + Register a PCI device so PCI configuration registers may be accessed aft= er + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function a= nd + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runti= me access. + @retval RETURN_UNSUPPORTED An attempt was made to call this functi= on + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PC= I device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources availabl= e to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + // + // Use PciSegmentLibGetEcamAddress() to validate the Address. + // + DEBUG_CODE ( + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count); + ); + return RETURN_SUCCESS; +} diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegme= ntInfo.inf b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegme= ntInfo.inf new file mode 100644 index 0000000000..9cd60764dc --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.= inf @@ -0,0 +1,46 @@ +## @file +# Instance of Base PCI Segment Library that support multi-segment PCI conf= iguration access. +# +# PCI Segment Library that consumes segment information provided by PciSeg= mentInfoLib to +# support multi-segment PCI configuration access through enhanced configu= ration access mechanism. +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D BasePciSegmentLibSegmentInfo + MODULE_UNI_FILE =3D BasePciSegmentLibSegmentInfo.uni + FILE_GUID =3D 3427D883-E093-4CC9-BE85-6BD4058E96E2 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PciSegmentLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC +# + +[Sources] + PciSegmentLibCommon.h + PciSegmentLibCommon.c + BasePciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + IoLib + DebugLib + PciSegmentInfoLib diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegme= ntInfo.uni b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegme= ntInfo.uni new file mode 100644 index 0000000000..ad33a5fdad --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.= uni @@ -0,0 +1,21 @@ +// /** @file +// Instance of Base PCI Segment Library that support multi-segment PCI con= figuration access. + +// PCI Segment Library that consumes segment information provided by PciSe= gmentInfoLib to +// support multi-segment PCI configuration access through enhanced config= uration access mechanism. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the B= SD License +// which accompanies this distribution. The full text of the license may b= e found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base = PCI Segment Library that support multi-segment PCI configuration access." + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment Libra= ry that consumes segment information provided by PciSegmentInfoLib to suppo= rt multi-segment PCI configuration access through enhanced configuration ac= cess mechanism." diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLi= b.c b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c new file mode 100644 index 0000000000..9c86608677 --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c @@ -0,0 +1,321 @@ +/** @file + Instance of Runtime PCI Segment Library that support multi-segment PCI c= onfiguration access. + + PCI Segment Library that consumes segment information provided by PciSeg= mentInfoLib to + support multi-segment PCI configuration access through enhanced configu= ration access mechanism. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "PciSegmentLibCommon.h" +#include +#include +#include +#include +#include +#include +#include + +/// +/// Define table for mapping PCI Segment MMIO physical addresses to virtua= l addresses at OS runtime +/// +typedef struct { + UINTN PhysicalAddress; + UINTN VirtualAddress; +} PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE; + +/// +/// Set Virtual Address Map Event +/// +EFI_EVENT mDxeRuntimePciSegmentLibVirtualNot= ifyEvent =3D NULL; + +/// +/// The number of PCI devices that have been registered for runtime access. +/// +UINTN mDxeRuntimePciSegmentLibNumberOfRu= ntimeRanges =3D 0; + +/// +/// The table of PCI devices that have been registered for runtime access. +/// +PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE *mDxeRuntimePciSegmentLibRegistrat= ionTable =3D NULL; + +/// +/// The table index of the most recent virtual address lookup. +/// +UINTN mDxeRuntimePciSegmentLibLastRuntim= eRange =3D 0; + +/** + Convert the physical PCI Express MMIO addresses for all registered PCI d= evices + to virtual addresses. + + @param[in] Event The event that is being processed. + @param[in] Context The Event Context. +**/ +VOID +EFIAPI +DxeRuntimePciSegmentLibVirtualNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + EFI_STATUS Status; + + // + // If there have been no runtime registrations, then just return + // + if (mDxeRuntimePciSegmentLibRegistrationTable =3D=3D NULL) { + return; + } + + // + // Convert physical addresses associated with the set of registered PCI = devices to + // virtual addresses. + // + for (Index =3D 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges;= Index++) { + Status =3D EfiConvertPointer (0, (VOID **) &(mDxeRuntimePciSegmentLibR= egistrationTable[Index].VirtualAddress)); + ASSERT_EFI_ERROR (Status); + } + + // + // Convert table pointer that is allocated from EfiRuntimeServicesData t= o a virtual address. + // + Status =3D EfiConvertPointer (0, (VOID **) &mDxeRuntimePciSegmentLibRegi= strationTable); + ASSERT_EFI_ERROR (Status); +} + +/** + The constructor function caches the PCI Express Base Address and creates= a + Set Virtual Address Map event to convert physical address to virtual add= resses. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor completed successfully. + @retval Other value The constructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeRuntimePciSegmentLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Register SetVirtualAddressMap () notify function + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DxeRuntimePciSegmentLibVirtualNotify, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mDxeRuntimePciSegmentLibVirtualNotifyEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + The destructor function frees any allocated buffers and closes the Set V= irtual + Address Map event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor completed successfully. + @retval Other value The destructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeRuntimePciSegmentLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // If one or more PCI devices have been registered for runtime access, t= hen + // free the registration table. + // + if (mDxeRuntimePciSegmentLibRegistrationTable !=3D NULL) { + FreePool (mDxeRuntimePciSegmentLibRegistrationTable); + } + + // + // Close the Set Virtual Address Map event + // + Status =3D gBS->CloseEvent (mDxeRuntimePciSegmentLibVirtualNotifyEvent); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Register a PCI device so PCI configuration registers may be accessed aft= er + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function a= nd + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runti= me access. + @retval RETURN_UNSUPPORTED An attempt was made to call this functi= on + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PC= I device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources availabl= e to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + RETURN_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Index; + VOID *NewTable; + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + UINT64 EcamAddress; + + // + // Convert Address to a ECAM address at the beginning of the PCI Configu= ration + // header for the specified PCI Bus/Dev/Func + // + Address &=3D ~(UINTN)EFI_PAGE_MASK; + SegmentInfo =3D GetPciSegmentInfo (&Count); + EcamAddress =3D PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count= ); + + // + // Return an error if this function is called after ExitBootServices(). + // + if (EfiAtRuntime ()) { + return RETURN_UNSUPPORTED; + } + if (sizeof (UINTN) =3D=3D sizeof (UINT32)) { + ASSERT (EcamAddress < BASE_4GB); + } + Address =3D (UINTN)EcamAddress; + + // + // See if Address has already been registerd for runtime access + // + for (Index =3D 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges;= Index++) { + if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress = =3D=3D Address) { + return RETURN_SUCCESS; + } + } + + // + // Get the GCD Memory Descriptor for the ECAM Address + // + Status =3D gDS->GetMemorySpaceDescriptor (Address, &Descriptor); + if (EFI_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + // + // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_M= EMORY so the OS + // will allocate a virtual address range for the 4KB PCI Configuration H= eader. + // + Status =3D gDS->SetMemorySpaceAttributes (Address, EFI_PAGE_SIZE, Descri= ptor.Attributes | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + // + // Grow the size of the registration table + // + NewTable =3D ReallocateRuntimePool ( + (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 0) * sizeo= f (PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE), + (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 1) * sizeo= f (PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE), + mDxeRuntimePciSegmentLibRegistrationTable + ); + if (NewTable =3D=3D NULL) { + return RETURN_OUT_OF_RESOURCES; + } + mDxeRuntimePciSegmentLibRegistrationTable =3D NewTable; + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibNumber= OfRuntimeRanges].PhysicalAddress =3D Address; + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibNumber= OfRuntimeRanges].VirtualAddress =3D Address; + mDxeRuntimePciSegmentLibNumberOfRuntimeRanges++; + + return RETURN_SUCCESS; +} + +/** + Return the linear address for the physical address. + + @param Address The physical address. + + @retval The linear address. +**/ +UINTN +PciSegmentLibVirtualAddress ( + IN UINTN Address + ) +{ + UINTN Index; + // + // If SetVirtualAddressMap() has not been called, then just return the p= hysical address + // + if (!EfiGoneVirtual ()) { + return Address; + } + + // + // See if there is a physical address match at the exact same index as t= he last address match + // + if (mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLa= stRuntimeRange].PhysicalAddress =3D=3D (Address & (~(UINTN)EFI_PAGE_MASK)))= { + // + // Convert the physical address to a virtual address and return the vi= rtual address + // + return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistratio= nTable[mDxeRuntimePciSegmentLibLastRuntimeRange].VirtualAddress; + } + + // + // Search the entire table for a physical address match + // + for (Index =3D 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges;= Index++) { + if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress = =3D=3D (Address & (~(UINTN)EFI_PAGE_MASK))) { + // + // Cache the matching index value + // + mDxeRuntimePciSegmentLibLastRuntimeRange =3D Index; + // + // Convert the physical address to a virtual address and return the = virtual address + // + return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrat= ionTable[Index].VirtualAddress; + } + } + + // + // No match was found. This is a critical error at OS runtime, so ASSER= T() and force a breakpoint. + // + ASSERT (FALSE); + CpuBreakpoint (); + + // + // Return the physical address + // + return Address; +} diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLi= bSegmentInfo.inf b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSeg= mentLibSegmentInfo.inf new file mode 100644 index 0000000000..e484af5b06 --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmen= tInfo.inf @@ -0,0 +1,55 @@ +## @file +# Instance of Runtime PCI Segment Library that support multi-segment PCI c= onfiguration access. +# +# PCI Segment Library that consumes segment information provided by PciSeg= mentInfoLib to +# support multi-segment PCI configuration access through enhanced configu= ration access mechanism. +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D DxeRuntimePciSegmentLibSegmentInfo + MODULE_UNI_FILE =3D DxeRuntimePciSegmentLibSegmentInfo.uni + FILE_GUID =3D F73EB3DE-F4E3-47CB-9F18-97796AE06314 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PciSegmentLib|DXE_RUNTIME_DRIVER + CONSTRUCTOR =3D DxeRuntimePciSegmentLibConstructor + DESTRUCTOR =3D DxeRuntimePciSegmentLibDestructor + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC +# + +[Sources] + PciSegmentLibCommon.h + PciSegmentLibCommon.c + DxeRuntimePciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + IoLib + DebugLib + PciSegmentInfoLib + UefiRuntimeLib + MemoryAllocationLib + DxeServicesTableLib + UefiBootServicesTableLib + +[Guids] + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLi= bSegmentInfo.uni b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSeg= mentLibSegmentInfo.uni new file mode 100644 index 0000000000..171fc7d16c --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmen= tInfo.uni @@ -0,0 +1,21 @@ +// /** @file +// Instance of Runtime PCI Segment Library that support multi-segment PCI = configuration access. + +// PCI Segment Library that consumes segment information provided by PciSe= gmentInfoLib to +// support multi-segment PCI configuration access through enhanced config= uration access mechanism. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the B= SD License +// which accompanies this distribution. The full text of the license may b= e found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Runti= me PCI Segment Library that support multi-segment PCI configuration access." + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment Libra= ry that consumes segment information provided by PciSegmentInfoLib to suppo= rt multi-segment PCI configuration access through enhanced configuration ac= cess mechanism." diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c = b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c new file mode 100644 index 0000000000..7b7324d673 --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c @@ -0,0 +1,1375 @@ +/** @file + Provide common routines used by BasePciSegmentLibSegmentInfo and + DxeRuntimePciSegmentLibSegmentInfo libraries. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "PciSegmentLibCommon.h" + +typedef struct { + UINT64 Register : 12; + UINT64 Function : 3; + UINT64 Device : 5; + UINT64 Bus : 8; + UINT64 Reserved1 : 4; + UINT64 Segment : 16; + UINT64 Reserved2 : 16; +} PCI_SEGMENT_LIB_ADDRESS_STRUCTURE; + +/** + Internal function that converts PciSegmentLib format address that encode= s the PCI Bus, Device, + Function and Register to ECAM (Enhanced Configuration Access Mechanism) = address. + + @param Address The address that encodes the PCI Bus, Device, Functio= n and + Register. + @param SegmentInfo An array of PCI_SEGMENT_INFO holding the segment info= rmation. + @param Count Number of segments. + + @retval ECAM address. +**/ +UINTN +PciSegmentLibGetEcamAddress ( + IN UINT64 Address, + IN CONST PCI_SEGMENT_INFO *SegmentInfo, + IN UINTN Count + ) +{ + while (Count !=3D 0) { + if (SegmentInfo->SegmentNumber =3D=3D ((PCI_SEGMENT_LIB_ADDRESS_STRUCT= URE *)&Address)->Segment) { + break; + } + SegmentInfo++; + Count--; + } + ASSERT (Count !=3D 0); + ASSERT ( + (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Reserved1 =3D=3D 0) = && + (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Reserved2 =3D=3D 0) + ); + ASSERT (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus >=3D Segmen= tInfo->StartBusNumber); + ASSERT (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus <=3D Segmen= tInfo->EndBusNumber); + + Address =3D SegmentInfo->BaseAddress + PCI_ECAM_ADDRESS ( + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus, + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Device, + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Function, + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Register); + + if (sizeof (UINTN) =3D=3D sizeof (UINT32)) { + ASSERT (Address < BASE_4GB); + } + + return PciSegmentLibVirtualAddress ((UINTN)Address); +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Addr= ess. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioRead8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Cou= nt)); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with th= e value specified by Value. + Value is returned. This function must guarantee that all PCI read and w= rite operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, F= unction, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioWrite8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Co= unt), Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-b= it value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by= OrData, + and writes the result to the 8-bit PCI configuration register specified = by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count= ), OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-= bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified b= y AndData, + and writes the result to the 8-bit PCI configuration register specified = by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioAnd8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Coun= t), AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-= bit value, + followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified b= y AndData, + performs a bitwise OR between the result of the AND operation and the va= lue specified by OrData, + and writes the result to the 8-bit PCI configuration register specified = by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioAndThenOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo= , Count), AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit fiel= d is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..7. + + @return The value of the bit field read from the PCI configuration regis= ter. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldRead8 (PciSegmentLibGetEcamAddress (Address, SegmentI= nfo, Count), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of t= he + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit an= d EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldWrite8 (PciSegmentLibGetEcamAddress (Address, Segment= Info, Count), StartBit, EndBit, Value); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, = and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, perform= s a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration registe= r is + returned. This function must guarantee that all PCI read and write opera= tions + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit a= nd EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInf= o, Count), StartBit, EndBit, OrData); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bit= wise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, perform= s a + bitwise AND between the read result and the value specified by AndData, = and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit = and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInf= o, Count), StartBit, EndBit, AndData); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the 8-bit por= t. + + Reads the 8-bit PCI configuration register specified by Address, perform= s a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that al= l PCI + read and write operations are serialized. Extra left bits in both AndDat= a and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit = and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit a= nd EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldAndThenOr8 (PciSegmentLibGetEcamAddress (Address, Seg= mentInfo, Count), StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Add= ress. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioRead16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Co= unt)); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with t= he value specified by Value. + Value is returned. This function must guarantee that all PCI read and w= rite operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, F= unction, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioWrite16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, C= ount), Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, perfor= ms a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 16-bit PCI configuration register specified by = Address. + The value written to the PCI configuration register is returned. This fu= nction + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Funct= ion and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Coun= t), OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-= bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified b= y AndData, + and writes the result to the 16-bit PCI configuration register specified= by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioAnd16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Cou= nt), AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-= bit value, + followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified b= y AndData, + performs a bitwise OR between the result of the AND operation and the va= lue specified by OrData, + and writes the result to the 16-bit PCI configuration register specified= by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioAndThenOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInf= o, Count), AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit fiel= d is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..15. + + @return The value of the bit field read from the PCI configuration regis= ter. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldRead16 (PciSegmentLibGetEcamAddress (Address, Segment= Info, Count), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of t= he + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit an= d EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldWrite16 (PciSegmentLibGetEcamAddress (Address, Segmen= tInfo, Count), StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, = writes + the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, perfor= ms a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration registe= r is + returned. This function must guarantee that all PCI read and write opera= tions + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit a= nd EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldOr16 (PciSegmentLibGetEcamAddress (Address, SegmentIn= fo, Count), StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bit= wise + AND, writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, perfor= ms a + bitwise AND between the read result and the value specified by AndData, = and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit = and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldOr16 (PciSegmentLibGetEcamAddress (Address, SegmentIn= fo, Count), StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, perfor= ms a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that al= l PCI + read and write operations are serialized. Extra left bits in both AndDat= a and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit = and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit a= nd EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldAndThenOr16 (PciSegmentLibGetEcamAddress (Address, Se= gmentInfo, Count), StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Add= ress. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioRead32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Co= unt)); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with t= he value specified by Value. + Value is returned. This function must guarantee that all PCI read and w= rite operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, F= unction, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioWrite32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, C= ount), Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a 32-b= it value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by= OrData, + and writes the result to the 32-bit PCI configuration register specified= by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Coun= t), OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-= bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified b= y AndData, + and writes the result to the 32-bit PCI configuration register specified= by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioAnd32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Cou= nt), AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-= bit value, + followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified b= y AndData, + performs a bitwise OR between the result of the AND operation and the va= lue specified by OrData, + and writes the result to the 32-bit PCI configuration register specified= by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are = serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioAndThenOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInf= o, Count), AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit fiel= d is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..31. + + @return The value of the bit field read from the PCI configuration regis= ter. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldRead32 (PciSegmentLibGetEcamAddress (Address, Segment= Info, Count), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of t= he + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit an= d EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldWrite32 (PciSegmentLibGetEcamAddress (Address, Segmen= tInfo, Count), StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, = and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, perfor= ms a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration registe= r is + returned. This function must guarantee that all PCI read and write opera= tions + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit a= nd EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldOr32 (PciSegmentLibGetEcamAddress (Address, SegmentIn= fo, Count), StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bit= wise + AND, and writes the result back to the bit field in the 32-bit register. + + + Reads the 32-bit PCI configuration register specified by Address, perfor= ms a bitwise + AND between the read result and the value specified by AndData, and writ= es the result + to the 32-bit PCI configuration register specified by Address. The value= written to + the PCI configuration register is returned. This function must guarante= e that all PCI + read and write operations are serialized. Extra left bits in AndData ar= e stripped. + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit = and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Fun= ction, and Register. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldOr32 (PciSegmentLibGetEcamAddress (Address, SegmentIn= fo, Count), StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, perfor= ms a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that al= l PCI + read and write operations are serialized. Extra left bits in both AndDat= a and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit = and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit a= nd EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit fi= eld. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit fie= ld. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + SegmentInfo =3D GetPciSegmentInfo (&Count); + return MmioBitFieldAndThenOr32 (PciSegmentLibGetEcamAddress (Address, Se= gmentInfo, Count), StartBit, EndBit, AndData, OrData); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buff= er. + + Reads the range of PCI configuration registers specified by StartAddress= and + Size into the buffer specified by Buffer. This function only allows the = PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to= read + from StartAdress to StartAddress + Size. Due to alignment restrictions, = 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning an= d the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus= , Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + UINTN Address; + + ASSERT (((StartAddress & 0xFFF) + Size) <=3D 0x1000); + + SegmentInfo =3D GetPciSegmentInfo (&Count); + Address =3D PciSegmentLibGetEcamAddress (StartAddress, SegmentInfo, Coun= t); + + if (Size =3D=3D 0) { + return 0; + } + + ASSERT (Buffer !=3D NULL); + + // + // Save Size for return + // + ReturnValue =3D Size; + + if ((Address & BIT0) !=3D 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer =3D MmioRead8 (Address); + Address +=3D sizeof (UINT8); + Size -=3D sizeof (UINT8); + Buffer =3D (UINT8*)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16) && (Address & BIT1) !=3D 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, MmioRead16 (Address)); + Address +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16*)Buffer + 1; + } + + while (Size >=3D sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, MmioRead32 (Address)); + Address +=3D sizeof (UINT32); + Size -=3D sizeof (UINT32); + Buffer =3D (UINT32*)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, MmioRead16 (Address)); + Address +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16*)Buffer + 1; + } + + if (Size >=3D sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer =3D MmioRead8 (Address); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddres= s and + Size from the buffer specified by Buffer. This function only allows the = PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrict= ions, + 8-bit and 16-bit PCI configuration write cycles may be used at the begin= ning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus= , Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + UINTN Address; + + ASSERT (((StartAddress & 0xFFF) + Size) <=3D 0x1000); + + SegmentInfo =3D GetPciSegmentInfo (&Count); + Address =3D PciSegmentLibGetEcamAddress (StartAddress, SegmentInfo, Coun= t); + + if (Size =3D=3D 0) { + return 0; + } + + ASSERT (Buffer !=3D NULL); + + // + // Save Size for return + // + ReturnValue =3D Size; + + if ((Address & BIT0) !=3D 0) { + // + // Write a byte if StartAddress is byte aligned + // + MmioWrite8 (Address, *(UINT8*)Buffer); + Address +=3D sizeof (UINT8); + Size -=3D sizeof (UINT8); + Buffer =3D (UINT8*)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16) && (Address & BIT1) !=3D 0) { + // + // Write a word if StartAddress is word aligned + // + MmioWrite16 (Address, ReadUnaligned16 (Buffer)); + Address +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16*)Buffer + 1; + } + + while (Size >=3D sizeof (UINT32)) { + // + // Write as many double words as possible + // + MmioWrite32 (Address, ReadUnaligned32 (Buffer)); + Address +=3D sizeof (UINT32); + Size -=3D sizeof (UINT32); + Buffer =3D (UINT32*)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + MmioWrite16 (Address, ReadUnaligned16 (Buffer)); + Address +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16*)Buffer + 1; + } + + if (Size >=3D sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + MmioWrite8 (Address, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h = b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h new file mode 100644 index 0000000000..4e1f523098 --- /dev/null +++ b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h @@ -0,0 +1,57 @@ +/** @file + Provide common routines used by BasePciSegmentLibSegmentInfo and + DxeRuntimePciSegmentLibSegmentInfo libraries. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef _PCI_SEGMENT_LIB_COMMON_H_ +#define _PCI_SEGMENT_LIB_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include + +/** + Return the linear address for the physical address. + + @param Address The physical address. + + @retval The linear address. +**/ +UINTN +PciSegmentLibVirtualAddress ( + IN UINTN Address + ); + +/** + Internal function that converts PciSegmentLib format address that encode= s the PCI Bus, Device, + Function and Register to ECAM (Enhanced Configuration Access Mechanism) = address. + + @param Address The address that encodes the PCI Bus, Device, Functio= n and + Register. + @param SegmentInfo An array of PCI_SEGMENT_INFO holding the segment info= rmation. + @param Count Number of segments. + + @retval ECAM address. +**/ +UINTN +PciSegmentLibGetEcamAddress ( + IN UINT64 Address, + IN CONST PCI_SEGMENT_INFO *SegmentInfo, + IN UINTN Count + ); + +#endif diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc index e553a702a3..19545aa398 100644 --- a/MdePkg/MdePkg.dsc +++ b/MdePkg/MdePkg.dsc @@ -70,6 +70,8 @@ [Components] MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf + MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf + MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentIn= fo.inf MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull= .inf --=20 2.12.2.windows.2 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel