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]
-=-=-=-=-=-=-=-=-=-=-=-
next parent 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