* [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
@ 2024-04-17 7:08 WangYang
0 siblings, 0 replies; 5+ messages in thread
From: WangYang @ 2024-04-17 7:08 UTC (permalink / raw)
To: sunilvl, git, devel; +Cc: Yang Wang, Ran Wang, Leif Lindholm, Michael D Kinney
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 (#117899): https://edk2.groups.io/g/devel/message/117899
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]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 5+ messages in thread
[parent not found: <17C6FF8EBB82206B.20815@groups.io>]
* Re: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
[not found] <17C6FF8EBB82206B.20815@groups.io>
@ 2024-05-15 7:40 ` WangYang
2024-05-15 8:36 ` Ni, Ray
0 siblings, 1 reply; 5+ messages in thread
From: WangYang @ 2024-05-15 7:40 UTC (permalink / raw)
To: devel; +Cc: sunilvl, git, Ran Wang, Leif Lindholm, Michael D Kinney
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]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
2024-05-15 7:40 ` WangYang
@ 2024-05-15 8:36 ` Ni, Ray
2024-05-16 2:54 ` WangYang
0 siblings, 1 reply; 5+ messages in thread
From: Ni, Ray @ 2024-05-15 8:36 UTC (permalink / raw)
To: devel@edk2.groups.io, wangyang@bosc.ac.cn
Cc: sunilvl@ventanamicro.com, git@danielschaefer.me, Ran Wang,
Leif Lindholm, Kinney, Michael D
[-- Attachment #1: Type: text/plain, Size: 915 bytes --]
1. The patch is too big. Can you split it to multiple smaller patches?
> +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;
1.
Both paths return the same PCI_SEG_CONFIG_BASE. Then why do you check the Bus number?
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118913): https://edk2.groups.io/g/devel/message/118913
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]
-=-=-=-=-=-=-=-=-=-=-=-
[-- Attachment #2: Type: text/html, Size: 6467 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
2024-05-15 8:36 ` Ni, Ray
@ 2024-05-16 2:54 ` WangYang
2024-05-17 2:41 ` suijingfeng
0 siblings, 1 reply; 5+ messages in thread
From: WangYang @ 2024-05-16 2:54 UTC (permalink / raw)
To: Ni, Ray
Cc: devel@edk2.groups.io, sunilvl@ventanamicro.com,
git@danielschaefer.me, Ran Wang, Leif Lindholm, Kinney, Michael D
[-- Attachment #1: Type: text/plain, Size: 1773 bytes --]
Hi,Ray
Thank you very much for your attention.
-----原始邮件-----
发件人:"Ni, Ray" <ray.ni@intel.com>
发送时间:2024-05-15 16:36:02 (星期三)
收件人: "devel@edk2.groups.io" <devel@edk2.groups.io>, "wangyang@bosc.ac.cn" <wangyang@bosc.ac.cn>
抄送: "sunilvl@ventanamicro.com" <sunilvl@ventanamicro.com>, "git@danielschaefer.me" <git@danielschaefer.me>, "Ran Wang" <wangran@bosc.ac.cn>, "Leif Lindholm" <quic_llindhol@quicinc.com>, "Kinney, Michael D" <michael.d.kinney@intel.com>
主题: Re: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
The patch is too big. Can you split it to multiple smaller patches?
As you said, this patch is indeed a bit big. The main reference is file “./Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.c” .
> +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;
> + }
> +
This part of the code is redundant and should be deleted
> + return PCI_SEG_CONFIG_BASE;
Both paths return the same PCI_SEG_CONFIG_BASE. Then why do you check the Bus number?
This part of the code is redundant and should be deleted.
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118946): https://edk2.groups.io/g/devel/message/118946
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]
-=-=-=-=-=-=-=-=-=-=-=-
[-- Attachment #2: Type: text/html, Size: 8521 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver
2024-05-16 2:54 ` WangYang
@ 2024-05-17 2:41 ` suijingfeng
0 siblings, 0 replies; 5+ messages in thread
From: suijingfeng @ 2024-05-17 2:41 UTC (permalink / raw)
To: WangYang, devel
On Thu, May 16, 2024 at 10:54 AM, WangYang wrote:
Hi,
>
> Hi,Ray
>
> Thank you very much for your attention.
>
The reviewer Ray told you that you patch has some small problems,
For example, the clause "if ((Bus == 1) || (Bus == 2) || (Bus == 3) || (Bus == 4)) " is useless.
As both code path returns same value.
You should solve this small problems, also cut this big patch into smaller pieces as smaller patch is easier to review.
and when all problem solved, you should send the updated patch as V2. Since this version is V1 as far as I know.
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119052): https://edk2.groups.io/g/devel/message/119052
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]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-05-17 17:54 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-17 7:08 [edk2-devel] [PATCH] XiangshanSeriesPkg:Add Support for Xilinx RC(PCIE) Driver WangYang
[not found] <17C6FF8EBB82206B.20815@groups.io>
2024-05-15 7:40 ` WangYang
2024-05-15 8:36 ` Ni, Ray
2024-05-16 2:54 ` WangYang
2024-05-17 2:41 ` suijingfeng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox