From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by mx.groups.io with SMTP id smtpd.web10.3276.1576188970006913551 for ; Thu, 12 Dec 2019 14:16:10 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20161025 header.b=bXdKcgKO; spf=pass (domain: gmail.com, ip: 209.85.128.67, mailfrom: lintonrjeremy@gmail.com) Received: by mail-wm1-f67.google.com with SMTP id d73so4114348wmd.1 for ; Thu, 12 Dec 2019 14:16:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=m7K056rv1WG1AtxIMQuVqyTsqw3Z7qnPMpYTGTrvFG0=; b=bXdKcgKOArC4OnndbgFcnk2hFWVkVOTrP3OT6xNqCXA8oVDX+qNKJq7iu5cS5WUwm8 CiCshr6wbLIISP+mor/X7QmuKBEBOa/4Q+kv6iFtWI1ZD324kyhyDLQPN+uZA2J4RNZ3 ilpP7c2oQRJbWYIJUWoEHVa2Y9ifTogBVU5v2kTQfsFUQSHqC9e6Db8Mxf0+SnIfHjll /F9UDM96HKxcgJMpVBJ2IPIxDctXUDdUdRb6OeV1hyUQXs/VGVWA85ylE4NzFz2Names bxVA5Msl9zsdq8p6v1B2hsqeUpyn+H3ucwm3L1ruCSRPuonYDQfWsZ8g0vegSBtER1m6 Ze0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=m7K056rv1WG1AtxIMQuVqyTsqw3Z7qnPMpYTGTrvFG0=; b=Y6t0lTKHWIjuOlc3M2ZCwXwOjuU0N/dynHnJTyfzoOFkDviieZ2E3uW8LYdZGqnAaI +wYaDVDwvwlgdwdSF9cvb86QXc73zCD4pCfKSeiYNTN/XbZpJuXJQ2vz7/KgKJFLWqac Mho4KakZ1ea6kl5zTeL+kGgyxahJkzPaWpITmIlsvSGpGA1OtAu5O7wgxcdSHfW6buiS hpeBgEe096YHK92OoCZPivhHFHtp2WgU+TORUYiVPyGZwiVd3pPO6S8Ns5SGMON+/Z8N gRxhiLmb4VmV6pzi8kRy+X37LPvY+cEa+OgLks2gtQK5aFQ8YbpulWvtIGI5lFcGXSGr g1sA== X-Gm-Message-State: APjAAAXCUpDdK+sB9Mr1lcNXl1PXMzhqqnIUsbqVDItpJwq72/4PGwyV bu2q15pdoD/BbU2aFqQre7eGIqKJ49FK3a+wL1Q= X-Google-Smtp-Source: APXvYqwQdvXavGf4rLArB0QtnXzRk3/gPF6TVncL3bi33xfDq5xW7DpvnBAsesLV0HekGgCuERaapwrRITWOWuqmlw0= X-Received: by 2002:a1c:f009:: with SMTP id a9mr8900387wmb.73.1576188967434; Thu, 12 Dec 2019 14:16:07 -0800 (PST) MIME-Version: 1.0 References: <20191212105502.8492-1-pete@akeo.ie> <20191212105502.8492-3-pete@akeo.ie> In-Reply-To: From: Jeremy Linton Date: Thu, 12 Dec 2019 16:15:54 -0600 Message-ID: Subject: Re: [edk2-platforms][PATCH 2/4] Silicon/Bcm27xx: Add segment library to handle nonstandard ECAM To: Ard Biesheuvel Cc: Pete Batard , Jeremy Linton , edk2-devel-groups-io , Leif Lindholm , =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= Content-Type: text/plain; charset="UTF-8" Hi, On Thu, Dec 12, 2019 at 7:35 AM Ard Biesheuvel wrote: > > On Thu, 12 Dec 2019 at 11:55, Pete Batard wrote: > > > > From: Jeremy Linton > > > > Signed-off-by: Pete Batard > > --- > > Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.c | 1432 ++++++++++++++++++++ > > Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.inf | 34 + > > 2 files changed, 1466 insertions(+) > > > > diff --git a/Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.c b/Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.c > > new file mode 100644 > > index 000000000000..78232d233c5a > > --- /dev/null > > +++ b/Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.c > > @@ -0,0 +1,1432 @@ > > +/** @file > > + * > > + * PCI Segment Library for Bcm2711 (RPi4) SoC > > + * > > + * Copyright (c) 2019, Jeremy Linton > > + * Copyright (c) 2017, Linaro, Ltd. All rights reserved.
> > + * Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.
> > + * > > + * SPDX-License-Identifier: BSD-2-Clause-Patent > > + * > > + **/ > > + > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +typedef enum { > > + PciCfgWidthUint8 = 0, > > + PciCfgWidthUint16, > > + PciCfgWidthUint32, > > + PciCfgWidthMax > > +} PCI_CFG_WIDTH; > > + > > +/* > > + * This PCIe config space is unusual... > > + * The root port is the first bytes of the register space (offset 0) > > + * The individual devices are then selected by computing their BDF index > > + * and writing that into the CFG_INDEX register (offset 0x9000) > > + * the "ECAM" data is then read/writeable at CFG_DATA (offset 0x8000) > > + */ > > + > > +#define EFI_PCI_ADDR_BUS(bus) ((bus>>20) & 0xFF) /* Note PCI_SEGMENT_LIB_ADDRESS */ > > +#define EFI_PCI_ADDR_DEV(dev) ((dev>>15) & 0x1F) > > +#define EFI_PCI_ADDR_FUN(fun) ((fun>>12) & 0x07) > > + > > +/** > > + 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 A The address to validate. > > + @param M Additional bits to assert to be zero. > > + > > +**/ > > +#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \ > > + ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0) > > + > > +/** > > + Internal worker function to obtain config space base address. > > + > > + @param Address The address that encodes the PCI Bus, Device, Function and > > + Register. > > + > > + @return The value read from the PCI configuration register. > > + > > +**/ > > + > > +STATIC > > +UINT64 > > +PciSegmentLibGetConfigBase ( > > + IN UINT64 Address > > + ) > > +{ > > + STATIC UINT64 LastAccess = 0; /* Avoid repeat CFG_INDEX updates */ > > This doesn't look safe to me in the face of concurrency: what happens > if the timer interrupt fires in the middle of this routine, and > executes an event callback that accesses the PCI config space of > another device? I'm not saying this is likely to happen, but we have > to deal with it nonetheless. No, I think your right, I had a comment around here about it not being safe (aka you get the wrong config space), but I removed it. OTOH, wasn't sure if it could happen in this code path. > > I think the only safe way is to perform the entire access with TPL set > to TPL_HIGH_LEVEL, i.e., raise it before calling > PciSegmentLibGetConfigBase() in each routine, and drop it after > performing the access. That is easy enough. > > > > + UINT64 Base; > > + UINT64 Offset; > > + > > + Base = PCIE_REG_BASE; > > + Offset = Address & 0xFFF; /* Pick off the 4k register offset */ > > + Address &= 0xFFFFF000; /* Clear the offset leave only the BDF */ > > + > > + /* The root port is at the base of the PCIe register space */ > > + if (Address != 0) { > > + /* The current device is at CFG_DATA */ > > + Base += PCIE_EXT_CFG_DATA; > > + if (LastAccess != Address) { > > + UINT32 dev = EFI_PCI_ADDR_DEV (Address); > > + /* > > + * Scan things out directly rather than translating the "bus" to a device, etc.. > > + * only we need to limit each bus to a single device. > > + */ > > + if (dev < 1) { > > + MmioWrite32 (PCIE_REG_BASE + PCIE_EXT_CFG_INDEX, Address); > > + LastAccess = Address; > > + } else { > > + LastAccess = 0; > > + return 0xFFFFFFFF; > > + } > > + } > > + } > > + return Base + Offset; > > +} > > + > > +/** > > + Internal worker function to read a PCI configuration register. > > + > > + @param Address The address that encodes the PCI Bus, Device, Function and > > + Register. > > + @param 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; > > + UINT64 Ret = 0; > > + > > + Base = PciSegmentLibGetConfigBase (Address); > > + > > + if (Base==0xFFFFFFFF) > > + return Base; > > + > > + switch (Width) { > > + case PciCfgWidthUint8: > > + Ret = MmioRead8 (Base); > > + break; > > + case PciCfgWidthUint16: > > + Ret = MmioRead16 (Base); > > + break; > > + case PciCfgWidthUint32: > > + Ret = MmioRead32 (Base); > > + break; > > + default: > > + ASSERT (FALSE); > > + } > > + return Ret; > > +} > > + > > +/** > > + Internal worker function to writes a PCI configuration register. > > + > > + @param Address The address that encodes the PCI Bus, Device, Function and > > + Register. > > + @param Width The width of data to write > > + @param 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); > > + > > + switch (Width) { > > + case PciCfgWidthUint8: > > + MmioWrite8 (Base, Data); > > + break; > > + case PciCfgWidthUint16: > > + MmioWrite16 (Base, Data); > > + break; > > + case PciCfgWidthUint32: > > + MmioWrite32 (Base, 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 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 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param AndData The value to AND with the PCI configuration register. > > + @param 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 Address The PCI configuration register to read. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..7. > > + @param 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. > > + > > + 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 Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). > > + > > + @param Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..7. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..7. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..7. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..7. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..7. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..7. > > + @param 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. > > + > > + 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(). > > + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). > > + > > + @param Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..7. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..7. > > + @param AndData The value to AND with the PCI configuration register. > > + @param 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 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function and > > + Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param AndData The value to AND with the PCI configuration register. > > + @param 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 Address The PCI configuration register to read. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..15. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..15. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..15. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..15. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..15. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 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 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..15. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..15. > > + @param AndData The value to AND with the PCI configuration register. > > + @param 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 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 Address The address that encodes the PCI Segment, Bus, Device, > > + Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, > > + and Register. > > + @param 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 Address The address that encodes the PCI Segment, Bus, Device, Function, > > + and Register. > > + @param AndData The value to AND with the PCI configuration register. > > + @param 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 Address The PCI configuration register to read. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..31. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..31. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..31. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..31. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..31. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..31. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..31. > > + @param 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 Address The PCI configuration register to write. > > + @param StartBit The ordinal of the least significant bit in the bit field. > > + Range 0..31. > > + @param EndBit The ordinal of the most significant bit in the bit field. > > + Range 0..31. > > + @param AndData The value to AND with the PCI configuration register. > > + @param 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 StartAddress The starting address that encodes the PCI Segment, Bus, > > + Device, Function and Register. > > + @param Size The size in bytes of the transfer. > > + @param 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 > > + // > > + *(volatile UINT8 *)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 > > + // > > + *(volatile UINT8 *)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 StartAddress The starting address that encodes the PCI Segment, Bus, > > + Device, Function and Register. > > + @param Size The size in bytes of the transfer. > > + @param 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); > > + > > + // The Bcm/Rpi has a single cfg which can be mapped > > + // to any given device on the bus, which means we need to remap > > + // it basically everytime a new config access is done > > + > > + // > > + // 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/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.inf b/Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.inf > > new file mode 100644 > > index 000000000000..2ee38c06368a > > --- /dev/null > > +++ b/Silicon/Broadcom/Bcm27xx/Library/Bcm2711PciSegmentLib/PciSegmentLib.inf > > @@ -0,0 +1,34 @@ > > +## @file > > +# PCI Segment Library for Bcm2711 (RPi4) SoC > > +# > > +# Copyright (c) 2019, Jeremy Linton > > +# Copyright (c) 2017, Linaro Ltd. All rights reserved.
> > +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
> > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x0001001B > > + BASE_NAME = PciSegmentLib > > + FILE_GUID = 74fe3f9e-0040-11ea-a7bf-5254005675a0 > > + MODULE_TYPE = BASE > > + VERSION_STRING = 1.0 > > + LIBRARY_CLASS = PciSegmentLib > > + > > +[Sources] > > + PciSegmentLib.c > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + Silicon/Broadcom/Bcm27xx/Bcm27xx.dec > > + > > +[LibraryClasses] > > + BaseLib > > + DebugLib > > + IoLib > > + PcdLib > > + > > +[FixedPcd] > > + gBcm27xxTokenSpaceGuid.PcdBcm27xxPciRegBase > > -- > > 2.21.0.windows.1 > >