From nobody Mon Feb 9 22:38:57 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+80481+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+80481+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1631262093; cv=none; d=zohomail.com; s=zohoarc; b=gAhQ0Hyquo/8LEZIG+QouiC7vzdTeBBdKoDpV0I8vIcUZurukEaQuHPnsBVlX2eHchF2qan1JmvHbNiLyJu2mJX6mkMlXMwh2fyTWFzr+z6/hCYQPkx/qvQEa5nT/YNrFG4uqTYN+d1Q3kAI0QndN6Fv5gRkcGUZxFQE3boSmQs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1631262093; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=8UYl1ibQcvg/WUYnsOR41XDUtZFWbf8mHcVC9xtY+C8=; b=h8foiUDa3d4JjEfGXEM3t6nTSFtq8s9ctNLGwShxGHmhmBV3b3KJm8OZt+hbIs4hw09lpmBo6bBRb2++wUv906P0kJiERoHp0bDgskEXeEVlB79Q28RGyxoQAIp8leEJlbzxuEuEYF26E6KMSF+AoY0V0Y5IxW1BDZjldI43et0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+80481+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1631262093669576.3675271425412; Fri, 10 Sep 2021 01:21:33 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id ki0oYY1788612xhH6mj5byOy; Fri, 10 Sep 2021 01:21:33 -0700 X-Received: from azure-sdnproxy-1.icoremail.net (azure-sdnproxy-1.icoremail.net [207.46.229.174]) by mx.groups.io with SMTP id smtpd.web12.6321.1631262090894054107 for ; Fri, 10 Sep 2021 01:21:32 -0700 X-Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-2 (Coremail) with SMTP id AQAAfwD3ItOiFTthaHN6Ag--.6677S2; Fri, 10 Sep 2021 16:21:54 +0800 (CST) X-Received: from localhost.localdomain (unknown [223.153.182.69]) by mail (Coremail) with SMTP id AQAAfwDHDId0FTthMxgAAA--.855S6; Fri, 10 Sep 2021 16:21:25 +0800 (CST) From: "Ling Jia" To: devel@edk2.groups.io Cc: Leif Lindholm , Ling Jia Subject: [edk2-devel] [PATCH v6 04/10] Silicon/Phytium: Added PciSegmentLib to FT2000/4 Date: Fri, 10 Sep 2021 16:20:57 +0800 Message-Id: <20210910082058.15194-5-jialing@phytium.com.cn> In-Reply-To: <20210910082058.15194-1-jialing@phytium.com.cn> References: <20210910082058.15194-1-jialing@phytium.com.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAfwDHDId0FTthMxgAAA--.855S6 X-CM-SenderInfo: xmldzxdqj61x51wl3zoofrzhdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWDJF1UXF17uF1Dtr1kZFy3CFg_yoW7Jr13to ZYvFy8Xr1vqw1xKF1xt3sxXw4fWFZ2kr1xArWFqrW5X3WvqFsa9a4Iqa1DJr97G3W7Kryk Xr95Za97JFWrt3Wrn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,jialing@phytium.com.cn X-Gm-Message-State: 1iuwF0M4CqvjkJNov67oiIcix1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1631262093; bh=zswdRA6xwtc8rsRO5FqAip6XeYANgvRqLoKhcYMM8GM=; h=Cc:Date:From:Reply-To:Subject:To; b=MkEWehHh/tKw175gDevBJPwUTzBPHFm1SO22kMGStyZDdT1MtuqkRXVWB1KZ0Pfpb93 hhACkGiu4VsYAhLlfia3zKaYgmCrgQc9GUGIOc9bhB5B0iLkLQ+L90PIk6WCbQNp78117 zXBEwtaRElEwb7H2txeUV6Kw1WUjAGhZ/GU= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1631262095690100016 Content-Type: text/plain; charset="utf-8" The PCI Segment Library for Phytium platform. with multiple RCs. Signed-off-by: Ling Jia Reviewed-by: Leif Lindholm --- Platform/Phytium/DurianPkg/DurianPkg.dsc | 9= +- Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.inf | 28= + Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.c | 1434= ++++++++++++++++++++ 3 files changed, 1464 insertions(+), 7 deletions(-) diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/Du= rianPkg/DurianPkg.dsc index 28e52e15e3..093b2cd9db 100644 --- a/Platform/Phytium/DurianPkg/DurianPkg.dsc +++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc @@ -35,7 +35,8 @@ PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf =20 [LibraryClasses.common.DXE_DRIVER] - + # Pci dependencies + PciSegmentLib|Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegme= ntLib.inf =20 ##########################################################################= ###### # @@ -262,12 +263,6 @@ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf =20 - # - # PCI Support - # - ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDevic= eDxe.inf - # # The following 2 module perform the same work except one operate variab= le. # Only one of both should be put into fdf. diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLi= b.inf b/Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.inf new file mode 100644 index 0000000000..67360016ef --- /dev/null +++ b/Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.inf @@ -0,0 +1,28 @@ +#/** @file +# PCI Segment Library for Phytium platform with multiple RCs. +# +# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION =3D 0x0001001b + BASE_NAME =3D PciSegmentLib + FILE_GUID =3D fa5173d2-40fe-11eb-9b2f-cb20dc669fd3 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PciSegmentLib + +[Sources] + PciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLi= b.c b/Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.c new file mode 100644 index 0000000000..273443fd5d --- /dev/null +++ b/Silicon/Phytium/FT2000-4Pkg/Library/PciSegmentLib/PciSegmentLib.c @@ -0,0 +1,1434 @@ +/** @file + PCI Segment Library for SoC with multiple RCs. + + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#define PCI_SEG_CONFIG_BASE 0x40000000 +#define PCIE_BIF_MODE 0x29100800 + +typedef enum { + PciCfgWidthUint8 =3D 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))) =3D=3D 0) + + +#define EXTRACT_PCIE_ADDRESS(Address, Bus, Device, Function) \ +{ \ + (Bus) =3D (((Address) >> 20) & 0xff); \ + (Device) =3D (((Address) >> 15) & 0x1f); \ + (Function) =3D (((Address) >> 12) & 0x07); \ +} + + +/** + This function geted the config base of PCI device. + @param[in] Address The address that encodes the PCI Bus, Device, Funct= ion and + Register. + + @return The value of the config base of PCI device. + +**/ +STATIC +UINT64 +PciSegmentLibGetConfigBase ( + IN UINT64 Address + ) +{ + UINT8 Bus; + UINT8 Device; + UINT8 Function; + UINT8 RootPortCount; + UINT8 Peu0RootPortCount; + UINT8 Peu1RootPortCount; + UINT32 BifMode; + UINT32 Peu0BifMode; + UINT32 Peu1BifMode; + + EXTRACT_PCIE_ADDRESS (Address, Bus, Device, Function); + BifMode =3D MmioRead32 (PCIE_BIF_MODE); + Peu0BifMode =3D BifMode & 0x3; + Peu1BifMode =3D (BifMode >> 2) & 0x3; + + if ((Peu0BifMode =3D=3D 1)) { + Peu0RootPortCount =3D 3; + } else { + Peu0RootPortCount =3D 2; + } + + if ((Peu1BifMode =3D=3D 1)) { + Peu1RootPortCount =3D 3; + } else { + Peu1RootPortCount =3D 2; + } + RootPortCount =3D Peu0RootPortCount + Peu1RootPortCount; + //ignore device > 0 or function > 0 on root port + if (RootPortCount =3D=3D 4) { + if ((Bus =3D=3D 1) || (Bus =3D=3D 2) || (Bus =3D=3D 3) || (Bus =3D=3D = 4)) { + if (Device !=3D 0 || Function !=3D 0) { + return 0xFFFFFFFF; + } + return PCI_SEG_CONFIG_BASE; + } + } else if (RootPortCount =3D=3D 5) { + if ((Bus =3D=3D 1) || (Bus =3D=3D 2) || (Bus =3D=3D 3) || (Bus =3D=3D = 4) || (Bus =3D=3D 5)) { + if (Device !=3D 0 || Function !=3D 0) { + return 0xFFFFFFFF; + } + return PCI_SEG_CONFIG_BASE; + } + } else if (RootPortCount =3D=3D 6) { + if ((Bus =3D=3D 1) || (Bus =3D=3D 2) || (Bus =3D=3D 3) || (Bus =3D=3D = 4) || (Bus =3D=3D 5) || (Bus =3D=3D 6)) { + if (Device !=3D 0 || Function !=3D 0) { + return 0xFFFFFFFF; + } + 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, Functi= on 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 =3D PciSegmentLibGetConfigBase (Address); + if (Base =3D=3D 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, Functi= on 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 =3D PciSegmentLibGetConfigBase (Address); + if (Base =3D=3D 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 aft= er + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param[in] Address The address that encodes the PCI Bus, D= evice, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runti= me access. + @retval RETURN_UNSUPPORTED An attempt was made to call this functi= on + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PC= I device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources availabl= e 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 Addr= ess. + 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, Dev= ice, 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 th= e value specified by Value. + Value is returned. This function must guarantee that all PCI read and w= rite operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param[in] Address The address that encodes the PCI Segment, Bus, D= evice, 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, Valu= e); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-b= it 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, Dev= ice, Function, and Register. + @param[in] OrData The value to OR with the PCI configuration registe= r. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) | O= rData)); +} + +/** + 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 b= y 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, Dev= ice, Function, and Register. + @param[in] AndData The value to AND with the PCI configuration regist= er. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & A= ndData)); +} + +/** + 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 b= y AndData, + performs a bitwise OR between the result of the AND operation and the va= lue 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, Dev= ice, Function, and Register. + @param[in] AndData The value to AND with the PCI configuration regis= ter. + @param[in] OrData The value to OR with the PCI configuration registe= r. + + @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 fiel= d 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 bi= t 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 regis= ter. + +**/ +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 t= he + 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 bi= t 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, Va= lue) + ); +} + +/** + 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, perform= s 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 registe= r is + returned. This function must guarantee that all PCI read and write opera= tions + 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 a= nd EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 registe= r. + + @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, OrDat= a) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bit= wise + 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, perform= s 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 bi= t 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 regist= er. + + @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, AndD= ata) + ); +} + +/** + 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, perform= s 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 al= l PCI + read and write operations are serialized. Extra left bits in both AndDat= a 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 bi= t 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 regist= er. + @param[in] OrData The value to OR with the result of the AND operati= on. + + @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 Add= ress. + 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, Dev= ice, 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 t= he value specified by Value. + Value is returned. This function must guarantee that all PCI read and w= rite 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, D= evice, 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, Va= lue); +} + +/** + 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, perfor= ms 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 registe= r is + returned. This function must guarantee that all PCI read and write opera= tions + 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, Devic= e, 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 b= y 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, Dev= ice, Function, and Register. + @param[in] AndData The value to AND with the PCI configuration regist= er. + + @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 b= y AndData, + performs a bitwise OR between the result of the AND operation and the va= lue 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, Dev= ice, Function, and Register. + @param[in] AndData The value to AND with the PCI configuration regist= er. + @param[in] OrData The value to OR with the PCI configuration registe= r. + + @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 fiel= d 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 bi= t 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 regis= ter. + +**/ +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 t= he + 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 an= d EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 a= nd EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 registe= r. + + @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, OrD= ata) + ); +} + +/** + 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, Dev= ice, Function, and Register. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 b= it 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, An= dData) + ); +} + +/** + 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, perfor= ms 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 al= l PCI + read and write operations are serialized. Extra left bits in both AndDat= a 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 a= nd EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 regist= er. + @param[in] OrData The value to OR with the result of the AND operati= on. + + @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, EndB= it, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Add= ress. + 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, Dev= ice, 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 t= he value specified by Value. + Value is returned. This function must guarantee that all PCI read and w= rite 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, D= evice, + 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-b= it 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, Dev= ice, Function, and Register. + @param[in] OrData The value to OR with the PCI configuration registe= r. + + @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 b= y 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, Dev= ice, Function, + and Register. + @param[in] AndData The value to AND with the PCI configuration regist= er. + + @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 b= y AndData, + performs a bitwise OR between the result of the AND operation and the va= lue 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, Dev= ice, Function, + and Register. + @param[in] AndData The value to AND with the PCI configuration regist= er. + @param[in] OrData The value to OR with the PCI configuration registe= r. + + @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 fiel= d 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 bi= t 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 regis= ter. + +**/ +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 t= he + 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 an= d EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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, perfor= ms 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 registe= r is + returned. This function must guarantee that all PCI read and write opera= tions + 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 a= nd EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 registe= r. + + @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, OrD= ata) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bit= wise + 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, perfor= ms a bitwise + AND between the read result and the value specified by AndData, and writ= es 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 guarante= e that all PCI + read and write operations are serialized. Extra left bits in AndData ar= e 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 bi= t 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 regist= er. + + @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, An= dData) + ); +} + +/** + 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, perfor= ms 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 al= l PCI + read and write operations are serialized. Extra left bits in both AndDat= a 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 a= nd EndBit, then ASSERT(). + + @param[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bi= t 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 regist= er. + @param[in] OrData The value to OR with the result of the AND operati= on. + + @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, EndB= it, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buff= er. + + 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 an= d 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 Segm= ent, 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 rea= d. + + @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) <=3D 0x1000); + + if (Size =3D=3D 0) { + return Size; + } + + ASSERT (Buffer !=3D NULL); + + // + // Save Size for return + // + ReturnValue =3D Size; + + if ((StartAddress & BIT0) !=3D 0) { + // + // Read a byte if StartAddress is byte aligned, + // Volatile ensure that the latest values are read every time. + // + *(UINT8 *)Buffer =3D PciSegmentRead8 (StartAddress); + StartAddress +=3D sizeof (UINT8); + Size -=3D sizeof (UINT8); + Buffer =3D (UINT8 *)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16) && (StartAddress & BIT1) !=3D 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16 *)Buffer + 1; + } + + while (Size >=3D sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress)); + StartAddress +=3D sizeof (UINT32); + Size -=3D sizeof (UINT32); + Buffer =3D (UINT32 *)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16 *)Buffer + 1; + } + + if (Size >=3D sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(UINT8 *)Buffer =3D 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 StartAddres= s 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 restrict= ions, + 8-bit and 16-bit PCI configuration write cycles may be used at the begin= ning + 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 Segm= ent, 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) <=3D 0x1000); + + if (Size =3D=3D 0) { + return 0; + } + + ASSERT (Buffer !=3D NULL); + + // + // Save Size for return + // + ReturnValue =3D Size; + + if ((StartAddress & BIT0) !=3D 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciSegmentWrite8 (StartAddress, *(UINT8 *)Buffer); + StartAddress +=3D sizeof (UINT8); + Size -=3D sizeof (UINT8); + Buffer =3D (UINT8 *)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16) && (StartAddress & BIT1) !=3D 0) { + // + // Write a word if StartAddress is word aligned + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16 *)Buffer + 1; + } + + while (Size >=3D sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress +=3D sizeof (UINT32); + Size -=3D sizeof (UINT32); + Buffer =3D (UINT32 *)Buffer + 1; + } + + if (Size >=3D sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress +=3D sizeof (UINT16); + Size -=3D sizeof (UINT16); + Buffer =3D (UINT16 *)Buffer + 1; + } + + if (Size >=3D sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciSegmentWrite8 (StartAddress, *(UINT8 *)Buffer); + } + + return ReturnValue; +} --=20 2.25.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#80481): https://edk2.groups.io/g/devel/message/80481 Mute This Topic: https://groups.io/mt/85504844/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-