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 <wangy...@bosc.ac.cn>
> 发送时间: 2024-04-17 15:08:06 (星期三)
> 收件人: suni...@ventanamicro.com, g...@danielschaefer.me, devel@edk2.groups.io
> 抄送: "Yang Wang" <wangy...@bosc.ac.cn>, "Ran Wang" <wang...@bosc.ac.cn>, "Leif 
> Lindholm" <quic_llind...@quicinc.com>, "Michael D Kinney" 
> <michael.d.kin...@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 <wang...@bosc.ac.cn>
> Cc: Leif Lindholm <quic_llind...@quicinc.com>
> Cc: Michael D Kinney <michael.d.kin...@intel.com>
> Cc: Sunil V L <suni...@ventanamicro.com>
> Cc: Daniel Schaefer <g...@danielschaefer.me>
> Signed-off-by: Yang Wang <wangy...@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/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to