From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- .../DxeRuntimePciLibPciExpress.c | 2148 +++++++++++++++++++ .../DxeRuntimePciLibPciExpress.cif | 11 + .../DxeRuntimePciLibPciExpress.inf | 78 + .../DxeRuntimePciLibPciExpress.mak | 76 + .../DxeRuntimePciLibPciExpress.sdl | 72 + ReferenceCode/Chipset/LynxPoint/Library/PchLib.cif | 14 + ReferenceCode/Chipset/LynxPoint/Library/PchLib.sdl | 55 + .../PchPciExpressHelpersLib.cif | 12 + .../PchPciExpressHelpersLib.inf | 66 + .../PchPciExpressHelpersLib.mak | 88 + .../PchPciExpressHelpersLib.sdl | 83 + .../PchPciExpressHelpersLibrary.c | 2201 ++++++++++++++++++++ .../PchPciExpressHelpersLibrary.h | 42 + .../LynxPoint/Library/PchPlatformLib/IobpAccess.c | 295 +++ .../Library/PchPlatformLib/PchPlatformLib.cif | 13 + .../Library/PchPlatformLib/PchPlatformLib.inf | 67 + .../Library/PchPlatformLib/PchPlatformLib.mak | 112 + .../Library/PchPlatformLib/PchPlatformLib.sdl | 93 + .../Library/PchPlatformLib/PchPlatformLibrary.c | 831 ++++++++ .../Library/PchPlatformLib/PchPlatformLibrary.h | 29 + .../Library/PchSmbusLib/Common/PchSmbusComLib.cif | 8 + .../Library/PchSmbusLib/Common/PchSmbusLib.c | 54 + .../Library/PchSmbusLib/Dxe/PchSmbusDxeLib.cif | 9 + .../Library/PchSmbusLib/Dxe/PchSmbusLib.h | 25 + .../Library/PchSmbusLib/Dxe/PchSmbusLibDxe.inf | 63 + .../LynxPoint/Library/PchSmbusLib/PchSmbusLib.cif | 14 + .../LynxPoint/Library/PchSmbusLib/PchSmbusLib.mak | 74 + .../LynxPoint/Library/PchSmbusLib/PchSmbusLib.sdl | 59 + .../Library/PchSmbusLib/Pei/PchSmbusLib.h | 25 + .../Library/PchSmbusLib/Pei/PchSmbusLibPei.inf | 64 + .../Library/PchSmbusLib/Pei/PchSmbusPeiLib.cif | 9 + .../Library/RcFviDxeLib/CreateFviLibrary.c | 225 ++ .../LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.cif | 12 + .../LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.inf | 67 + .../LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.mak | 69 + .../LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.sdl | 73 + .../LynxPoint/Library/RcFviDxeLib/RcFviLib.h | 49 + 37 files changed, 7285 insertions(+) create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.mak create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.sdl create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchLib.sdl create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.inf create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.mak create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.sdl create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/IobpAccess.c create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.inf create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.mak create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.sdl create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.c create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.h create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusComLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusLib.c create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusDxeLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLib.h create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLibDxe.inf create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.mak create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.sdl create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLib.h create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLibPei.inf create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusPeiLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/CreateFviLibrary.c create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.cif create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.inf create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.mak create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.sdl create mode 100644 ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviLib.h (limited to 'ReferenceCode/Chipset/LynxPoint/Library') diff --git a/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c new file mode 100644 index 0000000..b9aab0a --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c @@ -0,0 +1,2148 @@ +/** @file + PCI Library using PC Express access. + +@copyright + Copyright (c) 2005 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "DxeRuntimePciLibPciExpress.h" + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A) ASSERT (((A) &~0xfffffff) == 0) + +/** + PCI Express base address +**/ +STATIC UINTN mPciExpressBaseAddress; + +/** + Registered memory scope. +**/ +typedef struct _REGISTERED_ADDRESS_MAP { + UINTN PciAddress; + UINTN Length; + UINTN RuntimeAddress; +} REGISTERED_ADDRESS_MAP; + +#define PCI_LIB_ADDRESS_MAP_MAX_ITEM 64 + +STATIC REGISTERED_ADDRESS_MAP mPciLibAddressMap[PCI_LIB_ADDRESS_MAP_MAX_ITEM]; + +STATIC UINTN mPciLibAddressMapIndex = 0; + +/** + Virtual address notify event +**/ +STATIC EFI_EVENT mVirtualNofityEvent; + +/** + Get the base address of PCI Express memory space. + + @param[in] None + + @retval VOID Return The base address of PCI Express. +**/ +VOID * +EFIAPI +GetPciExpressBaseAddress ( + VOID + ) +{ + return (VOID *) (mPciExpressBaseAddress); +} + +/** + Generate Pci Express address. + If Address > 0x0FFFFFFF or can't get the match Pci address, then ASSERT(). + + @param[in] Address Pci address. + + @retval UINTN Pci Express address. +**/ +static +UINTN +EFIAPI +PreparePciExpressAddress ( + IN UINTN Address + ) +{ + UINTN Index; + + ASSERT_INVALID_PCI_ADDRESS (Address); + + if (EfiAtRuntime () == FALSE) { + return mPciExpressBaseAddress + Address; + } + + for (Index = 0; Index < PCI_LIB_ADDRESS_MAP_MAX_ITEM; Index++) { + if ((Address >= mPciLibAddressMap[Index].PciAddress) && + (Address < mPciLibAddressMap[Index].PciAddress + mPciLibAddressMap[Index].Length) + ) { + return mPciLibAddressMap[Index].RuntimeAddress + (Address - mPciLibAddressMap[Index].PciAddress); + } + } + + ASSERT (FALSE); + EFI_DEADLOOP (); + return 0; +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + + @retval UINT8 return The read value from the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressRead8 ( + IN UINTN Address + ) +{ + return MmioRead8 (PreparePciExpressAddress (Address)); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] Value The value to write + + @retval UINT8 The value to write to the MMIO register. +**/ +UINT8 +EFIAPI +PciExpressWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return MmioWrite8 (PreparePciExpressAddress (Address), Value); +} + +/** + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioOr8 (PreparePciExpressAddress (Address), OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioAnd8 (PreparePciExpressAddress (Address), AndData); +} + +/** + 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 inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioAndThenOr8 ( + PreparePciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to read. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + + @retval UINT8 The value of the bit field read from the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead8 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] Value New value of the bit field. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioBitFieldWrite8 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioBitFieldOr8 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioBitFieldAnd8 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciExpressBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioBitFieldAndThenOr8 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + + @retval UINT16 The read value from the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressRead16 ( + IN UINTN Address + ) +{ + return MmioRead16 (PreparePciExpressAddress (Address)); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] Value The value to write. + + @retval UINT16 The value written to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return MmioWrite16 (PreparePciExpressAddress (Address), Value); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioOr16 (PreparePciExpressAddress (Address), OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioAnd16 (PreparePciExpressAddress (Address), AndData); +} + +/** + 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 inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioAndThenOr16 ( + PreparePciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to read. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + + @retval UINT16 The value of the bit field read from the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead16 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] Value New value of the bit field. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioBitFieldWrite16 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioBitFieldOr16 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + 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. Extra left bits in AndData are stripped. + If Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioBitFieldAnd16 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciExpressBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioBitFieldAndThenOr16 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + + @retval UINT32 The read value from the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressRead32 ( + IN UINTN Address + ) +{ + return MmioRead32 (PreparePciExpressAddress (Address)); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] Value The value to write. + + @retval UINT32 The value written to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return MmioWrite32 (PreparePciExpressAddress (Address), Value); +} + +/** + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioOr32 (PreparePciExpressAddress (Address), OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioAnd32 (PreparePciExpressAddress (Address), AndData); +} + +/** + 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 inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioAndThenOr32 ( + PreparePciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to read. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + + @retval UNT32 The value of the bit field read from the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead32 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] Value New value of the bit field. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioBitFieldWrite32 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioBitFieldOr32 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioBitFieldAnd32 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciExpressBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioBitFieldAndThenOr32 ( + PreparePciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + 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 StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register. + @param[in] Size Size in bytes of the transfer. + @param[in] Buffer Pointer to a buffer receiving the data read. + + @retval UINTN Size in bytes of the transfer. +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *) Buffer = PciExpressRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8 *) Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Read a word if StartAddress is word aligned + // + *(volatile UINT16 *) Buffer = PciExpressRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16 *) Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + *(volatile UINT32 *) Buffer = PciExpressRead32 (StartAddress); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32 *) Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + *(volatile UINT16 *) Buffer = PciExpressRead16 (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 = PciExpressRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + 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 StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register. + @param[in] Size Size in bytes of the transfer. + @param[in] Buffer Pointer to a buffer containing the data to write. + + @retval UINTN Size in bytes of the transfer. +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciExpressWrite8 (StartAddress, *(UINT8 *) Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8 *) Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciExpressWrite16 (StartAddress, *(UINT16 *) Buffer); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16 *) Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciExpressWrite32 (StartAddress, *(UINT32 *) Buffer); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32 *) Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciExpressWrite16 (StartAddress, *(UINT16 *) Buffer); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16 *) Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciExpressWrite8 (StartAddress, *(UINT8 *) Buffer); + } + + return ReturnValue; +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + + @retval UINT8 The read value from the PCI configuration register. +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + return PciExpressRead8 (Address); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] Data The value to write. + + @retval UINT8 The value written to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Data + ) +{ + return PciExpressWrite8 (Address, Data); +} + +/** + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciExpressOr8 (Address, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciExpressAnd8 (Address, AndData); +} + +/** + 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 inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciExpressAndThenOr8 (Address, AndData, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to read. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + + @retval UINT8 The value of the bit field read from the PCI configuration register. +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead8 (Address, StartBit, EndBit); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] Value New value of the bit field. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value); +} + +/** + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData); +} + +/** + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT8 The value written back to the PCI configuration register. +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + + @retval UINT16 The read value from the PCI configuration register. +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + return PciExpressRead16 (Address); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] Data The value to write. + + @retval UINT16 The value written to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Data + ) +{ + return PciExpressWrite16 (Address, Data); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciExpressOr16 (Address, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciExpressAnd16 (Address, AndData); +} + +/** + 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 inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciExpressAndThenOr16 (Address, AndData, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to read. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + + @retval UINT16 The value of the bit field read from the PCI configuration register. +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead16 (Address, StartBit, EndBit); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] Value New value of the bit field. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData); +} + +/** + 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. Extra left bits in AndData are stripped. + If Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData); +} + +/** + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT16 The value written back to the PCI configuration register. +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + + @retval UINT32 The read value from the PCI configuration register. +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + return PciExpressRead32 (Address); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] Data The value to write. + + @retval UINT32 The value written to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Data + ) +{ + return PciExpressWrite32 (Address, Data); +} + +/** + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciExpressOr32 (Address, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciExpressAnd32 (Address, AndData); +} + +/** + 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 inclusive 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 Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address Address that encodes the PCI Bus, Device, Function and Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciExpressAndThenOr32 (Address, AndData, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to read. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + + @retval UINT32 The value of the bit field read from the PCI configuration register. +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead32 (Address, StartBit, EndBit); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] Value New value of the bit field. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value); +} + +/** + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] OrData The value to OR with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData); +} + +/** + 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] AndData The value to AND with the PCI configuration register. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData); +} + +/** + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive 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 Address > 0x0FFFFFFF, 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 PCI configuration register to write. + @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31. + @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] OrData The value to OR with the result of the AND operation. + + @retval UINT32 The value written back to the PCI configuration register. +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + 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 StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register. + @param[in] Size Size in bytes of the transfer. + @param[in] Buffer Pointer to a buffer receiving the data read. + + @retval UINTN Size in bytes of the transfer. +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + return PciExpressReadBuffer (StartAddress, Size, Buffer); +} + +/** + 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 StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register. + @param[in] Size Size in bytes of the transfer. + @param[in] Buffer Pointer to a buffer containing the data to write. + + @retval UINTN The value written back to the PCI configuration register. +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + return PciExpressWriteBuffer (StartAddress, Size, Buffer); +} + +/** + Register memory space + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If SmPciLibAddressMapIndex) > PCI_LIB_ADDRESS_MAP_MAX_ITEM, then ASSERT(). + + @param[in] Address Starting address of the memory space + @param[in] Length Length of the memory space + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +PciLibRegisterMemory ( + IN UINTN Address, + IN UINTN Length + ) +{ + UINTN Index; + + ASSERT_INVALID_PCI_ADDRESS (Address); + ASSERT (mPciLibAddressMapIndex < PCI_LIB_ADDRESS_MAP_MAX_ITEM); + + // + // If already registered + // + for (Index = 0; Index < mPciLibAddressMapIndex; Index++) { + if (mPciLibAddressMap[Index].PciAddress == Address) { + return EFI_SUCCESS; + } + } + + mPciLibAddressMap[mPciLibAddressMapIndex].PciAddress = Address; + mPciLibAddressMap[mPciLibAddressMapIndex].Length = Length; + mPciLibAddressMap[mPciLibAddressMapIndex].RuntimeAddress = mPciExpressBaseAddress + Address; + mPciLibAddressMapIndex++; + + return EFI_SUCCESS; +} + +/** + Virtual address nofity. + The event handler changes PCIE base address to an virtual address. + Starting address of registered memory scope is converted as well. + + @param[in] Event The event that be siganlled when virtual address changed + @param[in] Context The pointer of the ESAL procedure instance + + @retval None +**/ +VOID +EFIAPI +VirtualAddressNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + + for (Index = 0; Index < PCI_LIB_ADDRESS_MAP_MAX_ITEM; Index++) { + if (mPciLibAddressMap[Index].PciAddress != 0) { + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mPciLibAddressMap[Index].RuntimeAddress)); + } + } + + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &mPciExpressBaseAddress); +} + +/** + Constructor for Pci library. Register VirtualAddressNotifyEvent() notify function + It will ASSERT() if that operation fails + + @param[in] None + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +PciLibConstructor ( + VOID + ) +{ + EFI_STATUS Status; + + mPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress); + + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + EFI_TPL_NOTIFY, + VirtualAddressNotifyEvent, + NULL, + &mVirtualNofityEvent + ); + ASSERT_EFI_ERROR (Status); + + ZeroMem (mPciLibAddressMap, sizeof (mPciLibAddressMap)); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.cif b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.cif new file mode 100644 index 0000000..179a995 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.cif @@ -0,0 +1,11 @@ + + name = "DxeRuntimePciLibPciExpress" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\DxeRuntimePciLibPciExpress" + RefName = "DxeRuntimePciLibPciExpress" +[files] +"DxeRuntimePciLibPciExpress.sdl" +"DxeRuntimePciLibPciExpress.mak" +"DxeRuntimePciLibPciExpress.c" +"DxeRuntimePciLibPciExpress.inf" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf new file mode 100644 index 0000000..20fec36 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf @@ -0,0 +1,78 @@ +## @file +# Component description file for the DxeRuntimePciLibPciExpress +# +#@copyright +# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchDxeRuntimePciLibPciExpress +COMPONENT_TYPE = LIBRARY + +[sources.common] + DxeRuntimePciLibPciExpress.c + +[sources.ia32] + + +[sources.x64] + + +[sources.ipf] + + +[sources.ebc] + + +[includes.common] + . + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + +[libraries.common] + EdkIIGlueEdkDxeRuntimeDriverLib + +[libraries.ia32] + + +[libraries.x64] + + +[nmake.common] + LIB_STD_FLAGS = $(LIB_STD_FLAGS) /IGNORE:4006 /IGNORE:4221 + +[nmake.ia32] + C_FLAGS = $(C_FLAGS) -DMDE_CPU_IA32 + +[nmake.x64] + C_FLAGS = $(C_FLAGS) -DMDE_CPU_X64 + +[nmake.ipf] + C_FLAGS = $(C_FLAGS) -DMDE_CPU_IPF + +[nmake.ebc] + EBC_C_STD_FLAGS = $(EBC_C_STD_FLAGS) -DEDKII_GLUE_LIBRARY_IMPLEMENTATION + EBC_LIB_STD_FLAGS = $(EBC_LIB_STD_FLAGS) /IGNORE:4006 /IGNORE:4221 + EBC_C_STD_FLAGS = $(EBC_C_STD_FLAGS) -DMDE_CPU_EBC diff --git a/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.mak b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.mak new file mode 100644 index 0000000..2a0bb30 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.mak @@ -0,0 +1,76 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.mak 1 2/08/12 8:46a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:46a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.mak $ +# +# 1 2/08/12 8:46a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +# MAK file for the ModulePart:DxeRuntimePciLibPciExpress +EDK : DxeRuntimePciLibPciExpress + +DxeRuntimePciLibPciExpress : $(BUILD_DIR)\DxeRuntimePciLibPciExpress.mak DxeRuntimePciLibPciExpressBin + +$(BUILD_DIR)\DxeRuntimePciLibPciExpress.mak : $(DxeRuntimePciLibPciExpress_DIR)\$(@B).cif $(DxeRuntimePciLibPciExpress_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(DxeRuntimePciLibPciExpress_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +$(DxeRuntimePciLibPciExpressLib_LIB) : DxeRuntimePciLibPciExpress + +DxeRuntimePciLibPciExpress_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + +DxeCpuBuildDefine = \ +!IF "$(x64_BUILD)"=="1" + /DMDE_CPU_X64\ +!ELSE + /DMDE_CPU_IA32\ +!ENDIF + +DxeRuntimePciLibPciExpress_DEFINES = \ +$(CFLAGS) \ +$(DxeCpuBuildDefine) \ + +DxeRuntimePciLibPciExpressBin: + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS) \ + /f $(BUILD_DIR)\DxeRuntimePciLibPciExpress.mak all \ + "MY_INCLUDES=$(DxeRuntimePciLibPciExpress_INCLUDES)" \ + "CFLAGS=$(DxeRuntimePciLibPciExpress_DEFINES)"\ + TYPE=LIBRARY LIBRARIES= \ + LIBRARY_NAME=$(DxeRuntimePciLibPciExpressLib_LIB) +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.sdl b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.sdl new file mode 100644 index 0000000..5c09ab6 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.sdl @@ -0,0 +1,72 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.sdl 1 2/08/12 8:46a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:46a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.sdl $ +# +# 1 2/08/12 8:46a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "DxeRuntimePciLibPciExpress_SUPPORT" + Value = "1" + Help = "Main switch to enable DxeRuntimePciLibPciExpress support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +PATH + Name = "DxeRuntimePciLibPciExpress_DIR" +End + +MODULE + File = "DxeRuntimePciLibPciExpress.mak" + Help = "Includes DxeRuntimePciLibPciExpress.mak to Project" +End + +ELINK + Name = "DxeRuntimePciLibPciExpressLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\DxeRuntimePciLibPciExpress_Lib.lib" + Parent = "DxeRuntimePciLibPciExpressLib_LIB" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchLib.cif new file mode 100644 index 0000000..2f066b4 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchLib.cif @@ -0,0 +1,14 @@ + + name = "PchLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\" + RefName = "PchLib" +[files] +"PchLib.sdl" +[parts] +"DxeRuntimePciLibPciExpress" +"PchPciExpressHelpersLib" +"PchPlatformLib" +"PchSmbusLib" +"RcFviDxeLib" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchLib.sdl b/ReferenceCode/Chipset/LynxPoint/Library/PchLib.sdl new file mode 100644 index 0000000..b73418a --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchLib.sdl @@ -0,0 +1,55 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchLib.sdl 1 2/08/12 8:46a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:46a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchLib.sdl $ +# +# 1 2/08/12 8:46a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchLibrary_SUPPORT" + Value = 1 + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes + Help = "Main switch to enable PchLibrary support in Project" +End + +PATH + Name = "PchLibrary_DIR" +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.cif new file mode 100644 index 0000000..bffca56 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.cif @@ -0,0 +1,12 @@ + + name = "PchPciExpressHelpersLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\PchPciExpressHelpersLib" + RefName = "PchPciExpressHelpersLib" +[files] +"PchPciExpressHelpersLib.sdl" +"PchPciExpressHelpersLib.mak" +"PchPciExpressHelpersLibrary.c" +"PchPciExpressHelpersLibrary.h" +"PchPciExpressHelpersLib.inf" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.inf b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.inf new file mode 100644 index 0000000..aa731f8 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.inf @@ -0,0 +1,66 @@ +## @file +# Component description file for the PchPciExpressHelpersLib +# +#@copyright +# Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchPciExpressHelpersLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + PchPciExpressHelpersLibrary.c + +[sources.ia32] + + +[sources.x64] + + +[sources.ipf] + + +[sources.ebc] + + +[includes.common] + . + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Protocol/PchPlatformPolicy + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + +[libraries.common] + PchPlatformLib + +[libraries.ia32] + + +[libraries.x64] + + +[nmake.common] \ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.mak b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.mak new file mode 100644 index 0000000..e8ce73e --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.mak @@ -0,0 +1,88 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPciExpressHelpersLib/PchPciExpressHelpersLib.mak 2 10/16/12 4:57a Scottyang $ +# +# $Revision: 2 $ +# +# $Date: 10/16/12 4:57a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPciExpressHelpersLib/PchPciExpressHelpersLib.mak $ +# +# 2 10/16/12 4:57a Scottyang +# [TAG] EIP84720 +# [Category] Improvement +# [Description] Support Hot-Plug in Shark Bay +# [Files] PchRootPort.c, PchPcie.asl, PchPciExpressHelpersLib.mak, +# PchPciExpressHlpersLibrary.c, SB.sdl +# +# 1 2/08/12 8:47a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +all : PchPciExpressHelpersLib + +PchPciExpressHelpersLib : PchPciExpressHelpersDxeLib PchPciExpressHelpersPeiLib + +$(PchPciExpressHelpersDxeLib_LIB) : PchPciExpressHelpersDxeLib +$(PchPciExpressHelpersPeiLib_LIB) : PchPciExpressHelpersPeiLib + +PchPciExpressHelpersDxeLib : $(BUILD_DIR)\PchPciExpressHelpersLib.mak PchPciExpressHelpersLibDxeBin +PchPciExpressHelpersPeiLib : $(BUILD_DIR)\PchPciExpressHelpersLib.mak PchPciExpressHelpersLibPeiBin + +$(BUILD_DIR)\PchPciExpressHelpersLib.mak : $(PchPciExpressHelpersLib_DIR)\$(@B).cif $(PchPciExpressHelpersLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchPciExpressHelpersLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchPciExpressHelpersLib_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + +PchPciExpressHelpersLib_DEFINES=\ + $(CFLAGS)\ + +PchPciExpressHelpersLibDxeBin: + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchPciExpressHelpersLib.mak all \ + "MY_INCLUDES=$(PchPciExpressHelpersLib_INCLUDES)" \ + TYPE=LIBRARY LIBRARIES= \ + LIBRARY_NAME=$(PchPciExpressHelpersDxeLib_LIB) + +PchPciExpressHelpersLibPeiBin: +!IF "$(x64_BUILD)"=="1" + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32\ +!ELSE + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ +!ENDIF + /f $(BUILD_DIR)\PchPciExpressHelpersLib.mak all \ + "MY_INCLUDES=$(PchPciExpressHelpersLib_INCLUDES)" \ + "MY_DEFINES=$(PchPciExpressHelpersLib_DEFINES)" \ + LIBRARIES= \ + TYPE=PEI_LIBRARY LIBRARY_NAME=$(PchPciExpressHelpersPeiLib_LIB) +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.sdl b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.sdl new file mode 100644 index 0000000..1bb4ebc --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLib.sdl @@ -0,0 +1,83 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPciExpressHelpersLib/PchPciExpressHelpersLib.sdl 1 2/08/12 8:47a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:47a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPciExpressHelpersLib/PchPciExpressHelpersLib.sdl $ +# +# 1 2/08/12 8:47a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchPciExpressHelpersLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PchPciExpressHelpersLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +PATH + Name = "PchPciExpressHelpersLib_DIR" +End + +MODULE + File = "PchPciExpressHelpersLib.mak" + Help = "Includes PchPciExpressHelpersLib.mak to Project" +End + +ELINK + Name = "PchPciExpressHelpersDxeLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchPciExpressHelpersDxeLib_Lib.lib" + Parent = "PchPciExpressHelpersDxeLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PchPciExpressHelpersPeiLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchPciExpressHelpersPeiLib_Lib.lib" + Parent = "PchPciExpressHelpersPeiLib_LIB" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c new file mode 100644 index 0000000..7d622b3 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c @@ -0,0 +1,2201 @@ +/** @file + This file contains routines that support PCI Express initialization + +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchPciExpressHelpersLibrary.h" +// AMI_OVERRIDE, [EIP84720]> +#include "Token.h" +// AMI_OVERRIDE, [EIP84720]< + +/** + Find the Offset to a given Capabilities ID + CAPID list: + 0x01 = PCI Power Management Interface + 0x04 = Slot Identification + 0x05 = MSI Capability + 0x10 = PCI Express Capability + + @param[in] Bus Pci Bus Number + @param[in] Device Pci Device Number + @param[in] Function Pci Function Number + @param[in] CapId CAPID to search for + + @retval 0 CAPID not found + @retval Other CAPID found, Offset of desired CAPID +**/ +UINT8 +PcieFindCapId ( + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Function, + IN UINT8 CapId + ) +{ + UINT8 CapHeaderOffset; + UINT8 CapHeaderId; + UINTN DeviceBase; + + DeviceBase = MmPciAddress (0, Bus, Device, Function, 0); + + /// + /// Check the header layout to determine the Offset of Capabilities Pointer Register + /// + if ((MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) { + /// + /// If CardBus bridge, start at Offset 0x14 + /// + CapHeaderOffset = 0x14; + } else { + /// + /// Otherwise, start at Offset 0x34 + /// + CapHeaderOffset = 0x34; + } + /// + /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list. + /// + CapHeaderId = 0; + CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1)); + while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) { + CapHeaderId = MmioRead8 (DeviceBase + CapHeaderOffset); + if (CapHeaderId == CapId) { + return CapHeaderOffset; + } + /// + /// Each capability must be DWORD aligned. + /// The bottom two bits of all pointers (including the initial pointer at 34h) are reserved + /// and must be implemented as 00b although software must mask them to allow for future uses of these bits. + /// + CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset + 1) & ((UINT8) ~(BIT0 | BIT1)); + } + + return 0; +} + +/** + Search and return the offset of desired Pci Express Capability ID + CAPID list: + 0x0001 = Advanced Error Rreporting Capability + 0x0002 = Virtual Channel Capability + 0x0003 = Device Serial Number Capability + 0x0004 = Power Budgeting Capability + + @param[in] Bus Pci Bus Number + @param[in] Device Pci Device Number + @param[in] Function Pci Function Number + @param[in] CapId Extended CAPID to search for + + @retval 0 CAPID not found + @retval Other CAPID found, Offset of desired CAPID +**/ +UINT16 +PcieFindExtendedCapId ( + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Function, + IN UINT16 CapId + ) +{ + UINT16 CapHeaderOffset; + UINT16 CapHeaderId; + UINTN DeviceBase; + + DeviceBase = MmPciAddress (0, Bus, Device, Function, 0); + + /// + /// Start to search at Offset 0x100 + /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list. + /// + CapHeaderId = 0; + CapHeaderOffset = 0x100; + while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) { + CapHeaderId = MmioRead16 (DeviceBase + CapHeaderOffset); + if (CapHeaderId == CapId) { + return CapHeaderOffset; + } + /// + /// Each capability must be DWORD aligned. + /// The bottom two bits of all pointers are reserved and must be implemented as 00b + /// although software must mask them to allow for future uses of these bits. + /// + CapHeaderOffset = (MmioRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1)); + } + + return 0; +} + +/** + Map a TC to VC0 for port and endpoint + + @param[in] Bus1 The bus number of the port + @param[in] Device1 The device number of the port + @param[in] Function1 The function number of the port + @param[in] Bus2 The bus number of the endpoint + @param[in] Device2 The device number of the endpoint + @param[in] TCx The TC number + + @exception EFI_UNSUPPORTED Unsupported operation. + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PcieMapTcxVc0 ( + IN UINT8 Bus1, + IN UINT8 Device1, + IN UINT8 Function1, + IN UINT8 Bus2, + IN UINT8 Device2, + IN UINT8 TCx + ) +{ + UINT16 Offset; + UINTN DeviceBase1; + UINTN DeviceBase2; + UINT8 DeviceIndex; + UINT8 FunctionIndex; + UINT8 Function2; + + DeviceBase1 = MmPciAddress (0, Bus1, Device1, Function1, 0); + + /// + /// Set TCx-VC0 value on the port + /// + Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2); + if (Offset == 0) { + return EFI_UNSUPPORTED; + } + + MmioAndThenOr8 (DeviceBase1 + Offset + 0x014, (UINT8) (~0xF), 1); + MmioWrite8 (DeviceBase1 + Offset + 0x014, (UINT8) (1 << TCx)); + + /// + /// Set TCx-VC0 value on the Endpoint + /// + for (DeviceIndex = 0; DeviceIndex <= Device2; DeviceIndex++) { + DeviceBase2 = MmPciAddress (0, Bus2, DeviceIndex, 0, 0); + if (MmioRead16 (DeviceBase2 + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + continue; + } + /// + /// Check if EndPoint device is Multi-Function Device + /// + if (MmioRead8 (DeviceBase2 + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) { + /// + /// If multi-function Device, check function 0-7 + /// + Function2 = PCI_MAX_FUNC; + } else { + /// + /// Otherwise, check function 0 only + /// + Function2 = 0; + } + + for (FunctionIndex = 0; FunctionIndex <= Function2; FunctionIndex++) { + DeviceBase2 = MmPciAddress (0, Bus2, DeviceIndex, FunctionIndex, 0); + + Offset = PcieFindExtendedCapId (Bus2, DeviceIndex, FunctionIndex, 2); + if (Offset == 0) { + continue; + } + + MmioAndThenOr8 (DeviceBase2 + Offset + 0x014, (UINT8) (~0xF), 1); + MmioWrite8 (DeviceBase2 + Offset + 0x014, (UINT8) (1 << TCx)); + } + } + + return EFI_SUCCESS; +} + +/** + Set Common clock to Root port and Endpoint PCI device + + @param[in] Bus1 Root port Pci Bus Number + @param[in] Device1 Root port Pci Device Number + @param[in] Function1 Root port Pci Function Number + @param[in] Bus2 Endpoint Pci Bus Number + @param[in] Device2 Endpoint Pci Device Number + + @exception EFI_UNSUPPORTED Unsupported operation. + @retval EFI_SUCCESS VC mapping correctly initialized +**/ +EFI_STATUS +PcieSetCommonClock ( + IN UINT8 Bus1, + IN UINT8 Device1, + IN UINT8 Function1, + IN UINT8 Bus2, + IN UINT8 Device2 + ) +{ + UINT8 CapOffset1; + UINT8 CapOffset2; + BOOLEAN CommonClockSupport; + EFI_STATUS Status; + UINTN DeviceBase1; + UINTN DeviceBase2; + UINT16 RegData16; + UINT8 DeviceIndex; + UINT8 FunctionIndex; + UINT8 Function2; + + DeviceBase1 = MmPciAddress (0, Bus1, Device1, Function1, 0); + + /// + /// Get the pointer to the Port PCI Express Capability Structure. + /// + CommonClockSupport = FALSE; + CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (CapOffset1 == 0) { + return EFI_UNSUPPORTED; + } + /// + /// Check the Port Slot Clock Configuration Bit. + /// + if ((MmioRead16 (DeviceBase1 + CapOffset1 + 0x012) & BIT12) == 0) { + return EFI_UNSUPPORTED; + } + + for (DeviceIndex = 0; DeviceIndex <= Device2; DeviceIndex++) { + DeviceBase2 = MmPciAddress (0, Bus2, DeviceIndex, 0, 0); + if (MmioRead16 (DeviceBase2 + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + continue; + } + /// + /// Check if EndPoint device is Multi-Function Device + /// + if (MmioRead8 (DeviceBase2 + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) { + /// + /// If multi-function Device, check function 0-7 + /// + Function2 = PCI_MAX_FUNC; + } else { + /// + /// Otherwise, check function 0 only + /// + Function2 = 0; + } + + for (FunctionIndex = 0; FunctionIndex <= Function2; FunctionIndex++) { + DeviceBase2 = MmPciAddress (0, Bus2, DeviceIndex, FunctionIndex, 0); + /// + /// Check the Endpoint Slot Clock Configuration Bit. + /// + CapOffset2 = PcieFindCapId (Bus2, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP); + if ((CapOffset2 != 0) && ((MmioRead16 (DeviceBase2 + CapOffset2 + 0x012) & BIT12) != 0)) { + /// + /// Common clock is supported, set common clock bit on root port + /// and the endpoint + /// + if (CommonClockSupport == FALSE) { + MmioOr8 (DeviceBase1 + CapOffset1 + 0x010, BIT6); + CommonClockSupport = TRUE; + } + + MmioOr8 (DeviceBase2 + CapOffset2 + 0x010, BIT6); + } + } + } + /// + /// If common clock not supported on root port and endpoint, return EFI_UNSUPPORTED + /// + if (CommonClockSupport == FALSE) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_SUCCESS; + } + /// + /// Set Pci + D4h Bit 6 and Bit 12 to 1 for root port only + /// + if (Bus1 == 0) { + MmioOr32 (DeviceBase1 + 0xD4, ((UINT32)(BIT6 | BIT12))); + } + /// + /// Retrain the Link per PCI Express Specification. + /// + MmioOr8 (DeviceBase1 + CapOffset1 + 0x010, BIT5); + +// AMI_OVERRIDE >>> +#ifdef PCIE_CLEAR_RETRAIN_BIT_SUPPORT_FLAG + PchPmTimerStall (1); + + if((MmioRead8 (DeviceBase1 + CapOffset1 + 0x010) & BIT5) == 1){ + MmioAnd8 (DeviceBase1 + CapOffset1 + 0x010, BIT5); + } +#endif +// AMI_OVERRIDE <<< + + /// + /// Wait until Re-Training has completed. + /// + do { + RegData16 = MmioRead16 (DeviceBase1 + CapOffset1 + 0x012) & BIT11; + } while (RegData16 != 0); + + return Status; +} + +/** + This function enables the CLKREQ# PM on all the end point functions + + @param[in] Bus Pci Bus Number + @param[in] Device Pci Device Number + @param[in] RootFunction Rootport Function Number + + @retval None +**/ +VOID +PcieSetClkreq ( + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 RootFunction + ) +{ + UINT8 CapOffset; + UINTN DeviceBase; + UINT8 DeviceIndex; + UINT8 FunctionIndex; + UINT8 Function; + UINT32 Data32; + UINT16 GpioBase; + BOOLEAN ClkreqPerPortSupported; + PCH_SERIES PchSeries; + UINT8 RootPortNumber; + UINT32 RootComplexBar; + + + PchSeries = GetPchSeries(); + + if (PchSeries == PchLp) { + GpioBase = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE) + ) & B_PCH_LPC_GPIO_BASE_BAR; + + RootComplexBar = PCH_RCRB_BASE; + RootPortNumber = GetPchPcieRpNumber(RootComplexBar, RootFunction); + Data32 = (IoRead32 ((UINTN) (GpioBase + R_PCH_GP_X_CONFIG0(18 + RootPortNumber))) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + + if (Data32 != 0) { + /// + /// CLKREQ not supported on root port + /// + return; + } + } + + for (DeviceIndex = 0; DeviceIndex <= Device; DeviceIndex++) { + DeviceBase = MmPciAddress (0, Bus, DeviceIndex, 0, 0); + if (MmioRead16 (DeviceBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + continue; + } + + ClkreqPerPortSupported = TRUE; + + /// + /// Check if EndPoint device is Multi-Function Device + /// + if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) { + /// + /// If multi-function Device, check function 0-7 + /// + Function = PCI_MAX_FUNC; + } else { + /// + /// Otherwise, check function 0 only + /// + Function = 0; + } + /// + /// Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if + /// exists then enable the CLKREQ# bit (BIT8) on that function + /// + for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) { + /// + /// Find the PCIe Cap Id (offset 10h) + /// + CapOffset = PcieFindCapId (Bus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (CapOffset == 0) { + continue; + } + + DeviceBase = MmPciAddress (0, Bus, DeviceIndex, FunctionIndex, 0); + /// + /// Check if CLKREQ# is supported by the endpoints + /// + if ((MmioRead32 (DeviceBase + CapOffset + 0x0C) & BIT18) == 0) { + /// + /// CLKREQ# is not supported so dont do anything + /// + ClkreqPerPortSupported = FALSE; + break; + } + } + + if (ClkreqPerPortSupported == FALSE) { + continue; + } + /// + /// Now enable the CLKREQ# + /// + for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) { + /// + /// Find the PCIe Cap Id (offset 10h) + /// + CapOffset = PcieFindCapId (Bus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (CapOffset == 0) { + continue; + } + + DeviceBase = MmPciAddress (0, Bus, DeviceIndex, FunctionIndex, 0); + MmioOr16 (DeviceBase + CapOffset + 0x010, BIT8); + } + } +} + +/** + This function get or set the Max Payload Size on all the end point functions + + @param[in] EndPointBus The Bus Number of the Endpoint + @param[in] EndPointDevice The Device Number of the Endpoint + @param[in, out] MaxPayload The Max Payolad Size of the root port + @param[in] Operation True: Set the Max Payload Size on all the end point functions + False: Get the Max Payload Size on all the end point functions + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PcieMaxPayloadSize ( + IN UINT8 EndPointBus, + IN UINT8 EndPointDevice, + IN OUT UINT16 *MaxPayload, + IN BOOLEAN Operation + ) +{ + UINTN DeviceBase; + UINT8 PcieCapOffset; + UINT16 EndPointMaxPayload; + UINT8 DeviceIndex; + UINT8 FunctionIndex; + UINT8 EndPointFunction; + + /// + /// Obtain the Max Payload Size for all the end point functions + /// + for (DeviceIndex = 0; DeviceIndex <= EndPointDevice; DeviceIndex++) { + DeviceBase = MmPciAddress (0, EndPointBus, DeviceIndex, 0, 0); + if (MmioRead16 (DeviceBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + continue; + } + /// + /// Check if EndPoint device is Multi-Function Device + /// + if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) { + /// + /// If multi-function Device, check function 0-7 + /// + EndPointFunction = PCI_MAX_FUNC; + } else { + /// + /// Otherwise, check function 0 only + /// + EndPointFunction = 0; + } + + for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) { + DeviceBase = MmPciAddress (0, EndPointBus, DeviceIndex, FunctionIndex, 0); + if (MmioRead16 (DeviceBase + 0x0) != 0xFFFF) { + /// + /// Get the pointer to the Endpoint PCI Express Capability Structure. + /// + PcieCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (PcieCapOffset == 0) { + continue; + } + + if (Operation == TRUE) { + /// + /// Set the Max Payload Size of the end point function + /// + MmioAndThenOr16 ( + DeviceBase + PcieCapOffset + 0x08, + (UINT16)~(BIT7 | BIT6 | BIT5), + *MaxPayload << 5 + ); + } else { + /// + /// Get the end point function Max Payload Size support + /// + EndPointMaxPayload = MmioRead16 (DeviceBase + PcieCapOffset + 0x04) & (BIT2 | BIT1 | BIT0); + /// + /// Obtain the minimum Max Payload Size between the PCIE root Port and the end point functions + /// + if (*MaxPayload > EndPointMaxPayload) { + *MaxPayload = EndPointMaxPayload; + } + } + } + } + } + + return EFI_SUCCESS; +} + +/** + This function disable the forwarding of EOI messages unless it discovers + an IOAPIC behind this root port. + + @param[in] RootBus The Bus Number of the root port + @param[in] RootDevice The Device Number of the root port + @param[in] RootFunction The Function Number of the root port + @param[in] EndPointBus The Bus Number of the Endpoint + @param[in] EndPointDevice The Device Number of the Endpoint + + @exception EFI_UNSUPPORTED Unsupported operation. + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PcieSetEoiFwdDisable ( + IN UINT8 RootBus, + IN UINT8 RootDevice, + IN UINT8 RootFunction, + IN UINT8 EndPointBus, + IN UINT8 EndPointDevice + ) +{ + BOOLEAN IoApicBehind; + UINTN RootDeviceBase; + UINTN DeviceBase; + UINT8 ProgInterface; + UINT8 SubClassCode; + UINT8 BaseClassCode; + UINT8 DeviceIndex; + UINT8 FunctionIndex; + UINT8 EndPointFunction; + + IoApicBehind = FALSE; + RootDeviceBase = MmPciAddress (0, RootBus, RootDevice, RootFunction, 0); + + /// + /// Check if an IOAPIC behind the root port + /// + for (DeviceIndex = 0; DeviceIndex <= EndPointDevice; DeviceIndex++) { + DeviceBase = MmPciAddress (0, EndPointBus, DeviceIndex, 0, 0); + if (MmioRead16 (DeviceBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + continue; + } + /// + /// Check if EndPoint device is Multi-Function Device + /// + if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) { + /// + /// If multi-function Device, check function 0-7 + /// + EndPointFunction = PCI_MAX_FUNC; + } else { + /// + /// Otherwise, check function 0 only + /// + EndPointFunction = 0; + } + + for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) { + DeviceBase = MmPciAddress (0, EndPointBus, DeviceIndex, FunctionIndex, 0); + BaseClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 2); + SubClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 1); + ProgInterface = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET); + + if ((BaseClassCode == PCI_CLASS_SYSTEM_PERIPHERAL) && + (SubClassCode == PCI_SUBCLASS_PIC) && + ((ProgInterface == PCI_IF_APIC_CONTROLLER) || + (ProgInterface == PCI_IF_APIC_CONTROLLER2))) { + IoApicBehind = TRUE; + } + } + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 20 + /// If there is no IOAPIC behind the root port, set EOI Forwarding Disable bit (B0:D28:F0-F7:D4h[1]) to 1b. + /// + if (IoApicBehind == FALSE) { + #ifdef HOTPLUG_EOI_FLAG // AMI_OVERRIDE, [EIP84720]> + MmioOr8 (RootDeviceBase + 0xD4, (UINT8) (BIT1)); + #else + //Supporting _RMV method in asl code, and reading hotplug capability register of root port + //if hotplug disable, then set EOI Forwarding Disable bit + #ifdef TBT_UP_PORT_FUNC_FLAG + if((TBT_UP_PORT_FUNC == RootFunction) || (!(MmioRead8 (DeviceBase + 0x54) & 0x40))){ + #else + if(!(MmioRead8 (DeviceBase + 0x54) & 0x40)){ + #endif + MmioOr8 (RootDeviceBase + 0xD4, (UINT8) (BIT1)); + } + #endif // AMI_OVERRIDE, [EIP84720]< + } + + return EFI_SUCCESS; +} + +typedef enum { + CalculateAspm, + ManualAspm, + SetAspm +} OPERATION; + +/** + This function compares the actual latency in LatencyValue1 + with actual latency in LatencyValue2 and stores the minimum + back to LatencyValue1, in the required format. + If this is the first call, then LatencyValue1 will be replaced by LatencyValue2. + + @param[in, out] LatencyValue1 - Current latency value + @param[in] LatencyValue2 - Latency value from the Table + + @retval None +**/ +VOID +DetermineLatencyValue ( + IN OUT UINT16 *LatencyValue1, + IN UINT16 *LatencyValue2 + ) +{ + ASSERT (LTR_SCALE_VALUE (*LatencyValue1) < 6); + ASSERT (LTR_SCALE_VALUE (*LatencyValue2) < 6); + /// + /// If there are more than one device behind a bridge that are part of the override table, + /// store the lower latency value and corresponding scale bits back to LatencyValue1 + /// + if ((LTR_LATENCY_NS(*LatencyValue1) == 0) || (LTR_LATENCY_NS(*LatencyValue1) > LTR_LATENCY_NS(*LatencyValue2))) { + *LatencyValue1 = *LatencyValue2; + } +} + +/** + Calculate/Set EndPoint device Power management settings + + @param[in] RootDeviceBase The Root Port PCI Express address + @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure + @param[in] EndPointBus The Bus Number of the Endpoint + @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items + @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items + @param[in, out] LinkAspmVal Resulting Link ASPM value programmed + @param[in] Operation Operation Types + @param[in] NumOfDevLtrOverride Number of Device specific LTR override items + @param[in] DevLtrOverride Pointer to array of Device specific LTR policy override items + @param[in, out] LtrOverrideVal Resulting LTR override value to be programmed + @param[in] RootL1SubstateExtCapOffset The register offset of Root Port L1 Substates + @param[in, out] L1SubstatesSupported Input and return the result of L1 Substates support + @param[in] L1SubstatesConfig L1 Substates configurations + @param[in, out] PortCommonModeRestoreTime Input and return common mode restore time of L1 Substate setting + @param[in, out] PortTpowerOnValue Input and return power on value of L1 Substate setting + @param[in, out] PortTpowerOnScale Input and return power on scale of L1 Substate setting + @param[in] PchPwrOptPcie Pcie Power Optimizer Configuration + @param[in, out] AspmOverride Input and return the Aspm Override enable for pre-1.1 devices + @param[in, out] ClkreqPerPortSupported Input to check if clkreq per port is supportted + @param[in, out] RpAndEndPointsLtrSupported Return to check if all endpoints support LTR + @param[in] PolicyRevision Policy revision for codes compatibility + + @retval EFI_SUCCESS Successfully completed + @retval EFI_NOT_FOUND Can not find device + @retval EFI_OUT_OF_RESOURCES The endpoint device is a bridge, but the Subordinate Bus Number of + the root port is not greater than its Secondary Bus Number. You may + get this error if PCI emulation is not done before this function gets + called and the platform policy settings of "TempRootPortBusNumMax" and + "TempRootPortBusNumMin" do not provide enough resource for temp bus + number usage. +**/ +EFI_STATUS +PcieEndPointPm ( + IN UINTN RootDeviceBase, + IN UINT32 RootPcieCapOffset, + IN UINT8 EndPointBus, + IN UINT8 NumOfDevAspmOverride, + IN PCH_PCIE_DEVICE_ASPM_OVERRIDE *DevAspmOverride, + IN OUT UINT16 *LinkAspmVal, + IN OPERATION Operation, + IN UINT8 NumOfDevLtrOverride, + IN PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverride, + IN OUT UINT32 *LtrOverrideVal, + IN UINT16 RootL1SubstateExtCapOffset, + IN OUT BOOLEAN *L1SubstatesSupported, + IN PCH_PCIE_EXPRESS_L1SUBSTATES_CONTROL L1SubstatesConfig, + IN OUT UINT32 *PortCommonModeRestoreTime, + IN OUT UINT32 *PortTpowerOnValue, + IN OUT UINT32 *PortTpowerOnScale, + IN PCH_PCIE_PWR_OPT *PchPwrOptPcie, + IN OUT BOOLEAN *AspmOverride, + IN BOOLEAN *ClkreqPerPortSupported, + IN OUT BOOLEAN *RpAndEndPointsLtrSupported, + IN UINT8 PolicyRevision + ) +{ + EFI_STATUS Status; + UINTN EndPointBase; + UINT8 EndPointFunction; + UINT8 EndPointPcieCapOffset; + UINT8 PcieDeviceIndex; + UINT16 EndPointAspm; + UINT16 EndPointVendorId; + UINT16 EndPointDeviceId; + UINT8 EndPointRevId; + UINT8 EndPointBaseClassCode; + UINT8 EndPointSubClassCode; + UINT32 PortLxLat; + UINT32 EndPointLxLat; + UINT32 LxLat; + UINT8 DownStreamBusMin; + UINT8 ClassCode; + UINT8 RootDevSubBusNum; + BOOLEAN BusAssign; + UINT8 DeviceIndex; + UINT8 FunctionIndex; + UINT16 LtrExtendedCapOffset; + UINT32 DeviceCapabilities2; + UINT16 DefaultMaxLatency; + UINT16 Data16; + UINT32 Data32; + UINT16 EndPointL1SubStateCapOffset; + UINT32 RootDeviceL1Substates; + UINT32 EndPointL1Substates; + UINT8 EndPointPortCommonModeRestoreTime; + UINT8 EndPointTpowerOnScale; + UINT8 EndPointTpowerOnValue; + UINT32 Multiplier[4] = {2, 10, 100, 0}; + UINT32 EndPointL1SubstCapMask; + PCH_SERIES PchSeries; + + DefaultMaxLatency = 0; + PchSeries = GetPchSeries(); + for (DeviceIndex = 0; DeviceIndex <= PCI_MAX_DEVICE; DeviceIndex++) { + EndPointBase = MmPciAddress (0, EndPointBus, DeviceIndex, 0, 0); + if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + continue; + } + /// + /// Check if EndPoint device is Multi-Function Device + /// + if (MmioRead8 (EndPointBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) { + /// + /// If multi-function Device, check function 0-7 + /// + EndPointFunction = PCI_MAX_FUNC; + } else { + /// + /// Otherwise, check function 0 only + /// + EndPointFunction = 0; + } + + for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) { + /// + /// Get the pointer to the Endpoint PCI Express Capability Structure. + /// + EndPointPcieCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP); + + if (EndPointPcieCapOffset == 0) { + if (FunctionIndex < EndPointFunction) { + continue; + } else { + return EFI_NOT_FOUND; + } + } + EndPointBase = MmPciAddress (0, EndPointBus, DeviceIndex, FunctionIndex, 0); + EndPointVendorId = MmioRead16 (EndPointBase + R_PCH_PCIE_VENDOR_ID); + EndPointDeviceId = MmioRead16 (EndPointBase + R_PCH_PCIE_DEVICE_ID); + EndPointRevId = MmioRead8 (EndPointBase + R_PCH_PCIE_RID); + EndPointL1SubStateCapOffset = 0; + RootDeviceL1Substates = 0; + EndPointL1Substates = 0; + EndPointL1SubstCapMask = 0x0000001F; + if (PchSeries == PchLp) { + /// + /// Get the endpoint supports L1 Substates Capabilities + /// + for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) { + if ((PolicyRevision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) && + ((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) && + (EndPointVendorId == DevAspmOverride[PcieDeviceIndex].VendorId) && + (EndPointDeviceId == DevAspmOverride[PcieDeviceIndex].DeviceId) && + ((EndPointRevId == DevAspmOverride[PcieDeviceIndex].RevId) || + (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) { + if ((EndPointVendorId == 0x8086) && + ((EndPointDeviceId == 0x08B1) || (EndPointDeviceId == 0x08B2) || + (EndPointDeviceId == 0x08B3) || (EndPointDeviceId == 0x08B4))) { + if ((MmioRead32 (EndPointBase + DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset) & 0xFFFF) == 0xCAFE) { + EndPointL1SubStateCapOffset = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset; + EndPointL1SubstCapMask = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapMask; + } + } else { + EndPointL1SubStateCapOffset = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset; + EndPointL1SubstCapMask = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapMask; + } + } + } + if (EndPointL1SubStateCapOffset == 0) { + EndPointL1SubStateCapOffset = PcieFindExtendedCapId ( + EndPointBus, + DeviceIndex, + FunctionIndex, + 0x1E); + } + if (EndPointL1SubStateCapOffset != 0) { + RootDeviceL1Substates = MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04); + EndPointL1Substates = MmioRead32 (EndPointBase + EndPointL1SubStateCapOffset + 0x04); + } + } + DeviceCapabilities2 = MmioRead32 (EndPointBase + EndPointPcieCapOffset + 0x24); + if (((DeviceCapabilities2 & BIT11) == 0) || (PchPwrOptPcie->LtrEnable != TRUE)) { + *RpAndEndPointsLtrSupported = FALSE; + } + /// + /// Configure downstream device if present. + /// + + if (Operation == CalculateAspm || Operation == ManualAspm) { + if ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + 0x00C) & BIT18) != BIT18) { + *ClkreqPerPortSupported = FALSE; + } + EndPointAspm = (MmioRead16 (EndPointBase + EndPointPcieCapOffset + 0x00C) >> 10) & 3; + DEBUG ((EFI_D_INFO, "Endpoint Device %0x Capability ASPM: %0x\n", DeviceIndex, EndPointAspm)); + if (Operation == CalculateAspm) { + /// + /// Check endpoint for pre-1.1 devices based on the Role based Error Reporting Capability bit + /// and enable Aspm Override + /// + if (!(MmioRead16 (EndPointBase + EndPointPcieCapOffset + 0x4) & BIT15)) { + DEBUG ((EFI_D_INFO, "Override root port ASPM to L1 for pre-1.1 devices\n")); + *AspmOverride = TRUE; + } + /// + /// Mask APMC with values from lookup table. + /// RevID of 0xFF applies to all steppings. + /// + EndPointBaseClassCode = MmioRead8 (EndPointBase + R_PCH_PCIE_BCC); + EndPointSubClassCode = MmioRead8 (EndPointBase + R_PCH_PCIE_SCC); + + for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) { + if ((PolicyRevision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) && + ((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1L2Override) == PchPcieL1L2Override) && + ((DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) || + (DevAspmOverride[PcieDeviceIndex].VendorId == 0xFFFF)) && + ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) || + (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) && + ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) || + (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF)) && + ((DevAspmOverride[PcieDeviceIndex].BaseClassCode == EndPointBaseClassCode) || + (DevAspmOverride[PcieDeviceIndex].BaseClassCode == 0xFF)) && + ((DevAspmOverride[PcieDeviceIndex].SubClassCode == EndPointSubClassCode) || + (DevAspmOverride[PcieDeviceIndex].SubClassCode == 0xFF))) { + /// + /// Override value of 0xFF applies to all. + /// + EndPointAspm = DevAspmOverride[PcieDeviceIndex].EndPointAspm; + break; + } + } + /// + /// Check if L1 should be enabled based on port and endpoint L1 exit latency. + /// + if (EndPointAspm & BIT1) { + PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + 0x00C) & (BIT17 + BIT16 + BIT15); + EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + 0x00C) & (BIT17 + BIT16 + BIT15); + + LxLat = PortLxLat; + if (PortLxLat < EndPointLxLat) { + LxLat = EndPointLxLat; + } + /// + /// check if the value is bigger than endpoint L1 acceptable exit latency, if it is + /// larger than accepted value, then we should disable L1 + /// + LxLat >>= 6; + if (LxLat > (MmioRead32 (EndPointBase + EndPointPcieCapOffset + 0x004) & (BIT11 + BIT10 + BIT9))) { + EndPointAspm &= ~BIT1; + } + } + /// + /// Check if L0s should be enabled based on port and endpoint L0s exit latency. + /// + if (EndPointAspm & BIT0) { + PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + 0x00C) & (BIT14 + BIT13 + BIT12); + EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + 0x00C) & (BIT14 + BIT13 + BIT12); + + LxLat = PortLxLat; + if (PortLxLat < EndPointLxLat) { + LxLat = EndPointLxLat; + } + /// + /// check if the value is bigger than endpoint L0s acceptable exit latency, if it is + /// larger than accepted value, then we should disable L0s + /// + LxLat >>= 6; + if (LxLat > (MmioRead32 (EndPointBase + EndPointPcieCapOffset + 0x004) & (BIT8 + BIT7 + BIT6))) { + EndPointAspm &= ~BIT0; + } + } + } + + *LinkAspmVal &= EndPointAspm; + DEBUG ((EFI_D_INFO, "Calculate Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, EndPointAspm)); + if (PchSeries == PchLp) { + /// + /// Check if the endpoint supports L1 Substates Capabilities + /// + if ((EndPointL1SubStateCapOffset != 0) && (RootL1SubstateExtCapOffset != 0)) { + /// + /// If both Root and endpoint's L1 Sub-States Extended Capability Offset + 0x04[4:0] are 11111b, + /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised + /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on + /// Pcie root port. + /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value + /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on + /// both Pcie root port and device. + /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device + /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device + /// e. Program L1 Sub-States Extended Capability Offset + 0x08[4:0] to 01111b for both Pcie root port and device + /// + if (((RootDeviceL1Substates & 0x1F) == 0x1F) && + ((EndPointL1Substates & EndPointL1SubstCapMask) == EndPointL1SubstCapMask) && + (L1SubstatesConfig != PchPcieL1SubstatesDisabled)) { + *L1SubstatesSupported = TRUE; + EndPointPortCommonModeRestoreTime = (EndPointL1Substates >> 8) & 0xFF; + EndPointTpowerOnScale = (EndPointL1Substates >> 16) & 0x3; + EndPointTpowerOnValue = (EndPointL1Substates >> 19) & 0x1F; + + if (EndPointPortCommonModeRestoreTime > *PortCommonModeRestoreTime) { + *PortCommonModeRestoreTime = EndPointPortCommonModeRestoreTime; + } + + if ((EndPointTpowerOnValue * Multiplier[EndPointTpowerOnScale]) > + (*PortTpowerOnValue * Multiplier[*PortTpowerOnScale])) { + *PortTpowerOnValue = EndPointTpowerOnValue; + *PortTpowerOnScale = EndPointTpowerOnScale; + } + } + } + } + /// + /// For each device detected, scan the LTR override table + /// If there are endpoints connected directly to the rootport then + /// LtrOverrideVal will be replaced by the value from the table for that endpoint + /// If there are endpoints that are behind a bridge and that are also part of the table then + /// LtrOverrideVal will maintain the minimum of all such values. + /// A non zero value of LtrOverrideVal will indicate: + /// i):That there is atleast one entry in the LTR override Table + /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices + /// connected to this root port + /// + Data32 = *LtrOverrideVal; + if (DevLtrOverride != NULL) { + for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevLtrOverride; PcieDeviceIndex++) { + if ((DevLtrOverride[PcieDeviceIndex].VendorId == EndPointVendorId) && + ((DevLtrOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) || + (DevLtrOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) && + ((DevLtrOverride[PcieDeviceIndex].RevId == EndPointRevId) || + (DevLtrOverride[PcieDeviceIndex].RevId == 0xFF))) { + + /// + /// Get the Non-Snoop latency value from the table, compare and store the minimum + /// + if (DevLtrOverride[PcieDeviceIndex].NonSnoopLatency & BIT15) { + Data16 = (UINT16)((Data32 & 0xFFFF0000) >> 16); + DetermineLatencyValue(&Data16, &DevLtrOverride[PcieDeviceIndex].NonSnoopLatency); + Data32 = (Data32 & 0xFFFF) | ((UINT32)(Data16 << 16)); + } + + /// + /// Get the Snoop latency value from the table, compare and store the minimum + /// + if (DevLtrOverride[PcieDeviceIndex].SnoopLatency & BIT15) { + Data16 = (UINT16)(Data32 & 0xFFFF); + DetermineLatencyValue(&Data16, &DevLtrOverride[PcieDeviceIndex].SnoopLatency); + Data32 = (Data32 & 0xFFFF0000) | (UINT32)Data16; + } + *LtrOverrideVal = Data32; + break; + } + } + } + } else if (Operation == SetAspm) { + if (PchSeries == PchLp) { + if ((EndPointL1SubStateCapOffset != 0) && (*L1SubstatesSupported)) { + if (((RootDeviceL1Substates & 0x1F) == 0x1F) && + ((EndPointL1Substates & EndPointL1SubstCapMask) == EndPointL1SubstCapMask)) { + MmioAndThenOr32 ( + EndPointBase + EndPointL1SubStateCapOffset + 0x0C, + (UINT32) ~(0xF8), + (*PortTpowerOnValue << 3) + ); + MmioAndThenOr32 ( + EndPointBase + EndPointL1SubStateCapOffset + 0x0C, + (UINT32) ~(0x03), + *PortTpowerOnScale); + MmioAndThenOr32 ( + EndPointBase + EndPointL1SubStateCapOffset + 0x08, + (UINT32) ~(0xE3FF0000), + (UINT32) (BIT30 | BIT23 | BIT21) + ); + Data32 = (BIT3 | BIT2 | BIT1 | BIT0); + if (L1SubstatesConfig == PchPcieL1SubstatesL1_1) { + Data32 &= (UINT32)~(BIT0); + } + if (L1SubstatesConfig == PchPcieL1SubstatesL1_2) { + Data32 &= (UINT32)~(BIT1); + } + MmioAndThenOr32 ( + EndPointBase + EndPointL1SubStateCapOffset + 0x08, + (UINT32) ~(0x1F), + Data32 + ); + } + } + } + /// + /// Write it to the Link Control register + /// + DEBUG ((EFI_D_INFO, "Program Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, *LinkAspmVal)); + MmioAndThenOr16 (EndPointBase + EndPointPcieCapOffset + 0x10, 0xFFFC, *LinkAspmVal); + /// + /// PCH BIOS Spec Rev 0.5.5, Section 8.14.1 Power Optimizer Configuration + /// Step 3 + /// For PCIe Endpoint, + /// If Endpoint device supported LTR, Device Capabilities 2 Register Offset 24h [11] = 1b, + /// + if ((DeviceCapabilities2 & BIT11) && (PchPwrOptPcie->LtrEnable == TRUE)) { + /// + /// Step 3.1 + /// Program Endpoint LTR Mechanism Enable, Device Control 2 Register Offset 28h [10] = 1b + /// when device supports LTR but is not found in override table (table listing correct + /// latency requirements for devices that supports LTR and also for devices that do not + /// support LTR) + /// + if (DevLtrOverride != NULL) { + for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevLtrOverride; PcieDeviceIndex++) { + if ((DevLtrOverride[PcieDeviceIndex].VendorId != EndPointVendorId) || + ((DevLtrOverride[PcieDeviceIndex].DeviceId != EndPointDeviceId) && + (DevLtrOverride[PcieDeviceIndex].DeviceId != 0xFFFF)) || + ((DevLtrOverride[PcieDeviceIndex].RevId != EndPointRevId) && + (DevLtrOverride[PcieDeviceIndex].RevId != 0xFF))) { + MmioOr16 (EndPointBase + EndPointPcieCapOffset + 0x28, BIT10); + break; + } + } + } else { + MmioOr16 (EndPointBase + EndPointPcieCapOffset + 0x28, BIT10); + } + } + /// + /// Get the pointer to the Endpoint PCI Express Extended Capability Structure + /// and configure the Max Snoop and Max No-Snoop Latency for the endpoint + /// + LtrExtendedCapOffset = PcieFindExtendedCapId (EndPointBus, DeviceIndex, FunctionIndex, 0x18); + if (LtrExtendedCapOffset != 0) { + Data32 = *LtrOverrideVal; + if (PchSeries == PchH) { + DefaultMaxLatency = 0x0846; + } + if (PchSeries == PchLp) { + DefaultMaxLatency = 0x1003; + } + /// + /// PCH BIOS Spec Rev 0.5.6, Section 8.14.1 Power Optimizer Configuration + /// Step 3.2 + /// Program Endpoint Max Snoop Latency Register, Latency Tolerance Reporting(LTR) + /// Capability Offset 04h [15:0] with Intel recommended default value for max snoop + /// latency if there is no snoop latency override value getting programmed in the + /// override register else program the endpoint Max Snoop Latency Register with the + /// minimum of snoop latency override value for that root port and Intel recommended + /// default value for max snoop latency + /// Intel recommended default value for max snoop latency for LPT-H = 0x0846 + /// Intel recommended default value for max snoop latency for LPT-LP = 0x1003 + /// + if (PolicyRevision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { + DefaultMaxLatency = PchPwrOptPcie->LtrMaxSnoopLatency; + } + + Data16 = (UINT16)(Data32 & 0xFFFF); + /// + /// Set the max snoop latency to either the default max snoop latency or to the snoop latency override value + /// that is being programmed for this root port + /// + DetermineLatencyValue(&Data16, &DefaultMaxLatency); + MmioAndThenOr16 ( + EndPointBase + LtrExtendedCapOffset + 4, + (UINT16) (~0x1FFF), + Data16 + ); + /// + /// PCH BIOS Spec Rev 0.5.6, Section 8.14.1 Power Optimizer Configuration + /// Step 3.3 + /// Program Endpoint Max No-Snoop Latency Register, Latency Tolerance Reporting(LTR) + /// Capability Offset 06h [15:0] with Intel recommended default value for max no-snoop + /// latency if there is no No-snoop latency override value getting programmed in the + /// override register else program the endpoint Max No-Snoop Latency Register with the + /// minimum of No-snoop latency override value for that root port and Intel recommended + /// default value for max no-snoop latency + /// Intel recommended default value for max no-snoop latency for LPT-H = 0x0846 + /// Intel recommended default value for max no-snoop latency for LPT-LP = 0x1003 + /// + if (PolicyRevision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { + DefaultMaxLatency = PchPwrOptPcie->LtrMaxNoSnoopLatency; + } + Data16 = (UINT16)((Data32 & 0xFFFF0000) >> 16); + DetermineLatencyValue(&Data16, &DefaultMaxLatency); + MmioAndThenOr16 ( + EndPointBase + LtrExtendedCapOffset + 6, + (UINT16) (~0x1FFF), + Data16 + ); + } + /// + /// Step 4 + /// For PCIe Endpoint, + /// If Endpoint device supported OBFF, Device Capabilities 2 Register Offset 24h [19:18] = 2h, + /// + if ((DeviceCapabilities2 & BIT19) && (PchPwrOptPcie->ObffEnable == PCH_DEVICE_ENABLE)) { + /// + /// Step 4.1 + /// Program Endpoint OBFF Mechanism Enable, Device Control 2 Register Offset 28h [14:13] = 3h + /// + MmioOr16 (EndPointBase + EndPointPcieCapOffset + 0x28, (BIT14 + BIT13)); + } + } + /// + /// Check if this device is a bridge + /// + ClassCode = MmioRead8 (EndPointBase + R_PCH_PCIE_BCC); + + if (ClassCode == PCI_CLASS_BRIDGE) { + /// + /// Get the downstream Bus number + /// + DownStreamBusMin = (UINT8) (MmioRead32 (EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET) >> 8); + /// + /// If the Secondary Bus Number of endpoint device is not assigned + /// + if (DownStreamBusMin == 0) { + RootDevSubBusNum = (UINT8) (MmioRead32 (RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET) >> 16); + /// + /// If the endpoint device is a bridge, the Subordinate Bus Number of the root port will need to be greater + /// than the Secondary Bus Number of the root port (the Bus Number of endpoint device). + /// + if (RootDevSubBusNum > EndPointBus) { + /// + /// Assign the Primary, Secondary and Subordinate Bus Number to endpoint device + /// + MmioAndThenOr32 ( + EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, + 0xFF000000, + EndPointBus | (((UINT32) (EndPointBus + 1) << 8)) | ((UINT32) (RootDevSubBusNum << 16)) + ); + DownStreamBusMin = EndPointBus + 1; + } else { + return EFI_OUT_OF_RESOURCES; + } + + BusAssign = FALSE; + } else { + BusAssign = TRUE; + } + + if (DownStreamBusMin > EndPointBus) { + Status = PcieEndPointPm ( + RootDeviceBase, + RootPcieCapOffset, + DownStreamBusMin, + NumOfDevAspmOverride, + DevAspmOverride, + LinkAspmVal, + Operation, + NumOfDevLtrOverride, + DevLtrOverride, + LtrOverrideVal, + RootL1SubstateExtCapOffset, + L1SubstatesSupported, + L1SubstatesConfig, + PortCommonModeRestoreTime, + PortTpowerOnValue, + PortTpowerOnScale, + PchPwrOptPcie, + AspmOverride, + ClkreqPerPortSupported, + RpAndEndPointsLtrSupported, + PolicyRevision + ); + if (Status == EFI_NOT_FOUND) { + DEBUG ((EFI_D_INFO, "Check DownStreamBus:%d and no device found!\n", DownStreamBusMin)); + } + + if (BusAssign == FALSE) { + /// + /// Clear Bus Numbers. + /// + MmioAnd32 (EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000); + } + } + } + } + } + + return EFI_SUCCESS; +} + +/** + This function checks if the root port and downstream device support Clkreq per port, ASPM L1 and L1 substates + + @param[in] RootBus Pci Bus Number of the root port + @param[in] RootDevice Pci Device Number of the root port + @param[in] RootFunction Pci Function Number of the root port + @param[in] RootPortAspm Root port Aspm configuration + @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items + @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + @param[in] NumOfDevLtrOverride Number of Device specific LTR override items + @param[in] DevLtrOverride Pointer to array of Device specific LTR policy override items + @param[in] PchPwrOptPcie Pcie Power Optimizer Configuration + @param[in, out] L1SubstatesSupported Flag to indicate if L1 Substates are supported + @param[in] L1SubstatesConfig L1 Substates configuration + @param[in] PolicyRevision Revision of the policy + @param[in, out] AspmVal Aspm value for both rootport and end point devices + @param[in, out] ClkreqPerPortSupported Clkreq support for both rootport and endpoint devices + @param[out] LtrSupported Check and return if all endpoints support LTR + + @retval EFI_SUCCESS The function completed successfully + @exception EFI_UNSUPPORTED The pointer to the Port PCI Express Capability Structure is not found +**/ +EFI_STATUS +PcieCheckPmConfig ( + IN UINT8 RootBus, + IN UINT8 RootDevice, + IN UINT8 RootFunction, + IN PCH_PCI_EXPRESS_ASPM_CONTROL RootPortAspm, + IN UINT8 NumOfDevAspmOverride, + IN PCH_PCIE_DEVICE_ASPM_OVERRIDE *DevAspmOverride, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax, + IN UINT8 NumOfDevLtrOverride, + IN PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverride, + IN PCH_PCIE_PWR_OPT *PchPwrOptPcie, + IN OUT BOOLEAN *L1SubstatesSupported, + IN PCH_PCIE_EXPRESS_L1SUBSTATES_CONTROL L1SubstatesConfig, + IN UINT8 PolicyRevision, + IN OUT UINT16 *AspmVal, + IN OUT BOOLEAN *ClkreqPerPortSupported, + OUT BOOLEAN *LtrSupported + ) +{ + EFI_STATUS Status; + UINTN RootDeviceBase; + UINT32 RootPcieCapOffset; + UINT8 EndPointBus; + OPERATION Operation; + UINT16 SlotStatus; + BOOLEAN BusAssign; + UINT32 DeviceCapabilities2; + UINT32 LtrOvrVal; + UINT32 Data32Or; + UINT16 GpioBase; + UINT32 RootComplexBar; + UINT16 RootL1SubstateExtCapOffset; + UINT32 PortCommonModeRestoreTime; + UINT32 PortTpowerOnValue; + UINT32 PortTpowerOnScale; + BOOLEAN AspmOverride; + PCH_SERIES PchSeries; + UINT8 RootPortNumber; + + PchSeries = GetPchSeries(); + Status = EFI_SUCCESS; + RootDeviceBase = MmPciAddress (0, RootBus, RootDevice, RootFunction, 0); + RootComplexBar = PCH_RCRB_BASE; + PortCommonModeRestoreTime = 0; + PortTpowerOnValue = 0; + PortTpowerOnScale = 0; + *L1SubstatesSupported = FALSE; + AspmOverride = FALSE; + *ClkreqPerPortSupported = FALSE; + GpioBase = 0; + + if (MmioRead16 (RootDeviceBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + return EFI_NOT_FOUND; + } + if (PchSeries == PchLp) { + GpioBase = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE) + ) & B_PCH_LPC_GPIO_BASE_BAR; + + RootPortNumber = GetPchPcieRpNumber(RootComplexBar, RootFunction); + Data32Or = (IoRead32 ((UINTN) (GpioBase + R_PCH_GP_X_CONFIG0(18 + RootPortNumber))) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + + if (Data32Or == 0) { + *ClkreqPerPortSupported = TRUE; + } + } + + /// + /// Get the pointer to the Port PCI Express Capability Structure. + /// + RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (RootPcieCapOffset == 0) { + return EFI_UNSUPPORTED; + } + DeviceCapabilities2 = MmioRead32 (RootDeviceBase + RootPcieCapOffset + 0x24); + + *AspmVal = (MmioRead16 (RootDeviceBase + RootPcieCapOffset + 0x00C) >> 10) & 3; + if (RootPortAspm == PchPcieAspmAutoConfig) { + Operation = CalculateAspm; + } else { + Operation = ManualAspm; + *AspmVal &= RootPortAspm; + } + /// + /// Get the downstream Bus number + /// + EndPointBus = (UINT8) (MmioRead32 (RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET) >> 8); + /// + /// If the Secondary Bus Number of the root port is not assigned + /// Note: + /// It will be better that PCI emulation has been done before PcieSetPm(). Or, you will need to assign + /// a larger number to TempRootPortBusNumMax to support the specific card which has many bridges behind. + /// If it is not, the platform policy settings of "TempRootPortBusNumMax" and "TempRootPortBusNumMin" + /// will be assigned to the Subordinate and Secondary Bus Number of the root ports. + /// The assigned bus number will be cleared in the end of PcieSetPm(). + /// + if (EndPointBus == 0) { + MmioAndThenOr32 ( + RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, + 0xFF0000FF, + ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16)) + ); + EndPointBus = TempBusNumberMin; + BusAssign = FALSE; + } else { + BusAssign = TRUE; + } + /// + /// Check whether the slot has a device connected + /// + SlotStatus = MmioRead16 (RootDeviceBase + RootPcieCapOffset + 0x1A); + LtrOvrVal = 0; + + RootL1SubstateExtCapOffset = 0; + if (PchSeries == PchLp) { + RootL1SubstateExtCapOffset = PcieFindExtendedCapId (RootBus, RootDevice, RootFunction, 0x1E); + if (RootL1SubstateExtCapOffset != 0) { + PortCommonModeRestoreTime = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04) >> 8) & 0xFF; + PortTpowerOnScale = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04) >> 16) & 0x3; + PortTpowerOnValue = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04) >> 19) & 0x1F; + } + } + /// + /// Obtain initial ASPM settings from respective port capability registers. + /// Scan LTR override table for device match and calculate the lowest override + /// value to be programmed into B0:D28:F0~F7 + 400h + /// + if (EndPointBus != 0 && (SlotStatus & BIT6) != 0) { + Status = PcieEndPointPm ( + RootDeviceBase, + RootPcieCapOffset, + EndPointBus, + NumOfDevAspmOverride, + DevAspmOverride, + AspmVal, + Operation, + NumOfDevLtrOverride, + DevLtrOverride, + &LtrOvrVal, + RootL1SubstateExtCapOffset, + L1SubstatesSupported, + L1SubstatesConfig, + &PortCommonModeRestoreTime, + &PortTpowerOnValue, + &PortTpowerOnScale, + PchPwrOptPcie, + &AspmOverride, + ClkreqPerPortSupported, + LtrSupported, + PolicyRevision + ); + } + + if (BusAssign == FALSE) { + /// + /// Clear Bus Numbers. + /// + MmioAnd32 (RootDeviceBase + 0x018, 0xFF0000FF); + } + + return Status; +} +/** + This function performs the Power Management settings for root port and downstream device + + @param[in] RootBus Pci Bus Number of the root port + @param[in] RootDevice Pci Device Number of the root port + @param[in] RootFunction Pci Function Number of the root port + @param[in] RootPortAspm Root port Aspm configuration + @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items + @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + @param[in] NumOfDevLtrOverride Number of Device specific LTR override items + @param[in] DevLtrOverride Pointer to array of Device specific LTR policy override items + @param[in] PchPwrOptPcie Pcie Power Optimizer Configuration + @param[in, out] L1SubstatesSupported Flag to indicate if L1 Substates are supported + @param[in] L1SubstatesConfig L1 Substates configuration + @param[in] PolicyRevision Policy revision for codes compatibility + @param[in] FirstRpToSetPm Indicates if this is the first root port to be set + @param[in] L1SupportedInAllEnabledPorts Check if L1 is supported in all enabled ports + @param[in] ClkreqSupportedInAllEnabledPorts Check if clkreq is supported in all enabled ports + @param[out] LtrSupported Check and return if all endpoints support LTR + + @retval EFI_SUCCESS The function completed successfully + @exception EFI_UNSUPPORTED The pointer to the Port PCI Express Capability Structure is not found +**/ +EFI_STATUS +PcieSetPm ( + IN UINT8 RootBus, + IN UINT8 RootDevice, + IN UINT8 RootFunction, + IN PCH_PCI_EXPRESS_ASPM_CONTROL RootPortAspm, + IN UINT8 NumOfDevAspmOverride, + IN PCH_PCIE_DEVICE_ASPM_OVERRIDE *DevAspmOverride, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax, + IN UINT8 NumOfDevLtrOverride, + IN PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverride, + IN PCH_PCIE_PWR_OPT *PchPwrOptPcie, + IN OUT BOOLEAN *L1SubstatesSupported, + IN PCH_PCIE_EXPRESS_L1SUBSTATES_CONTROL L1SubstatesConfig, + IN UINT8 PolicyRevision, + IN BOOLEAN FirstRPToSetPm, + IN BOOLEAN L1SupportedInAllEnabledPorts, + IN BOOLEAN ClkreqSupportedInAllEnabledPorts, + OUT BOOLEAN *LtrSupported + ) +{ + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports + /// + /// When enabling L0s / L1 support, BIOS should enable upstream device before downstream + /// device. When disabling ASPM, BIOS should make sure downstream device is disabled + /// before upstream device. + /// The System BIOS must perform the following steps to enable + /// L0s/L1 on the root ports: + /// + /// 1. Determine whether the endpoint supports L1 by checking the Active State Link PM + /// Support field of the endpoint Link Capability Register. If the endpoint does not + /// support L1, the System BIOS can skip the L1 calculations below. Likewise, System + /// BIOS should not enable L1 on the root port or the endpoint if the endpoint does not + /// support L1. + /// 2. Calculate the total L0s and L1 exit latency. A description of this calculation + /// is provided in Section 8.3.1.1. + /// 3. Compare the calculated total exit latency with Endpoint L0s/L1 Acceptable Latency + /// read from the Device Capabilities Register of the Endpoint to determine if L0s or + /// L1 can be enabled for all or some of the links on the entire path to satisfy the + /// Acceptable Latency reported by the Endpoint. The Exit Latency fields reported by + /// the registers are given as a range. It is recommended that System BIOS uses the + /// high end of the range for the latency calculation and comparison. For example, if + /// the latency field reports "2 us to less than 4 us", then 4 us should be used for + /// the calculation. + /// 4. If the comparison in step 3 indicates L0s and L1 can be enabled on a root port and + /// the endpoints attached to the root port, then set the root port register + /// D28:F0~F7:Reg E8h[1], then set the APMC field, D28:F0~F7:Reg 50h[1:0] to 11b and write + /// the same value to the APMC field of the endpoint Link Control register. If the + /// comparison in step 1 indicates only L0s can be enabled on a root port and the + /// endpoints attached to the root port, then set the APMC field, D28:F0~F7:Reg 50h[1:0] + /// to 01b and write the same value to the APMC field of the endpoint Link Control + /// register. + /// + /// NOTE: current implementation does not support full length exit latency calculation + /// + UINT16 AspmVal; + EFI_STATUS Status; + UINTN RootDeviceBase; + UINT32 RootPcieCapOffset; + UINT8 EndPointBus; + OPERATION Operation; + UINT16 SlotStatus; + BOOLEAN BusAssign; + UINT32 DeviceCapabilities2; + UINT32 LtrOvrVal; + UINT32 Data32Or; + UINT8 Data8And; + UINT8 Data8Or; + UINT16 GpioBase; + BOOLEAN ClkreqPerPortSupported; + UINT32 RootComplexBar; + UINT16 RootL1SubstateExtCapOffset; + UINT32 PortCommonModeRestoreTime; + UINT32 PortTpowerOnValue; + UINT32 PortTpowerOnScale; + BOOLEAN AspmOverride; + PCH_SERIES PchSeries; + UINT8 RootPortNumber; +#ifdef ULT_FLAG + UINT32 Data32; + UINT8 Response; +#endif // ULT_FLAG + + PchSeries = GetPchSeries(); + Status = EFI_SUCCESS; + RootDeviceBase = MmPciAddress (0, RootBus, RootDevice, RootFunction, 0); + RootComplexBar = PCH_RCRB_BASE; + PortCommonModeRestoreTime = 0; + PortTpowerOnValue = 0; + PortTpowerOnScale = 0; + *L1SubstatesSupported = FALSE; + AspmOverride = FALSE; + ClkreqPerPortSupported = FALSE; + GpioBase = 0; + + if (MmioRead16 (RootDeviceBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) { + return EFI_NOT_FOUND; + } + if (PchSeries == PchLp) { + GpioBase = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE) + ) & B_PCH_LPC_GPIO_BASE_BAR; + + RootPortNumber = GetPchPcieRpNumber(RootComplexBar, RootFunction); + Data32Or = (IoRead32 ((UINTN) (GpioBase + R_PCH_GP_X_CONFIG0(18 + RootPortNumber))) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + + if (Data32Or == 0) { + ClkreqPerPortSupported = TRUE; + } + } + + /// + /// Get the pointer to the Port PCI Express Capability Structure. + /// + RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (RootPcieCapOffset == 0) { + return EFI_UNSUPPORTED; + } + DeviceCapabilities2 = MmioRead32 (RootDeviceBase + RootPcieCapOffset + 0x24); + + /// + /// Enable LTR mechanism for this root port if it is capable + /// + if ((DeviceCapabilities2 & BIT11) && (PchPwrOptPcie->LtrEnable == TRUE)) { + MmioOr16 (RootDeviceBase + RootPcieCapOffset + 0x28, BIT10); + } + + /// + /// Enable OBFF using WAKE# signaling for this root port if it is capable + /// + if ((DeviceCapabilities2 & BIT19) && (PchPwrOptPcie->ObffEnable == TRUE)) { + MmioOr16 (RootDeviceBase + RootPcieCapOffset + 0x28, (BIT14 + BIT13)); + } + AspmVal = (MmioRead16 (RootDeviceBase + RootPcieCapOffset + 0x00C) >> 10) & 3; + if (RootPortAspm == PchPcieAspmAutoConfig) { + Operation = CalculateAspm; + } else { + Operation = ManualAspm; + AspmVal &= RootPortAspm; + } + /// + /// Get the downstream Bus number + /// + EndPointBus = (UINT8) (MmioRead32 (RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET) >> 8); + /// + /// If the Secondary Bus Number of the root port is not assigned + /// Note: + /// It will be better that PCI emulation has been done before PcieSetPm(). Or, you will need to assign + /// a larger number to TempRootPortBusNumMax to support the specific card which has many bridges behind. + /// If it is not, the platform policy settings of "TempRootPortBusNumMax" and "TempRootPortBusNumMin" + /// will be assigned to the Subordinate and Secondary Bus Number of the root ports. + /// The assigned bus number will be cleared in the end of PcieSetPm(). + /// + if (EndPointBus == 0) { + MmioAndThenOr32 ( + RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, + 0xFF0000FF, + ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16)) + ); + EndPointBus = TempBusNumberMin; + BusAssign = FALSE; + } else { + BusAssign = TRUE; + } + /// + /// Check whether the slot has a device connected + /// + SlotStatus = MmioRead16 (RootDeviceBase + RootPcieCapOffset + 0x1A); + LtrOvrVal = 0; + + RootL1SubstateExtCapOffset = 0; + if (PchSeries == PchLp) { + RootL1SubstateExtCapOffset = PcieFindExtendedCapId (RootBus, RootDevice, RootFunction, 0x1E); + if (RootL1SubstateExtCapOffset != 0) { + PortCommonModeRestoreTime = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04) >> 8) & 0xFF; + PortTpowerOnScale = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04) >> 16) & 0x3; + PortTpowerOnValue = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + 0x04) >> 19) & 0x1F; + } + } + /// + /// Obtain initial ASPM settings from respective port capability registers. + /// Scan LTR override table for device match and calculate the lowest override + /// value to be programmed into B0:D28:F0~F7 + 400h + /// + if (EndPointBus != 0 && (SlotStatus & BIT6) != 0) { + Status = PcieEndPointPm ( + RootDeviceBase, + RootPcieCapOffset, + EndPointBus, + NumOfDevAspmOverride, + DevAspmOverride, + &AspmVal, + Operation, + NumOfDevLtrOverride, + DevLtrOverride, + &LtrOvrVal, + RootL1SubstateExtCapOffset, + L1SubstatesSupported, + L1SubstatesConfig, + &PortCommonModeRestoreTime, + &PortTpowerOnValue, + &PortTpowerOnScale, + PchPwrOptPcie, + &AspmOverride, + &ClkreqPerPortSupported, + LtrSupported, + PolicyRevision + ); + if (PchPwrOptPcie->LtrEnable == PCH_DEVICE_ENABLE) { + if (PolicyRevision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { + if (PchPwrOptPcie->SnoopLatencyOverrideMode == 1) { + LtrOvrVal &= 0xFFFF0000; + LtrOvrVal |= (UINT32) BIT15 | + (UINT32) (PchPwrOptPcie->SnoopLatencyOverrideMultiplier << 10) | + (UINT32) (PchPwrOptPcie->SnoopLatencyOverrideValue); + } + + if (PchPwrOptPcie->NonSnoopLatencyOverrideMode == 1) { + LtrOvrVal &= 0x0000FFFF; + LtrOvrVal |= (UINT32) BIT31 | + (UINT32) (PchPwrOptPcie->NonSnoopLatencyOverrideMultiplier << 26) | + (UINT32) (PchPwrOptPcie->NonSnoopLatencyOverrideValue << 16); + } + } + if (LtrOvrVal != 0) { + /// + /// Program B0:D28:F0~F7 + 400h only if we find a device in the LTR override table + /// + MmioWrite32 (RootDeviceBase + R_PCH_PCIE_LTROVR, LtrOvrVal); + /// + /// Step 1.2 + /// Program B0:D28:F0~F7 + 404h [1:0] = 11b for ports which has a PCIe device + /// device attached to it. + /// + Data32Or = BIT1 | BIT0; + if (PolicyRevision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { + if (PchPwrOptPcie->SnoopLatencyOverrideMode == 0) { + Data32Or &= (UINT32) ~BIT0; + } + if (PchPwrOptPcie->NonSnoopLatencyOverrideMode == 0) { + Data32Or &= (UINT32) ~BIT1; + } + if (PchPwrOptPcie->LtrConfigLock == PCH_DEVICE_ENABLE) { + /// + /// Set the lock bit + /// + Data32Or |= BIT2; + } + } + MmioWrite32 (RootDeviceBase + R_PCH_PCIE_LTROVR2, Data32Or); + } + } + } +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + /// + /// If both Root and endpoint's L1 Sub-States Extended Capability Offset + 0x04[4:0] are 11111b, + /// + if (*L1SubstatesSupported) { + /// + /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and Set the highest value advertised + /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on both + /// Pcie root port and device. + /// + MmioAndThenOr32 ( + RootDeviceBase + RootL1SubstateExtCapOffset + 0x08, + (UINT32) ~(0xFF00), + (UINT32) PortCommonModeRestoreTime << 8 + ); + + /// + /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and Set the highest value + /// advertised between PCIe root port and device to L1 Sub-States Extended Capability Offset + 0x0C [7:0] on + /// both Pcie root port and device. + MmioAndThenOr32 ( + RootDeviceBase + RootL1SubstateExtCapOffset + 0x0C, + 0xFFFFFF04, + (UINT32) ((PortTpowerOnValue << 3) | PortTpowerOnScale) + ); + + /// + /// c. Set L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device + /// d. Set L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device + /// + MmioAndThenOr32 ( + RootDeviceBase + RootL1SubstateExtCapOffset + 0x08, + (UINT32) ~(0xE3FF0000), + (UINT32) (BIT30 | BIT23 | BIT21) + ); + + /// + /// e. If clkreq per port is suported, set D28:F0~F5:420h[0] to 1b prior to L1 enabling + /// + if (((AspmVal & V_PCH_PCIE_LCTL_APMC_L1) == V_PCH_PCIE_LCTL_APMC_L1) && ClkreqPerPortSupported) { + MmioOr32 (RootDeviceBase + R_PCH_PCIE_PCIEPMECTL, BIT0); + } + + /// + /// f. Set L1 Sub-States Extended Capability Offset + 0x08[4:0] to 01111b for both Pcie root port and device + /// + Data32Or = (BIT3 | BIT2 | BIT1 | BIT0); + if (L1SubstatesConfig == PchPcieL1SubstatesL1_1) { + Data32Or &= (UINT32)~(BIT0); + } + if (L1SubstatesConfig == PchPcieL1SubstatesL1_2) { + Data32Or &= (UINT32)~(BIT1); + } + MmioAndThenOr32 ( + RootDeviceBase + RootL1SubstateExtCapOffset + 0x08, + (UINT32) ~(BIT4 | BIT3 | BIT2 | BIT1 | BIT0), + Data32Or + ); + } + + + if ((AspmVal & V_PCH_PCIE_LCTL_APMC_L1) == V_PCH_PCIE_LCTL_APMC_L1) { + /// + /// Program D28:F0~F5:E2h[5:4] to 11b prior to enabling ASPM L1, + /// if all enabled ports support ASPM L1 + /// + if (FirstRPToSetPm && L1SupportedInAllEnabledPorts) { + Status = PchIobpExecution ( + RootComplexBar, + 0xE00000E0, + PciConfigRead, + 0xE0 + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + &Data32, + &Response + ); + ASSERT_EFI_ERROR (Status); + Data32 |= ((B_PCH_PCIE_RPPGEN_LMSDOCGE | B_PCH_PCIE_RPPGEN_SEOCGE) << 16); + Status = PchIobpExecution ( + RootComplexBar, + 0xE00000E0, + PciConfigWrite, + 0xE0 + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + &Data32, + &Response + ); + ASSERT_EFI_ERROR (Status); + } + + if (ClkreqPerPortSupported) { + /// + /// Program D28:F0~F5:420h[17] to 0b prior to enabling ASPM L1 + /// + if (*L1SubstatesSupported) { + MmioAnd32 (RootDeviceBase + R_PCH_PCIE_PCIEPMECTL, (UINT32)~B_PCH_PCIE_PCIEPMECTL_L1LE); + } + + /// + /// Program D28:F0~F5:420h[29] to 1b, when D28:F0:E1h[6] is set to 1b + /// + Data32Or = B_PCH_PCIE_PCIEPMECTL_DLSULDLSD; + MmioOr32 ( + RootDeviceBase + R_PCH_PCIE_PCIEPMECTL, + Data32Or + ); + + /// + /// If dedicated CLKREQ# per-port is supported on all enabled ports, set D28:F0:E1h[6] to 1b prior to enabling ASPM L1 + /// + if (FirstRPToSetPm && ClkreqSupportedInAllEnabledPorts) { + Status = PchIobpExecution ( + RootComplexBar, + 0xE00000E0, + PciConfigRead, + 0xE0 + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + &Data32, + &Response + ); + ASSERT_EFI_ERROR (Status); + Data32 |= (B_PCH_PCIE_RPDCGEN_POCGE << 8); + Status = PchIobpExecution ( + RootComplexBar, + 0xE00000E0, + PciConfigWrite, + 0xE0 + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + &Data32, + &Response + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } +#endif // ULT_FLAG + /// + /// Set Root Port Aspm and enable LTR capability of the device + /// + MmioAndThenOr16 (RootDeviceBase + RootPcieCapOffset + 0x010, 0xFFFC, AspmVal); + /// + /// Based on the Role based Error Reporting Capability bit, for pre-1.1 devices, + /// program root port 0xD4[4] to 1 and 0xD4[3:2] to 10. + /// + if (AspmOverride) { + MmioAndThenOr8 (RootDeviceBase + R_PCH_PCIE_MPC2, + (UINT8)~(B_PCH_PCIE_MPC2_ASPMCOEN | B_PCH_PCIE_MPC2_ASPMCO), + (B_PCH_PCIE_MPC2_ASPMCOEN | V_PCH_PCIE_MPC2_ASPMCO_L1) + ); + } else { + MmioAnd8 (RootDeviceBase + R_PCH_PCIE_MPC2, (UINT8)~(B_PCH_PCIE_MPC2_ASPMCOEN | B_PCH_PCIE_MPC2_ASPMCO)); + } + /// + /// PCH BIOS Spec Rev 0.5.5, Section 8.14.1 Power Optimizer Configuration + /// Step 1 + /// Enable support Latency Tolerance Reporting (LTR) + /// + + if (EndPointBus != 0 && (SlotStatus & BIT6) != 0) { + /// + /// Set Endpoint Aspm and LTR capabilities + /// + Status = PcieEndPointPm ( + RootDeviceBase, + RootPcieCapOffset, + EndPointBus, + NumOfDevAspmOverride, + DevAspmOverride, + &AspmVal, + SetAspm, + NumOfDevLtrOverride, + DevLtrOverride, + &LtrOvrVal, + RootL1SubstateExtCapOffset, + L1SubstatesSupported, + L1SubstatesConfig, + &PortCommonModeRestoreTime, + &PortTpowerOnValue, + &PortTpowerOnScale, + PchPwrOptPcie, + &AspmOverride, + &ClkreqPerPortSupported, + LtrSupported, + PolicyRevision + ); + } + + if (BusAssign == FALSE) { + /// + /// Clear Bus Numbers. + /// + MmioAnd32 (RootDeviceBase + 0x018, 0xFF0000FF); + } + + if (!EFI_ERROR (Status)) { + /// + /// If L0s and L1 can be enabled on a root port and the endpoints attached to the root port, + /// then set the root port register D28:Fx:Reg E8h[1] + /// + if (AspmVal == V_PCH_PCIE_LCTL_APMC_L0S_L1) { + if (PchSeries == PchLp) { + /// + /// Set the root port register D28:Fx:REG E8h[3:2] to 10b before setting D28:Fx:Reg E8h[0] or E8h[1] + /// + Data8Or = BIT3; + Data8And = (UINT8) ~(V_PCH_PCIE_PECR1_FIELD_3); + MmioAndThenOr8 ( + RootDeviceBase + R_PCH_PCIE_PECR1, + Data8And, + Data8Or + ); + } + MmioOr8 (RootDeviceBase + R_PCH_PCIE_PECR1, B_PCH_PCIE_PECR1_FIELD_2); + } + } + + return Status; +} + +/** + Initializes the root port and its down stream devices + + @param[in] RootPortBus Pci Bus Number of the root port + @param[in] RootPortDevice Pci Device Number of the root port + @param[in] RootPortFunc Pci Function Number of the root port + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + @param[in, out] MaxPayload The Max Payolad Size of the root port + @param[out] DeviceClassDword Get the downstream device code dword for unstream RootPort reference + + @retval EFI_SUCCESS Successfully completed + @retval EFI_NOT_FOUND Can not find device. +**/ +EFI_STATUS +PchPcieInitDownstreamDevices ( + IN UINT8 RootPortBus, + IN UINT8 RootPortDevice, + IN UINT8 RootPortFunc, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax, + IN OUT UINT16 *MaxPayload, + OUT UINT32 *DeviceClassDword + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINTN RPBase; + UINTN EndPointBase; + + RPBase = MmPciAddress (0, RootPortBus, RootPortDevice, RootPortFunc, 0); + /// + /// Temporarily Hardcode the Root Port Bridge Number to TempBusNumberMin + /// + MmioAndThenOr32 ( + RPBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, + 0xFF000000, + RootPortBus | ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16)) + ); + /// + /// This Endpoint check should immediately pass. Howerver, a 1.0s delay + /// has been added to match the timing requirements of the PCI Express Base + /// Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s + /// after a reset of a device, before it may determine that a device which + /// fails to return a Successful Completion status for a valid Configuration + /// Request is a broken device"). + /// + EndPointBase = MmPciAddress (0, TempBusNumberMin, 0, 0, 0); + /// + /// A config write is required in order for the device to re-capture the Bus number, + /// according to PCI Express Base Specification, 2.2.6.2 ("Note that the Bus Number + /// and Device Number may be changed at run time, and so it is necessary to re-capture + /// this information with each and every Configuration Write Request") + /// + MmioWrite8 (EndPointBase + 0x0, 0); + for (Index = 0; Index < 100000; Index++) { + if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF) { + break; + } + + PchPmTimerStall (10); + } + + if (Index >= 100000) { + /// + /// Clear Bus Numbers. + /// + MmioAnd32 (RPBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000); + return EFI_NOT_FOUND; + } + /// + /// Get the device class code dword for upstream RootPort reference + /// + if (DeviceClassDword != NULL) { + *DeviceClassDword = MmioRead32 (EndPointBase + R_PCH_PCIE_RID); + } + /// + /// Get the Max Payload Size on all the end point functions + /// + PcieMaxPayloadSize (TempBusNumberMin, PCI_MAX_DEVICE, MaxPayload, FALSE); + /// + /// Check if this device is a bridge + /// + if (MmioRead8 (EndPointBase + R_PCH_PCIE_BCC) == PCI_CLASS_BRIDGE) { + /// + /// Initialize downstream devices + /// + if (TempBusNumberMax > TempBusNumberMin) { + Status = PchPcieInitDownstreamDevices ( + TempBusNumberMin, + 0, + 0, + TempBusNumberMin + 1, + TempBusNumberMax, + MaxPayload, + NULL + ); + } + } + /// + /// Complete Common Port and Endpoint Configuration. + /// + /// + /// Map TC0-VC0 + /// + PcieMapTcxVc0 (RootPortBus, RootPortDevice, (UINT8) RootPortFunc, TempBusNumberMin, PCI_MAX_DEVICE, 0x0); + + /// + /// Set Common Clock for inserted cards + /// + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports + /// Before determining whether ASPM can be enabled or not, + /// the System BIOS must perform the following steps: + /// + /// For PCH H + /// 1. Update the Link Capabilities of the DMI to indicate L1 is + /// supported on the interface by setting the LCAP Register + /// RCBA + 21A4h [11:10] = 11b + /// (Done in PchPm.c) + /// + /// 2. Enable L0s on DMI for Desktop platforms by setting the APMC field, + /// RCBA + offset 21A8h[1:0] to 01b. + /// Enable L0s/L1 on DMI by setting RCBA + offset 21A8h[1:0] to 11b. + /// (Done in PchPm.c) + /// + /// 3. For each root port, read the Slot Clock Configuration bit, D28:F0~F7:Reg 52h[12], + /// of the root port and the endpoint device connected to the port (i.e., D0:F0 on the + /// secondary bus behind the root port). If both components have this bit set, then the + /// System BIOS should set the Common Clock Configuration (CCC) bit, D28:F0~F7:Reg 50h[6], + /// for both components at both sides of the link to indicate that components at both ends + /// of the link use a common clock source. + /// + /// 4. If the CCC bit was changed by the System BIOS in step 3, System BIOS should initiate + /// a link training by setting the Retrain Link (RL) bit, D28:F0~F7:Reg 50h[5], and then poll the Link + /// Training (LT) bit, D28:F0~F7:Reg 52h[11], until it is clear. + /// Note that System BIOS should save and restore CCC bit on S3. + /// + PcieSetCommonClock (RootPortBus, RootPortDevice, (UINT8) RootPortFunc, TempBusNumberMin, PCI_MAX_DEVICE); + + /// + /// Enable the PCIe CLKREQ# + /// + PcieSetClkreq (TempBusNumberMin, PCI_MAX_DEVICE, (UINT8) RootPortFunc); + + /// + /// Set the Max Payload Size on all the end point functions + /// + PcieMaxPayloadSize (TempBusNumberMin, PCI_MAX_DEVICE, MaxPayload, TRUE); + + /// + /// Disable the forwarding of EOI messages unless it discovers an IOAPIC behind this root port + /// + PcieSetEoiFwdDisable (RootPortBus, RootPortDevice, RootPortFunc, TempBusNumberMin, PCI_MAX_DEVICE); + /// + /// Clear Bus Numbers + /// + MmioAnd32 (RPBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000); + + return EFI_SUCCESS; +} + +/** + Initializes the root port and its down stream devices + + @param[in] RootPortBus Pci Bus Number of the root port + @param[in] RootPortDevice Pci Device Number of the root port + @param[in] RootPortFunc Pci Function Number of the root port + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + @param[out] DeviceClassDword Get the downstream device code dword for unstream RootPort reference + + @retval EFI_SUCCESS Successfully completed + @retval EFI_NOT_FOUND Can not find device. +**/ +EFI_STATUS +PchPcieInitRootPortDownstreamDevices ( + IN UINT8 RootPortBus, + IN UINT8 RootPortDevice, + IN UINT8 RootPortFunc, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax, + OUT UINT32 *DeviceClassDword + ) +{ + UINT16 SlotStatus; + UINTN RPBase; + UINT16 RootPortMaxPayload; + UINT8 PcieCapOffset; + EFI_STATUS Status; + + RPBase = MmPciAddress (0, RootPortBus, RootPortDevice, RootPortFunc, 0); + /// + /// Check for a Presence Detect Change. + /// + SlotStatus = MmioRead16 (RPBase + R_PCH_PCIE_SLSTS); + + /// + /// Check whether the slot has a device connected + /// + if ((SlotStatus & BIT6) == 0) { + return EFI_NOT_FOUND; + } + /// + /// Get the pointer to the Endpoint PCI Express Capability Structure. + /// + PcieCapOffset = PcieFindCapId ( + RootPortBus, + RootPortDevice, + RootPortFunc, + EFI_PCI_CAPABILITY_ID_PCIEXP + ); + + /// + /// Get the root port Max Payload Size support + /// + RootPortMaxPayload = MmioRead16 (RPBase + PcieCapOffset + 0x04) & (BIT2 | BIT1 | BIT0); + + /// + /// Initialize downstream devices + /// + Status = PchPcieInitDownstreamDevices ( + RootPortBus, + RootPortDevice, + RootPortFunc, + TempBusNumberMin, + TempBusNumberMax, + &RootPortMaxPayload, + DeviceClassDword + ); + + /// + /// Set the PCIE root Port Max Payload Size + /// + MmioAndThenOr16 (RPBase + PcieCapOffset + 0x08, (UINT16)~(BIT7 | BIT6 | BIT5), RootPortMaxPayload << 5); + + return Status; +} diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h new file mode 100644 index 0000000..7f32fe0 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h @@ -0,0 +1,42 @@ +/** @file + Header file for PCH Pci Express helps library implementation. + +@copyright + Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +**/ +#ifndef _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_ +#define _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#include "PchPlatformPolicy.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "PchPciExpressHelperslib.h" +#include "pci23.h" +#include "pci22.h" +#endif + +#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9) +#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12) + +// +// LTR related macros +// +#define LTR_LATENCY_VALUE(x) ((x) & LTR_VALUE_MASK) +#define LTR_SCALE_VALUE(x) (((x) & LTR_SCALE_MASK) >> 10) +#define LTR_LATENCY_NS(x) (LTR_LATENCY_VALUE(x) * (1 << (5 * LTR_SCALE_VALUE(x)))) + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/IobpAccess.c b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/IobpAccess.c new file mode 100644 index 0000000..d21a181 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/IobpAccess.c @@ -0,0 +1,295 @@ +/** @file + Program IOBP register. + +@copyright + Copyright (c) 2009 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchPlatformLibrary.h" + +/** + Configures PCH IOBP + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_DEVICE_ERROR Transaction fail +**/ +EFI_STATUS +EFIAPI +ProgramIobp ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ) +{ + UINT32 Data32; + UINT8 ResponseStatus; + EFI_STATUS Status; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.4 IOSF SBI Programming + /// Step 1 to Step 8 + /// + Status = ReadIobp (RootComplexBar, Address, &Data32); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Step 9 + /// Update the SBI data accordingly + /// + Data32 &= AndMask; + Data32 |= OrMask; + /// + /// Step 10 + /// Set RCBA + 2338h[15:8] = 00000111b + /// + MmioAndThenOr16 ( + (RootComplexBar + R_PCH_RCRB_IOBPS), + (UINT16) (~B_PCH_RCRB_IOBPS_IOBPIA), + (UINT16) V_PCH_RCRB_IOBPS_IOBPIA_W + ); + /// + /// Step 11 + /// Write RCBA + 2334h[31:0] with updated SBI data + /// + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_IOBPD), Data32); + + /// + /// Step 12 + /// Set RCBA + 233Ah[15:0] = F000h + /// + MmioWrite16 ( + (RootComplexBar + 0x233A), + 0xF000 + ); + + /// + /// Step 13 + /// Set RCBA + 2338h[0] = 1b + /// + MmioOr16 ( + (RootComplexBar + R_PCH_RCRB_IOBPS), + (UINT16) BIT0 + ); + + /// + /// Step 14 + /// Poll RCBA + Offset 2338h[0] = 0b + /// + while (MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS_BUSY); + + /// + /// Step 15 + /// Check if RCBA + 2338h[2:1] = 00b for successful transaction + /// + ResponseStatus = MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS; + if (ResponseStatus == V_PCH_RCRB_IOBPS_SUCCESS) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } +} + +/** + Read data from PCH IOBP register block + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[out] Data Data contain in the IOBP register block + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_DEVICE_ERROR Transaction fail +**/ +EFI_STATUS +EFIAPI +ReadIobp ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + OUT UINT32 *Data + ) +{ + UINT8 ResponseStatus; + + /// + /// Step 1 Poll RCBA + 2338[0] = 0b + /// + while (MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS_BUSY); + + /// + /// Step 2 + /// Write RCBA + Offset 2330h[31:0] with IOBP register address + /// + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_IOBPIRI), Address); + /// + /// Step 3 + /// Set RCBA + 2338h[15:8] = 00000110b + /// + MmioAndThenOr16 ( + (RootComplexBar + R_PCH_RCRB_IOBPS), + (UINT16) (~B_PCH_RCRB_IOBPS_IOBPIA), + (UINT16) V_PCH_RCRB_IOBPS_IOBPIA_R + ); + /// + /// Step 4 + /// Set RCBA + 233Ah[15:0] = F000h + /// + MmioWrite16 ( + (RootComplexBar + 0x233A), + 0xF000 + ); + /// + /// Step 5 + /// Set RCBA + 2338h[0] = 1b + /// + MmioOr16 ( + (RootComplexBar + R_PCH_RCRB_IOBPS), + (UINT16) BIT0 + ); + + /// + /// Step 6 + /// Poll RCBA + Offset 2338h[0] = 0b, Polling for Busy bit + /// + while (MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS_BUSY); + + /// + /// Step 7 + /// Check if RCBA + 2338h[2:1] = 00b for successful transaction + /// + ResponseStatus = MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS; + if (ResponseStatus == V_PCH_RCRB_IOBPS_SUCCESS) { + /// + /// Step 8 + /// Read RCBA + 2334h[31:0] for IOBP data + /// + *Data = MmioRead32 (RootComplexBar + R_PCH_RCRB_IOBPD); + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } +} + +/** + Configures PCH IOBP + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] Opcode Iobp Opcode + @param[in] RouteId Route Id + @param[in, out] Data32 Read/Write data + @param[out] Response Response + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_DEVICE_ERROR Transaction fail +**/ +EFI_STATUS +EFIAPI +PchIobpExecution ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN PCH_IOBP_OPCODE Opcode, + IN UINT8 RouteId, + IN OUT UINT32 *Data32, + OUT UINT8 *Response + ) +{ + /// + /// Step 1 Poll RCBA + 2338[0] = 0b + /// + while (MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS_BUSY); + /// + /// Step 2 + /// Write RCBA + Offset 2330h[31:0] with IOBP register address + /// + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_IOBPIRI), Address); + /// + /// Step 3 + /// Set RCBA + 2338h[15:8] to the opcode passed in + /// + MmioAndThenOr16 ( + (RootComplexBar + R_PCH_RCRB_IOBPS), + (UINT16) (~B_PCH_RCRB_IOBPS_IOBPIA), + (UINT16) (Opcode << 8) + ); + /// + /// Step 4 + /// Set RCBA + 233Ah[15:8] = F0h + /// Set RCBA + 233Ah[7:0] = Route Id passed in + /// + MmioWrite16 ( + (RootComplexBar + 0x233A), + (0xF000 | RouteId) + ); + switch (Opcode) { + case MemoryMapWrite: + case IoMapWrite: + case PciConfigWrite: + case PrivateControlWrite: + /// + /// Step 5 + /// Write RCBA + 2334h[31:0] with updated SBI data + /// + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_IOBPD), *Data32); + break; + default: + break; + } + /// + /// Step 6 + /// Set RCBA + 2338h[0] = 1b + /// + MmioOr16 ( + (RootComplexBar + R_PCH_RCRB_IOBPS), + (UINT16) BIT0 + ); + + /// + /// Step 7 + /// Poll RCBA + Offset 2338h[0] = 0b, Polling for Busy bit + /// + while (MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS_BUSY); + + /// + /// Step 8 + /// Check if RCBA + 2338h[2:1] = 00b for successful transaction + /// + *Response = MmioRead8 (RootComplexBar + R_PCH_RCRB_IOBPS) & B_PCH_RCRB_IOBPS; + if (*Response == V_PCH_RCRB_IOBPS_SUCCESS) { + switch (Opcode) { + case MemoryMapRead: + case IoMapRead: + case PciConfigRead: + case PrivateControlRead: + /// + /// Step 9 + /// Read RCBA + 2334h[31:0] for IOBP data + /// + *Data32 = MmioRead32 (RootComplexBar + R_PCH_RCRB_IOBPD); + break; + default: + break; + } + + return EFI_SUCCESS; + } + return EFI_DEVICE_ERROR; +} diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.cif new file mode 100644 index 0000000..d146e3b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.cif @@ -0,0 +1,13 @@ + + name = "PchPlatformLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\PchPlatformLib" + RefName = "PchPlatformLib" +[files] +"PchPlatformLib.mak" +"PchPlatformLib.sdl" +"PchPlatformLibrary.h" +"PchPlatformLibrary.c" +"PchPlatformLib.inf" +"IobpAccess.c" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.inf b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.inf new file mode 100644 index 0000000..2aa9a25 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.inf @@ -0,0 +1,67 @@ +## @file +# Component description file for PEI/DXE PCH Platform Lib +# +#@copyright +# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + + +[defines] +BASE_NAME = PchPlatformLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + PchPlatformLibrary.h + PchPlatformLibrary.c + IobpAccess.c + +[sources.ia32] + +[sources.x64] + +[sources.ipf] + +[includes.common] + $(EDK_SOURCE)/Foundation/Efi + . + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include +# +# Typically the sample code referenced will be available in the code base already +# So keep this include at the end to defer to the source base definition +# and only use the sample code definition if source base does not include these files. +# + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode + +[libraries.common] + EdkIIGlueBasePciLibPciExpress + EdkIIGlueBaseLib + +[nmake.common] diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.mak b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.mak new file mode 100644 index 0000000..d6ca967 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.mak @@ -0,0 +1,112 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPlatformLib/PchPlatformLib.mak 3 10/16/12 2:52a Scottyang $ +# +# $Revision: 3 $ +# +# $Date: 10/16/12 2:52a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPlatformLib/PchPlatformLib.mak $ +# +# 3 10/16/12 2:52a Scottyang +# [TAG] EIP103924 +# [Category] Improvement +# [Description] Update RC 0.7.1 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +# 2 7/02/12 9:17a Victortu +# +# 1 2/08/12 8:48a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +# MAK file for the ModulePart:PchPlatformLib +EDK : PchPlatformLib + +PchPlatformLib : PchPlatformSmmLib PchPlatformDxeLib PchPlatformPeiLib + +$(PchPlatformSmmLib_LIB) : PchPlatformSmmLib +$(PchPlatformDxeLib_LIB) : PchPlatformDxeLib +$(PchPlatformPeiLib_LIB) : PchPlatformPeiLib + +PchPlatformSmmLib : $(BUILD_DIR)\PchPlatformLib.mak PchPlatformLibSmmBin + +PchPlatformDxeLib : $(BUILD_DIR)\PchPlatformLib.mak PchPlatformLibDxeBin + +PchPlatformPeiLib : $(BUILD_DIR)\PchPlatformLib.mak PchPlatformLibPeiBin + +$(BUILD_DIR)\PchPlatformLib.mak : $(PchPlatformLib_DIR)\$(@B).cif $(PchPlatformLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchPlatformLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchPlatformLib_INCLUDES =\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + $(EDK_INCLUDES)\ + +PchPlatformLib_LIBS=\ + $(EdkIIGlueBaseLib_LIB)\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + +PchPlatformLibSmmBin : $(PchPlatformLib_LIBS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchPlatformLib.mak all\ + "MY_INCLUDES=$(PchPlatformLib_INCLUDES)" \ + TYPE=LIBRARY \ + LIBRARIES=\ + LIBRARY_NAME=$(PchPlatformSmmLib_LIB) + +PchPlatformLibDxeBin : $(PchPlatformLib_LIBS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchPlatformLib.mak all\ + "MY_INCLUDES=$(PchPlatformLib_INCLUDES)" \ + "CFLAGS=$(CFLAGS) $(PchPlatformLib_DEFINES)"\ + TYPE=LIBRARY \ + LIBRARIES=\ + LIBRARY_NAME=$(PchPlatformDxeLib_LIB) + +PchPlatformLibPeiBin : $(PchPlatformLib_LIBS) +!IF "$(x64_BUILD)"=="1" + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32\ +!ELSE + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ +!ENDIF + /f $(BUILD_DIR)\PchPlatformLib.mak all\ + "MY_INCLUDES=$(PchPlatformLib_INCLUDES)"\ + "CFLAGS=$(CFLAGS) $(PchPlatformLib_DEFINES)"\ + TYPE=PEI_LIBRARY \ + LIBRARIES=\ + LIBRARY_NAME=$(PchPlatformPeiLib_LIB) +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.sdl b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.sdl new file mode 100644 index 0000000..4704a8c --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLib.sdl @@ -0,0 +1,93 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPlatformLib/PchPlatformLib.sdl 1 2/08/12 8:48a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:48a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchPlatformLib/PchPlatformLib.sdl $ +# +# 1 2/08/12 8:48a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchPlatformLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PchPlatformLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchPlatformLib_DIR" +End + +MODULE + Help = "Includes PchPlatformLib.mak to Project" + File = "PchPlatformLib.mak" +End + +ELINK + Name = "PchPlatformSmmLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchPlatformSmmLib.lib" + Parent = "PchPlatformSmmLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PchPlatformDxeLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchPlatformDxeLib.lib" + Parent = "PchPlatformDxeLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PchPlatformPeiLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchPlatformPeiLib.lib" + Parent = "PchPlatformPeiLib_LIB" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.c b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.c new file mode 100644 index 0000000..2d9c6ac --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.c @@ -0,0 +1,831 @@ +/** @file + PCH Platform Lib implementation. +@copyright + Copyright (c) 2004 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchPlatformLibrary.h" + +/** + Delay for at least the request number of microseconds. + This function would be called by runtime driver, please do not use any MMIO marco here. + + @param[in] Microseconds Number of microseconds to delay. + + @retval NONE +**/ +VOID +EFIAPI +PchPmTimerStall ( + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINTN CurrentTick; + UINTN OriginalTick; + UINTN RemainingTick; + UINT16 AcpiBaseAddr; + + if (Microseconds == 0) { + return; + } + /// + /// Please use PciRead here, it will link to MmioRead + /// if the caller is a Runtime driver, please use PchDxeRuntimePciLibPciExpress library, refer + /// PciExpressRead() on Library\DxeRuntimePciLibPciExpress\DxeRuntimePciLibPciExpress.c for the details. + /// For the rest please use EdkIIGlueBasePciLibPciExpress library + /// + AcpiBaseAddr = PciRead16 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE) + ) & B_PCH_LPC_ACPI_BASE_BAR; + + OriginalTick = IoRead32 ((UINTN) (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL; + CurrentTick = OriginalTick; + + /// + /// The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks + /// + Ticks = Microseconds * 358 / 100 + OriginalTick + 1; + + /// + /// The loops needed by timer overflow + /// + Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL; + + /// + /// Remaining clocks within one loop + /// + RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL; + + /// + /// not intend to use TMROF_STS bit of register PM1_STS, because this adds extra + /// one I/O operation, and maybe generate SMI + /// + while ((Counts != 0) || (RemainingTick > CurrentTick)) { + CurrentTick = IoRead32 ((UINTN) (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL; + /// + /// Check if timer overflow + /// + if ((CurrentTick < OriginalTick)) { + if (Counts != 0) { + Counts--; + } else { + /// + /// If timer overflow and Counts equ to 0, that means we already stalled more than + /// RemainingTick, break the loop here + /// + break; + } + } + + OriginalTick = CurrentTick; + } +} + +/** + Check whether SPI is in descriptor mode + + @param[in] PchRootComplexBar The PCH Root Complex Bar + + @retval TRUE SPI is in descriptor mode + @retval FALSE SPI is not in descriptor mode +**/ +BOOLEAN +EFIAPI +PchIsSpiDescriptorMode ( + IN UINTN PchRootComplexBar + ) +{ + if ((MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FDV) == B_PCH_SPI_HSFS_FDV) { + MmioAndThenOr32 ( + PchRootComplexBar + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)), + (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLVALSIG) + ); + if ((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FDOD)) == V_PCH_SPI_FDBAR_FLVALSIG) { + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +/** + Return Pch stepping type + + @param[in] None + + @retval PCH_STEPPING Pch stepping type +**/ +PCH_STEPPING +EFIAPI +PchStepping ( + VOID + ) +{ + UINT8 RevId; + UINT16 LpcDeviceId; + + RevId = MmioRead8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RID) + ); + + LpcDeviceId = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_DEVICE_ID) + ); + + if (IS_PCH_LPTH_LPC_DEVICE_ID (LpcDeviceId)) { + switch (RevId) { + case V_PCH_LPT_LPC_RID_2: + return LptHB0; + break; + + case V_PCH_LPT_LPC_RID_3: + return LptHC0; + break; + + case V_PCH_LPT_LPC_RID_4: + return LptHC1; + break; + + case V_PCH_LPT_LPC_RID_5: + return LptHC2; + break; + + default: + return PchSteppingMax; + break; + } + } + + if (IS_PCH_LPTLP_LPC_DEVICE_ID (LpcDeviceId)) { + switch (RevId) { + case V_PCH_LPT_LPC_RID_2: + return LptLpB0; + break; + + case V_PCH_LPT_LPC_RID_3: + return LptLpB1; + break; + + case V_PCH_LPT_LPC_RID_4: + return LptLpB2; + break; + + default: + return PchSteppingMax; + break; + } + } + + return PchSteppingMax; +} + +/** + Determine if PCH is supported + + @param[in] None + + @retval TRUE PCH is supported + @retval FALSE PCH is not supported +**/ +BOOLEAN +IsPchSupported ( + VOID + ) +{ + UINT16 LpcDeviceId; + + LpcDeviceId = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_DEVICE_ID) + ); + + /// + /// Verify that this is a supported chipset + /// + if (MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_VENDOR_ID) + ) != V_PCH_LPC_VENDOR_ID || + !IS_PCH_LPT_LPC_DEVICE_ID (LpcDeviceId)) { + DEBUG ((EFI_D_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x!\n", LpcDeviceId)); + return FALSE; + } + + return TRUE; +} + +/** + This function can be called to enable/disable Alternate Access Mode + + @param[in] PchRootComplexBar The PCH Root Complex Bar + @param[in] AmeCtrl If TRUE, enable Alternate Access Mode. + If FALSE, disable Alternate Access Mode. + + @retval NONE +**/ +VOID +EFIAPI +PchAlternateAccessMode ( + IN UINTN PchRootComplexBar, + IN BOOLEAN AmeCtrl + ) +{ + UINT32 Data32Or; + UINT32 Data32And; + + Data32Or = 0; + Data32And = 0xFFFFFFFF; + + if (AmeCtrl == TRUE) { + /// + /// Enable Alternate Access Mode + /// Note: The RTC Index field (including the NMI mask at bit7) is write-only + /// for normal operation and can only be read in Alt Access Mode. + /// + Data32Or = (UINT32) (B_PCH_RCRB_GCS_AME); + } + + if (AmeCtrl == FALSE) { + /// + /// Disable Alternate Access Mode + /// + Data32And = (UINT32) ~(B_PCH_RCRB_GCS_AME); + } + + /// + /// Program Alternate Access Mode Enable bit + /// + MmioAndThenOr32 ( + PchRootComplexBar + R_PCH_RCRB_GCS, + Data32And, + Data32Or + ); + + /// + /// Reads back for posted write to take effect + /// + MmioRead32(PchRootComplexBar + R_PCH_RCRB_GCS); +} + +/** + Check whether Gbe Region is valid in SPI Flash + + @param[in] PchRootComplexBar The PCH Root Complex Bar + + @retval TRUE Gbe Region is valid + @retval FALSE Gbe Region is invalid +**/ +BOOLEAN +EFIAPI +PchIsGbeRegionValid ( + IN UINTN PchRootComplexBar + ) +{ + /// + /// If the GbE region is not used, + /// Region Limit of Flash Region 3 (GbE) Register (SPIBAR + 60h[30:16]) must be programmed to 0000h + /// Region Base of Flash Region 3 (GbE) Register (SPIBAR + 60h[14:0] ) must be programmed to 7FFFh + /// + if (PchIsSpiDescriptorMode (PchRootComplexBar) == TRUE) { + if (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG3_GBE) == 0x00007FFF) { + return FALSE; + } else { + return TRUE; + } + } else { + return FALSE; + } +} + +/** + Check if integrated Gbe controller present + + @param[in] None + + @retval TRUE Integrated Gbe present + @retval FALSE Integrated Gbe not present +**/ +BOOLEAN +EFIAPI +PchIsIntegratedGbePresent ( + IN VOID + ) +{ + UINT32 Softstrap4; + UINT32 Softstrap15; + BOOLEAN IntegratedGbe; + + /// + /// Check if Gbe region is present by reading PCH straps 15 (bit 6) and 4 (bits 1:0) + /// + MmioAnd32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)) + ); + + MmioOr32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP4) + ); + + Softstrap4 = MmioRead32 (PCH_RCRB_BASE + R_PCH_SPI_FDOD); + + MmioAnd32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)) + ); + + MmioOr32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP15) + ); + + Softstrap15 = MmioRead32 (PCH_RCRB_BASE + R_PCH_SPI_FDOD); + + /// + /// Both values have to be non-zero if integrated phy present + /// + IntegratedGbe = !!(Softstrap4 & B_PCH_SPI_STRP4_PHYCON) && !!(Softstrap15 & B_PCH_SPI_STRP15_IWL_EN); + + return IntegratedGbe; +} + +/** + Return Pch Series + + @param[in] None + + @retval PCH_SERIES Pch Series +**/ +PCH_SERIES +EFIAPI +GetPchSeries ( + VOID + ) +{ + UINT16 LpcDeviceId; + UINT32 PchSeries; + + /// + /// Please use PciRead here, it will link to MmioRead + /// if the caller is a Runtime driver, please use PchDxeRuntimePciLibPciExpress library, refer + /// PciExpressRead() on Library\DxeRuntimePciLibPciExpress\DxeRuntimePciLibPciExpress.c for the details. + /// For the rest please use EdkIIGlueBasePciLibPciExpress library + /// + LpcDeviceId = PciRead16 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_DEVICE_ID) + ); + + if (IS_PCH_LPTH_LPC_DEVICE_ID (LpcDeviceId)) { + PchSeries = PchH; + } else if (IS_PCH_LPTLP_LPC_DEVICE_ID (LpcDeviceId)) { + PchSeries = PchLp; + } else { + PchSeries = PchUnknownSeries; + DEBUG ((EFI_D_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId)); + ASSERT (FALSE); + } + + return PchSeries; +} + +/** + Get Pch Maximum Pcie Root Port Number + + @param[in] None + + @retval Pch Maximum Pcie Root Port Number +**/ +UINT8 +EFIAPI +GetPchMaxPciePortNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_PCIE_MAX_ROOT_PORTS; + + case PchH: + return LPTH_PCIE_MAX_ROOT_PORTS; + + default: + return 0; + } +} + +/** + Get Pch Maximum Sata Port Number + + @param[in] None + + @retval Pch Maximum Sata Port Number +**/ +UINT8 +EFIAPI +GetPchMaxSataPortNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_AHCI_MAX_PORTS; + + case PchH: + return LPTH_AHCI_MAX_PORTS; + + default: + return 0; + } +} + +/** + Get Pch Maximum Sata Controller Number + + @param[in] None + + @retval Pch Maximum Sata Controller Number +**/ +UINT8 +EFIAPI +GetPchMaxSataControllerNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_SATA_MAX_CONTROLLERS; + + case PchH: + return LPTH_SATA_MAX_CONTROLLERS; + + default: + return 0; + } +} + +/** + Get Pch Maximum Usb Port Number of EHCI Controller + + @param[in] None + + @retval Pch Maximum Usb Port Number of EHCI Controller +**/ +UINT8 +EFIAPI +GetPchEhciMaxUsbPortNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_EHCI_MAX_PORTS; + + case PchH: + return LPTH_EHCI_MAX_PORTS; + + default: + return 0; + } +} + +/** + Get Pch Maximum EHCI Controller Number + + @param[in] None + + @retval Pch Maximum EHCI Controller Number +**/ +UINT8 +EFIAPI +GetPchEhciMaxControllerNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_EHCI_MAX_CONTROLLERS; + + case PchH: + return LPTH_EHCI_MAX_CONTROLLERS; + + default: + return 0; + } +} + +/** + Get Pch Usb Maximum Physical Port Number + + @param[in] None + + @retval Pch Usb Maximum Physical Port Number +**/ +UINT8 +EFIAPI +GetPchUsbMaxPhysicalPortNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_USB_MAX_PHYSICAL_PORTS; + + case PchH: + return LPTH_USB_MAX_PHYSICAL_PORTS; + + default: + return 0; + } +} + +/** + Get Pch Maximum Usb2 Port Number of XHCI Controller + + @param[in] None + + @retval Pch Maximum Usb2 Port Number of XHCI Controller +**/ +UINT8 +EFIAPI +GetPchXhciMaxUsb2PortNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_XHCI_MAX_USB2_PORTS; + + case PchH: + return LPTH_XHCI_MAX_USB2_PORTS; + + default: + return 0; + } +} + +/** + Get Pch Maximum Usb3 Port Number of XHCI Controller + + @param[in] None + + @retval Pch Maximum Usb3 Port Number of XHCI Controller +**/ +UINT8 +EFIAPI +GetPchXhciMaxUsb3PortNum ( + VOID + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_XHCI_MAX_USB3_PORTS; + + case PchH: + return LPTH_XHCI_MAX_USB3_PORTS; + + default: + return 0; + } +} + +/** + Query PCH to determine the Pm Status + + @param[in] PmStatus - The Pch Pm Status to be probed + + @retval Return TRUE if Status querried is Valid or FALSE if otherwise +**/ +BOOLEAN +GetPchPmStatus ( + PCH_PM_STATUS PmStatus + ) +{ + UINT16 PmCon2; + UINT16 PmCon3; + + PmCon2 = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GEN_PMCON_2 + ) + ); + PmCon3 = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GEN_PMCON_3 + ) + ); + + switch(PmStatus){ + case WarmBoot: + if (PmCon2 & B_PCH_LPC_GEN_PMCON_MEM_SR) { + return TRUE; + } + break; + + case PwrFlr: + if (PmCon3 & B_PCH_LPC_GEN_PMCON_PWR_FLR) { + return TRUE; + } + break; + + case PwrFlrSys: + if (PmCon2 & B_PCH_LPC_GEN_PMCON_SYSPWR_FLR) { + return TRUE; + } + break; + + case PwrFlrPch: + if (PmCon2 & B_PCH_LPC_GEN_PMCON_PWROK_FLR) { + return TRUE; + } + break; + + case ColdBoot: + /// + /// Check following conditions for cold boot. + /// (1)GEN_PMCON_2 (0:31:0 offset 0A2) bit[5] = 0 + /// (2)GEN_PMCON_2 (0:31:0 offset 0A2) bit[1] = 1 + /// (3)GEN_PMCON_3 (0:31:0 offset 0A4) bit[1] = 1 + /// + if ((PmCon3 & B_PCH_LPC_GEN_PMCON_PWR_FLR) && + (PmCon2 & B_PCH_LPC_GEN_PMCON_SYSPWR_FLR) && + (!(PmCon2 & B_PCH_LPC_GEN_PMCON_MEM_SR))) { + return TRUE; + } + break; + + default: + break; + } + + return FALSE; +} + +/** + Get Pch Pcie Root Port Function Number by Root Port Number + + @param[in] UINT8 Root Port Number (start from 0) + + @retval Pch Pcie Root Port Function Number +**/ +UINT8 +EFIAPI +GetPchPcieRpfn ( + IN UINTN PchRootComplexBar, + IN UINT8 RpNumber + ) +{ + return ((MmioRead32(PchRootComplexBar + R_PCH_RCRB_RPFN) >> (RpNumber * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN); +} + +/** + Get Pch Pcie Root Port Number by Root Port Function Number + + @param[in] UINT8 Root Port Function Number + + @retval Pch Pcie Root Port Number + @retval 0xFF No Root Port Number found +**/ +UINT8 +EFIAPI +GetPchPcieRpNumber ( + IN UINTN PchRootComplexBar, + IN UINT8 Rpfn + ) +{ + UINT8 PortIndex; + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum(); PortIndex++) { + if (((MmioRead32(PchRootComplexBar + R_PCH_RCRB_RPFN) >> (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN) == Rpfn) { + return PortIndex; + } + } + + //Assert if function number not found for a root port + ASSERT (FALSE); + return 0xff; +} + + +/** + Returns GbE over PCIe port number. + + @return Root port number (0-based) + @retval 0xff +**/ +UINTN +PchGetGbePortNumber ( + VOID + ) +{ + UINT32 Softstrap9; + UINT32 GbePortSel; + + /// + /// Check if Intel PHY Over PCI Express Enable by reading PCH straps 9 (bit 11) + /// + MmioAnd32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)) + ); + + MmioOr32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP9) + ); + + Softstrap9 = MmioRead32 (PCH_RCRB_BASE + R_PCH_SPI_FDOD); + + /// + /// If Intel PHY Over PCI Express Enable bit is set, return GbE port number + /// + if (Softstrap9 & B_PCH_SPI_STRP9_GBE_PCIE_EN) { + GbePortSel = (Softstrap9 & B_PCH_SPI_STRP9_GBE_PCIE_PSC) >> N_PCH_SPI_STRP9_GBE_PCIE_PSC; + DEBUG ((EFI_D_INFO, "GbePortSel=%d\n", GbePortSel)); + if (GetPchSeries () == PchLp) { + switch (GbePortSel) { + case 0: return 2; // Root Port 3 + case 1: return 3; // Root Port 4 + case 2: // Root Port 5, lane 0 + case 3: // Root Port 5, lane 1 + case 4: // Root Port 5, lane 2 + case 5: // Root Port 5, lane 3 + return 4; + default: + ASSERT (FALSE); + } + } else { + return GbePortSel; + } + } + + return 0xff; +} diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.h b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.h new file mode 100644 index 0000000..0eec474 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchPlatformLib/PchPlatformLibrary.h @@ -0,0 +1,29 @@ +/** @file + Header file for PCH Platform Lib implementation. + +@copyright + Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +**/ +#ifndef _PCH_PLATFORM_LIBRARY_IMPLEMENTATION_H_ +#define _PCH_PLATFORM_LIBRARY_IMPLEMENTATION_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#include "Library/EdkIIGlueMemoryAllocationLib.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#endif + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusComLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusComLib.cif new file mode 100644 index 0000000..c6371c9 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusComLib.cif @@ -0,0 +1,8 @@ + + name = "PchSmbusComLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\PchSmbusLib\Common\" + RefName = "PchSmbusComLib" +[files] +"PchSmbusLib.c" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusLib.c b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusLib.c new file mode 100644 index 0000000..dcb46e2 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Common/PchSmbusLib.c @@ -0,0 +1,54 @@ +/** @file + This file contains routines that support PCH SMBUS FUNCTION + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchSmbusLib.h" + +/** + This function provides a standard way to execute Smbus sequential + I2C Read. This function allows the PCH to perform block reads to + certain I2C devices, such as serial E2PROMs. Typically these data + bytes correspond to an offset (address) within the serial memory + chips. + + @param[in] SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Buffer Pointer to the buffer to store the bytes read + from the SMBUS + @param[out] Status eturn status for the executed command. + + @retval UINTN The number of bytes read +**/ +UINTN +EFIAPI +SmBusSeqI2CRead ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS * Status OPTIONAL + ) +{ + UINTN Length; + + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Length = SMBUS_LIB_LENGTH (SmBusAddress); + return InternalSmBusExec (EfiSmbusReadByte, SmBusAddress, Length, Buffer, Status); +} diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusDxeLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusDxeLib.cif new file mode 100644 index 0000000..b1b49b0 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusDxeLib.cif @@ -0,0 +1,9 @@ + + name = "PchSmbusDxeLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\PchSmbusLib\Dxe\" + RefName = "PchSmbusDxeLib" +[files] +"PchSmbusLib.h" +"PchSmbusLibDxe.inf" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLib.h b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLib.h new file mode 100644 index 0000000..64c639d --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLib.h @@ -0,0 +1,25 @@ +/** @file + Header file for PCH Smbus DXE Lib implementation. + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +**/ +#ifndef _PCH_SMBUS_DXE_LIBRARY_IMPLEMENTATION_H_ +#define _PCH_SMBUS_DXE_LIBRARY_IMPLEMENTATION_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "DxeSmbusLibInternal.h" +#endif +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLibDxe.inf b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLibDxe.inf new file mode 100644 index 0000000..57c7e50 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Dxe/PchSmbusLibDxe.inf @@ -0,0 +1,63 @@ +## @file +# Component description file for DXE PCH Smbus Lib +# +#@copyright +# Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchSmbusLibDxe +COMPONENT_TYPE = LIBRARY + +[sources.common] + ../Common/PchSmbusLib.c + +[sources.ia32] + +[sources.x64] + +[sources.ipf] + +[includes.common] + $(EDK_SOURCE)/Foundation/Efi + . + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Library/DxeSmbusLib +# +# Typically the sample code referenced will be available in the code base already +# So keep this include at the end to defer to the source base definition +# and only use the sample code definition if source base does not include these files. +# + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode + +[libraries.common] + + +[nmake.common] diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.cif new file mode 100644 index 0000000..3263fa9 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.cif @@ -0,0 +1,14 @@ + + name = "PchSmbusLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\PchSmbusLib\" + RefName = "PchSmbusLib" +[files] +"PchSmbusLib.sdl" +"PchSmbusLib.mak" +"Common\PchSmbusComLib.cif" +"Common\PchSmbusLib.c" +[parts] +"PchSmbusDxeLib" +"PchSmbusPeiLib" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.mak b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.mak new file mode 100644 index 0000000..35a4d8e --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.mak @@ -0,0 +1,74 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchSmbusLib/PchSmbusLib.mak 1 2/08/12 8:49a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:49a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/PchSmbusLib/PchSmbusLib.mak $ +# +# 1 2/08/12 8:49a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +all : PchSmbusLib + +$(PchSmbusLib_LIB) : PchSmbusLib + +PchSmbusLib : $(BUILD_DIR)\PchSmbusLib.mak PchSmbusLibBin + +$(BUILD_DIR)\PchSmbusLib.mak : $(PchSmbusLib_DIR)\$(@B).cif $(PchSmbusLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchSmbusLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchSmbusPeiLib_INCLUDES=\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + /I$(EdkIIGluePeiSmbusLib_DIR)\ + /I$(PchSmbusLib_DIR)\Pei\ + +PchSmbusDxeLib_INCLUDES=\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + /I$(EdkIIGlueDxeSmbusLib_DIR)\ + /I$(PchSmbusLib_DIR)\Dxe\ + +PchSmbusLibBin : + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchSmbusLib.mak all\ + "MY_INCLUDES=$(PchSmbusDxeLib_INCLUDES)" \ + TYPE=LIBRARY +!IF "$(x64_BUILD)"=="1" + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32\ + /f $(BUILD_DIR)\PchSmbusLib.mak all\ + "MY_INCLUDES=$(PchSmbusPeiLib_INCLUDES)" \ + TYPE=PEI_LIBRARY +!ENDIF +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.sdl b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.sdl new file mode 100644 index 0000000..4f41e9a --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/PchSmbusLib.sdl @@ -0,0 +1,59 @@ +TOKEN + Name = "PchSmbusLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PchSmbusLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchSmbusLib_DIR" +End + +MODULE + Help = "Includes PchSmbusLib.mak to Project" + File = "PchSmbusLib.mak" +End + +ELINK + Name = "PchSmbusDxeLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "PchSmbusPeiLib_LIB" + InvokeOrder = ReplaceParent +End + +TOKEN + Name = "PchSmbusLib_LIB" + Value = "$$(LIB_BUILD_DIR)\PchSmbusLib.lib" + TokenType = Expression + TargetMAK = Yes +End + +ELINK + Name = "$(PchSmbusLib_LIB)" + Parent = "PchSmbusDxeLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(EdkIIGlueDxeSmbusLib_LIB)" + Parent = "PchSmbusDxeLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(PchSmbusLib_LIB)" + Parent = "PchSmbusPeiLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(EdkIIGluePeiSmbusLib_LIB)" + Parent = "PchSmbusPeiLib_LIB" + InvokeOrder = AfterParent +End diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLib.h b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLib.h new file mode 100644 index 0000000..b169af6 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLib.h @@ -0,0 +1,25 @@ +/** @file + Header file for PCH Smbus PEI Lib implementation. + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +**/ +#ifndef _PCH_SMBUS_PEI_LIBRARY_IMPLEMENTATION_H_ +#define _PCH_SMBUS_PEI_LIBRARY_IMPLEMENTATION_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "PeiSmbusLibInternal.h" +#endif +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLibPei.inf b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLibPei.inf new file mode 100644 index 0000000..e533165 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusLibPei.inf @@ -0,0 +1,64 @@ +## @file +# Component description file for PEI PCH Smbus Lib +# +#@copyright +# Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchSmbusLibPei +COMPONENT_TYPE = LIBRARY + +[sources.common] + ../Common/PchSmbusLib.c + +[sources.ia32] + +[sources.x64] + +[sources.ipf] + +[includes.common] + $(EDK_SOURCE)/Foundation/Efi + . + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Library/PeiSmbusLib +# +# Typically the sample code referenced will be available in the code base already +# So keep this include at the end to defer to the source base definition +# and only use the sample code definition if source base does not include these files. +# + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode + +[libraries.common] + + +[nmake.common] diff --git a/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusPeiLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusPeiLib.cif new file mode 100644 index 0000000..22aba6f --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/PchSmbusLib/Pei/PchSmbusPeiLib.cif @@ -0,0 +1,9 @@ + + name = "PchSmbusPeiLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\PchSmbusLib\Pei\" + RefName = "PchSmbusPeiLib" +[files] +"PchSmbusLib.h" +"PchSmbusLibPei.inf" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/CreateFviLibrary.c b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/CreateFviLibrary.c new file mode 100644 index 0000000..e97d65b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/CreateFviLibrary.c @@ -0,0 +1,225 @@ +/** @file + Firmware Version Info Interface Lib implementation. + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "RcFviLib.h" + +EFI_DATA_HUB_PROTOCOL *mDataHub = NULL; + +/** + Initialize callback context for Firmware Version Info (FVI) Interface Spec v0.7 + implementation. + + @param[in] String The pointer to the string for calculating length + + @retval None +**/ +UINT32 +GetStringLen ( + IN UINT8 *String + ) +{ + UINT8 Length; + + for (Length = 0; *String != 0; String++, Length++) { + if (Length >= SMBIOS_STRING_MAX_LENGTH) { + break; + } + } + + return (UINT32) (Length + 1); +} + +/** + Initialize callback context for Firmware Version Info (FVI) Interface Spec v0.7 + implementation. + + @param[in] Type Value is defined in SMBIOS Type 14 - Group Associaction structure - item type. + @param[in] Count Number of elements included by this SMBIOS table + @param[in] FviContext Context of FVI elements for data hub log + + @retval None +**/ +VOID +InitFviDataHubCbContext ( + IN UINT8 Type, + IN UINT8 Count, + IN FVI_DATA_HUB_CALLBACK_CONTEXT *FviContext + ) +{ + /// + /// Locate the Data hub protocol + /// + if (mDataHub == NULL) { + gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **)&mDataHub); + } + + if (FviContext != NULL) { + FviContext->FviHeader.FviHdr.Header.Type = Type; + FviContext->FviHeader.FviHdr.Count = Count; + FviContext->FviHeader.FviHdr.Header.Length = sizeof (FVI_HEADER) + FVI_ELEMENTS_SIZE_NOSTRING * Count; + } else { + ASSERT (FALSE); + } + + return ; +} + +/** + Create the Reference code version info as per Firmware Version Info (FVI) Interface Spec v0.7 + to Data Hub. + + @param[in] FviContext Pointer to the notification functions context, which is context of FVI + elements for data hub log + + @retval None +**/ +VOID +CreateRcFviDatahub ( + IN FVI_DATA_HUB_CALLBACK_CONTEXT *FviContext + ) +{ + VOID *Registration; + + if (mDataHub == NULL) { + EfiCreateProtocolNotifyEvent ( + &gEfiDataHubProtocolGuid, + EFI_TPL_CALLBACK, + DataHubCallback, + (VOID *) FviContext, + &Registration + ); + } else { + DataHubCallback ((EFI_EVENT) NULL, (VOID *) FviContext); + } +} + +/** + Publish the Reference code version info as per Firmware Version Info (FVI) Interface Spec v0.7 + using MiscSubClass Data Hub. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification functions context, which is implementation dependent. + + @retval None +**/ +VOID +EFIAPI +DataHubCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + FVI_DATA_HUB_CALLBACK_CONTEXT *FviContext; + UINT8 Index; + UINT8 StrIndex; + UINT8 *Record; + UINT8 *LastRecord; + UINT8 *String; + UINT8 Count; + UINT32 Length; + FVI_ELEMENT_AND_FUNCTION *NewElement; + + Status = EFI_SUCCESS; + if (mDataHub == NULL) { + Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **)&mDataHub); + } + + if ((mDataHub != NULL) && (Context != NULL)) { + + if (Event != NULL) { + gBS->CloseEvent (Event); + } + + FviContext = (FVI_DATA_HUB_CALLBACK_CONTEXT *) Context; + Count = FviContext->FviHeader.FviHdr.Count; + + /// + /// Allocate a buffer to record data sorted later + /// + Length = sizeof (MISC_SUBCLASS_FVI_HEADER) + (sizeof (FVI_ELEMENTS) * Count); + + Status = EFI_OUT_OF_RESOURCES; + Record = (UINT8 *) AllocateZeroPool (Length); + if (Record != NULL) { + LastRecord = Record; + + /// + /// Copy the headers including Data Hub and SMBIOS FviSmbios OEM type + /// + CopyMem (LastRecord, &(FviContext->FviHeader), sizeof (MISC_SUBCLASS_FVI_HEADER)); + LastRecord += sizeof (MISC_SUBCLASS_FVI_HEADER); + String = LastRecord + FVI_ELEMENTS_SIZE_NOSTRING * Count; + + NewElement = FviContext->Elements; + + /// + /// Copy elements including strings + /// + for (Index = 0, StrIndex = 1; Index < Count; Index++) { + if (NewElement->Function != NULL) { + NewElement->Function (&(NewElement->Element)); + } + + /// + /// If string is implemented for ComponentName or VersionString, and then string + /// index of ComponentName or VersionString can't be zero. The string index of + /// ComponentName and VersionString will be updated and calculated while analyse + /// all elements here.String index must be non-zero if implemented. + /// + if (NewElement->Element.ComponentName != 0) { + NewElement->Element.ComponentName = StrIndex; + Length = GetStringLen (NewElement->Element.NameString); + CopyMem (String, &(NewElement->Element.NameString), Length); + String += Length; + StrIndex++; + } + + if (NewElement->Element.VersionString != 0) { + NewElement->Element.VersionString = StrIndex; + Length = GetStringLen (NewElement->Element.VerString); + CopyMem (String, &(NewElement->Element.VerString), Length); + String += Length; + StrIndex++; + } + + CopyMem (LastRecord, &(NewElement->Element), FVI_ELEMENTS_SIZE_NOSTRING); + LastRecord += FVI_ELEMENTS_SIZE_NOSTRING; + + NewElement++; + } + + Length = (UINT32) (String - Record) + 1; + Status = mDataHub->LogData ( + mDataHub, + &gMiscSubClassName, + &gMiscProducerGuid, + EFI_DATA_RECORD_CLASS_DATA, + (VOID *) Record, + Length + ); + } + + ASSERT (!EFI_ERROR (Status)); + if (Record != NULL) { + FreePool (Record); + } + } +} diff --git a/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.cif b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.cif new file mode 100644 index 0000000..57f9263 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.cif @@ -0,0 +1,12 @@ + + name = "RcFviDxeLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Library\RcFviDxeLib" + RefName = "RcFviDxeLib" +[files] +"RcFviDxeLib.sdl" +"RcFviDxeLib.mak" +"CreateFviLibrary.c" +"RcFviLib.h" +"RcFviDxeLib.inf" + diff --git a/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.inf b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.inf new file mode 100644 index 0000000..ad9f04c --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.inf @@ -0,0 +1,67 @@ +## @file +# Component description file for the PchRcFviDxeLib +# +#@copyright +# Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = RcFviDxeLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + CreateFviLibrary.c + +[sources.ia32] + + +[sources.x64] + + +[sources.ipf] + + +[sources.ebc] + + +[includes.common] + . + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + +[libraries.common] + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueDxeServicesTableLib + EdkIIGlueDxeMemoryAllocationLib + EdkFrameworkProtocolLib +[libraries.ia32] + + +[libraries.x64] + + +[nmake.common] \ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.mak b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.mak new file mode 100644 index 0000000..4e8a698 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.mak @@ -0,0 +1,69 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/RcFviDxeLib/RcFviDxeLib.mak 1 2/08/12 8:50a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:50a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/RcFviDxeLib/RcFviDxeLib.mak $ +# +# 1 2/08/12 8:50a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +# +#************************************************************************* +all : RcFviDxeLib + +$(RcFviDxeLib_LIB) : RcFviDxeLib + +RcFviDxeLib : $(BUILD_DIR)\RcFviDxeLib.mak RcFviDxeLibBin + +$(BUILD_DIR)\RcFviDxeLib.mak : $(RcFviDxeLib_DIR)\$(@B).cif $(RcFviDxeLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(RcFviDxeLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +RcFviDxeLib_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + +RcFviDxeLib_LIB_LINKS =\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + +RcFviDxeLibBin: + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\RcFviDxeLib.mak all \ + "MY_INCLUDES=$(RcFviDxeLib_INCLUDES)" \ + TYPE=LIBRARY \ + LIBRARY_NAME=$(RcFviDxeLib_LIB) + +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.sdl b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.sdl new file mode 100644 index 0000000..15c1fd4 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviDxeLib.sdl @@ -0,0 +1,73 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/RcFviDxeLib/RcFviDxeLib.sdl 1 2/08/12 8:50a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:50a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLib/RcFviDxeLib/RcFviDxeLib.sdl $ +# +# 1 2/08/12 8:50a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +# +#************************************************************************* +TOKEN + Name = "RcFviDxeLib_SUPPORT" + Value = "1" + Help = "Main switch to enable RcFviDxeLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +PATH + Name = "RcFviDxeLib_DIR" +End + +MODULE + File = "RcFviDxeLib.mak" + Help = "Includes RcFviDxeLib.mak to Project" +End + +ELINK + Name = "RcFviDxeLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\RcFviDxeLib_Lib.lib" + Parent = "RcFviDxeLib_LIB" + InvokeOrder = AfterParent +End + +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviLib.h b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviLib.h new file mode 100644 index 0000000..70a5556 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Library/RcFviDxeLib/RcFviLib.h @@ -0,0 +1,49 @@ +/** @file + Header file for Reference code Firmware Version Info Interface Lib implementation. + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +**/ +#ifndef _RC_FVI_LIBRARY_IMPLEMENTATION_H_ +#define _RC_FVI_LIBRARY_IMPLEMENTATION_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#include "EdkIIGlueDxe.h" +#include "Library/EdkIIGlueMemoryAllocationLib.h" + +#include EFI_GUID_DEFINITION (DataHubRecords) +#include EFI_PROTOCOL_CONSUMER (DataHub) + +#include "RcFviDxeLib.h" + +#endif + +/** + Publish the Reference code version info as per Firmware Version Info (FVI) Interface Spec v0.7 + using MiscSubClass Data Hub. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification functions context, which is implementation dependent. + + @retval None +**/ +VOID +EFIAPI +DataHubCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); +#endif -- cgit v1.2.3