public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "WangYang" <wangyang@bosc.ac.cn>
To: devel@edk2.groups.io
Cc: sunilvl@ventanamicro.com, git@danielschaefer.me,
	 "Ran Wang" <wangran@bosc.ac.cn>,
	 "Leif Lindholm" <quic_llindhol@quicinc.com>,
	 "Michael D Kinney" <michael.d.kinney@intel.com>
Subject: Re: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
Date: Wed, 15 May 2024 15:40:47 +0800 (GMT+08:00)	[thread overview]
Message-ID: <29ca357a.eb.18f7b3255cd.Coremail.wangyang@bosc.ac.cn> (raw)
In-Reply-To: <17C6FF8EBB82206B.20815@groups.io>

Hi,Sunil V L

   Thank you very much for your attention.
   How about this status.
   This patch is based on  https://edk2.groups.io/g/devel/topic/105437172#msg118579.   
   I also want to know the status of this patch(https://edk2.groups.io/g/devel/topic/105437172#msg118579).  
   
Best Regards,
Yang Wang

> -----原始邮件-----
> 发件人: WangYang <wangyang@bosc.ac.cn>
> 发送时间: 2024-04-17 15:08:06 (星期三)
> 收件人: sunilvl@ventanamicro.com, git@danielschaefer.me, devel@edk2.groups.io
> 抄送: "Yang Wang" <wangyang@bosc.ac.cn>, "Ran Wang" <wangran@bosc.ac.cn>, "Leif Lindholm" <quic_llindhol@quicinc.com>, "Michael D Kinney" <michael.d.kinney@intel.com>
> 主题: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
> 
> 1.Xilinx RC is XDMA
> 2.Support NVME storage
> 
> Nvme storage needs to be formatted to FAT32 format.
> 
> Reviewed-by: Ran Wang <wangran@bosc.ac.cn>
> Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Sunil V L <sunilvl@ventanamicro.com>
> Cc: Daniel Schaefer <git@danielschaefer.me>
> Signed-off-by: Yang Wang <wangyang@bosc.ac.cn>
> ---
>  .../XiangshanSeriesPkg/NanhuDev/NanhuDev.dsc  |   30 +-
>  .../XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf  |   13 +-
>  .../NanhuDev/NanhuDev.fdf.inc                 |    1 +
>  .../PciHostBridgeLib/PciHostBridgeLib.c       |  273 ++++
>  .../PciHostBridgeLib/PciHostBridgeLib.inf     |   48 +
>  .../Library/PciSegmentLib/PciSegmentLib.c     | 1391 +++++++++++++++++
>  .../Library/PciSegmentLib/PciSegmentLib.inf   |   29 +
>  Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec         |   20 +
>  8 files changed, 1802 insertions(+), 3 deletions(-)
>  create mode 100644 Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
>  create mode 100644 Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>  create mode 100755 Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.c
>  create mode 100755 Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.inf
> 
> diff --git a/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.dsc b/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.dsc
> index 7dcd7c4313..85934f66be 100644
> --- a/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.dsc
> +++ b/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.dsc
> @@ -239,6 +239,9 @@
>    PlatformBootManagerLib|Platform/RISC-V/PlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
>    PlatformMemoryTestLib|Platform/RISC-V/PlatformPkg/Library/PlatformMemoryTestLibNull/PlatformMemoryTestLibNull.inf
>    PlatformUpdateProgressLib|Platform/RISC-V/PlatformPkg/Library/PlatformUpdateProgressLibNull/PlatformUpdateProgressLibNull.inf
> +  # Pci dependencies
> +  PciSegmentLib|Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.inf
> +  PciHostBridgeLib|Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>  
>  [LibraryClasses.common.UEFI_APPLICATION]
>    PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
> @@ -262,6 +265,24 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
>  
>  [PcdsFixedAtBuild]
> +  #
> +  # XILINX PCI Root Complex
> +  #
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0x40000000
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|FALSE
> +  gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation|0x0
> +  gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation|0x50000000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciConfigBase|0x40000000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciConfigSize|0x10000000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciBusMin|0
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciBusMax|255
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciIoBase|0x00000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciIoSize|0xf00000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio32Base|0x50000000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio32Size|0x10000000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio64Base|0x1000000000
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio64Size|0x0000000000
> +
>    gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
>    gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
>    gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
> @@ -427,11 +448,13 @@
>    MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
>  !endif
>  
> -  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
> +  Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
> +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>      <LibraryClasses>
>        PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
>    }
> +  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
>    MdeModulePkg/Universal/Metronome/Metronome.inf
>    MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
>    MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf {
> @@ -440,6 +463,11 @@
>    }
>    EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
>  
> +  #
> +  # NVME Support
> +  #
> +  MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
> +
>    #
>    # RISC-V Platform module
>    #
> diff --git a/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf b/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf
> index d54bb73353..45c96f58a0 100644
> --- a/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf
> +++ b/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf
> @@ -69,8 +69,6 @@ INF  OvmfPkg/Fdt/HighMemDxe/HighMemDxe.inf
>  
>  INF  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
>  INF  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
> -INF  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
> -INF  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
>  INF  MdeModulePkg/Universal/Metronome/Metronome.inf
>  INF  EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
>  
> @@ -127,6 +125,17 @@ INF  ShellPkg/Application/Shell/Shell.inf
>  
>  !include NetworkPkg/Network.fdf.inc
>  
> +#
> +# PCI Support
> +#
> +INF Silicon/RISC-V/ProcessorPkg/Universal/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
> +INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +
> +# NVMe boot devices
> +#
> +INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
> +
>  #
>  # Usb Support
>  #
> diff --git a/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf.inc b/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf.inc
> index b78d25f83e..66934e5efe 100644
> --- a/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf.inc
> +++ b/Platform/Bosc/XiangshanSeriesPkg/NanhuDev/NanhuDev.fdf.inc
> @@ -60,3 +60,4 @@ SET gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase              = 0x310B00
>  SET gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate                   = 115200
>  SET gHisiTokenSpaceGuid.PcdSerialPortSendDelay                        = 50
>  SET gHisiTokenSpaceGuid.PcdUartClkInHz                                = 50000000
> +
> diff --git a/Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 0000000000..a25728affc
> --- /dev/null
> +++ b/Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,273 @@
> +/** @file
> +  PCI host bridge library instance for NanHuDev SOC.
> +
> +  Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
> +  Copyright (c) 2024, Bosc. All rights reserved.<BR>ved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +#include <Library/IoLib.h>
> +
> +#pragma pack(1)
> +
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
> +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
> +
> +#pragma pack ()
> +
> +#define BIT(nr)         (1UL << (nr))
> +#define GENMASK(h, l) \
> +    (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
> +
> +/* Register definitions */
> +#define XILINX_PCIE_REG_VSEC		0x0000012c
> +#define XILINX_PCIE_REG_BIR		0x00000130
> +#define XILINX_PCIE_REG_IDR		0x00000138
> +#define XILINX_PCIE_REG_IMR		0x0000013c
> +#define XILINX_PCIE_REG_PSCR		0x00000144
> +#define XILINX_PCIE_REG_RPSC		0x00000148
> +#define XILINX_PCIE_REG_MSIBASE1	0x0000014c
> +#define XILINX_PCIE_REG_MSIBASE2	0x00000150
> +#define XILINX_PCIE_REG_RPEFR		0x00000154
> +#define XILINX_PCIE_REG_RPIFR1		0x00000158
> +#define XILINX_PCIE_REG_RPIFR2		0x0000015c
> +#define XILINX_PCIE_REG_IDRN            0x00000160
> +#define XILINX_PCIE_REG_IDRN_MASK       0x00000164
> +#define XILINX_PCIE_REG_MSI_LOW		0x00000170
> +#define XILINX_PCIE_REG_MSI_HI		0x00000174
> +#define XILINX_PCIE_REG_MSI_LOW_MASK	0x00000178
> +#define XILINX_PCIE_REG_MSI_HI_MASK	0x0000017c
> +
> +/* Interrupt registers definitions */
> +#define XILINX_PCIE_INTR_LINK_DOWN	BIT(0)
> +#define XILINX_PCIE_INTR_HOT_RESET	BIT(3)
> +#define XILINX_PCIE_INTR_CFG_TIMEOUT	BIT(8)
> +#define XILINX_PCIE_INTR_CORRECTABLE	BIT(9)
> +#define XILINX_PCIE_INTR_NONFATAL	BIT(10)
> +#define XILINX_PCIE_INTR_FATAL		BIT(11)
> +#define XILINX_PCIE_INTR_INTX		BIT(16)
> +#define XILINX_PCIE_INTR_MSI		BIT(17)
> +#define XILINX_PCIE_INTR_SLV_UNSUPP	BIT(20)
> +#define XILINX_PCIE_INTR_SLV_UNEXP	BIT(21)
> +#define XILINX_PCIE_INTR_SLV_COMPL	BIT(22)
> +#define XILINX_PCIE_INTR_SLV_ERRP	BIT(23)
> +#define XILINX_PCIE_INTR_SLV_CMPABT	BIT(24)
> +#define XILINX_PCIE_INTR_SLV_ILLBUR	BIT(25)
> +#define XILINX_PCIE_INTR_MST_DECERR	BIT(26)
> +#define XILINX_PCIE_INTR_MST_SLVERR	BIT(27)
> +#define XILINX_PCIE_IMR_ALL_MASK	0x0FF30FE9
> +#define XILINX_PCIE_IDR_ALL_MASK	0xFFFFFFFF
> +#define XILINX_PCIE_IDRN_MASK           GENMASK(19, 16)
> +
> +/* Root Port Error FIFO Read Register definitions */
> +#define XILINX_PCIE_RPEFR_ERR_VALID	BIT(18)
> +#define XILINX_PCIE_RPEFR_REQ_ID	GENMASK(15, 0)
> +#define XILINX_PCIE_RPEFR_ALL_MASK	0xFFFFFFFF
> +
> +/* Root Port Interrupt FIFO Read Register 1 definitions */
> +#define XILINX_PCIE_RPIFR1_INTR_VALID	BIT(31)
> +#define XILINX_PCIE_RPIFR1_MSI_INTR	BIT(30)
> +#define XILINX_PCIE_RPIFR1_INTR_MASK	GENMASK(28, 27)
> +#define XILINX_PCIE_RPIFR1_ALL_MASK	0xFFFFFFFF
> +#define XILINX_PCIE_RPIFR1_INTR_SHIFT	27
> +#define XILINX_PCIE_IDRN_SHIFT          16
> +#define XILINX_PCIE_VSEC_REV_MASK	GENMASK(19, 16)
> +#define XILINX_PCIE_VSEC_REV_SHIFT	16
> +#define XILINX_PCIE_FIFO_SHIFT		5
> +
> +/* Bridge Info Register definitions */
> +#define XILINX_PCIE_BIR_ECAM_SZ_MASK	GENMASK(18, 16)
> +#define XILINX_PCIE_BIR_ECAM_SZ_SHIFT	16
> +
> +/* Root Port Interrupt FIFO Read Register 2 definitions */
> +#define XILINX_PCIE_RPIFR2_MSG_DATA	GENMASK(15, 0)
> +
> +/* Root Port Status/control Register definitions */
> +#define XILINX_PCIE_REG_RPSC_BEN	BIT(0)
> +
> +/* Phy Status/Control Register definitions */
> +#define XILINX_PCIE_REG_PSCR_LNKUP	BIT(11)
> +
> +/* ECAM definitions */
> +#define ECAM_BUS_NUM_SHIFT		20
> +#define ECAM_DEV_NUM_SHIFT		12
> +
> +/* Number of MSI IRQs */
> +#define XILINX_NUM_MSI_IRQS		64
> +#define INTX_NUM                        4
> +
> +#define DMA_BRIDGE_BASE_OFF		0xCD8
> +
> +
> +#define END_DEVICE_PATH_DEF { END_DEVICE_PATH_TYPE, \
> +                              END_ENTIRE_DEVICE_PATH_SUBTYPE, \
> +                              { END_DEVICE_PATH_LENGTH, 0 } \
> +                            }
> +
> +#define ACPI_DEVICE_PATH_DEF(UID) {{ ACPI_DEVICE_PATH, ACPI_DP, \
> +                                     { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
> +                                       (UINT8) (sizeof (ACPI_HID_DEVICE_PATH) >> 8)} \
> +                                     }, \
> +                                     EISA_PNP_ID (0x0A03), UID \
> +                                  }
> +
> +STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[] = {
> +  {
> +    ACPI_DEVICE_PATH_DEF (0),
> +    END_DEVICE_PATH_DEF
> +  },
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +STATIC PCI_ROOT_BRIDGE mRootBridge = {
> +  0,                                              // Segment
> +  0,                                              // Supports
> +  0,                                              // Attributes
> +  FALSE,                                           // DmaAbove4G
> +  FALSE,                                          // NoExtendedConfigSpace
> +  FALSE,                                          // ResourceAssigned
> +  0,           // AllocationAttributes
> +  {
> +    // Bus
> +    FixedPcdGet32 (PcdPciBusMin),
> +    FixedPcdGet32 (PcdPciBusMax)
> +  }, {
> +    // Io
> +    FixedPcdGet64 (PcdPciIoBase),
> +    FixedPcdGet64 (PcdPciIoBase) + FixedPcdGet64 (PcdPciIoSize) - 1
> +  }, {
> +    // Mem
> +    FixedPcdGet32 (PcdPciMmio32Base),
> +    FixedPcdGet32 (PcdPciMmio32Base) + (FixedPcdGet32 (PcdPciMmio32Size) - 1)
> +    //0x7FFFFFFF
> +  }, {
> +    // MemAbove4G
> +    FixedPcdGet64 (PcdPciMmio64Base),
> +    FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size) - 1
> +  }, {
> +    // PMem
> +    MAX_UINT64,
> +    0
> +  }, {
> +    // PMemAbove4G
> +    MAX_UINT64,
> +    0
> +  },
> +  (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath
> +};
> +
> +/**
> +  Return all the root bridge instances in an array.
> +
> +  @param[out] Count  Return the count of root bridge instances.
> +
> +  @return All the root bridge instances in an array.
> +          The array should be passed into PciHostBridgeFreeRootBridges()
> +          when it's not used.
> +
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> +  OUT UINTN     *Count
> +  )
> +{
> +  /* Enable the Bridge enable bit */
> +  UINT64 PciConfigBase = FixedPcdGet64 (PcdPciConfigBase);
> +  UINT32 Rpsc = MmioRead32 (PciConfigBase + XILINX_PCIE_REG_RPSC);
> +  MmioWrite32 (PciConfigBase + XILINX_PCIE_REG_RPSC, Rpsc | XILINX_PCIE_REG_RPSC_BEN);
> +  DEBUG ((DEBUG_INFO, "PciHostBridgeGetRootBridges():%d PciConfigBase:0x%x Rpsc:0x%x XILINX_PCIE_REG_RPSC_BEN:0x%x\n", \
> +              __LINE__, PciConfigBase, Rpsc, Rpsc | XILINX_PCIE_REG_RPSC_BEN));
> +
> +  *Count = 1;
> +  return &mRootBridge;
> +}
> +
> +
> +/**
> +  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
> +
> +  @param[in] Bridges The root bridge instances array.
> +  @param[in] Count   The count of the array.
> +
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeFreeRootBridges (
> +  IN PCI_ROOT_BRIDGE *Bridges,
> +  IN UINTN           Count
> +  )
> +{
> +
> +}
> +
> +
> +/**
> +  Inform the platform that the resource conflict happens.
> +
> +  @param[in] HostBridgeHandle Handle of the Host Bridge.
> +  @param[in] Configuration    Pointer to PCI I/O and PCI memory resource
> +                          descriptors. The Configuration contains the resources
> +                          for all the root bridges. The resource for each root
> +                          bridge is terminated with END descriptor and an
> +                          additional END is appended indicating the end of the
> +                          entire resources. The resource descriptor field
> +                          values follow the description in
> +                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +                          SubmitResources().
> +
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeResourceConflict (
> +  IN EFI_HANDLE                        HostBridgeHandle,
> +  IN VOID                              *Configuration
> +  )
> +{
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
> +  BOOLEAN IsPrefetchable;
> +
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
> +      ASSERT (Descriptor->ResType <
> +              ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr));
> +      DEBUG ((DEBUG_INFO, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
> +              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
> +              Descriptor->AddrLen,
> +              Descriptor->AddrRangeMax
> +              ));
> +      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +
> +        IsPrefetchable = (Descriptor->SpecificFlag &
> +          EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0;
> +
> +        DEBUG ((DEBUG_INFO, "     Granularity/SpecificFlag = %ld / %02x%s\n",
> +          Descriptor->AddrSpaceGranularity,
> +          Descriptor->SpecificFlag,
> +          (IsPrefetchable) ? L" (Prefetchable)" : L""
> +          ));
> +      }
> +    }
> +    //
> +    // Skip the end descriptor for root bridge
> +    //
> +    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
> +    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (
> +                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
> +                   );
> +  }
> +}
> diff --git a/Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 0000000000..1620936736
> --- /dev/null
> +++ b/Silicon/Bosc/NanHuPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,48 @@
> +#/** @file
> +#  PCI Host Bridge Library instance for Bosc SOC.
> +#
> +#  Copyright (C) 2020, Bosc Technology Co, Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2024, Bosc. All rights reserved.<BR>ved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001b
> +  BASE_NAME                      = PciHostBridgeLib
> +  FILE_GUID                      = 7F418E45-0127-454E-9CBB-F5FCF237E383
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
> +
> +#
> +# The following information is for reference only and not required by the build
> +# tools.
> +#
> +#  VALID_ARCHITECTURES           = RISCV64
> +#
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +
> +[Guids]
> +
> +[FixedPcd]
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciBusMin
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciBusMax
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciIoBase
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciIoSize
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio32Base
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio32Size
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio64Base
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio64Size
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciConfigBase
> diff --git a/Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.c
> new file mode 100755
> index 0000000000..8e463fcc79
> --- /dev/null
> +++ b/Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.c
> @@ -0,0 +1,1391 @@
> +/** @file
> +  PCI Segment Library for SoC with multiple RCs.
> +
> +  Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
> +  Copyright (c) 2024, Bosc. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +
> +#define PCI_SEG_CONFIG_BASE       0x40000000
> +
> +typedef enum {
> +  PciCfgWidthUint8 = 0,
> +  PciCfgWidthUint16,
> +  PciCfgWidthUint32,
> +  PciCfgWidthMax
> +} PCI_CFG_WIDTH;
> +
> +/**
> +  Assert the validity of a PCI Segment address.
> +  A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63
> +
> +  @param[in]  A The address to validate.
> +  @param[in]  M Additional bits to assert to be zero.
> +
> +**/
> +#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
> +ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
> +
> +
> +#define EXTRACT_PCIE_ADDRESS(Address, Bus, Device, Function) \
> +{ \
> +  (Bus)      = (((Address) >> 20) & 0xff);   \
> +  (Device)   = (((Address) >> 15) & 0x1f);   \
> +  (Function) = (((Address) >> 12) & 0x07);   \
> +}
> +
> +
> +/**
> +  This function  geted the config base of PCI device.
> +  @param[in]  Address  The address that encodes the PCI Bus, Device, Function and
> +                       Register.
> +
> +  @return The value of the config base of PCI device.
> +
> +**/
> +STATIC
> +UINT64
> +PciSegmentLibGetConfigBase (
> +  IN  UINT64      Address
> +  )
> +{
> +  UINT8 Bus;
> +  UINT8 Device;
> +  UINT8 Function;
> +
> +  EXTRACT_PCIE_ADDRESS (Address, Bus, Device, Function);
> +  if ((Bus == 1) || (Bus == 2) || (Bus == 3) || (Bus == 4)) {
> +    return PCI_SEG_CONFIG_BASE;
> +  }
> +
> +  return PCI_SEG_CONFIG_BASE;
> +}
> +
> +/**
> +  Internal worker function to read a PCI configuration register.
> +
> +  @param[in]  Address The address that encodes the PCI Bus, Device, Function and
> +                      Register.
> +  @param[in]  Width   The width of data to read
> +
> +  @return The value read from the PCI configuration register.
> +
> +**/
> +STATIC
> +UINT32
> +PciSegmentLibReadWorker (
> +  IN  UINT64                      Address,
> +  IN  PCI_CFG_WIDTH               Width
> +  )
> +{
> +  UINT64    Base;
> +
> +  Base = PciSegmentLibGetConfigBase (Address);
> +  if (Base == 0xFFFFFFFF) {
> +    return 0xFFFFFFFF;
> +  }
> +
> +  switch (Width) {
> +  case PciCfgWidthUint8:
> +    return MmioRead8 (Base + (UINT32)Address);
> +  case PciCfgWidthUint16:
> +    return MmioRead16 (Base + (UINT32)Address);
> +  case PciCfgWidthUint32:
> +    return MmioRead32 (Base + (UINT32)Address);
> +  default:
> +    ASSERT (FALSE);
> +  }
> +
> +  return 0;
> +}
> +
> +
> +/**
> +  Internal worker function to writes a PCI configuration register.
> +
> +  @param[in]  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param[in]  Width   The width of data to write
> +  @param[in]  Data    The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +STATIC
> +UINT32
> +PciSegmentLibWriteWorker (
> +  IN  UINT64                      Address,
> +  IN  PCI_CFG_WIDTH               Width,
> +  IN  UINT32                      Data
> +  )
> +{
> +  UINT64    Base;
> +
> +  Base = PciSegmentLibGetConfigBase (Address);
> +  if (Base == 0xFFFFFFFF) {
> +    return 0xFFFFFFFF;
> +  }
> +
> +  switch (Width) {
> +  case PciCfgWidthUint8:
> +    MmioWrite8 (Base + (UINT32)Address, Data);
> +    break;
> +  case PciCfgWidthUint16:
> +    MmioWrite16 (Base + (UINT32)Address, Data);
> +    break;
> +  case PciCfgWidthUint32:
> +    MmioWrite32 (Base + (UINT32)Address, Data);
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +  }
> +
> +  return Data;
> +}
> +
> +/**
> +  Register a PCI device so PCI configuration registers may be accessed after
> +  SetVirtualAddressMap().
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +
> +  @param[in]      Address          The address that encodes the PCI Bus, Device, Function and
> +                                   Register.
> +
> +  @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
> +  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
> +                                   after ExitBootServices().
> +  @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
> +                                   at runtime could not be mapped.
> +  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
> +                                   complete the registration.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +PciSegmentRegisterForRuntimeAccess (
> +  IN UINTN  Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
> +
> +  return RETURN_UNSUPPORTED;
> +}
> +
> +/**
> +  Reads an 8-bit PCI configuration register.
> +
> +  Reads and returns the 8-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function,
> +                    and Register.
> +
> +  @return The 8-bit PCI configuration register specified by Address.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentRead8 (
> +  IN UINT64                    Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
> +
> +  return (UINT8) PciSegmentLibReadWorker (Address, PciCfgWidthUint8);
> +}
> +
> +/**
> +  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[in]  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  Value       The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentWrite8 (
> +  IN UINT64                    Address,
> +  IN UINT8                     Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
> +
> +  return (UINT8) PciSegmentLibWriteWorker (Address, PciCfgWidthUint8, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address,
> +  performs a bitwise OR between the read result and the value specified by OrData,
> +  and writes the result to the 8-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentOr8 (
> +  IN UINT64                    Address,
> +  IN UINT8                     OrData
> +  )
> +{
> +  return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) | OrData));
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address,
> +  performs a bitwise AND between the read result and the value specified by AndData,
> +  and writes the result to the 8-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +  If any reserved bits in Address are set, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentAnd8 (
> +  IN UINT64                    Address,
> +  IN UINT8                     AndData
> +  )
> +{
> +  return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData));
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value,
> +  followed a  bitwise OR with another 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address,
> +  performs a bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and the value specified by OrData,
> +  and writes the result to the 8-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  AndData    The value to AND with the PCI configuration register.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentAndThenOr8 (
> +  IN UINT64                    Address,
> +  IN UINT8                     AndData,
> +  IN UINT8                     OrData
> +  )
> +{
> +  return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData));
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in an 8-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to read.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentBitFieldRead8 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit
> +  )
> +{
> +  return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit);
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  8-bit register is returned.
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentBitFieldWrite8 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT8                     Value
> +  )
> +{
> +  return PciSegmentWrite8 (
> +           Address,
> +           BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentBitFieldOr8 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT8                     OrData
> +  )
> +{
> +  return PciSegmentWrite8 (
> +           Address,
> +           BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 8-bit register.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentBitFieldAnd8 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT8                     AndData
> +  )
> +{
> +  return PciSegmentWrite8 (
> +           Address,
> +           BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +  @param[in]  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciSegmentBitFieldAndThenOr8 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT8                     AndData,
> +  IN UINT8                     OrData
> +  )
> +{
> +  return PciSegmentWrite8 (
> +           Address,
> +           BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData)
> +           );
> +}
> +
> +/**
> +  Reads a 16-bit PCI configuration register.
> +
> +  Reads and returns the 16-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +
> +  @return The 16-bit PCI configuration register specified by Address.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentRead16 (
> +  IN UINT64                    Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
> +
> +  return (UINT16) PciSegmentLibReadWorker (Address, PciCfgWidthUint16);
> +}
> +
> +/**
> +  Writes a 16-bit PCI configuration register.
> +
> +  Writes the 16-bit PCI configuration register specified by Address with the value specified by Value.
> +  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param[in]  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  Value       The value to write.
> +
> +  @return The parameter of Value.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentWrite16 (
> +  IN UINT64                    Address,
> +  IN UINT16                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
> +
> +  return (UINT16) PciSegmentLibWriteWorker (Address, PciCfgWidthUint16, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 16-bit PCI configuration register with
> +  a 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param[in]  Address The address that encodes the PCI Segment, Bus, Device, Function and
> +                  Register.
> +  @param[in]  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentOr16 (
> +  IN UINT64                    Address,
> +  IN UINT16                    OrData
> +  )
> +{
> +  return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData));
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address,
> +  performs a bitwise AND between the read result and the value specified by AndData,
> +  and writes the result to the 16-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentAnd16 (
> +  IN UINT64                    Address,
> +  IN UINT16                    AndData
> +  )
> +{
> +  return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData));
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
> +  followed a  bitwise OR with another 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address,
> +  performs a bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and the value specified by OrData,
> +  and writes the result to the 16-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentAndThenOr16 (
> +  IN UINT64                    Address,
> +  IN UINT16                    AndData,
> +  IN UINT16                    OrData
> +  )
> +{
> +  return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData));
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 16-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to read.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentBitFieldRead16 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit
> +  )
> +{
> +  return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit);
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  16-bit register is returned.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentBitFieldWrite16 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT16                    Value
> +  )
> +{
> +  return PciSegmentWrite16 (
> +           Address,
> +           BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value)
> +           );
> +}
> +
> +/**
> +  Reads the 16-bit PCI configuration register specified by Address,
> +  performs a bitwise OR between the read result and the value specified by OrData,
> +  and writes the result to the 16-bit PCI configuration register specified by Address.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentBitFieldOr16 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT16                    OrData
> +  )
> +{
> +  return PciSegmentWrite16 (
> +           Address,
> +           BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR,
> +  and writes the result back to the bit field in the 16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address,
> +  performs a bitwise OR between the read result and the value specified by OrData,
> +  and writes the result to the 16-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +  Extra left bits in OrData are stripped.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    The ordinal of the least significant bit in a byte is bit 0.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    The ordinal of the most significant bit in a byte is bit 7.
> +  @param[in]  AndData   The value to AND with the read value from the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentBitFieldAnd16 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT16                    AndData
> +  )
> +{
> +  return PciSegmentWrite16 (
> +           Address,
> +           BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +  @param[in]  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciSegmentBitFieldAndThenOr16 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT16                    AndData,
> +  IN UINT16                    OrData
> +  )
> +{
> +  return PciSegmentWrite16 (
> +           Address,
> +           BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData)
> +           );
> +}
> +
> +/**
> +  Reads a 32-bit PCI configuration register.
> +
> +  Reads and returns the 32-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function,
> +                    and Register.
> +
> +  @return The 32-bit PCI configuration register specified by Address.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentRead32 (
> +  IN UINT64                    Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
> +
> +  return PciSegmentLibReadWorker (Address, PciCfgWidthUint32);
> +}
> +
> +/**
> +  Writes a 32-bit PCI configuration register.
> +
> +  Writes the 32-bit PCI configuration register specified by Address with the value specified by Value.
> +  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param[in]  Address     The address that encodes the PCI Segment, Bus, Device,
> +                      Function, and Register.
> +  @param[in]  Value       The value to write.
> +
> +  @return The parameter of Value.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentWrite32 (
> +  IN UINT64                    Address,
> +  IN UINT32                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
> +
> +  return PciSegmentLibWriteWorker (Address, PciCfgWidthUint32, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address,
> +  performs a bitwise OR between the read result and the value specified by OrData,
> +  and writes the result to the 32-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentOr32 (
> +  IN UINT64                    Address,
> +  IN UINT32                    OrData
> +  )
> +{
> +  return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address,
> +  performs a bitwise AND between the read result and the value specified by AndData,
> +  and writes the result to the 32-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function,
> +                    and Register.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentAnd32 (
> +  IN UINT64                    Address,
> +  IN UINT32                    AndData
> +  )
> +{
> +  return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
> +  followed a  bitwise OR with another 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address,
> +  performs a bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and the value specified by OrData,
> +  and writes the result to the 32-bit PCI configuration register specified by Address.
> +  The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are serialized.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param[in]  Address   The address that encodes the PCI Segment, Bus, Device, Function,
> +                    and Register.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentAndThenOr32 (
> +  IN UINT64                    Address,
> +  IN UINT32                    AndData,
> +  IN UINT32                    OrData
> +  )
> +{
> +  return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData);
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 32-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is returned.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to read.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentBitFieldRead32 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit
> +  )
> +{
> +  return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit);
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  32-bit register is returned.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentBitFieldWrite32 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT32                    Value
> +  )
> +{
> +  return PciSegmentWrite32 (
> +           Address,
> +           BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentBitFieldOr32 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT32                    OrData
> +  )
> +{
> +  return PciSegmentWrite32 (
> +           Address,
> +           BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 32-bit register.
> +
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a bitwise
> +  AND between the read result and the value specified by AndData, and writes the result
> +  to the 32-bit PCI configuration register specified by Address. The value written to
> +  the PCI configuration register is returned.  This function must guarantee that all PCI
> +  read and write operations are serialized.  Extra left bits in AndData are stripped.
> +  If any reserved bits in Address are set, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentBitFieldAnd32 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT32                    AndData
> +  )
> +{
> +  return PciSegmentWrite32 (
> +           Address,
> +           BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData)
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If any reserved bits in Address are set, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param[in]  Address   The PCI configuration register to write.
> +  @param[in]  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param[in]  AndData   The value to AND with the PCI configuration register.
> +  @param[in]  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciSegmentBitFieldAndThenOr32 (
> +  IN UINT64                    Address,
> +  IN UINTN                     StartBit,
> +  IN UINTN                     EndBit,
> +  IN UINT32                    AndData,
> +  IN UINT32                    OrData
> +  )
> +{
> +  return PciSegmentWrite32 (
> +           Address,
> +           BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData)
> +           );
> +}
> +
> +/**
> +  Reads a range of PCI configuration registers into a caller supplied buffer.
> +
> +  Reads the range of PCI configuration registers specified by StartAddress and
> +  Size into the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be read. Size is
> +  returned. When possible 32-bit PCI configuration read cycles are used to read
> +  from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
> +  and 16-bit PCI configuration read cycles may be used at the beginning and the
> +  end of the range.
> +
> +  If any reserved bits in StartAddress are set, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param[in]  StartAddress  The starting address that encodes the PCI Segment, Bus,
> +                        Device, Function and Register.
> +  @param[in]  Size          The size in bytes of the transfer.
> +  @param[in]  Buffer        The pointer to a buffer receiving the data read.
> +
> +  @return Size
> +
> +**/
> +UINTN
> +EFIAPI
> +PciSegmentReadBuffer (
> +  IN  UINT64                   StartAddress,
> +  IN  UINTN                    Size,
> +  OUT VOID                     *Buffer
> +  )
> +{
> +  UINTN                             ReturnValue;
> +
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
> +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> +
> +  if (Size == 0) {
> +    return Size;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // Save Size for return
> +  //
> +  ReturnValue = Size;
> +
> +  if ((StartAddress & BIT0) != 0) {
> +    //
> +    // Read a byte if StartAddress is byte aligned,
> +    //
> +    MmioWrite8 ((UINTN)Buffer, PciSegmentRead8 (StartAddress));
> +    StartAddress += sizeof (UINT8);
> +    Size -= sizeof (UINT8);
> +    Buffer = (UINT8 *)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
> +    //
> +    // Read a word if StartAddress is word aligned
> +    //
> +    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16 *)Buffer + 1;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Read as many double words as possible
> +    //
> +    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32 *)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Read the last remaining word if exist
> +    //
> +    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16 *)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Read the last remaining byte if exist
> +    //
> +    MmioWrite8 ((UINTN)Buffer, PciSegmentRead8 (StartAddress));
> +  }
> +
> +  return ReturnValue;
> +}
> +
> +
> +/**
> +  Copies the data in a caller supplied buffer to a specified range of PCI
> +  configuration space.
> +
> +  Writes the range of PCI configuration registers specified by StartAddress and
> +  Size from the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be written. Size is
> +  returned. When possible 32-bit PCI configuration write cycles are used to
> +  write from StartAdress to StartAddress + Size. Due to alignment restrictions,
> +  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
> +  and the end of the range.
> +
> +  If any reserved bits in StartAddress are set, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param[in]  StartAddress  The starting address that encodes the PCI Segment, Bus,
> +                        Device, Function and Register.
> +  @param[in]  Size          The size in bytes of the transfer.
> +  @param[in]  Buffer        The pointer to a buffer containing the data to write.
> +
> +  @return The parameter of Size.
> +
> +**/
> +UINTN
> +EFIAPI
> +PciSegmentWriteBuffer (
> +  IN UINT64                    StartAddress,
> +  IN UINTN                     Size,
> +  IN VOID                      *Buffer
> +  )
> +{
> +  UINTN                             ReturnValue;
> +
> +  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
> +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> +
> +  if (Size == 0) {
> +    return 0;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // Save Size for return
> +  //
> +  ReturnValue = Size;
> +
> +  if ((StartAddress & BIT0) != 0) {
> +    //
> +    // Write a byte if StartAddress is byte aligned
> +    //
> +    PciSegmentWrite8 (StartAddress, *(UINT8 *)Buffer);
> +    StartAddress += sizeof (UINT8);
> +    Size -= sizeof (UINT8);
> +    Buffer = (UINT8 *)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
> +    //
> +    // Write a word if StartAddress is word aligned
> +    //
> +    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16 *)Buffer + 1;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Write as many double words as possible
> +    //
> +    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32 *)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Write the last remaining word if exist
> +    //
> +    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16 *)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Write the last remaining byte if exist
> +    //
> +    PciSegmentWrite8 (StartAddress, *(UINT8 *)Buffer);
> +  }
> +
> +  return ReturnValue;
> +}
> diff --git a/Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.inf
> new file mode 100755
> index 0000000000..29d1758410
> --- /dev/null
> +++ b/Silicon/Bosc/NanHuPkg/Library/PciSegmentLib/PciSegmentLib.inf
> @@ -0,0 +1,29 @@
> +#/** @file
> +#  PCI Segment Library for Bosc NanHuDev platform with Xilinx XDMA RCs.
> +#
> +#  Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reser
> +#  Copyright (c) 2024, Bosc. All rights reserved.<BR>ved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001b
> +  BASE_NAME                      = PciSegmentLib
> +  FILE_GUID                      = B0DD53D5-30C6-48CB-849D-BEB935B57D78
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciSegmentLib
> +
> +[Sources]
> +  PciSegmentLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  IoLib
> diff --git a/Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec b/Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec
> index e975ae42d0..9f553a5b0a 100644
> --- a/Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec
> +++ b/Silicon/Bosc/NanHuPkg/NanHuDevPkg.dec
> @@ -20,6 +20,7 @@
>  [Protocols]
>  
>  [Guids]
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid  = { 0x245C5C80, 0x7945, 0x43BE, { 0xB4, 0x01, 0xC9, 0x92, 0x8A, 0x13, 0xDD, 0x0A }}
>  
>  [PcdsFixedAtBuild]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x0|UINT64|0x00001004
> @@ -27,5 +28,24 @@
>    gHisiTokenSpaceGuid.PcdSerialPortSendDelay|0x0|UINT32|0x00001006
>    gHisiTokenSpaceGuid.PcdUartClkInHz|0x0|UINT32|0x00001007
>  
> +  #
> +  # PCI configuration address space
> +  #
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciConfigBase|0x0|UINT64|0x00000008
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciConfigSize|0x0|UINT64|0x00000009
> +
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x0000000a
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x0000000b
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT32|0x0000000c
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT32|0x0000000d
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x0000000e
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x0000000f
> +
> +  #
> +  # Inclusive range of allowed PCI buses.
> +  #
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciBusMin|0x0|UINT32|0x00000010
> +  gBoscNanHuDdevPlatformPkgTokenSpaceGuid.PcdPciBusMax|0x0|UINT32|0x00000011
> +
>  [UserExtensions.TianoCore."ExtraFiles"]
>    NanHuPkgExtra.uni
> -- 
> 2.34.1
> 
> 
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118912): https://edk2.groups.io/g/devel/message/118912
Mute This Topic: https://groups.io/mt/105572700/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



       reply	other threads:[~2024-05-15  7:41 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <17C6FF8EBB82206B.20815@groups.io>
2024-05-15  7:40 ` WangYang [this message]
2024-05-15  8:36   ` [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver Ni, Ray
2024-05-16  2:54     ` WangYang
2024-05-17  2:41       ` suijingfeng
2024-04-17  7:08 WangYang

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=29ca357a.eb.18f7b3255cd.Coremail.wangyang@bosc.ac.cn \
    --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