From: "Gao, Liming" <liming.gao@intel.com>
To: "Ni, Ruiyu" <ruiyu.ni@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH 4/5] MdePkg/PciSegmentLib: Add instances that consumes PciSegmentInfoLib
Date: Mon, 14 Aug 2017 06:58:40 +0000 [thread overview]
Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A14D770220@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <20170804064437.120328-5-ruiyu.ni@intel.com>
Ray:
I have several comments on this patch.
1) New library instance supports multiple segment. Their file header should describe this message instead of segment 0 only.
2) MdePkg\Library\PciSegmentLibSegmentInfo\BasePciSegmentLib.c miss file header.
3) The internal function PciSegmentLibGetEcamAddress() has no function header.
Thanks
Liming
>-----Original Message-----
>From: Ni, Ruiyu
>Sent: Friday, August 04, 2017 2:45 PM
>To: edk2-devel@lists.01.org
>Cc: Gao, Liming <liming.gao@intel.com>
>Subject: [PATCH 4/5] MdePkg/PciSegmentLib: Add instances that consumes
>PciSegmentInfoLib
>
>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 <ruiyu.ni@intel.com>
>Cc: Liming Gao <liming.gao@intel.com>
>---
> .../PciSegmentLibSegmentInfo/BasePciSegmentLib.c | 53 +
> .../BasePciSegmentLibSegmentInfo.inf | 45 +
> .../BasePciSegmentLibSegmentInfo.uni | 21 +
> .../DxeRuntimePciSegmentLib.c | 331 +++++
> .../DxeRuntimePciSegmentLibSegmentInfo.inf | 54 +
> .../DxeRuntimePciSegmentLibSegmentInfo.uni | 21 +
> .../PciSegmentLibSegmentInfo/PciSegmentLibCommon.c | 1364
>++++++++++++++++++++
> .../PciSegmentLibSegmentInfo/PciSegmentLibCommon.h | 46 +
> MdePkg/MdePkg.dsc | 2 +
> 9 files changed, 1937 insertions(+)
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInf
>o.inf
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInf
>o.uni
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSeg
>mentInfo.inf
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSeg
>mentInfo.uni
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c
> create mode 100644
>MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h
>
>diff --git a/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c
>b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c
>new file mode 100644
>index 0000000000..e2d3287f0c
>--- /dev/null
>+++ b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c
>@@ -0,0 +1,53 @@
>+#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 after
>+ SetVirtualAddressMap().
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address The address that encodes the PCI Bus, Device, Function
>and
>+ Register.
>+
>+ @retval RETURN_SUCCESS The PCI device was registered for runtime
>access.
>+ @retval RETURN_UNSUPPORTED An attempt was made to call this
>function
>+ after ExitBootServices().
>+ @retval RETURN_UNSUPPORTED The resources required to access the
>PCI device
>+ at runtime could not be mapped.
>+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources
>available to
>+ complete the registration.
>+
>+**/
>+RETURN_STATUS
>+EFIAPI
>+PciSegmentRegisterForRuntimeAccess (
>+ IN UINTN Address
>+ )
>+{
>+ //
>+ // Use PciSegmentLibGetEcamAddress() to validate the Address.
>+ //
>+ DEBUG_CODE (
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count);
>+ );
>+ return RETURN_SUCCESS;
>+}
>diff --git
>a/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentI
>nfo.inf
>b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentI
>nfo.inf
>new file mode 100644
>index 0000000000..021b9d9f4f
>--- /dev/null
>+++
>b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentI
>nfo.inf
>@@ -0,0 +1,45 @@
>+## @file
>+# Instance of PCI Segment Library based on PCI Library.
>+#
>+# PCI Segment Library that layers on top of the PCI Library which only
>+# supports segment 0 PCI configuration access.
>+#
>+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
>+#
>+# 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 IMPLIED.
>+#
>+#
>+##
>+
>+[Defines]
>+ INF_VERSION = 0x00010005
>+ BASE_NAME = BasePciSegmentLibSegmentInfo
>+ MODULE_UNI_FILE = BasePciSegmentLibSegmentInfo.uni
>+ FILE_GUID = 3427D883-E093-4CC9-BE85-6BD4058E96E2
>+ MODULE_TYPE = BASE
>+ VERSION_STRING = 1.0
>+ LIBRARY_CLASS = PciSegmentLib
>+
>+#
>+# The following information is for reference only and not required by the
>build tools.
>+#
>+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
>+#
>+
>+[Sources]
>+ PciSegmentLibCommon.c
>+ BasePciSegmentLib.c
>+
>+[Packages]
>+ MdePkg/MdePkg.dec
>+
>+[LibraryClasses]
>+ BaseLib
>+ IoLib
>+ DebugLib
>+ PciSegmentInfoLib
>diff --git
>a/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentI
>nfo.uni
>b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentI
>nfo.uni
>new file mode 100644
>index 0000000000..f5893d96d0
>--- /dev/null
>+++
>b/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentI
>nfo.uni
>@@ -0,0 +1,21 @@
>+// /** @file
>+// Instance of PCI Segment Library based on PCI Library.
>+//
>+// PCI Segment Library that layers on top of the PCI Library which only
>+// supports segment 0 PCI configuration access.
>+//
>+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>+//
>+// 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 IMPLIED.
>+//
>+// **/
>+
>+
>+#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI
>Segment Library based on PCI Library."
>+
>+#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment
>Library that layers on top of the PCI Library which only supports segment 0 PCI
>configuration access."
>diff --git
>a/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c
>b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c
>new file mode 100644
>index 0000000000..b1e6f791d8
>--- /dev/null
>+++
>b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c
>@@ -0,0 +1,331 @@
>+/** @file
>+ PCI Segment Library for DXE/Runtime modules.
>+
>+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
>+ 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 IMPLIED.
>+
>+**/
>+
>+#include "PciSegmentLibCommon.h"
>+#include <PiDxe.h>
>+#include <Guid/EventGroup.h>
>+#include <Library/UefiRuntimeLib.h>
>+#include <Library/DxeServicesTableLib.h>
>+#include <Library/UefiBootServicesTableLib.h>
>+#include <Library/MemoryAllocationLib.h>
>+#include <Library/PciSegmentInfoLib.h>
>+
>+///
>+/// Define table for mapping PCI Segment MMIO physical addresses to
>virtual addresses at OS runtime
>+///
>+typedef struct {
>+ UINTN PhysicalAddress;
>+ UINTN VirtualAddress;
>+} PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE;
>+
>+///
>+/// Set Virtual Address Map Event
>+///
>+EFI_EVENT mDxeRuntimePciSegmentLibVirtualNotifyEvent =
>NULL;
>+
>+///
>+/// The number of PCI devices that have been registered for runtime access.
>+///
>+UINTN
>mDxeRuntimePciSegmentLibNumberOfRuntimeRanges = 0;
>+
>+///
>+/// The table of PCI devices that have been registered for runtime access.
>+///
>+PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE
>*mDxeRuntimePciSegmentLibRegistrationTable = NULL;
>+
>+///
>+/// The table index of the most recent virtual address lookup.
>+///
>+UINTN mDxeRuntimePciSegmentLibLastRuntimeRange = 0;
>+
>+/**
>+ Convert the physical PCI Express MMIO addresses for all registered PCI
>devices
>+ 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 == NULL) {
>+ return;
>+ }
>+
>+ //
>+ // Convert physical addresses associated with the set of registered PCI
>devices to
>+ // virtual addresses.
>+ //
>+ for (Index = 0; Index <
>mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
>+ Status = EfiConvertPointer (0, (VOID **)
>&(mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress));
>+ ASSERT_EFI_ERROR (Status);
>+ }
>+
>+ //
>+ // Convert table pointer that is allocated from EfiRuntimeServicesData to a
>virtual address.
>+ //
>+ Status = EfiConvertPointer (0, (VOID **)
>&mDxeRuntimePciSegmentLibRegistrationTable);
>+ 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
>addresses.
>+
>+ @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 = 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
>Virtual
>+ 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, then
>+ // free the registration table.
>+ //
>+ if (mDxeRuntimePciSegmentLibRegistrationTable != NULL) {
>+ FreePool (mDxeRuntimePciSegmentLibRegistrationTable);
>+ }
>+
>+ //
>+ // Close the Set Virtual Address Map event
>+ //
>+ Status = gBS->CloseEvent (mDxeRuntimePciSegmentLibVirtualNotifyEvent);
>+ ASSERT_EFI_ERROR (Status);
>+
>+ return Status;
>+}
>+
>+/**
>+ Register a PCI device so PCI configuration registers may be accessed after
>+ SetVirtualAddressMap().
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address The address that encodes the PCI Bus, Device, Function
>and
>+ Register.
>+
>+ @retval RETURN_SUCCESS The PCI device was registered for runtime
>access.
>+ @retval RETURN_UNSUPPORTED An attempt was made to call this
>function
>+ after ExitBootServices().
>+ @retval RETURN_UNSUPPORTED The resources required to access the
>PCI device
>+ at runtime could not be mapped.
>+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources
>available to
>+ complete the registration.
>+
>+**/
>+RETURN_STATUS
>+EFIAPI
>+PciSegmentRegisterForRuntimeAccess (
>+ IN UINTN Address
>+ )
>+{
>+ 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
>Configuration
>+ // header for the specified PCI Bus/Dev/Func
>+ //
>+ Address &= ~(UINTN)0xfff;
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ EcamAddress = PciSegmentLibGetEcamAddress (Address, SegmentInfo,
>Count);
>+ DEBUG ((DEBUG_ERROR, "EcamAddress = %p\n", EcamAddress));
>+
>+ //
>+ // Return an error if this function is called after ExitBootServices().
>+ //
>+ if (EfiAtRuntime ()) {
>+ return RETURN_UNSUPPORTED;
>+ }
>+ if (sizeof (UINTN) == sizeof (UINT32)) {
>+ ASSERT (EcamAddress < BASE_4GB);
>+ }
>+ Address = (UINTN)EcamAddress;
>+ DEBUG ((DEBUG_ERROR, "Address = %p\n", Address));
>+
>+ //
>+ // See if Address has already been registerd for runtime access
>+ //
>+ for (Index = 0; Index <
>mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
>+ if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress
>== Address) {
>+ DEBUG ((DEBUG_ERROR, "%d\n", __LINE__));
>+ return RETURN_SUCCESS;
>+ }
>+ }
>+
>+ //
>+ // Get the GCD Memory Descriptor for the ECAM Address
>+ //
>+ Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);
>+ if (EFI_ERROR (Status)) {
>+ DEBUG ((DEBUG_ERROR, "%d\n", __LINE__));
>+ return RETURN_UNSUPPORTED;
>+ }
>+
>+ //
>+ // Mark the 4KB region for the PCI Express Bus/Dev/Func as
>EFI_RUNTIME_MEMORY so the OS
>+ // will allocate a virtual address range for the 4KB PCI Configuration Header.
>+ //
>+ Status = gDS->SetMemorySpaceAttributes (Address, 0x1000,
>Descriptor.Attributes | EFI_MEMORY_RUNTIME);
>+ if (EFI_ERROR (Status)) {
>+ DEBUG ((DEBUG_ERROR, "%d\n", __LINE__));
>+ return RETURN_UNSUPPORTED;
>+ }
>+
>+ //
>+ // Grow the size of the registration table
>+ //
>+ NewTable = ReallocateRuntimePool (
>+ (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 0) * sizeof
>(PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE),
>+ (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 1) * sizeof
>(PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE),
>+ mDxeRuntimePciSegmentLibRegistrationTable
>+ );
>+ if (NewTable == NULL) {
>+ DEBUG ((DEBUG_ERROR, "%d\n", __LINE__));
>+ return RETURN_OUT_OF_RESOURCES;
>+ }
>+ mDxeRuntimePciSegmentLibRegistrationTable = NewTable;
>+
>mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibN
>umberOfRuntimeRanges].PhysicalAddress = Address;
>+
>mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibN
>umberOfRuntimeRanges].VirtualAddress = 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
>physical address
>+ //
>+ if (!EfiGoneVirtual ()) {
>+ return Address;
>+ }
>+
>+ DEBUG ((DEBUG_ERROR, "Dump Begin: \n"));
>+ for (Index = 0; Index <
>mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
>+ DEBUG ((DEBUG_ERROR, "%d: %p %p\n", Index,
>mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress,
>+ mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress));
>+ }
>+ DEBUG ((DEBUG_ERROR, "Dump End\n"));
>+
>+ //
>+ // See if there is a physical address match at the exact same index as the
>last address match
>+ //
>+ if
>(mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibL
>astRuntimeRange].PhysicalAddress == (Address & (~(UINTN)0xfff))) {
>+ //
>+ // Convert the physical address to a virtual address and return the virtual
>address
>+ //
>+ return (Address & 0xfff) +
>mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibL
>astRuntimeRange].VirtualAddress;
>+ }
>+
>+ //
>+ // Search the entire table for a physical address match
>+ //
>+ for (Index = 0; Index <
>mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
>+ if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress
>== (Address & (~(UINTN)0xfff))) {
>+ //
>+ // Cache the matching index value
>+ //
>+ mDxeRuntimePciSegmentLibLastRuntimeRange = Index;
>+ //
>+ // Convert the physical address to a virtual address and return the virtual
>address
>+ //
>+ return (Address & 0xfff) +
>mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress;
>+ }
>+ }
>+
>+ //
>+ // No match was found. This is a critical error at OS runtime, so ASSERT()
>and force a breakpoint.
>+ //
>+ ASSERT (FALSE);
>+ CpuBreakpoint ();
>+
>+ //
>+ // Return the physical address
>+ //
>+ return Address;
>+}
>diff --git
>a/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSe
>gmentInfo.inf
>b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSe
>gmentInfo.inf
>new file mode 100644
>index 0000000000..de5d1623bf
>--- /dev/null
>+++
>b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSe
>gmentInfo.inf
>@@ -0,0 +1,54 @@
>+## @file
>+# Instance of PCI Segment Library based on PCI Library.
>+#
>+# PCI Segment Library that layers on top of the PCI Library which only
>+# supports segment 0 PCI configuration access.
>+#
>+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
>+#
>+# 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 IMPLIED.
>+#
>+#
>+##
>+
>+[Defines]
>+ INF_VERSION = 0x00010005
>+ BASE_NAME = DxeRuntimePciSegmentLibSegmentInfo
>+ MODULE_UNI_FILE = DxeRuntimePciSegmentLibSegmentInfo.uni
>+ FILE_GUID = F73EB3DE-F4E3-47CB-9F18-97796AE06314
>+ MODULE_TYPE = DXE_RUNTIME_DRIVER
>+ VERSION_STRING = 1.0
>+ LIBRARY_CLASS = PciSegmentLib|DXE_RUNTIME_DRIVER
>+ CONSTRUCTOR = DxeRuntimePciSegmentLibConstructor
>+ DESTRUCTOR = DxeRuntimePciSegmentLibDestructor
>+
>+#
>+# The following information is for reference only and not required by the
>build tools.
>+#
>+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
>+#
>+
>+[Sources]
>+ 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/DxeRuntimePciSegmentLibSe
>gmentInfo.uni
>b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSe
>gmentInfo.uni
>new file mode 100644
>index 0000000000..f5893d96d0
>--- /dev/null
>+++
>b/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSe
>gmentInfo.uni
>@@ -0,0 +1,21 @@
>+// /** @file
>+// Instance of PCI Segment Library based on PCI Library.
>+//
>+// PCI Segment Library that layers on top of the PCI Library which only
>+// supports segment 0 PCI configuration access.
>+//
>+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>+//
>+// 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 IMPLIED.
>+//
>+// **/
>+
>+
>+#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI
>Segment Library based on PCI Library."
>+
>+#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment
>Library that layers on top of the PCI Library which only supports segment 0 PCI
>configuration access."
>diff --git
>a/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c
>b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c
>new file mode 100644
>index 0000000000..07b9c5540f
>--- /dev/null
>+++ b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c
>@@ -0,0 +1,1364 @@
>+/** @file
>+ PCI Segment Library that layers on top of the PCI Library which only
>+ supports segment 0 PCI configuration access.
>+
>+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
>+ 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 IMPLIED.
>+
>+**/
>+
>+#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;
>+
>+UINTN
>+PciSegmentLibGetEcamAddress (
>+ IN UINT64 Address,
>+ IN CONST PCI_SEGMENT_INFO *SegmentInfo,
>+ IN UINTN Count
>+ )
>+{
>+ while (Count != 0) {
>+ if (SegmentInfo->SegmentNumber ==
>((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Segment) {
>+ break;
>+ }
>+ SegmentInfo++;
>+ Count--;
>+ }
>+ ASSERT (Count != 0);
>+ ASSERT (
>+ (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Reserved1 ==
>0) &&
>+ (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Reserved2 ==
>0)
>+ );
>+ ASSERT (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus >=
>SegmentInfo->StartBusNumber);
>+ ASSERT (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus <=
>SegmentInfo->EndBusNumber);
>+
>+ Address = 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) == 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 Address.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+
>+ @return The 8-bit PCI configuration register specified by Address.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentRead8 (
>+ IN UINT64 Address
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioRead8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count));
>+}
>+
>+/**
>+ Writes an 8-bit PCI configuration register.
>+
>+ Writes the 8-bit PCI configuration register specified by Address with the
>value specified by Value.
>+ Value is returned. This function must guarantee that all PCI read and write
>operations are serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param Value The value to write.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentWrite8 (
>+ IN UINT64 Address,
>+ IN UINT8 Value
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioWrite8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), Value);
>+}
>+
>+/**
>+ Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit
>value.
>+
>+ Reads the 8-bit PCI configuration register specified by Address,
>+ performs a bitwise OR between the read result and the value specified by
>OrData,
>+ and writes the result to the 8-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentOr8 (
>+ IN UINT64 Address,
>+ IN UINT8 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = 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 by
>AndData,
>+ and writes the result to the 8-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param AndData The value to AND with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentAnd8 (
>+ IN UINT64 Address,
>+ IN UINT8 AndData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioAnd8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo,
>Count), AndData);
>+}
>+
>+/**
>+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
>value,
>+ followed a bitwise OR with another 8-bit value.
>+
>+ Reads the 8-bit PCI configuration register specified by Address,
>+ performs a bitwise AND between the read result and the value specified by
>AndData,
>+ performs a bitwise OR between the result of the AND operation and the
>value specified by OrData,
>+ and writes the result to the 8-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param AndData The value to AND with the PCI configuration register.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentAndThenOr8 (
>+ IN UINT64 Address,
>+ IN UINT8 AndData,
>+ IN UINT8 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = 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 field is
>+ specified by the StartBit and the EndBit. The value of the bit field is
>+ returned.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 7, then ASSERT().
>+ If EndBit is greater than 7, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+
>+ @param Address PCI configuration register to read.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..7.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..7.
>+
>+ @return The value of the bit field read from the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentBitFieldRead8 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldRead8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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 the
>+ 8-bit register is returned.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 7, then ASSERT().
>+ If EndBit is greater than 7, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If Value is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..7.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..7.
>+ @param Value New value of the bit field.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentBitFieldWrite8 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT8 Value
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldWrite8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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, performs a
>+ bitwise OR between the read result and the value specified by
>+ OrData, and writes the result to the 8-bit PCI configuration register
>+ specified by Address. The value written to the PCI configuration register is
>+ returned. This function must guarantee that all PCI read and write
>operations
>+ are serialized. Extra left bits in OrData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 7, then ASSERT().
>+ If EndBit is greater than 7, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If OrData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..7.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..7.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentBitFieldOr8 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT8 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldOr8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), StartBit, EndBit, OrData);
>+}
>+
>+/**
>+ Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
>+ AND, and writes the result back to the bit field in the 8-bit register.
>+
>+ Reads the 8-bit PCI configuration register specified by Address, performs a
>+ bitwise AND between the read result and the value specified by AndData,
>and
>+ writes the result to the 8-bit PCI configuration register specified by
>+ Address. The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>+ serialized. Extra left bits in AndData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 7, then ASSERT().
>+ If EndBit is greater than 7, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If AndData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..7.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..7.
>+ @param AndData The value to AND with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentBitFieldAnd8 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT8 AndData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldOr8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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 port.
>+
>+ Reads the 8-bit PCI configuration register specified by Address, performs a
>+ bitwise AND followed by a bitwise OR between the read result and
>+ the value specified by AndData, and writes the result to the 8-bit PCI
>+ configuration register specified by Address. The value written to the PCI
>+ configuration register is returned. This function must guarantee that all PCI
>+ read and write operations are serialized. Extra left bits in both AndData and
>+ OrData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 7, then ASSERT().
>+ If EndBit is greater than 7, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If AndData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+ If OrData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..7.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..7.
>+ @param AndData The value to AND with the PCI configuration register.
>+ @param OrData The value to OR with the result of the AND operation.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT8
>+EFIAPI
>+PciSegmentBitFieldAndThenOr8 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT8 AndData,
>+ IN UINT8 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldAndThenOr8 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), StartBit, EndBit, AndData, OrData);
>+}
>+
>+/**
>+ Reads a 16-bit PCI configuration register.
>+
>+ Reads and returns the 16-bit PCI configuration register specified by Address.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+
>+ @return The 16-bit PCI configuration register specified by Address.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentRead16 (
>+ IN UINT64 Address
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioRead16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count));
>+}
>+
>+/**
>+ Writes a 16-bit PCI configuration register.
>+
>+ Writes the 16-bit PCI configuration register specified by Address with the
>value specified by Value.
>+ Value is returned. This function must guarantee that all PCI read and write
>operations are serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param Value The value to write.
>+
>+ @return The parameter of Value.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentWrite16 (
>+ IN UINT64 Address,
>+ IN UINT16 Value
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioWrite16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), Value);
>+}
>+
>+/**
>+ Performs a bitwise OR of a 16-bit PCI configuration register with
>+ a 16-bit value.
>+
>+ Reads the 16-bit PCI configuration register specified by Address, performs a
>+ bitwise OR between the read result and the value specified by OrData, and
>+ writes the result to the 16-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned. This function
>+ must guarantee that all PCI read and write operations are serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function and
>+ Register.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentOr16 (
>+ IN UINT64 Address,
>+ IN UINT16 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo,
>Count), OrData);
>+}
>+
>+/**
>+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
>value.
>+
>+ Reads the 16-bit PCI configuration register specified by Address,
>+ performs a bitwise AND between the read result and the value specified by
>AndData,
>+ and writes the result to the 16-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param AndData The value to AND with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentAnd16 (
>+ IN UINT64 Address,
>+ IN UINT16 AndData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioAnd16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), AndData);
>+}
>+
>+/**
>+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
>value,
>+ followed a bitwise OR with another 16-bit value.
>+
>+ Reads the 16-bit PCI configuration register specified by Address,
>+ performs a bitwise AND between the read result and the value specified by
>AndData,
>+ performs a bitwise OR between the result of the AND operation and the
>value specified by OrData,
>+ and writes the result to the 16-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param AndData The value to AND with the PCI configuration register.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentAndThenOr16 (
>+ IN UINT64 Address,
>+ IN UINT16 AndData,
>+ IN UINT16 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioAndThenOr16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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 field is
>+ specified by the StartBit and the EndBit. The value of the bit field is
>+ returned.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+ If StartBit is greater than 15, then ASSERT().
>+ If EndBit is greater than 15, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+
>+ @param Address PCI configuration register to read.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..15.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..15.
>+
>+ @return The value of the bit field read from the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentBitFieldRead16 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldRead16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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 the
>+ 16-bit register is returned.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+ If StartBit is greater than 15, then ASSERT().
>+ If EndBit is greater than 15, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If Value is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..15.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..15.
>+ @param Value New value of the bit field.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentBitFieldWrite16 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT16 Value
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldWrite16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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, performs a
>+ bitwise OR between the read result and the value specified by
>+ OrData, and writes the result to the 16-bit PCI configuration register
>+ specified by Address. The value written to the PCI configuration register is
>+ returned. This function must guarantee that all PCI read and write
>operations
>+ are serialized. Extra left bits in OrData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+ If StartBit is greater than 15, then ASSERT().
>+ If EndBit is greater than 15, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If OrData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..15.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..15.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentBitFieldOr16 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT16 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldOr16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), StartBit, EndBit, OrData);
>+}
>+
>+/**
>+ Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
>+ AND, writes the result back to the bit field in the 16-bit register.
>+
>+ Reads the 16-bit PCI configuration register specified by Address, performs a
>+ bitwise AND between the read result and the value specified by AndData,
>and
>+ writes the result to the 16-bit PCI configuration register specified by
>+ Address. The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>+ serialized. Extra left bits in AndData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 16-bit boundary, then ASSERT().
>+ If StartBit is greater than 15, then ASSERT().
>+ If EndBit is greater than 15, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If AndData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..15.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..15.
>+ @param AndData The value to AND with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentBitFieldAnd16 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT16 AndData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldOr16 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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, performs a
>+ bitwise AND followed by a bitwise OR between the read result and
>+ the value specified by AndData, and writes the result to the 16-bit PCI
>+ configuration register specified by Address. The value written to the PCI
>+ configuration register is returned. This function must guarantee that all PCI
>+ read and write operations are serialized. Extra left bits in both AndData and
>+ OrData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 15, then ASSERT().
>+ If EndBit is greater than 15, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If AndData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+ If OrData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..15.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..15.
>+ @param AndData The value to AND with the PCI configuration register.
>+ @param OrData The value to OR with the result of the AND operation.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT16
>+EFIAPI
>+PciSegmentBitFieldAndThenOr16 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT16 AndData,
>+ IN UINT16 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldAndThenOr16 (PciSegmentLibGetEcamAddress
>(Address, SegmentInfo, Count), StartBit, EndBit, AndData, OrData);
>+}
>+
>+/**
>+ Reads a 32-bit PCI configuration register.
>+
>+ Reads and returns the 32-bit PCI configuration register specified by Address.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+
>+ @return The 32-bit PCI configuration register specified by Address.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentRead32 (
>+ IN UINT64 Address
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioRead32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count));
>+}
>+
>+/**
>+ Writes a 32-bit PCI configuration register.
>+
>+ Writes the 32-bit PCI configuration register specified by Address with the
>value specified by Value.
>+ Value is returned. This function must guarantee that all PCI read and write
>operations are serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param Value The value to write.
>+
>+ @return The parameter of Value.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentWrite32 (
>+ IN UINT64 Address,
>+ IN UINT32 Value
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioWrite32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), Value);
>+}
>+
>+/**
>+ Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit
>value.
>+
>+ Reads the 32-bit PCI configuration register specified by Address,
>+ performs a bitwise OR between the read result and the value specified by
>OrData,
>+ and writes the result to the 32-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentOr32 (
>+ IN UINT64 Address,
>+ IN UINT32 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo,
>Count), OrData);
>+}
>+
>+/**
>+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
>value.
>+
>+ Reads the 32-bit PCI configuration register specified by Address,
>+ performs a bitwise AND between the read result and the value specified by
>AndData,
>+ and writes the result to the 32-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param AndData The value to AND with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentAnd32 (
>+ IN UINT64 Address,
>+ IN UINT32 AndData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioAnd32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), AndData);
>+}
>+
>+/**
>+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
>value,
>+ followed a bitwise OR with another 32-bit value.
>+
>+ Reads the 32-bit PCI configuration register specified by Address,
>+ performs a bitwise AND between the read result and the value specified by
>AndData,
>+ performs a bitwise OR between the result of the AND operation and the
>value specified by OrData,
>+ and writes the result to the 32-bit PCI configuration register specified by
>Address.
>+ The value written to the PCI configuration register is returned.
>+ This function must guarantee that all PCI read and write operations are
>serialized.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param AndData The value to AND with the PCI configuration register.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentAndThenOr32 (
>+ IN UINT64 Address,
>+ IN UINT32 AndData,
>+ IN UINT32 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioAndThenOr32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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 field is
>+ specified by the StartBit and the EndBit. The value of the bit field is
>+ returned.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+ If StartBit is greater than 31, then ASSERT().
>+ If EndBit is greater than 31, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+
>+ @param Address PCI configuration register to read.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..31.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..31.
>+
>+ @return The value of the bit field read from the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentBitFieldRead32 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldRead32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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 the
>+ 32-bit register is returned.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+ If StartBit is greater than 31, then ASSERT().
>+ If EndBit is greater than 31, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If Value is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..31.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..31.
>+ @param Value New value of the bit field.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentBitFieldWrite32 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT32 Value
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldWrite32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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, performs a
>+ bitwise OR between the read result and the value specified by
>+ OrData, and writes the result to the 32-bit PCI configuration register
>+ specified by Address. The value written to the PCI configuration register is
>+ returned. This function must guarantee that all PCI read and write
>operations
>+ are serialized. Extra left bits in OrData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 31, then ASSERT().
>+ If EndBit is greater than 31, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If OrData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..31.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..31.
>+ @param OrData The value to OR with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentBitFieldOr32 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT32 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldOr32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, Count), StartBit, EndBit, OrData);
>+}
>+
>+/**
>+ Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
>+ AND, and writes the result back to the bit field in the 32-bit register.
>+
>+
>+ Reads the 32-bit PCI configuration register specified by Address, performs a
>bitwise
>+ AND between the read result and the value specified by AndData, and
>writes the result
>+ to the 32-bit PCI configuration register specified by Address. The value
>written to
>+ the PCI configuration register is returned. This function must guarantee
>that all PCI
>+ read and write operations are serialized. Extra left bits in AndData are
>stripped.
>+ If any reserved bits in Address are set, then ASSERT().
>+ If Address is not aligned on a 32-bit boundary, then ASSERT().
>+ If StartBit is greater than 31, then ASSERT().
>+ If EndBit is greater than 31, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If AndData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address Address that encodes the PCI Segment, Bus, Device,
>Function, and Register.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..31.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..31.
>+ @param AndData The value to AND with the PCI configuration register.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentBitFieldAnd32 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT32 AndData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldOr32 (PciSegmentLibGetEcamAddress (Address,
>SegmentInfo, 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, performs a
>+ bitwise AND followed by a bitwise OR between the read result and
>+ the value specified by AndData, and writes the result to the 32-bit PCI
>+ configuration register specified by Address. The value written to the PCI
>+ configuration register is returned. This function must guarantee that all PCI
>+ read and write operations are serialized. Extra left bits in both AndData and
>+ OrData are stripped.
>+
>+ If any reserved bits in Address are set, then ASSERT().
>+ If StartBit is greater than 31, then ASSERT().
>+ If EndBit is greater than 31, then ASSERT().
>+ If EndBit is less than StartBit, then ASSERT().
>+ If AndData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+ If OrData is larger than the bitmask value range specified by StartBit and
>EndBit, then ASSERT().
>+
>+ @param Address PCI configuration register to write.
>+ @param StartBit The ordinal of the least significant bit in the bit field.
>+ Range 0..31.
>+ @param EndBit The ordinal of the most significant bit in the bit field.
>+ Range 0..31.
>+ @param AndData The value to AND with the PCI configuration register.
>+ @param OrData The value to OR with the result of the AND operation.
>+
>+ @return The value written back to the PCI configuration register.
>+
>+**/
>+UINT32
>+EFIAPI
>+PciSegmentBitFieldAndThenOr32 (
>+ IN UINT64 Address,
>+ IN UINTN StartBit,
>+ IN UINTN EndBit,
>+ IN UINT32 AndData,
>+ IN UINT32 OrData
>+ )
>+{
>+ UINTN Count;
>+ PCI_SEGMENT_INFO *SegmentInfo;
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ return MmioBitFieldAndThenOr32 (PciSegmentLibGetEcamAddress
>(Address, SegmentInfo, Count), StartBit, EndBit, AndData, OrData);
>+}
>+
>+/**
>+ Reads a range of PCI configuration registers into a caller supplied buffer.
>+
>+ Reads the range of PCI configuration registers specified by StartAddress and
>+ Size into the buffer specified by Buffer. This function only allows the PCI
>+ configuration registers from a single PCI function to be read. Size is
>+ returned. When possible 32-bit PCI configuration read cycles are used to
>read
>+ from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
>+ and 16-bit PCI configuration read cycles may be used at the beginning and
>the
>+ end of the range.
>+
>+ If any reserved bits in StartAddress are set, then ASSERT().
>+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
>+ If Size > 0 and Buffer is NULL, then ASSERT().
>+
>+ @param StartAddress 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) <= 0x1000);
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ Address = PciSegmentLibGetEcamAddress (StartAddress, SegmentInfo,
>Count);
>+
>+ if (Size == 0) {
>+ return 0;
>+ }
>+
>+ ASSERT (Buffer != NULL);
>+
>+ //
>+ // Save Size for return
>+ //
>+ ReturnValue = Size;
>+
>+ if ((Address & BIT0) != 0) {
>+ //
>+ // Read a byte if StartAddress is byte aligned
>+ //
>+ *(volatile UINT8 *)Buffer = MmioRead8 (Address);
>+ Address += sizeof (UINT8);
>+ Size -= sizeof (UINT8);
>+ Buffer = (UINT8*)Buffer + 1;
>+ }
>+
>+ if (Size >= sizeof (UINT16) && (Address & BIT1) != 0) {
>+ //
>+ // Read a word if StartAddress is word aligned
>+ //
>+ WriteUnaligned16 (Buffer, MmioRead16 (Address));
>+ Address += sizeof (UINT16);
>+ Size -= sizeof (UINT16);
>+ Buffer = (UINT16*)Buffer + 1;
>+ }
>+
>+ while (Size >= sizeof (UINT32)) {
>+ //
>+ // Read as many double words as possible
>+ //
>+ WriteUnaligned32 (Buffer, MmioRead32 (Address));
>+ Address += sizeof (UINT32);
>+ Size -= sizeof (UINT32);
>+ Buffer = (UINT32*)Buffer + 1;
>+ }
>+
>+ if (Size >= sizeof (UINT16)) {
>+ //
>+ // Read the last remaining word if exist
>+ //
>+ WriteUnaligned16 (Buffer, MmioRead16 (Address));
>+ Address += sizeof (UINT16);
>+ Size -= sizeof (UINT16);
>+ Buffer = (UINT16*)Buffer + 1;
>+ }
>+
>+ if (Size >= sizeof (UINT8)) {
>+ //
>+ // Read the last remaining byte if exist
>+ //
>+ *(volatile UINT8 *)Buffer = 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 StartAddress
>and
>+ Size from the buffer specified by Buffer. This function only allows the PCI
>+ configuration registers from a single PCI function to be written. Size is
>+ returned. When possible 32-bit PCI configuration write cycles are used to
>+ write from StartAdress to StartAddress + Size. Due to alignment restrictions,
>+ 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
>+ and the end of the range.
>+
>+ If any reserved bits in StartAddress are set, then ASSERT().
>+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
>+ If Size > 0 and Buffer is NULL, then ASSERT().
>+
>+ @param StartAddress 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) <= 0x1000);
>+
>+ SegmentInfo = GetPciSegmentInfo (&Count);
>+ Address = PciSegmentLibGetEcamAddress (StartAddress, SegmentInfo,
>Count);
>+
>+ if (Size == 0) {
>+ return 0;
>+ }
>+
>+ ASSERT (Buffer != NULL);
>+
>+ //
>+ // Save Size for return
>+ //
>+ ReturnValue = Size;
>+
>+ if ((Address & BIT0) != 0) {
>+ //
>+ // Write a byte if StartAddress is byte aligned
>+ //
>+ MmioWrite8 (Address, *(UINT8*)Buffer);
>+ Address += sizeof (UINT8);
>+ Size -= sizeof (UINT8);
>+ Buffer = (UINT8*)Buffer + 1;
>+ }
>+
>+ if (Size >= sizeof (UINT16) && (Address & BIT1) != 0) {
>+ //
>+ // Write a word if StartAddress is word aligned
>+ //
>+ MmioWrite16 (Address, ReadUnaligned16 (Buffer));
>+ Address += sizeof (UINT16);
>+ Size -= sizeof (UINT16);
>+ Buffer = (UINT16*)Buffer + 1;
>+ }
>+
>+ while (Size >= sizeof (UINT32)) {
>+ //
>+ // Write as many double words as possible
>+ //
>+ MmioWrite32 (Address, ReadUnaligned32 (Buffer));
>+ Address += sizeof (UINT32);
>+ Size -= sizeof (UINT32);
>+ Buffer = (UINT32*)Buffer + 1;
>+ }
>+
>+ if (Size >= sizeof (UINT16)) {
>+ //
>+ // Write the last remaining word if exist
>+ //
>+ MmioWrite16 (Address, ReadUnaligned16 (Buffer));
>+ Address += sizeof (UINT16);
>+ Size -= sizeof (UINT16);
>+ Buffer = (UINT16*)Buffer + 1;
>+ }
>+
>+ if (Size >= 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..4f50d526a0
>--- /dev/null
>+++
>b/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h
>@@ -0,0 +1,46 @@
>+/** @file
>+ PCI Segment Library that layers on top of the PCI Library which only
>+ supports segment 0 PCI configuration access.
>+
>+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
>+ 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 IMPLIED.
>+
>+**/
>+
>+#ifndef _PCI_SEGMENT_LIB_COMMON_H_
>+#define _PCI_SEGMENT_LIB_COMMON_H_
>+
>+#include <Base.h>
>+#include <IndustryStandard/PciExpress21.h>
>+#include <Library/BaseLib.h>
>+#include <Library/DebugLib.h>
>+#include <Library/IoLib.h>
>+#include <Library/PciSegmentLib.h>
>+#include <Library/PciSegmentInfoLib.h>
>+
>+/**
>+ Return the linear address for the physical address.
>+
>+ @param Address The physical address.
>+
>+ @retval The linear address.
>+**/
>+UINTN
>+PciSegmentLibVirtualAddress (
>+ IN UINTN 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/BasePciSegmentLibSegmentInf
>o.inf
>+
>MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSeg
>mentInfo.inf
>
>MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.in
>f
> MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
>
>MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull
>.inf
>--
>2.12.2.windows.2
next prev parent reply other threads:[~2017-08-14 6:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-04 6:44 [PATCH 0/5] Add new implementation of PciSegmentLib and S3PciSegmentLib class&instance Ruiyu Ni
2017-08-04 6:44 ` [PATCH 1/5] MdePkg/PciSegmentLib: Fix typo in function header comments Ruiyu Ni
2017-08-04 6:44 ` [PATCH 2/5] MdePkg/PciExpress: Add macro PCI_ECAM_ADDRESS Ruiyu Ni
2017-08-04 6:44 ` [PATCH 3/5] MdePkg/PciSegmentInfoLib: Add PciSegmentInfoLib class and instance Ruiyu Ni
2017-08-04 6:44 ` [PATCH 4/5] MdePkg/PciSegmentLib: Add instances that consumes PciSegmentInfoLib Ruiyu Ni
2017-08-14 6:58 ` Gao, Liming [this message]
2017-08-04 6:44 ` [PATCH 5/5] MdePkg/S3PciSegmentLib: Add S3PciSegmentLib class and instance Ruiyu Ni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A89E2EF3DFEDB4C8BFDE51014F606A14D770220@shsmsx102.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox