From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Core/CORE_PEI/PciCfg.c | 491 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 Core/CORE_PEI/PciCfg.c (limited to 'Core/CORE_PEI/PciCfg.c') diff --git a/Core/CORE_PEI/PciCfg.c b/Core/CORE_PEI/PciCfg.c new file mode 100644 index 0000000..c831953 --- /dev/null +++ b/Core/CORE_PEI/PciCfg.c @@ -0,0 +1,491 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//***************************************************************************** +// $Header: /Alaska/SOURCE/Core/EDK/PeiMain/PciCfg.c 12 8/12/11 12:24p Artems $ +// +// $Revision: 12 $ +// +// $Date: 8/12/11 12:24p $ +//***************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/EDK/PeiMain/PciCfg.c $ +// +// 12 8/12/11 12:24p Artems +// EIP 64107: Added changes for module to be compliant with PI +// specification v 1.2 +// +// 11 3/22/11 5:15p Felixp +// Method of invocation of the in-memory entry point has changed +// from LOAD_HOB to eLink registered under PeiCoreMemoryInstalled. +// This is more efficient. +// +// 10 2/05/11 3:44p Artems +// Changed functions calling interfaces to meet PI 1.0 specification +// requirements +// +// 9 11/05/09 5:01p Oleksiyy +// EIP 27821 Support for 64 bit operations in PciRead and PciWrite added. +// To use this functions CpuIo.c, IA32CLib.c, x64AsmLib.asm files should +// be updated also. +// +// 8 7/08/09 5:53p Vyacheslava +// Updated according to the coding standards. +// +// 7 6/16/05 10:56a Felixp +// 1. Once memory is available, PEI Core PEIMs that created PEIM_LOAD_HOB +// are reallocated to memory. +// 2. ImagePei.c removed +// 3. FileLoader moved from DxeIpl to PEI Core +// +// 6 6/06/05 7:49p Felixp +// +// 5 6/06/05 1:25p Felixp +// +// 4 6/03/05 3:45p Felixp +// Updated to support changes introduced in PEI CIS 0.91 +// +// 3 3/04/05 9:43a Mandal +// +// 2 1/18/05 3:21p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 8 1/28/04 3:24a Felixp +// +// 7 1/27/04 3:58a Felixp +// Bug fixes and improvements as a part of PEI CORE integration +// +// 6 12/29/03 5:25p Felixp +// preffix 'EFI_' added to the names of the PEIM descriptor structures and +// flags +// +// 5 12/15/03 4:35p Robert +// +// 4 12/15/03 4:25p Robert +// +// 3 12/15/03 12:41p Robert +// changed position of GUID definition below PPI include +// +// 2 12/15/03 11:54a Robert +// Updated the definitions of PPI includes and removed the entry point +// definitions +// +// 1 12/11/03 5:34p Robert +// Initial Check in +// +//***************************************************************************** +// +// +// Name: PciCfg.c +// +// Description: This file contains the implementation of the PCI Cfg I/O +// specification. For questions about the specification refer to the +// PEI CIS specification chapter 9 +// +// +//***************************************************************************** + +// Module specific Includes +#include +// PPI Produced +#include + +// Module specific macros +// Make a PCI Access address out of the value that is passed in. Clear the lowest 2 bits +// PCI accesses are always 4 byte aligned +#define GET_PCI_ADDRESS(x) \ +(0x080000000 | (((UINTN)x & 0x0FF000000) >> 8) | (((UINTN)x & 0x0FF0000)>> 5) | (x & 0x0700) | (x & 0x0FC)) + +// Function Prototypes +EFI_STATUS PciRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +); + +EFI_STATUS PciWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +); + +EFI_STATUS PciModify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, +#if PI_SPECIFICATION_VERSION<0x00010000 + IN UINTN SetBits, + IN UINTN ClearBits +#else + IN VOID *SetBits, + IN VOID *ClearBits +#endif +); + + +// Local Definitions +EFI_PEI_PCI_CFG2_PPI mPciCfgPpi = { + PciRead, + PciWrite, + PciModify +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPciCfg2PpiGuid, + &mPciCfgPpi + } +}; + +// Function Definitions + +// +//============================================================================ +// Procedure: PciCfgMemInit +// +// Description: This function installs the PCI Configuration PPI and exits +// +// Input: +// *FfsHeader - pointer to the header of the current firmware file system +// **PeiServices - pointer to the Pei Services function and data structure +// +// Output: EFI_SUCCESS +// +//============================================================================ +// + +EFI_STATUS EFIAPI PciCfgMemInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + // update PCI Config pointer + (*PeiServices)->PciCfg = &mPciCfgPpi; + return EFI_SUCCESS; +} + +// +//============================================================================ +// Procedure: PciCfgInit +// +// Description: This function installs the PCI Configuration PPI and exits +// +// Input: +// *FfsHeader - pointer to the header of the current firmware file system +// **PeiServices - pointer to the Pei Services function and data structure +// +// Output: EFI_SUCCESS +// +//============================================================================ +// + +EFI_STATUS EFIAPI PciCfgInit ( + IN EFI_PEI_FILE_HANDLE FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_STATUS Status; + + // Install the PCI Config Ppi + (*PeiServices)->PciCfg = &mPciCfgPpi; + Status = (*PeiServices)->InstallPpi( PeiServices, mPpiList ); + return Status; +} + +// +//============================================================================ +// Procedure: PciRead +// +// Description: This function Reads a value from the PCI Config space and +// returns that value in Buffer. +// +// Input: +// **PeiServices - Pointer to the PEI Core data Structure +// *This - Pointer to the instance of the PCI Config PPI +// Width - Size of the data to be read from the configuration space +// Address - PCI address of the register to be read(Bus/Dev/Func/Reg) +// *Buffer - The data read from the requested PCI Configuration register +// +// Output: EFI_SUCCESS +// +//============================================================================ +// + +EFI_STATUS PciRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +) +{ + UINT64 IoAddr; + UINT32 PciAddr; + EFI_PEI_CPU_IO_PPI *CpuIo = (*PeiServices)->CpuIo; + EFI_PEI_PCI_CFG_PPI_WIDTH TmpWidth; + UINT8 *Buffer8=(UINT8*)Buffer; + + if (((Width & 3) == EfiPeiPciCfgWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiPeiPciCfgWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + // Make a usable PCI address out of the Address passed in + PciAddr = (UINT32)GET_PCI_ADDRESS(Address); + + // Access 0xCF8 and use corrected address to enable the read to PCI + IoAddr = 0x0CF8; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + + // Access 0xCFC to get the data requested. Increment IoAddr to + // read the correct register from the PCI Config space + IoAddr = 0x0CFC + (Address & 0x03); + + TmpWidth=Width; + + if ((Width & 3) > EfiPeiPciCfgWidthUint32)TmpWidth=Width-1; + // Read the register requested. Use the passed in Width value to + // indicate the number of bytes to read. If Width = 8 bytes - split into two reads + CpuIo->Io.Read( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)Buffer8 + ); + // no formatting should be needed on the output data. Read the correct + // register and the correct width should format the data properly + + if (Width == TmpWidth) return EFI_SUCCESS; + + IoAddr = 0x0CF8; + PciAddr = PciAddr + 4; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + // Read the next 4 bytes + IoAddr = 0x0CFC; + CpuIo->Io.Read( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)(Buffer8+4) + ); + + + + + return EFI_SUCCESS; +} + +// +//============================================================================ +// Procedure: PciWrite +// +// Description: This function writes a value to the PCI Config space +// +// Input: +// **PeiServices - Pointer to the PEI Core data Structure +// *This - Pointer to the instance of the PCI Config PPI +// Width - Size of the data to write to the configuration space +// Address - PCI address of the register to write to (Bus/Dev/Func/Reg) +// *Buffer - The data to write to the requested PCI Configuration register +// +// Output: EFI_SUCCESS +// +//============================================================================ +// + +EFI_STATUS PciWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +) +{ + UINT64 IoAddr; + UINT32 PciAddr; + EFI_PEI_CPU_IO_PPI *CpuIo = (*PeiServices)->CpuIo; + EFI_PEI_PCI_CFG_PPI_WIDTH TmpWidth; + UINT8 *Buffer8=(UINT8*)Buffer; + if (((Width & 3) == EfiPeiPciCfgWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiPeiPciCfgWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + // Make a usable PCI address out of the Address passed in + PciAddr = (UINT32)GET_PCI_ADDRESS(Address); + + // Access 0xCF8 and use corrected address to enable the read to PCI + IoAddr = 0x0CF8; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + + // Access 0xCFC to get the data requested. Increment IoAddr to + // read the correct register from the PCI Config space + IoAddr = 0x0CFC + (Address & 0x03); + + TmpWidth=Width; + + if ((Width & 3) > EfiPeiPciCfgWidthUint32) TmpWidth = Width - 1; + // Write the register requested. Use the passed in Width value to + // indicate the number of bytes to read. If Width = 8 bytes - split into two writes + CpuIo->Io.Write( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)Buffer8 + ); + + + if (Width == TmpWidth) return EFI_SUCCESS; + + // Access 0xCF8 and use next 4 bytes address to enable the read to PCI + IoAddr = 0x0CF8; + PciAddr = PciAddr + 4; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + + // Write the next 4 bytes + IoAddr = 0x0CFC; + CpuIo->Io.Write( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)(Buffer8+4) + ); + + + return EFI_SUCCESS; +} + +// +//============================================================================ +// Procedure: PciModify +// +// Description: This function modifies a value in the PCI Config space. +// This function uses the SetBits and ClearBits values to modify the +// register. First the ClearBits value is used to clear the unwanted bits +// then the SetBits value is used to set the wanted bits. +// +// Input: +// **PeiServices - Pointer to the PEI Core data Structure +// *This - Pointer to the instance of the PCI Config PPI +// Width - Size of the data to write to the configuration space +// Address - PCI address of the register to write to (Bus/Dev/Func/Reg) +// SetBits - The bits in the register that need to be set +// ClearBits - The bits in the register that should be cleared +// +// Output: EFI_SUCCESS +// +//============================================================================ +// + +EFI_STATUS PciModify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, +#if PI_SPECIFICATION_VERSION<0x00010000 + IN UINTN SetBits, + IN UINTN ClearBits +#else + IN VOID *SetBits, + IN VOID *ClearBits +#endif +) +{ + EFI_STATUS Status; + UINTN Data; + if (((Width & 3) == EfiPeiPciCfgWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiPeiPciCfgWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + Status = PciRead ( + PeiServices, + This, + Width, + Address, + &Data + ); +#if PI_SPECIFICATION_VERSION<0x00010000 + Data = SetBits | (Data & (~ClearBits)); +#else + Data = *(UINTN*)SetBits | (Data & (~*(UINTN*)ClearBits)); +#endif + Status = PciWrite ( + PeiServices, + This, + Width, + Address, + &Data + ); + + return Status; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* -- cgit v1.2.3