diff options
Diffstat (limited to 'Chipset/SB/SBGeneric.c')
-rw-r--r-- | Chipset/SB/SBGeneric.c | 3717 |
1 files changed, 3717 insertions, 0 deletions
diff --git a/Chipset/SB/SBGeneric.c b/Chipset/SB/SBGeneric.c new file mode 100644 index 0000000..efdedd4 --- /dev/null +++ b/Chipset/SB/SBGeneric.c @@ -0,0 +1,3717 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2013, 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 Chipset/SBGeneric.c 27 1/29/15 4:14a Mirayang $ +// +// $Revision: 27 $ +// +// $Date: 1/29/15 4:14a $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SBGeneric.c $ +// +// 27 1/29/15 4:14a Mirayang +// [TAG] EIP200269 +// [Category] New Feature +// [Description] For add FlashSmi : Label 4.6.5.5_FlashSmi_00 +// ($/Alaska/SOURCE/Modules/FlashSmi) +// +// 26 5/16/14 6:16a Barretlin +// [TAG] EIP167087 +// [Category] Improvement +// [Description] BIOS security improvement on Haswell CRB project +// [Files] SBGeneric.c SBDxe.c SBCspLib.h Sb.sdl Sb.sd +// +// 25 1/24/14 2:49a Barretlin +// [TAG] EIP136638 +// [Category] Improvement +// [Description] fix programming error +// [Files] SBGeneric.c PchResetCommon.c +// +// 24 12/30/13 6:01a Barretlin +// [TAG] EIP144559 +// [Category] Improvement +// [Description] S3 can't resume via USB KB & MS under usb3.0 port in +// special case +// [Files] SBSMI.c SBSMI.h SBGeneric.c +// +// 23 11/19/13 7:32a Barretlin +// [TAG] EIP141917 +// [Category] New Feature +// [Description] Support SetTimer() with HPET Timer on Lynx Point +// [Files] SB.sdl SBGeneric.c SBDxe.c SbHpet.h sbProtocal.cif +// SamrtTimer.sdl +// +// 22 4/29/13 1:58a Scottyang +// [TAG] None +// [Category] Improvement +// [Description] THe NMI read port should before index update. +// [Files] SBGeneric.c +// +// 21 4/19/13 6:35a Wesleychen +// [TAG] None +// [Category] Improvement +// [Description] Update GbES02SxWorkaround() and add +// UsbS02SxWorkaround() for SBPwrBtnHandler(). +// [Files] SBSMI.c; SBSMI.h; SBGeneric.c; SBCspLib.h +// +// 20 4/01/13 6:43a Scottyang +// [TAG] EIP119703 +// [Category] Improvement +// [Description] Clear RTC before BIOS flash capsule function enter S3. +// [Files] SBGeneric.c +// +// 19 3/19/13 8:33a Scottyang +// [TAG] None +// [Category] Improvement +// [Description] Improve alternate access mode enable/disable routine. +// [Files] SBGeneric.c, SBCspLib.h, SBSMI.c +// +// 18 3/19/13 8:19a Scottyang +// [TAG] EIP118158 +// [Category] Improvement +// [Description] Correct SBLib_CmosRead () offset. +// [Files] SmiHandlerPorting2.c, SBDxe.c, SBGeneric.c, SBSmm.c, +// SmiHandlerPorting.c +// +// 17 3/12/13 7:44a Scottyang +// [TAG] EIP106722 +// [Category] Improvement +// [Description] Clear RTC before capsule function enter S3. +// [Files] SBGeneric.c +// +// 16 1/11/13 4:36a Scottyang +// [TAG] None +// [Category] Improvement +// [Description] Add ReadCmos() / WriteCmos() from SB template. +// [Files] SBGeneric.c +// +// 15 1/11/13 12:46a Scottyang +// [TAG] EIP81593 +// [Category] Improvement +// [Description] Added new SDL token "COLD_RESET_WITH_POWER_CYCLE". +// [Files] SB.sdl, SBGeneric.c, PchResetCommon.c, +// PchResetCommonLib.sdl +// +// 14 1/10/13 8:20a Scottyang +// [TAG] EIP111666 +// [Category] New Feature +// [Description] Support OEM reset callback function Elink. +// [Files] SB.mak, SBCspLib.h, SBGeneric.c, SB.sdl, PchReset.c +// +// 13 11/21/12 3:07a Scottyang +// +// 11 11/19/12 3:52a Scottyang +// [TAG] EIP106353 +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] The system has assert error when PFAT is Disabled and Debug +// Mode is Enabled. +// [RootCause] Use build time PFAT flag that make some code not run whrn +// PFAT disable. +// [Solution] Detect PFAT flag useing MSR. +// [Files] SBGeneric, SB.mak +// +// 10 10/30/12 10:02p Scottyang +// [TAG] None +// [Category] Improvement +// [Description] Remove clear SMI state and Y2K roller for PFAT +// function. +// [Files] SBSMI.c, SBGeneric.c +// +// 9 10/25/12 11:57p Scottyang +// [TAG] EIP100108 +// [Category] Improvement +// [Description] Support Capsule 2.0. +// [Files] SBGeneric.c +// +// 8 10/19/12 2:46a Scottyang +// [TAG] EIP93461 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] System halt when AFUDOS is running with /N /ME command. +// [RootCause] An unexpected BIOSWR_STS is set, it causes BIOS stuck +// at SMM dispatcher. +// [Solution] Clear BIOSWR_STS if BIOS Lock Enable is not set. +// [Files] SmiHandlerPorting2.c; SmmChildDispatch2Main.c +// SmmChildDispatcher2.sdl; SmmChildDispatch2.h +// SB\SBGeneric.c +// +// 7 10/01/12 5:53a Victortu +// [TAG] None +// [Category] Improvement +// [Description] Update for PFTA support. +// [Files] SBGeneric.c +// +// 6 9/26/12 3:54a Victortu +// [TAG] None +// [Category] Improvement +// [Description] Update for PCH LP GPIO compatible. +// [Files] SB.sdl, SB.H, AcpiModeEnable.c, AcpiModeEnable.sdl, +// SBDxe.c, SBGeneric.c, SBPEI.c, SBSMI.c, SleepSmi.c, +// SmiHandlerPorting.c, SmiHandlerPorting2.c +// +// 5 9/12/12 5:19a Victortu +// [TAG] None +// [Category] Improvement +// [Description] Remove useless HdmiVerbTable. +// [Files] SB.sdl, SBCspLib.h, SBDxe.c, SBGeneric.c +// +// 4 8/24/12 6:50a Victortu +// [TAG] None +// [Category] Improvement +// [Description] Remove useless SB_SHADOW_CONTROL. +// [Files] SB.sdl, SBCspLib.h, SBGeneric.c +// +// 3 7/02/12 10:17a Victortu +// [TAG] None +// [Category] Improvement +// [Description] Updated and modified for PCH RC 0.6.0. +// [Files] SBGeneric.c, SB.sdl, SBCspLib.h, SBDxe.c, SBPEI.c +// +// 2 6/13/12 11:34p Victortu +// [TAG] None +// [Category] Improvement +// [Description] Implement Warm Boot function for Secure Flash feature. +// [Files] SB.H, SB.mak, SB.sdl, SBDxe.c, SBGeneric.c, SBPEI.c, +// SBSMI.c +// +// 1 2/08/12 8:24a Yurenlai +// Intel Lynx Point/SB eChipset initially releases. +// +//************************************************************************* +//<AMI_FHDR_START> +// +// Name: SBGeneric.C +// +// Description: This file contains south bridge related code that is needed +// for both PEI & DXE stage. +// To avoid code duplication this file is made as a library and +// linked both in PEI & DXE south bridge FFS. +// +// Notes: MAKE SURE NO PEI OR DXE SPECIFIC CODE IS NEEDED +// +//<AMI_FHDR_END> +//************************************************************************* + +//--------------------------------------------------------------------------- +// Include(s) +//--------------------------------------------------------------------------- + +#include <Efi.h> +#include <Token.h> +#include <AmiPeiLib.h> +#include <AmiDxeLib.h> +#include <Protocol\PciRootBridgeIo.h> +#include <AmiCspLib.h> +#include "PchAccess.h" +#include "RTC.h" +#if Capsule2_0_SUPPORT +#include <capsule.h> //CAPSULE20 +#endif +#include <Include\PchRegs.h> +#include <Include\PchRegs\PchRegsLpc.h> + +#if CSM_SUPPORT +#include <Protocol\LegacyInterrupt.h> +#endif + +#include "CpuRegs.h" // EIP106353 + +#if defined HPET_PROTOCOL_SUPPORT && HPET_PROTOCOL_SUPPORT == 1 +#include <Protocol\SbHpet.h> +#endif + +//--------------------------------------------------------------------------- +// Constant, Macro and Type Definition(s) +//--------------------------------------------------------------------------- +// Constant Definition(s) + +#ifndef BIT35 // EIP106353 >> +#define BIT35 0x0000000800000000ULL +#endif // EIP106353 << + +#if CSM_SUPPORT + +#define MAX_PIRQS 8 // Porting Required. + +#endif + +#ifndef CAPSULE_SUPPORT + +#if defined Capsule2_0_SUPPORT && Capsule2_0_SUPPORT +#define CAPSULE_SUPPORT 1 +#else +#define CAPSULE_SUPPORT 0 +#endif + +#endif + +// Macro Definition(s) + +// Type Definition(s) + +typedef VOID (SB_OEM_S3_WARMRESET_CALLBACK) (VOID); + +typedef EFI_STATUS (SB_RUN_RESET_CALLBACK) ( + IN EFI_RESET_TYPE ResetType +); + +typedef struct { + UINT8 Device; + UINT8 Function; +} USB_CONTROLLER; + +// Function Prototype(s) + +//--------------------------------------------------------------------------- +// Variable and External Declaration(s) +//--------------------------------------------------------------------------- +// Variable Declaration(s) +#if defined CAPSULE_SUPPORT && CAPSULE_SUPPORT == 1 +extern SB_OEM_S3_WARMRESET_CALLBACK \ + SB_OEM_S3_WARMRESET_CALLBACK_LIST EndOfList; +SB_OEM_S3_WARMRESET_CALLBACK* SbS3InsteadOfWarmResetCallBackList[] = \ + {SB_OEM_S3_WARMRESET_CALLBACK_LIST NULL}; +#endif + +extern SB_RUN_RESET_CALLBACK SB_RUN_RESET_CALLBACK_LIST EndOfList1; +SB_RUN_RESET_CALLBACK* SbRunResetCallbackList[] = {SB_RUN_RESET_CALLBACK_LIST NULL}; + +//--------------------------------------------------------------------------- +// The following table contains the information regarding the PIRQ routing +// registers and other South Bridge registers that need to be restored +// during the S3 wakeup. +// Mention all register address (bus, device, function , register), specify +// the size of the register ans the mask also. +//--------------------------------------------------------------------------- + +BOOT_SCRIPT_SB_PCI_REG_SAVE gSBRegsSaveTbl[] = { + {SB_REG(SB_REG_PIRQ_A), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_B), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_C), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_D), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_E), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_F), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_G), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_PIRQ_H), EfiBootScriptWidthUint8, 0xff}, + {SB_REG(SB_REG_GEN_PMCON_1),EfiBootScriptWidthUint16, 0xffff},// SMI Timer + {SB_REG(SB_REG_GEN_PMCON_3),EfiBootScriptWidthUint16, 0xffff},// SMI Timer + {SB_REG(SB_REG_LPC_IO_DEC), EfiBootScriptWidthUint16, 0xffff}, + {SB_REG(SB_REG_LPC_EN), EfiBootScriptWidthUint16, 0xffff}, + {SB_REG(SB_REG_GEN1_DEC), EfiBootScriptWidthUint32, 0xffffffff}, + {SB_REG(SB_REG_GEN2_DEC), EfiBootScriptWidthUint32, 0xffffffff}, + {SB_REG(SB_REG_GEN3_DEC), EfiBootScriptWidthUint32, 0xffffffff}, + {SB_REG(SB_REG_GEN4_DEC), EfiBootScriptWidthUint32, 0xffffffff}, +}; + +#define NUM_SB_PCI_REG_SAVE \ + sizeof(gSBRegsSaveTbl)/ sizeof(BOOT_SCRIPT_SB_PCI_REG_SAVE) + +#if CSM_SUPPORT + +UINT8 bMaxPIRQ = MAX_PIRQS; // For CSM +UINT8 bRouterBus = SB_BUS; // PORTING REQUIRED (Use appropriate Equate) +UINT8 bRouterDevice = SB_DEV; // PORTING REQUIRED (Use appropriate Equate) +UINT8 bRouterFunction = SB_FUN; // PORTING REQUIRED (Use appropriate Equate) +UINT8 RRegs[MAX_PIRQS] = { SB_REG_PIRQ_A, \ + SB_REG_PIRQ_B, \ + SB_REG_PIRQ_C, \ + SB_REG_PIRQ_D, \ + SB_REG_PIRQ_E, \ + SB_REG_PIRQ_F, \ + SB_REG_PIRQ_G, \ + SB_REG_PIRQ_H }; // Porting required + +#endif +// Local variable +static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *gPciRootBridgeIo; + +// GUID Definition(s) + +// Protocol Definition(s) + +// External Declaration(s) + +// Function Definition(s) +BOOLEAN CheckOff20hBit28(IN UINT32 GbEBase); +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Start OF CSM Related Porting Hooks +//--------------------------------------------------------------------------- + +#if CSM_SUPPORT + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBGen_InitializeRouterRegisters +// +// Description: This function is clears the routing registers to default +// values +// +// Input: PciRBIo - Root bridge IO protocol pointer +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SBGen_InitializeRouterRegisters ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRBIo ) +{ + UINT8 RegIdx; + + gPciRootBridgeIo = PciRBIo; // Save RB IO value for later use + + for (RegIdx = 0; RegIdx < MAX_PIRQS; RegIdx++) + WRITE_PCI8_SB(RRegs[RegIdx], 0x80); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBGen_GetPIRQIndex +// +// Description: This function returns the 0 based PIRQ index (PIRQ0, 1 etc) +// based on the PIRQ register number specified in the routing +// table. +// +// Input: PIRQRegister - Register number of the PIR +// +// Output: An 8Bit Index for RRegs table, its range is 0 - (MAX_PIRQ -1) +// if PIRQRegister is invalid, then 0xff will be returned. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 SBGen_GetPIRQIndex ( + IN UINT8 PIRQRegister ) +{ + UINT8 rrIndx = 0; + + while ((rrIndx < MAX_PIRQS) && (RRegs[rrIndx] != PIRQRegister)) rrIndx++; + + if (rrIndx == MAX_PIRQS) return 0xff; + + return rrIndx; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBGen_ReadPirq +// +// Description: This function reads the IRQ associated with the PIRQ from +// the chipset register +// +// Input: This - Pointer to Legacy interrupt protocol +// PirqNumber - PIRQ number to read +// PirqData - IRQ programmed for this PIRQ (BIT7 will be +// set if the PIRQ is not programmed) +// +// Output: EFI_STATUS +// EFI_SUCCESS - On successfull IRQ value return +// EFI_INVALID_PARAMETER - If PirqNumber is greater than max +// PIRQs +// +// Notes: Here is the control flow of this function: +// 1. If Invalid PirqNumber, return EFI_INVALID_PARAMETER. +// 2. Read into *PriqData from PIRQ register for Pirq requested +// 3. Return EFI_SUCCESS. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SBGen_ReadPirq ( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + IN UINT8 PirqNumber, + OUT UINT8 *PirqData ) +{ + if (PirqNumber > MAX_PIRQS) return EFI_INVALID_PARAMETER; + + // If Pirq is not routed, bit 7 is set, however specification does not + // specify a return error for this condition. + *PirqData = READ_PCI8_SB(RRegs[PirqNumber]); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBGen_WritePirq +// +// Description: This function writes an IRQ value allocated for the PIRQ by +// programming the chipset register +// +// Input: This - Pointer to Legacy interrupt protocol +// PirqNumber - PIRQ number to read +// PirqData - IRQ to be programmed +// +// Output: EFI_STATUS +// EFI_SUCCESS - On successfull IRQ value return +// EFI_INVALID_PARAMETER - If PirqNumber is greater than +// max PIRQs or PirqData is greater +// than 15 (MAX IRQ) +// +// Notes: Here is the control flow of this function: +// 1. If Invalid PirqNumber or PirqData is greater than 15, +// return EFI_INVALID_PARAMETER. +// 2. Write PirqData to PIRQ register for Pirq requested. +// 3. Return EFI_SUCCESS. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SBGen_WritePirq ( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + IN UINT8 PirqNumber, + IN UINT8 PirqData ) +{ + UINT8 PirqValue = PirqData & 0x0f; + + if (PirqNumber > MAX_PIRQS) return EFI_INVALID_PARAMETER; + if (PirqData > 15) return EFI_INVALID_PARAMETER; + + WRITE_PCI8_SB(RRegs[PirqNumber], PirqValue); + + return EFI_SUCCESS; +} + +//--------------------------------------------------------------------------- +#endif // END OF CSM Related Porting Hooks +//--------------------------------------------------------------------------- +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SbFindCapPtr +// +// Description: This function searches the PCI address space for the PCI +// device specified for a particular capability ID and returns +// the offset in the PCI address space if one found +// +// Input: UINT64 PciAddress, +// UINT8 CapId +// +// Output: Capability ID Address if one found +// Otherwise returns 0 +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 SbFindCapPtr( + IN UINT64 PciAddress, + IN UINT8 CapId +) +{ + UINT8 Value; + UINT32 Address = (UINT32)PciAddress; + + Address = (Address & 0xffffff00) | 6; //PCI Status Register. + Value = READ_MEM8(Address + 0); + + if (Value == 0xff) return 0; // No device. + if (!(Value & (1 << 4))) return 0; // Check if capabilities list. + + *(UINT8*)&Address = 0x34; // Register to First capabilities pointer + // if 0, then capabilities + for(;;) + { + Value = READ_MEM8(Address + 0); + if (Value == 0) return 0; + + *(UINT8*)&Address = Value; // PciAddress = ptr to CapID + Value = READ_MEM8(Address + 0); // New cap ptr. + + //If capablity ID, return register that points to it. + if (Value == CapId) return Address; + + ++Address; // Equals to next capability pointer. + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBSwSmiWriteToBootScript +// +// Description: Write SB necessary SW SMIs to boot script. +// +// Input: *BootScriptSave - Pointer to Boot Scrpit Save Protocol. +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SBSwSmiWriteToBootScript ( + IN AMI_S3_SAVE_PROTOCOL *BootScriptSave ) +{ + + UINT8 Value8; + + // Generate an ACPI Enable SMI when S3 resuming. + Value8 = SW_SMI_ACPI_ENABLE; + BOOT_SCRIPT_S3_IO_WRITE_MACRO( BootScriptSave, \ + EfiBootScriptWidthUint8, \ + SW_SMI_IO_ADDRESS, \ + 1, \ + &Value8 ); + + // Generate a Software SMI to enable SB patched codes when S3 resuming. + Value8 = SW_SMI_SB_ACPI_S3; + BOOT_SCRIPT_S3_IO_WRITE_MACRO( BootScriptSave, \ + EfiBootScriptWidthUint8, \ + SW_SMI_IO_ADDRESS, \ + 1, \ + &Value8); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBGen_WriteBootScript +// +// Description: This writes the PIRQ to boot script before booting. +// +// Input: *BootScriptSave - Pointer to Boot Scrpit Save Protocol. +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SBGen_WriteBootScript ( + IN AMI_S3_SAVE_PROTOCOL *BootScriptSave ) +{ + UINTN i; + UINT32 Value32; + + //Porting required: Write Boot Script + for (i = 0; i < NUM_SB_PCI_REG_SAVE; ++i) { + gPciRootBridgeIo->Pci.Read( gPciRootBridgeIo, \ + gSBRegsSaveTbl[i].Width, + gSBRegsSaveTbl[i].Address, + 1, + &Value32 ); + Value32 &= gSBRegsSaveTbl[i].Mask; + BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO( BootScriptSave, \ + gSBRegsSaveTbl[i].Width, \ + gSBRegsSaveTbl[i].Address, \ + 1, \ + &Value32 ); + } + + SBSwSmiWriteToBootScript(BootScriptSave); + + return EFI_SUCCESS; +} + +#if SB_RESET_PPI_SUPPORT +#if defined CAPSULE_SUPPORT && CAPSULE_SUPPORT == 1 +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_S3InsteadOfWarmResetCallBack +// +// Description: This function calls registered callbacks for S3 RTC/Timer +// (WarmBoot) eLink. +// +// Input: None +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_S3InsteadOfWarmResetCallBack (VOID) +{ + UINTN i; + + for (i = 0; SbS3InsteadOfWarmResetCallBackList[i] != NULL; i++) + SbS3InsteadOfWarmResetCallBackList[i](); +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_S3InsteadOfWarmReset +// +// Description: This function puts system into ACPI S3 State. +// if token ENABLE_RTC_ONE_SECOND_WAKEUP = 1, then it setups RTC +// 1 second alarm as well. +// +// Input: None +// +// Output: None, system will enter ACPI S3 State. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_S3InsteadOfWarmReset (VOID) +{ +#if ENABLE_RTC_ONE_SECOND_WAKEUP + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + BOOLEAN InBCD = TRUE; + + // Determine if RTC is in BCD mode + if ( READ_IO8_RTC(0x0b) & 0x4 ) InBCD = FALSE; // Bit 2 + + // Wait for time update to complete before reading the values, + // while bit 7 is set the time update is in progress. + while( READ_IO8_RTC(0x0a) & 0x80 ); + + // Read current hour, minute, second + Hour = READ_IO8_RTC(0x04); // Hours + Minute = READ_IO8_RTC(0x02); // Minutes + Second = READ_IO8_RTC(0x00); // Seconds + + // Convert second to decimal from BCD and increment by 1 + if (InBCD) Second = (Second >> 4) * 10 + (Second & 0x0F); + Second += 2; + + if (Second > 59) { + Second -= 60; + if (InBCD) Minute = (Minute >> 4) * 10 + (Minute & 0x0F); + Minute++; + if (Minute > 59){ + Minute = 0; + if (InBCD) Hour = (Hour >> 4) * 10 + (Hour & 0x0F); + Hour++; + // Check 24 hour mode/12 hour mode, Bit1 1=24hour else 12 hour + if ( READ_IO8_RTC(0x0b) & 0x2 ) { + if(Hour > 23) Hour = 0; + } else { + if(Hour > 11) Hour = 0; + } + + if (InBCD) Hour = Hour % 10 + ( (Hour / 10) << 4 ) ; + } + + if (InBCD) Minute = Minute % 10 + ( (Minute / 10) << 4 ) ; + } + + // Convert from decimal to BCD + if (InBCD) Second = Second % 10 + ( (Second / 10) << 4 ) ; + + // Set the alarm + WRITE_IO8_RTC(0x05, Hour); // Hours Alarm + WRITE_IO8_RTC(0x03, Minute); // Minutes Alarm + WRITE_IO8_RTC(0x01, Second); // Seconds Alarm + + // [EIP119703]> + // Clear date alarm. + WRITE_IO8_RTC(0x0D, READ_IO8_RTC(0x0D) & BIT07); + // <[EIP119703] + + // Enable the alarm + SET_IO8_RTC(0x0b, 0x20); // Bit 5 + + if (READ_IO16_PM(ACPI_IOREG_PM1_STS) & 0x400) { + READ_IO8_RTC(0x8C); + WRITE_IO16_PM(ACPI_IOREG_PM1_STS, 0x400); // 0x00 + } + + // Set RTC_EN bit in PM1_EN to wake up from the alarm + SET_IO16_PM(ACPI_IOREG_PM1_EN, 0x400 ); // 0x02 +#endif + + // Do any specific porting if needed. + SBLib_S3InsteadOfWarmResetCallBack(); + + // Enable Sleep SMI for all S3 sleep SMI callback functions. + SET_IO32_PM(ACPI_IOREG_SMI_EN, BIT04); // 0x30 + // Triger S3 sleep callback functions. + RW_IO32_PM(ACPI_IOREG_PM1_CNTL, 0x1400, 0x1c00 ); // 0x04 + SET_IO32_PM(ACPI_IOREG_PM1_CNTL, 0x2000 ); // 0x04 +} +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------------------- +// Procedure: SB_Shutdown +// Description: This function Shuts the system down (S5) +// +// Input: VOID +// +// Output: VOID +// +//----------------------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SB_Shutdown(VOID) +{ + //Check if Sleep SMI is enabled we will disable it. + RESET_IO16_PM(R_PCH_SMI_EN, BIT04); // 0x30 + + //Clear All PM Statuses + WRITE_IO16_PM(R_PCH_ACPI_PM1_STS, \ + READ_IO16_PM(R_PCH_ACPI_PM1_STS)); // 0x00 + + //Go to S5 + SET_IO16_PM(R_PCH_ACPI_PM1_CNT, 0x0f << 10); // 0x04 + + EFI_DEADLOOP() +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ClearGPIOResetSelect +// +// Description: Intel PCH Specification update rev 1.02, +// Document Changes 24. Update sec 19.5 +// 19.5 Addttional Consideration, Step 2 +// System BIOS is recommended to clear "GPIO Reset Select" +// registers [GP_RST_SEL1(GPIOBASE + offset 60h), GP_RST_SEL2 +// (GPIOBASE + offset 64h), GP_RST_SEL3(GPIOBASE + offset 68h) +// before issuing a hard or global reset unless specially +// requested by the platform designer. +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ClearGPIOResetSelect(VOID) +{ + WRITE_IO32 (GPIO_BASE_ADDRESS + GP_IOREG_GP_RST_SEL1, BIT30); // 0x60 + WRITE_IO32 (GPIO_BASE_ADDRESS + GP_IOREG_GP_RST_SEL2, BIT30); // 0x64 + WRITE_IO32 (GPIO_BASE_ADDRESS + GP_IOREG_GP_RST_SEL3, BIT30); // 0x68 +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SbLib_RunTimeResetCallback +// +// Description: Dispatch E-Link SbRuntimeResetElinkList. +// +// Input: IN EFI_RESET_TYPE ResetType +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +SbLib_RunTimeResetCallback( + IN EFI_RESET_TYPE ResetType + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN i; + + for (i = 0; SbRunResetCallbackList[i] != NULL; i++) + Status = SbRunResetCallbackList[i](ResetType); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_ResetSystem +// +// Description: This function is the reset call interface function published +// by the reset PPI +// +// Input: ResetType - Type of reset to be generated +// +// Output: SYSTEM RESET +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_ResetSystem ( + IN EFI_RESET_TYPE ResetType ) +{ + UINT8 OutputData; + UINT32 Data32; + UINT16 Data16; +#if defined CAPSULE_SUPPORT && CAPSULE_SUPPORT == 1 + EFI_GUID SbWarmResetGuid = SB_WARM_RESET_GUID; + CHAR16 SbWarmResetVar[] = SB_WARM_RESET_VARIABLE; + UINT32 SbWarmResetFlag = SB_WARM_RESET_TAG; + EFI_STATUS Status = EFI_SUCCESS; + EFI_GUID gCapsuleVendorGuid = EFI_CAPSULE_AMI_GUID; + EFI_PHYSICAL_ADDRESS IoData; + UINTN Size = sizeof(EFI_PHYSICAL_ADDRESS); +#endif + + SbLib_RunTimeResetCallback(ResetType); + + switch (ResetType) { + case EfiResetWarm: +#if defined CAPSULE_SUPPORT && CAPSULE_SUPPORT == 1 + if (pRS->GetVariable(CAPSULE_UPDATE_VAR,&gCapsuleVendorGuid, NULL, &Size, &IoData) == EFI_SUCCESS) { + Status = pRS->SetVariable( SbWarmResetVar, \ + &SbWarmResetGuid, \ + EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS, \ + sizeof(SbWarmResetFlag), \ + &SbWarmResetFlag ); + + SBLib_S3InsteadOfWarmReset(); + return; + } +#endif + WRITE_IO8 (R_PCH_RST_CNT, V_PCH_RST_CNT_SOFTSTARTSTATE); + OutputData = V_PCH_RST_CNT_SOFTRESET; + break; + + case EfiResetCold: + WRITE_IO8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDSTARTSTATE); + // [EIP81593]> +#if defined COLD_RESET_WITH_POWER_CYCLE && \ + COLD_RESET_WITH_POWER_CYCLE == 1 + OutputData = V_PCH_RST_CNT_FULLRESET; +#else + OutputData = V_PCH_RST_CNT_HARDRESET; +#endif + // <[EIP81593] + break; + + case EfiResetShutdown: + // + // Firstly, ACPI decode must be enabled + // + SET_PCI8_SB(R_PCH_LPC_ACPI_CNT, B_PCH_LPC_ACPI_CNT_ACPI_EN); + + // + // Then, GPE0_EN should be disabled to avoid any GPI waking up the system from S5 + // + Data16 = 0; + + WRITE_IO32_PM(R_PCH_ACPI_GPE0a_EN, Data16); + WRITE_IO16_PM(R_PCH_ACPI_GPE0b_EN, Data16); + + // + // Secondly, PwrSts register must be cleared + // + // Write a "1" to bit[8] of power button status register at + // (PM_BASE + PM1_STS_OFFSET) to clear this bit + // + Data16 = B_PCH_SMI_STS_PM1_STS_REG; + WRITE_IO16_PM(R_PCH_ACPI_PM1_STS, Data16); + + // + // Finally, transform system into S5 sleep state + // + Data32 = READ_IO32_PM(R_PCH_ACPI_PM1_CNT); + Data32 &= ~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN); + Data32 |= V_PCH_ACPI_PM1_CNT_S5; + WRITE_IO32_PM(R_PCH_ACPI_PM1_CNT, Data32); + Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN; + WRITE_IO32_PM(R_PCH_ACPI_PM1_CNT, Data32); + + EFI_DEADLOOP () + + default: + return; + } + + WRITE_IO8 (R_PCH_RST_CNT, OutputData); + // + // Waiting for system reset + // + EFI_DEADLOOP () +} + +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_ExtResetSystem +// +// Description: This function is the extended reset call interface function +// provided by SB. +// +// Input: ResetType - The extended type of reset to be generated +// +// Output: SYSTEM RESET +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_ExtResetSystem ( + IN SB_EXT_RESET_TYPE ResetType ) +{ + UINT16 GpioBase; + UINT8 OutputData; + EFI_STATUS Status = EFI_SUCCESS; + + GpioBase = READ_PCI16_SB (R_PCH_LPC_GPIO_BASE) & B_PCH_LPC_GPIO_BASE_BAR; + + // Issue some delay before system reset. +#if SB_STALL_PPI_SUPPORT + Status = CountTime(4000, PM_BASE_ADDRESS); // 1ms +#endif + + // Disable All SMI Enables, include the Global SMI. + WRITE_IO32_PM(ACPI_IOREG_SMI_EN, 0); // 0x30 + + switch (ResetType) { + case SbResetFull: + case SbResetGlobal: + WRITE_IO32 ((GpioBase + R_PCH_GP_RST_SEL), 0); + WRITE_IO32 ((GpioBase + R_PCH_GP_RST_SEL2), 0); + WRITE_IO32 ((GpioBase + R_PCH_GP_RST_SEL3), 0); + + if (ResetType == SbResetGlobal) + SET_PCI32_SB(R_PCH_LPC_PMIR, B_PCH_LPC_PMIR_CF9GR); + + OutputData = V_PCH_RST_CNT_FULLRESET; + break; + + default: + return; + } + + WRITE_IO8 (R_PCH_RST_CNT, OutputData); + + // We should never get this far + EFI_DEADLOOP(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: StopUsb +// +// Description: This routine stops all USB controller action. +// +// Input: Bus - The PCI bus number for the USB controller +// Dev - The PCI device number for the USB controller +// Fun - The PCI function number for the USB controller +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID StopUsb ( + IN UINT8 Bus, + IN UINT8 Dev, + IN UINT8 Fun ) +{ +//#### UINT32 MmioBase; +//#### UINT16 IoBase; +//#### UINT16 TimeOut = 0x1000; + +//#### if (READ_PCI32(Bus, Dev, Fun, 0) != 0xffffffff) { +//#### if ((READ_PCI32(Bus, Dev, Fun, 4) & 0x3) == 0) return; +//#### if (READ_PCI8(Bus, Dev, Fun, USB_REG_PI) == 0x20) { // USB 2.0 +//#### WRITE_PCI8(Bus, Dev, Fun, USB20_REG_LEGSUP_EXTCS, 0); // 0x6C +//#### MmioBase = READ_PCI32(Bus, Dev, Fun, USB20_REG_MEM_BASE_ADDR); +//#### RESET_MEM32(MmioBase | 0x20, 1); +//#### while (READ_MEM32(MmioBase | 0x20) & 1) { +//#### TimeOut--; +//#### if (TimeOut == 0) break; +//#### } +//#### } else { // USB 1.1 +//#### WRITE_PCI8(Bus, Dev, Fun, USB_REG_LEGSUP, 0); // 0xC0 +//#### IoBase = READ_PCI32(Bus, Dev, Fun, USB_REG_BASE_ADDR) & 0xfffe; +//#### RESET_IO16(IoBase, 1); +//#### while (IoRead16(IoBase) & 1) { +//#### TimeOut--; +//#### if (TimeOut == 0) break; +//#### } +//#### } +//#### } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: UsbS02SxWorkaround +// +// Description: PCH BIOS Spec Rev 0.5.0, Section 12.10.1 +// Additional Programming Requirements prior to enter S4/S5 +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +UsbS02SxWorkaround ( + VOID + ) +{ + UINT8 Index; + UINTN EhciPciRegBase; + UINT32 UsbBar; + UINT16 CmdReg; + UINT16 PowerState; + USB_CONTROLLER EhciControllersMap[PchEhciControllerMax] = { + { + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI + }, + { + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2 + } + }; + + /// + /// System BIOS must execute the following steps prior to enter S4/S5. + /// + for (Index = 0; Index < GetPchEhciMaxControllerNum (); Index++) { + /// + /// Step 1 + /// Read "Memory Base Address (MEM_BASE) Register" of D26/D29:F0 + /// + EhciPciRegBase = MmPciAddress (PCIEX_BASE_ADDRESS, 0, EhciControllersMap[Index].Device, EhciControllersMap[Index].Function, 0); + UsbBar = MmioRead32 (EhciPciRegBase + R_PCH_EHCI_MEM_BASE); + CmdReg = MmioRead16 (EhciPciRegBase + R_PCH_EHCI_COMMAND_REGISTER); + PowerState = MmioRead16 (EhciPciRegBase + R_PCH_EHCI_PWR_CNTL_STS); + + if (UsbBar != 0xFFFFFFFF) { + /// + /// Check if the Ehci device is in D3 power state + /// + if ((PowerState & B_PCH_EHCI_PWR_CNTL_STS_PWR_STS) == V_PCH_EHCI_PWR_CNTL_STS_PWR_STS_D3) { + /// + /// Step 2 + /// Set "Power State" bit of PWR_CNTL_STS register, D26/D29:F0:54h [1:0] = 0h + /// + MmioWrite16 (EhciPciRegBase + R_PCH_EHCI_PWR_CNTL_STS, (PowerState &~B_PCH_EHCI_PWR_CNTL_STS_PWR_STS)); + /// + /// Step 3 + /// Write back the value from step 1 to the "Memory Base Address (MEM_BASE) Register" of D26/D29:F0 + /// + MmioWrite32 (EhciPciRegBase + R_PCH_EHCI_MEM_BASE, UsbBar); + /// + /// Step 4 + /// Enable "Memory Space Enable (MSE)" bit, set D26/D29:F0:04h [1] = 1b. + /// + SET_MEM16 ( + EhciPciRegBase + R_PCH_EHCI_COMMAND_REGISTER, + (UINT16) (B_PCH_EHCI_COMMAND_MSE) + ); + } + /// + /// Step 5 + /// Clear "Asynchronous Schedule Enable" and "Periodic Schedule Enable" bits, if "Run/Stop (RS)" bit, MEM_BASE + offset 20h [0] = 1b. + /// Proceed to steps below if "Run/Stop (RS)" bit, MEM_BASE + offset 20h [0] = 0b. + /// + if (!(MmioRead32 (UsbBar + R_PCH_EHCI_USB2CMD) & B_PCH_EHCI_USB2CMD_RS)) { + RESET_MEM32 (UsbBar + R_PCH_EHCI_USB2CMD, (UINT32)(B_PCH_EHCI_USB2CMD_ASE | B_PCH_EHCI_USB2CMD_PSE)); + SET_MEM32 (UsbBar + R_PCH_EHCI_USB2CMD, B_PCH_EHCI_USB2CMD_RS); + } + /// + /// Step 6 + /// If "Port Enabled/Disabled" bit of Port N Status and Control (PORTSC) Register is set, MEM_BASE + 64h [2] = 1b, + /// proceed steps below else continue with S4/S5. + /// + if ((MmioRead32 (UsbBar + R_PCH_EHCI_PORTSC0) & R_PCH_EHCI_PORTSC0_PORT_EN_DIS)) { + /// + /// Step 7 + /// Ensure that "Suspend" bit of Port N Status and Control (PORTSC) Register is set, MEM_BASE + 64h [7] = 1b. + /// + if (!(MmioRead32 (UsbBar + R_PCH_EHCI_PORTSC0) & R_PCH_EHCI_PORTSC0_SUSPEND)) { + SET_MEM32 (UsbBar + R_PCH_EHCI_PORTSC0, R_PCH_EHCI_PORTSC0_SUSPEND); + } + /// + /// Step 8 + /// Set delay of 25ms + /// + CountTime((25 * 1000), PM_BASE_ADDRESS); + /// + /// Step 9 + /// Clear "Run/Stop (RS)" bit, MEM_BASE + offset 20h [0] = 0b. + /// + RESET_MEM32 (UsbBar + R_PCH_EHCI_USB2CMD, (UINT32)(B_PCH_EHCI_USB2CMD_RS)); + } + /// + /// If the EHCI device is in D3 power state before executing this WA + /// + if ((PowerState & B_PCH_EHCI_PWR_CNTL_STS_PWR_STS) == V_PCH_EHCI_PWR_CNTL_STS_PWR_STS_D3) { + /// + /// Restore PCI Command Register + /// + MmioWrite16 (EhciPciRegBase + R_PCH_EHCI_COMMAND_REGISTER, CmdReg); + /// + /// Set "Power State" bit of PWR_CNTL_STS register to D3 state, D26/D29:F0:54h [1:0] = 3h + /// + MmioWrite16 (EhciPciRegBase + R_PCH_EHCI_PWR_CNTL_STS, PowerState); + } + /// + /// Step 10 + /// Continue with S4/S5 + /// + } + } +} + // [EIP83075]> +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: XhciS5Workaround +// +// Description: PCH BIOS Spec Rev 0.7.0, Section 13.5 +// Additional xHCI Controller Configurations Prior to Entering S5 +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID XhciS5Workaround ( VOID ) +{ + UINT32 XhciMmioBase; + // + // Check if XHCI controller is enabled + // + if ((READ_MEM32_RCRB(R_PCH_RCRB_FUNC_DIS) & B_PCH_RCRB_FUNC_DIS_XHCI) != 0) { + return ; + } + // + // System BIOS must execute the following steps for all steppings prior to S5 + // + // + XhciMmioBase = READ_PCI32( DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_XHCI, \ + PCI_FUNCTION_NUMBER_PCH_XHCI, \ + R_PCH_XHCI_MEM_BASE + ) & ~(0x0F); + + if (XhciMmioBase != 0) { + //Clear "Run/Stop (RS)" bit, + RESET_MEM32(XhciMmioBase + R_PCH_XHCI_USBCMD, B_PCH_XHCI_USBCMD_RS); + } + // Step 1 + // Set D3hot state - 11b + // + SET_PCI8( DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_XHCI, \ + PCI_FUNCTION_NUMBER_PCH_XHCI, \ + R_PCH_XHCI_PWR_CNTL_STS, \ + (BIT00 | BIT01) + ); + + // + // Step 2 + // Set "PME Enable" bit of PWR_CNTL_STS register, D20:F0:74h[8] = 1h + // + SET_PCI16( DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_XHCI, \ + PCI_FUNCTION_NUMBER_PCH_XHCI, \ + R_PCH_XHCI_PWR_CNTL_STS, \ + BIT08 + ); +} + // <[EIP83075] + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_BeforeShutdown +// +// Description: This routine will be called before shutdown or ACPI S5,(If +// S5 Sleep SMI is enabled. +// +// Input: None +// +// Output: None +// +// Notes: Porting required if any workaround is needed. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_BeforeShutdown (VOID) +{ + UINT8 DevNo; + UINT8 FunNo; + +//#### StopUsb( EUSB_BUS, EUSB_DEV, EUSB_FUN ); + + for (DevNo = 0; DevNo < 0x20 ; DevNo++) { + if (READ_PCI32(0, DevNo, 0, PCI_VID) != 0xffffffff) { + FunNo = (READ_PCI8(0, DevNo, 0, PCI_HDR) & 0x80) ? 8 : 1; + do { + FunNo--; + if (READ_PCI32(0, DevNo, FunNo, PCI_VID) != 0xffffffff) { + RESET_PCI16(0, DevNo, FunNo, PCI_CMD, 4); + } + } while (FunNo); + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_Shutdown +// +// Description: Shutdown the system (Enter soft-off/S5) +// +// Input: None +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_Shutdown (VOID) +{ + UINT16 Buffer16; + + // Clear ME wake status + ClearMeWakeSts(); + + UsbS02SxWorkaround(); + XhciS5Workaround(); // [EIP83075] + + // Disable Sleep SMI + RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x10); // 0x30 + + SBLib_BeforeShutdown(); + + // Clear power button status + Buffer16 = READ_IO16(PM_BASE_ADDRESS) | (UINT16)(1 << 8); + do { + WRITE_IO16(PM_BASE_ADDRESS, Buffer16); + for (Buffer16 = 0; Buffer16 < 0x100; Buffer16++) + WRITE_IO8(IO_DELAY_PORT, (UINT8)Buffer16); + Buffer16 = READ_IO16(PM_BASE_ADDRESS); + } while (Buffer16 & 0x100); + + // Enter soft-off/S5 + RW_IO16(PM_BASE_ADDRESS + ACPI_IOREG_PM1_CNTL, \ + (SLP_S5 | 8 ) << 10, 15 << 10); + + // We should never get this far + EFI_DEADLOOP(); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure:ClearMeWakeSts +// +// Description: Clear the ME wake up status. +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ClearMeWakeSts(VOID) +{ +// Mmio32(SB_RCBA, ICH_RCRB_PRSTS) |= BIT00; + SET_MEM8_RCRB(R_PCH_RCRB_PRSTS, BIT00); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: Enable_GbE_PME +// +// Description: Enable the Gigabit Ethernet Controller PME +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID Enable_GbE_PME(VOID) +{ + if (READ_PCI16_LAN(R_PCH_LAN_VENDOR_ID) != 0xffff) + { + if (GetPchSeries() == PchLp) { + WRITE_IO16_PM(ACPI_PCHLP_IOREG_GPE0_STS+0x0c, BIT13); + SET_IO16_PM(ACPI_PCHLP_IOREG_GPE0_EN+0x0c, BIT13); + } else { + WRITE_IO16_PM(ACPI_IOREG_GPE0_STS, BIT13); + SET_IO16_PM(ACPI_IOREG_GPE0_EN, BIT13); + } + SET_PCI16_LAN(R_PCH_LAN_PMCS, BIT08); + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: HighBitSet32 +// +// Description: Returns the bit position of the highest bit set in a 32-bit value. Equivalent +// to log2(x). +// +// Input: Operand - Operand The 32-bit operand to evaluate. +// +// Output: Position of the highest bit set in Operand if found. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + for (BitIndex = -1; Operand != 0; BitIndex++, Operand >>= 1); + return BitIndex; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetPowerOfTwo32 +// +// Description: Returns the value of the highest bit set in a 32-bit value. Equivalent to +// 1 << HighBitSet32(x). +// +// Input: Operand - Operand The 32-bit operand to evaluate. +// +// Output: Return 1 << HighBitSet32(Operand) +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ) +{ + if (Operand == 0) { + return 0; + } + + return 1ul << HighBitSet32 (Operand); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ChipsetFlashDeviceWriteEnable +// +// Description: This function is invoked to do any chipset specific +// operations, that are necessary when enabling the Flash Part +// for writing. +// +// Input: None +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ChipsetFlashDeviceWriteEnable (VOID) +{ +// UINT32 Data32; + + // + // Set BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 1b + // + RW_PCI8_SB(SB_REG_BIOS_CNTL, BIT00, BIT05); + + // + // PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling + // If the following steps are implemented: + // - Set the SMM_BWP bit (B0:D31:F0 Offset DCh [5]) = 1b + // - Follow the 1st recommendation in section 3.6 + // the BIOS Region can only be updated by following the steps bellow: + // - Once all threads enter SMM + // - Read memory location FED30880h OR with 00000001h, place the result in EAX, + // and write data to lower 32 bits of MSR 1FEh (sample code available) + // - Set BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 1b + // - Modify BIOS Region + // - Clear BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 0b + // - Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX, + // and write data to lower 32 bits of MSR 1FEh (sample code available) + // + + // + // Check if SMM_BWP bit and BLE bit are both set + // + if ((READ_PCI8_SB(SB_REG_BIOS_CNTL) & 0x22) == 0x22) { + // + // Read memory location FED30880h OR with 00000001h, place the result in EAX, + // and write data to lower 32 bits of MSR 1FEh (sample code available) + // + // EIP106353 >> + if ( !((ReadMsr (MSR_PLATFORM_INFO) & B_MSR_PLATFORM_INFO_PFAT_AVAIL) && + (ReadMsr (MSR_PLAT_FRMW_PROT_CTRL) & B_MSR_PLAT_FRMW_PROT_CTRL_EN)) ) { +// Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0); +// WriteMsr(0x1FE, Data32); + } + // EIP106353 << + } + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ChipsetFlashDeviceWriteDisable +// +// Description: This function is invoked to do any chipset specific +// operations, that are necessary when disabling the Flash Part +// for writing. +// +// Input: None +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ChipsetFlashDeviceWriteDisable (VOID) +{ +// UINT32 Data32; + + // + // Clear BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 0b + // + RESET_PCI8_SB(SB_REG_BIOS_CNTL, BIT00); + // + // Check if SMM_BWP bit and BLE bit are both set + // + if ((READ_PCI8_SB(SB_REG_BIOS_CNTL) & 0x22) == 0x22) { + // + // Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX, + // and write data to lower 32 bits of MSR 1FEh (sample code available) + // + // EIP106353 >> + if ( !((ReadMsr (MSR_PLATFORM_INFO) & B_MSR_PLATFORM_INFO_PFAT_AVAIL) && + (ReadMsr (MSR_PLAT_FRMW_PROT_CTRL) & B_MSR_PLAT_FRMW_PROT_CTRL_EN)) ) { +// Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0); +// WriteMsr (0x1FE, Data32); + } + // EIP106353 << + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// Procedure: BiosLockEnableSMIFlashHook +// +// Description: The procedure clears BIOSWR_STS after Enable Flash SWSMI, +// for prevent that AFU write operation fail when BIOS Lock +// is enabled. +// +// Input: UINT8 SwSmiNum +// UINT64 Buffer +// +// Output: UINT64 Buffer +// +// Returns: NONE +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +BiosLockEnableSMIFlashHook ( + IN UINT8 SwSmiNum, + IN OUT UINT64 Buffer +) +{ + if ((SwSmiNum != 0x20) || \ + ((READ_PCI8_SB(R_PCH_LPC_BIOS_CNTL) & B_PCH_LPC_BIOS_CNTL_BLE) == 0)) + return; + + // Clear BIOSWR_STS + SET_IO16_TCO(R_PCH_TCO1_STS, B_PCH_TCO1_STS_BIOSWR); + + // Clear TCO_STS + SET_IO16_PM(R_PCH_SMI_STS, B_PCH_SMI_STS_TCO); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBIsDefaultConfigMode +// +// Description: This function determines if the system should boot with the +// default configuration. +// +// Input: EFI_PEI_SERVICES - Pointer to the PEI services table +// EFI_PEI_READ_ONLY_VARIABLE2_PPI - Pointer to the Read +// Variable#2 PPI +// (The pointer can be used to read and enumerate existing NVRAM +// variables) +// +// Output: TRUE - Firmware will boot with default configuration. +// +// Notes: 1. If boot with default configuration is detected, default +// values for NVRAM variables are used. +// 2. Normally we have to check RTC power status or CMOS clear +// jumper status to determine whether the system should boot +// with the default configuration. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN SBIsDefaultConfigMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadVariablePpi ) +{ + UINT8 Buffer8; + + Buffer8 = READ_PCI8_SB(SB_REG_GEN_PMCON_3); // 0xA4 + return (Buffer8 & 4) ? TRUE : FALSE; +} + +#if SB_STALL_PPI_SUPPORT + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CountTime +// +// Description: This function delays for the number of micro seconds passed in +// +// Input: DelayTime - Number of microseconds(us) to delay +// BaseAddr - The I/O base address of the ACPI registers +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CountTime ( + IN UINTN DelayTime, + IN UINT16 BaseAddr ) // Only needs to be 16 bit for I/O address +{ +// The following code is to generate delay for specified amount of micro +// seconds using ACPI timer. + UINTN TicksNeeded; + UINT32 TimerValue; + UINT32 NewTimerValue; + UINTN OverFlow; + UINTN TheRest; + UINTN EndValue; + + // Set up timer to point to the ACPI Timer register + BaseAddr += ACPI_IOREG_PM1_TMR; // *** PORTING NEEDED + + // There are 3.58 ticks per us, so we have to convert the number of us + // passed in to the number of ticks that need to pass before the timer has + // expired convert us to Ticks, don't loose significant figures or as few + // as possible do integer math in ticks/tens of ns and then divide by 100 + // to get ticks per us + OverFlow = 0; + +//#### TheRest = TicksNeeded = (DelayTime * 358) /100; + TicksNeeded = DelayTime * 3; //(DelayTime * 3) + TicksNeeded += (DelayTime) / 2; //(DelayTime * 5)/10 + TicksNeeded += (DelayTime * 2) / 25; //(DelayTime * 8)/100 + TheRest = TicksNeeded; + + // 32 bits corresponds to approz 71 mins no delay should be that long + // otherwise get the number of times the counter will have to overflow + // to delay as long as needed + if (NUM_BITS_IN_ACPI_TIMER < MAX_ACPI_TIMER_BITS) { + OverFlow = TicksNeeded / (1 << NUM_BITS_IN_ACPI_TIMER); + TheRest = TicksNeeded % (1 << NUM_BITS_IN_ACPI_TIMER); + } + + // Read ACPI Timer + TimerValue = IoRead32( BaseAddr ); + + // Need to adjust the values based off of the start time + EndValue = TheRest + TimerValue; + + // Check for overflow on addition. possibly a problem + if (EndValue < TimerValue) { + OverFlow++; + } else { + if (NUM_BITS_IN_ACPI_TIMER < MAX_ACPI_TIMER_BITS) { + // Here make sure that EndValue is less than the max value + // of the counter + OverFlow += EndValue / (1 << NUM_BITS_IN_ACPI_TIMER); + EndValue = EndValue % (1 << NUM_BITS_IN_ACPI_TIMER); + } + } + + // Let the timer wrap around as many times as calculated + while (OverFlow) { + // read timer amd look to see if the new value read is less than + // the current timer value. if this happens the timer overflowed + NewTimerValue = IoRead32(BaseAddr); + + if (NewTimerValue < TimerValue) OverFlow--; + + TimerValue = NewTimerValue; + } + + // Now wait for the correct number of ticks that need to occur after + // all the needed overflows + while (EndValue > TimerValue) { + NewTimerValue = IoRead32(BaseAddr); + + // check to see if the timer overflowed. if it did then + // the time has elapsed. Because EndValue should be greater than + // TimerValue + if (NewTimerValue < TimerValue) break; + + TimerValue = NewTimerValue; + } + + return EFI_SUCCESS; +} + + +#endif + +//--------------------------------------------------------------------------- + +#if CMOS_MANAGER_SUPPORT +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ReadWriteCmosBank2 +// +// Description: This function is used to access addresses in the CMOS +// register range (0x80-0xff), for PEI and DXE boot phases. +// +// Input: **PeiServices - PEI Services table pointer +// (NULL in DXE phase) +// AccessType - ReadType or WriteType to specify the +// type of access +// CmosRegister - The CMOS register to access +// *CmosParameterValue - Pointer to the data variable to be +// accessed +// +// Output: EFI_STATUS (return value) +// EFI_SUCCESS - The access operation was successfull. +// Otherwise - A valid EFI error code is returned. +// +// Modified: None +// +// Referrals: IoRead8, IoWrite8 +// +// Notes: This function is used when a translation from logical address +// to index port value is required. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ReadWriteCmosBank2 ( + IN EFI_PEI_SERVICES **PeiServices, // NULL in DXE phase + IN CMOS_ACCESS_TYPE AccessType, + IN UINT16 CmosRegister, + IN OUT UINT8 *CmosParameterValue ) +{ + if ((CmosRegister < 0x80) || (CmosRegister > 0xff)) + return EFI_INVALID_PARAMETER; + + // Some chipsets require tranlation from the logical CMOS address to a + // physical CMOS index port value. However, other chipsets do not require + // a translation and the index/data port can be directly used for + // accessing the second bank. + + IoWrite8( CMOS_IO_EXT_INDEX, (UINT8)CmosRegister ); + + if (AccessType == ReadType) { + *CmosParameterValue = IoRead8( CMOS_IO_EXT_DATA ); + } else { + IoWrite8( CMOS_IO_EXT_DATA, *CmosParameterValue ); + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbGetRtcPowerStatus +// +// Description: This function is checked CMOS battery is good or not. +// +// Input: **PeiServices - PEI Services table pointer (NULL in DXE phase) +// +// Output: BOOLEAN +// TRUE - The CMOS is battery is good. +// FALSE - The CMOS is battery is bad. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN SbGetRtcPowerStatus ( + IN EFI_PEI_SERVICES **PeiServices ) +{ + return (READ_PCI8_SB(SB_REG_GEN_PMCON_3) & 4) ? FALSE : TRUE; // 0xA4 +} + +#endif // #if CMOS_MANAGER_SUPPORT + //Improve alternate access mode >> +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SwitchAlternateAccessMode +// +// Description: Enable or disable Alternate Access Mode. +// +// Input: TRUE: Enable Alternate Access Mode +// FALSE: Disable Alternate Access Mode +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SwitchAlternateAccessMode +( + BOOLEAN Switch +) +{ + if (Switch) { + do { + // Enable Alternate Access Mode + SET_MEM32_RCRB(R_PCH_RCRB_GCS, B_PCH_RCRB_GCS_AME); + } while((READ_MEM32_RCRB(R_PCH_RCRB_GCS) & B_PCH_RCRB_GCS_AME) == 0); + } else { + do { + // Disable Alternate Access Mode + RESET_MEM32_RCRB(R_PCH_RCRB_GCS, B_PCH_RCRB_GCS_AME); + } while(READ_MEM32_RCRB(R_PCH_RCRB_GCS) & B_PCH_RCRB_GCS_AME); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ReadPort70h +// +// Description: Read port 70h. +// +// Input: None +// +// Output: Data of port 70h. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 ReadPort70h ( VOID ) +{ + UINT8 Port70h; + + SwitchAlternateAccessMode (TRUE); + + Port70h = IoRead8(RTC_INDEX_REG); + + SwitchAlternateAccessMode (FALSE); + + return Port70h; +} //Improve alternate access mode << + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ReadCmos +// +// Description: This function reads one byte from CMOS register addressed by Index +// +// Input: UINT8 Index +// +// Output: UINT8 - read value +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 ReadCmos( + IN UINT8 Index +) +{ + // Read bit 7 (NMI setting). + UINT8 NMI = 0; + volatile UINT8 Value; + BOOLEAN IntState = CPULib_GetInterruptState(); + UINT8 RtcIndexPort; + UINT8 RtcDataPort; + + CPULib_DisableInterrupt(); + + if (Index < 0x80) { + // Standard CMOS + RtcIndexPort = RTC_INDEX_REG; + RtcDataPort = RTC_DATA_REG; + + if (Index < 0x80) //Improve alternate access mode >> + // Save current NMI_EN. + NMI = ReadPort70h() & RTC_NMI_MASK; //Improve alternate access mode << + + } else { + // Upper CMOS + RtcIndexPort = CMOS_IO_EXT_INDEX; + RtcDataPort = CMOS_IO_EXT_DATA; + } + + Index &= ~RTC_NMI_MASK; + + IoWrite8(RtcIndexPort, Index | NMI); + Value = IoRead8(RtcDataPort); // Read register. + + if (IntState) CPULib_EnableInterrupt(); + + return (UINT8)Value; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: WriteCmos +// +// Description: This function writes value to CMOS register addressed by Index +// +// Input: UINT8 Index - CMOS register index +// UINT8 Value - value to write +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID WriteCmos( + IN UINT8 Index, + IN UINT8 Value +) +{ + // Read bit 7 (NMI setting). + UINT8 NMI = 0; + BOOLEAN IntState = CPULib_GetInterruptState(); + UINT8 RtcIndexPort; + UINT8 RtcDataPort; + + CPULib_DisableInterrupt(); + + if (Index < 0x80) { + // Standard CMOS + RtcIndexPort = RTC_INDEX_REG; + RtcDataPort = RTC_DATA_REG; + + //Improve alternate access mode >> + // Save current NMI_EN. + NMI = ReadPort70h() & RTC_NMI_MASK; + //Improve alternate access mode << + } else { + // Upper CMOS + RtcIndexPort = CMOS_IO_EXT_INDEX; + RtcDataPort = CMOS_IO_EXT_DATA; + } + + Index &= ~RTC_NMI_MASK; + + IoWrite8(RtcIndexPort, Index | NMI); + IoWrite8(RtcDataPort, Value); // Write Register. + + if (IntState) CPULib_EnableInterrupt(); +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbLib_GetSmiState +// +// Description: This function returns SMI state +// +// Input: None +// +// Output: TRUE - SMI enabled, FALSE - SMI disabled +// +// Note: This function must work at runtime. Do not use boot time +// services/protocols. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN SbLib_GetSmiState (VOID) +{ +#if SMM_SUPPORT + static BOOLEAN OriginalSmiState = FALSE; + static BOOLEAN HadBeenCame = FALSE; + volatile BOOLEAN SmiState = (READ_IO32_PM(ACPI_IOREG_SMI_EN) & 1) ? \ + TRUE : FALSE; + + if (HadBeenCame && SmiState) HadBeenCame = FALSE; + + if (HadBeenCame) { + SmiState = OriginalSmiState; + } else { + OriginalSmiState = SmiState; + HadBeenCame = TRUE; + } + + return SmiState; +#else + return FALSE; +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbLib_SmiDisable +// +// Description: This function disables SMI +// +// Input: None +// +// Output: None +// +// Note: This function should be used ONLY in critical parts of code. +// This function must work at runtime. Do not use boot time +// services/protocols +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SbLib_SmiDisable (VOID) +{ +#if SMM_SUPPORT + RESET_IO32_PM(ACPI_IOREG_SMI_EN, 3); // 0x30 +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbLib_SmiEnable +// +// Description: This function enables SMI +// +// Input: None +// +// Output: None +// +// Note: This function should be used ONLY in critical parts of code. +// This function must work at runtime. Do not use boot time +// services/protocols +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SbLib_SmiEnable (VOID) +{ + +#if SMM_SUPPORT + SET_IO32_PM(ACPI_IOREG_SMI_EN, 2); // 0x30 + SET_IO32_PM(ACPI_IOREG_SMI_EN, 1); // 0x30 +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CspLibCheckPowerLoss +// +// Description: This function is PM Specific function to check and Report to +// the System Status Code - CMOS Battary and Power Supply Power +// loss/failure. Also it responcibe of clearing PM Power Loss +// Statuses +// +// Input: None +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CspLibCheckPowerLoss (VOID) +{ + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbLib_SetLpcDeviceDecoding +// +// Description: This function sets LPC Bridge Device Decoding +// +// Input: *LpcPciIo - Pointer to LPC PCI IO Protocol +// Base - I/O base address, if Base is 0 means disabled the +// decode of the device +// DevUid - The device Unique ID +// Type - Device Type, please refer to AMISIO.h +// +// Output: EFI_STATUS +// EFI_SUCCESS - Set successfully. +// EFI_UNSUPPORTED - There is not proper Device Decoding +// register for the device UID. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SbLib_SetLpcDeviceDecoding ( + IN EFI_PCI_IO_PROTOCOL *LpcPciIo, + IN UINT16 Base, + IN UINT8 DevUid, + IN SIO_DEV_TYPE Type ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + + // Porting Required + UINT16 ComRng[] = { 0x3f8, 0x2f8, 0x220, 0x228, \ + 0x238, 0x2e8, 0x338, 0x3e8, 0}; + UINT16 LptRange[] = { 0x378, 0x278, 0x3bc, 0}; + UINT16 FpcRange[] = { 0x3f0, 0x370, 0}; + UINT16 IoRangeMask16 = 0xffff; + UINT16 IoRangeSet16 = 0; + UINT16 IoEnMask16 = 0xffff; + UINT16 IoEnSet16 = 0; + UINT8 i; + + switch (Type) { + // FDC Address Range + case (dsFDC) : + if (Base == 0) IoEnMask16 &= ~BIT03; + else { + for (i = 0; (FpcRange[i] != 0) && (FpcRange[i] != Base); i++); + if (FpcRange[i]) { + IoEnSet16 |= BIT03; + IoRangeMask16 &= ~BIT12; + IoRangeSet16 |= (i << 12); + } + else return EFI_UNSUPPORTED; + } + break; + + // LPT Address Range + case (dsLPT) : + if (Base == 0) IoEnMask16 &= ~BIT02; + else { + for (i = 0; (LptRange[i] != 0) && (LptRange[i] != Base); i++); + if (LptRange[i]) { + IoEnSet16 |= BIT02; + IoRangeMask16 &= ~(BIT09 | BIT08); + IoRangeSet16 |= (i << 8); + } else return EFI_UNSUPPORTED; + } + break; + + // COM x Address Range + case (dsUART) : + if (Base == 0) { + switch (DevUid) { + case 0 : + IoEnMask16 &= ~BIT00; + break; + case 1 : + IoEnMask16 &= ~BIT01; + break; + case 2 : + break; + case 3 : + break; + default: + break; + } + } else { + if (DevUid < 2) { + for (i = 0; (ComRng[i] != 0) && (ComRng[i] != Base); i++); + if (ComRng[i]) { + if (DevUid) { + IoEnSet16 |= BIT01; + IoRangeMask16 &= ~(BIT06 | BIT05 | BIT04); + IoRangeSet16 |= (i << 4); + } else { + IoEnSet16 |= BIT00; + IoRangeMask16 &= ~(BIT02 | BIT01 | BIT00); + IoRangeSet16 |= i; + } + } else return EFI_UNSUPPORTED; + } else { + SbLib_SetLpcGenericDecoding( LpcPciIo, \ + Base , \ + 8, \ + TRUE ); + } + } + break; + + // KBC Address Enable + case (dsPS2K) : + case (dsPS2M) : + case (dsPS2CK) : + case (dsPS2CM) : + if (Base == 0) IoEnMask16 &= ~BIT10; + else IoEnSet16 |= BIT10; + break; + + // Game Port Address Enable + case (dsGAME) : + if (Base == 0) IoEnMask16 &= ~(BIT09 | BIT08); + else { + if (Base == 0x200) { + IoEnSet16 |= BIT08; + } else { + if (Base == 0x208) IoEnSet16 |= BIT09; + else return EFI_UNSUPPORTED; + } + } + break; + + // Other Address Enable + case (0xff) : + switch (Base) { + case (0x2e) : + IoEnSet16 |= BIT12; + break; + case (0x4e) : + IoEnSet16 |= BIT13; + break; + case (0x62) : + case (0x63) : + case (0x64) : + case (0x65) : + case (0x66) : + IoEnSet16 |= BIT11; + break; + case (0) : + return EFI_UNSUPPORTED; + break; + default : + SbLib_SetLpcGenericDecoding( LpcPciIo, \ + Base , \ + 4, \ + TRUE ); + break; + } + +//#### if (Base == 0x2e) IoEnSet16 |= BIT12; +//#### else { +//#### if (Base == 0x4e) IoEnSet16 |= BIT13; +//#### else { +//#### if (Base) SbLib_SetLpcGenericDecoding( LpcPciIo, \ +//#### Base , \ +//#### 4, \ +//#### TRUE ); +//#### else return EFI_UNSUPPORTED; +//#### } +//#### } + + break; + + default : + return EFI_UNSUPPORTED; + } + + RW_PCI16_SB(SB_REG_LPC_IO_DEC, IoRangeSet16, ~IoRangeMask16); // 0x80 + RW_PCI16_SB(SB_REG_LPC_EN, IoEnSet16, ~IoEnMask16); // 0x82 + // Porting End + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbLib_SetLpcGenericDecoding +// +// Description: This function sets LPC Bridge Generic Decoding +// +// Input: *LpcPciIo - Pointer to LPC PCI IO Protocol +// Base - I/O base address +// Length - I/O Length +// Enabled - Enable/Disable the generic decode range register +// +// Output: EFI_STATUS +// EFI_SUCCESS - Set successfully. +// EFI_UNSUPPORTED - This function is not implemented or the +// Length more than the maximum supported +// size of generic range decoding. +// EFI_INVALID_PARAMETER - the Input parameter is invalid. +// EFI_OUT_OF_RESOURCES - There is not available Generic +// Decoding Register. +// EFI_NOT_FOUND - the generic decode range will be disabled +// is not found. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SbLib_SetLpcGenericDecoding ( + IN EFI_PCI_IO_PROTOCOL *LpcPciIo, + IN UINT16 Base, + IN UINT16 Length, + IN BOOLEAN Enable ) +{ + // Porting Required + UINT32 IoGenDecode32; + UINT16 IoGenDecIndex; + UINT16 Buffer16; + UINT8 Bsf8 = 0; + UINT8 Bsr8 = 0; + + if (Length > 0x100) return EFI_UNSUPPORTED; + + if (Length == 0) return EFI_INVALID_PARAMETER; + + if (Length < 4) Length = 4; + + // Read I/O Generic Decodes Register. + for (IoGenDecIndex = 0; IoGenDecIndex < 4; IoGenDecIndex++) { + IoGenDecode32 = READ_PCI32_SB(SB_REG_GEN1_DEC + IoGenDecIndex * 4); + if (Enable) { + if ((IoGenDecode32 & 1) == 0) break; + } else { + if (((IoGenDecode32 & 0xfffc) == Base) && (IoGenDecode32 & 1)) { + IoGenDecode32 = 0; // Disable & clear the base/mask fields + break; + } + } + } + + if (Enable) { + if (IoGenDecIndex == 4) return EFI_OUT_OF_RESOURCES; + + Buffer16 = Length; + while ((Buffer16 % 2) == 0) { + Buffer16 /= 2; + Bsf8++; + } + + while (Length) { + Length >>= 1; + Bsr8++; + } + + if (Bsf8 == (Bsr8 - 1)) Bsr8--; + + Length = (1 << Bsr8) - 1 ; + + Base &= (~Length); + + IoGenDecode32 = Base | (UINT32)((Length >> 2) << 18) | 1; + + } else { + if (IoGenDecIndex == 4) return EFI_NOT_FOUND; + } + + WRITE_PCI32_SB(SB_REG_GEN1_DEC + IoGenDecIndex * 4, IoGenDecode32); + // Porting End + + return EFI_SUCCESS; + +} + +//--------------------------------------------------------------------------- +#if SMM_SUPPORT +//--------------------------------------------------------------------------- + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBSmmSaveRestoreStates +// +// Description: This hook is called in the very SMI entry and exit. +// Save/Restore chipset data if needed. +// +// Input: Save - TRUE = Save / FALSE = Restore +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SBSmmSaveRestoreStates ( + IN BOOLEAN Save ) +{ + static volatile UINT8 StoreCMOS; + static volatile UINT8 StoreExtCMOS; + static volatile UINT32 StoreCF8; + static volatile UINT32 AltAcc; + static volatile UINT8 RtcRegA; + UINT8 SbCmosMiscFlag = 0; +#if defined(HPET_APIC_INTERRUPT_MODE) && (HPET_APIC_INTERRUPT_MODE != 0) + static volatile BOOLEAN IsHpetApicEn = FALSE; + static volatile UINT8 StoreIoApicIndex; + volatile UINT8 Irq; +#endif + UINT32 Data32 =0; + + if (Save) { + StoreCF8 = IoRead32(0xcf8); // Store CF8 (PCI index) + + // Save Alternate access bit. + AltAcc = READ_MEM32_RCRB(RCRB_MMIO_GCS) & 0x10; + + StoreCMOS = ReadPort70h(); // Save 0x70 + + StoreExtCMOS = IoRead8(CMOS_IO_EXT_INDEX); // Save 0x72 + +#if defined CMOS_MANAGER_SUPPORT && CMOS_MANAGER_SUPPORT + IoWrite8(CMOS_IO_EXT_INDEX, SB_CMOS_MISC_FLAG_REG); + IoWrite8(CMOS_IO_EXT_DATA, 0); +#endif +#if defined(HPET_APIC_INTERRUPT_MODE) && (HPET_APIC_INTERRUPT_MODE != 0) + StoreIoApicIndex = MMIO_READ8(APCB); + IsHpetApicEn = IsHpetApicEnable(); + if (IsHpetApicEn) { + Irq = GetHpetApicPin(); + IoApicMaskIrq(Irq); + } +#endif + + Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0); + WriteMsr(0x1FE, Data32); + + } else { + do { + RtcRegA = SBLib_CmosRead(RTC_REG_A_INDEX); + } while (RtcRegA & 0x80); + +#if defined CMOS_MANAGER_SUPPORT && CMOS_MANAGER_SUPPORT + IoWrite8(CMOS_IO_EXT_INDEX, SB_CMOS_MISC_FLAG_REG); + SbCmosMiscFlag = IoRead8(CMOS_IO_EXT_DATA); + + if (SbCmosMiscFlag & ENABLE_NMI_BEFORE_SMI_EXIT) + StoreCMOS &= ~BIT07; // Enable NMI_EN + + if (SbCmosMiscFlag & DISABLE_NMI_BEFORE_SMI_EXIT) + StoreCMOS |= BIT07; // Disable NMI_EN +#endif + + IoWrite8(CMOS_ADDR_PORT, StoreCMOS); // Restore 0x70 + IoWrite8(CMOS_IO_EXT_INDEX, StoreExtCMOS); // Restore 0x72 + + // Restore Alternate access bit. + do { //Improve alternate access mode >> + RW_MEM32_RCRB(RCRB_MMIO_GCS, AltAcc, 0x10); + } while ((READ_MEM32_RCRB(RCRB_MMIO_GCS) & 0x10) != AltAcc); //Improve alternate access mode << + + IoWrite32(0xcf8, StoreCF8); // Restore 0xCF8 (PCI index) + +#if defined(HPET_APIC_INTERRUPT_MODE) && (HPET_APIC_INTERRUPT_MODE != 0) + if (IsHpetApicEn) { + Irq = GetHpetApicPin(); + IoApicUnmaskIrq(Irq); + IoApicEoi(Irq); + } + + MMIO_WRITE8(APCB, StoreIoApicIndex); + StoreIoApicIndex = MMIO_READ8(APCB); +#endif + + Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0); + WriteMsr(0x1FE, Data32); + + } + + return EFI_SUCCESS; +} + +//--------------------------------------------------------------------------- +#endif // END OF SMM Related Porting Hooks +//--------------------------------------------------------------------------- + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBProtectedPciDevice +// +// Description: This function is called by PCI Bus Driver before configuring +// or disabling any PCI device. This function should examine the +// Vendor/Device ID or PCI Bus, Device and Function numbers to +// make sure it is not a south bridge device or any other device +// which should no be configured by PCI Bus Driver. +// +// Input: *PciDevice - Pointer to PCI Device Info structure. +// +// Output: EFI_STATUS +// EFI_SUCCESS - SKIP this device, do not touch +// PCI Command register. +// EFI_UNSUPPORTED - DON'T SKIP this device do complete +// enumeration as usual. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SBProtectedPciDevice ( + IN PCI_DEV_INFO *PciDevice ) +{ + +//####if ((PciDevice->Address.Addr.Bus == SMBUS_BUS) && \ +//#### (PciDevice->Address.Addr.Device == SMBUS_DEV) && \ +//#### (PciDevice->Address.Addr.Function == SMBUS_FUN)) { +//#### +//#### return EFI_SUCCESS; +//####} + + return EFI_UNSUPPORTED; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBProgramPciDevice +// +// Description: This function is called by PCI Bus Driver before installing +// Protocol Interface for the input device. +// +// Input: *PciDevice - Pointer to PCI Device Info structure. +// +// Output: EFI_SUCCESS +// +// Notes: All resource in the device had been assigned, but the command +// register is disabled. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SBProgramPciDevice ( + IN PCI_DEV_INFO *PciDevice ) +{ + +//####if ((PciDevice->Address.Addr.Bus == EUSB_BUS) && \ +//#### (PciDevice->Address.Addr.Device == EUSB_DEV) && \ +//#### (PciDevice->Address.Addr.Function == EUSB_FUN)) { +//#### // Do any porting if needed. +//####} + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBUpdatePciDeviceAttributes +// +// Description: This function is called by PCI Bus Driver, can be used to +// the attributes of the PCI device. +// +// Input: *PciDevice - Pointer to PCI Device Info structure. +// *Attributes - Attributes bitmask which caller whants to +// change. +// Capabilities - The PCI device supports Capabilityes +// Set - Specifies weathere to set or reset given +// "Attributes". +// +// Output: EFI_SUCCESS +// +// Notes: This routine may be invoked twice depend on the device type, +// the first time is at BDS phase, the second is before +// legacy boot. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SBUpdatePciDeviceAttributes ( + IN PCI_DEV_INFO *PciDevice, + IN OUT UINT64 *Attributes, + IN UINT64 Capabilities, + IN BOOLEAN Set ) +{ + +//####if ((PciDevice->Address.Addr.Bus == EUSB_BUS) && \ +//#### (PciDevice->Address.Addr.Device == EUSB_DEV) && \ +//#### (PciDevice->Address.Addr.Function == EUSB_FUN)) { +//#### // Do any porting if needed. +//####} + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ReadSPIDescriptor +// +// Description: Read SPI Descriptor. +// +// Input: FDSS - Flash Descriptor Section Select. +// FDSI - Flash Descriptor Section Index. +// FDOD - Flash Descriptor Observability Data +// +// Output:EFI_SUCCESS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ReadSPIDescriptor( + IN UINT8 FDSS, + IN UINT8 FDSI, + OUT UINT32 *FDOD +) +{ + UINT32 Buffer32; + + WRITE_MEM32_SPI(R_RCRB_SPI_FDOC, 0); + + Buffer32 = READ_MEM32_SPI(R_RCRB_SPI_FDOD); + + if (Buffer32 != 0x0ff0a55a) //Improve alternate access mode + return EFI_NOT_FOUND; + + Buffer32 = ((UINT32)FDSS << 12) | ((UINT32)FDSI << 2); + WRITE_MEM32_SPI(R_RCRB_SPI_FDOC, Buffer32); + *FDOD = READ_MEM32_SPI(R_RCRB_SPI_FDOD); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetTotalFlashRomSize +// +// Description: Read SPI Descriptor to get Total Flash size. +// +// Input: None +// +// Output: UINT32 - Flash Rom Size +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 GetTotalFlashRomSize ( VOID ) +{ + UINT32 TotalRomSize = 0; + UINT32 CtrlData; + UINT8 NumSpi = 0; + + // Select to Flash Map 0 Register to get the number of flash Component + CtrlData = MmioRead32((SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_RCRB_SPI_FDOC)); + CtrlData &= (UINT32)(~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)); + CtrlData |= (UINT32)(V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP0); + MmioWrite32((SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_RCRB_SPI_FDOC), CtrlData); + + switch ( MmioRead16 (SB_RCBA + R_PCH_SPI_FDOD) & B_PCH_SPI_FDBAR_NC ) { + case V_PCH_SPI_FDBAR_NC_1: + NumSpi = 1; + break; + case V_PCH_SPI_FDBAR_NC_2: + NumSpi = 2; + break; + default: + break; + } + //if (NumSpi == 0) ASSERT_EFI_ERROR(EFI_DEVICE_ERROR); + + // Select to Flash Components Register to get the Component 1 Density + CtrlData = MmioRead32((SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_RCRB_SPI_FDOC)); + CtrlData &= (UINT32)(~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)); + CtrlData |= (UINT32)(V_PCH_SPI_FDOC_FDSS_COMP | R_PCH_SPI_FCBA_FLCOMP); + MmioWrite32((SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_RCRB_SPI_FDOC), CtrlData); + + /// Copy Component 1 Density + switch ( (UINT8) MmioRead32 (SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_RCRB_SPI_FDOD) & B_PCH_SPI_FLCOMP_COMP1_MASK ) { + case V_PCH_SPI_FLCOMP_COMP1_512KB: + TotalRomSize += (UINT32) (512 << KBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_1MB: + TotalRomSize += (UINT32) (1 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_2MB: + TotalRomSize += (UINT32) (2 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_4MB: + TotalRomSize += (UINT32) (4 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_8MB: + TotalRomSize += (UINT32) (8 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_16MB: + TotalRomSize += (UINT32) (16 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_32MB: + TotalRomSize += (UINT32) (32 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP1_64MB: + TotalRomSize += (UINT32) (64 << MBShift); + break; + default: + break; + } // end of switch + + // Copy Component 2 Density + if(NumSpi == 2){ + switch ( (UINT8) MmioRead32 (SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_RCRB_SPI_FDOD) & B_PCH_SPI_FLCOMP_COMP2_MASK ) { + case V_PCH_SPI_FLCOMP_COMP2_512KB: + TotalRomSize += (UINT32) (512 << KBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_1MB: + TotalRomSize += (UINT32) (1 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_2MB: + TotalRomSize += (UINT32) (2 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_4MB: + TotalRomSize += (UINT32) (4 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_8MB: + TotalRomSize += (UINT32) (8 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_16MB: + TotalRomSize += (UINT32) (16 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_32MB: + TotalRomSize += (UINT32) (32 << MBShift); + break; + case V_PCH_SPI_FLCOMP_COMP2_64MB: + TotalRomSize += (UINT32) (64 << MBShift); + break; + default: + break; + } // end of switch + }// end of if + //if (TotalRomSize == 0) ASSERT_EFI_ERROR(EFI_DEVICE_ERROR); + + return TotalRomSize; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SbGetSpiRegionAddresses +// +// Description: Read SPI Descriptor to get flash rom base address and length +// of one region +// +// Input: AMI_SB_SPI_RANGE_TYPE - Region Type +// +// Output: UINT32 - BaseAddress +// UINT32 - EndAddress +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SbGetSpiRangeAddresses( + IN AMI_SB_SPI_RANGE_TYPE RangeType, + OUT UINT32 *BaseAddress, + OUT UINT32 *EndAddress ) +{ + UINT32 ReadValue = 0; + + if (!((RangeType > AnyType) && (RangeType < PchSpiRangeTypeMax))) { + return EFI_INVALID_PARAMETER; + } + + if (RangeType <= SecondaryBiosType) { + ReadValue = MmioRead32 (SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_SB_RCRB_SPI_FREG0_FLASHD + (S_SB_SPI_FREGX * ((UINTN) (RangeType - 1)))); + *BaseAddress = (ReadValue & B_SB_SPI_FREGX_BASE_MASK) << 12; + *EndAddress = ((ReadValue & B_SB_SPI_FREGX_LIMIT_MASK) >> 4) | 0x00000FFF; + } else if (RangeType == BfpregType) { + ReadValue = MmioRead32 (SB_RCRB_BASE_ADDRESS + SPI_BASE_ADDRESS + R_SB_RCRB_SPI_BFPR); + *BaseAddress = (ReadValue & B_SB_SPI_BFPR_PRB) << 12; + *EndAddress = ((ReadValue & B_SB_SPI_BFPR_PRL) >> 4) | 0x00000FFF; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SbFlashProtectedRegion +// +// Description: This routine provides H/W read/write-protection of the BIOS +// region. If chipset supports "SPI Flash Protected Range +// registers", then program them to protect BIOS region in SPI +// Flash. +// +// Input: None +// +// Output: EFI_STATUS +// EFI_SUCCESS - Set successfully. +// EFI_OUT_OF_RESOURCES - There is no available register +// for this call. +// EFI_INVALID_PARAMETER - The parameter of input is +// invalid +// EFI_UNSUPPORTED - Chipset or H/W is not supported. +// +// Notes: Porting required +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SbFlashProtectedRange( VOID ) +{ + // + // Porting required if chipset is able to support H/W protection of + // BIOS region. + // + EFI_STATUS Status = EFI_SUCCESS; + UINT32 RegIndex; + UINT32 TotalFlashRomSize; + UINT32 FlashRangeBaseAddr = 0; + UINT32 FlashRangeEndAddr = 0; + volatile UINT32 Value32, AddrCheck; + SPI_PROTECTED_RANGE_CONIFG SpiProtectedRange[] = {SPI_PROTECTED_RANGE_0, + SPI_PROTECTED_RANGE_1, + SPI_PROTECTED_RANGE_2, + SPI_PROTECTED_RANGE_3, + SPI_PROTECTED_RANGE_4}; + + // Get Total ROM size first + TotalFlashRomSize = GetTotalFlashRomSize(); + + for (RegIndex = 0; RegIndex < 5; RegIndex++) { + // Check Read or Write protected is enable or not + if (!(SpiProtectedRange[RegIndex].ReadProtectEnable || \ + SpiProtectedRange[RegIndex].WriteProtectEnable)) + continue; + + // Check Protected Range Length should not be 0 + if(SpiProtectedRange[RegIndex].ProtectedRangeLength == 0) + continue; + + switch (SpiProtectedRange[RegIndex].ProtectedRangeType){ + case BiosType: + case MeType: + case GbeType: + Status = SbGetSpiRangeAddresses(SpiProtectedRange[RegIndex].ProtectedRangeType, &FlashRangeBaseAddr, &FlashRangeEndAddr); + if(!EFI_ERROR(Status)){ + AddrCheck = (UINT32)(SpiProtectedRange[RegIndex].ProtectedRangeBase) + FlashRangeBaseAddr; + if (AddrCheck > FlashRangeEndAddr) + return EFI_INVALID_PARAMETER; + AddrCheck += (UINT32)(SpiProtectedRange[RegIndex].ProtectedRangeLength - 1); + if (AddrCheck > FlashRangeEndAddr) + return EFI_INVALID_PARAMETER; + + Value32 = *(UINT32 *)(SB_RCBA + SPI_BASE_ADDRESS + (R_SB_RCRB_SPI_PR0 + (RegIndex * 4))); + Value32 = (((UINT32)(SpiProtectedRange[RegIndex].ProtectedRangeBase) + FlashRangeBaseAddr) & 0x1FFF000) >> 12; + Value32 |= ((((UINT32)(SpiProtectedRange[RegIndex].ProtectedRangeBase + SpiProtectedRange[RegIndex].ProtectedRangeLength - 1) + FlashRangeBaseAddr) & 0x1FFF000) << 4); + } else return Status; + + break; + case AnyType: + // Exceed the address of protected range base. + if (SpiProtectedRange[RegIndex].ProtectedRangeBase >= (UINTN)TotalFlashRomSize) + return EFI_INVALID_PARAMETER; + + Value32 = *(UINT32 *)(SB_RCBA + SPI_BASE_ADDRESS + (R_SB_RCRB_SPI_PR0 + (RegIndex * 4))); + Value32 = (UINT32)(SpiProtectedRange[RegIndex].ProtectedRangeBase & 0x1FFF000) >> 12; + Value32 |= (((UINT32)(SpiProtectedRange[RegIndex].ProtectedRangeBase + SpiProtectedRange[RegIndex].ProtectedRangeLength - 1) & 0x1FFF000) << 4); + break; + } // end of switch + + if (SpiProtectedRange[RegIndex].ReadProtectEnable) Value32 |= B_SB_SPI_PRx_RPE; + if (SpiProtectedRange[RegIndex].WriteProtectEnable) Value32 |= B_SB_SPI_PRx_WPE; + *(UINT32 *)(SB_RCBA + SPI_BASE_ADDRESS + (R_SB_RCRB_SPI_PR0 + (RegIndex * 4))) = Value32; + } // for loop + + return Status; +} + +//--------------------------------------------------------------------------- +// Standard I/O Access Routines, No Porting Required. +//--------------------------------------------------------------------------- + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RtcRead +// +// Description: Read specific RTC/CMOS RAM +// +// Input: Location Point to RTC/CMOS RAM offset for read +// +// Output: nONE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 RtcRead ( IN UINT8 Location ) +{ + return ReadCmos(Location); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RtcWrite +// +// Description: Write specific RTC/CMOS RAM +// +// Parameters: Location Point to RTC/CMOS RAM offset for write +// Value The data that will be written to RTC/CMOS RAM +// +// Returns: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +RtcWrite ( + IN UINT8 Location, + IN UINT8 Value + ) +{ + WriteCmos(Location, Value); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ReadIo8IdxData +// +// Description: This function reads an 8bit value from a specific I/O +// Index/Data port. +// +// Input: IoBase16 - A 16 Bit I/O Address for Index I/O Port +// RegIdx8 - An 8 Bit Register offset +// +// Output: An 8Bit data read from the specific Index/Data I/O port. +// +// Notes: The default Data I/O Port is the Index I/O Port plus 1, if +// your Data I/O Port is not that, please modify below +// "++IoBase16". +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 ReadIo8IdxData ( + IN UINT16 IoBase16, + IN UINT8 RegIdx8 ) +{ + IoWrite8( IoBase16, RegIdx8 ); + return IoRead8( ++IoBase16 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WriteIo8IdxData +// +// Description: This function writes an 8bit value to a specific I/O +// Index/Data port. +// +// Input: IoBase16 - A 16 Bit I/O Address for Index I/O Port +// RegIdx8 - An 8 Bit Register Index +// Value8 - An 8 Bit Value to write. +// +// Output: None +// +// Notes: The default Data I/O Port is the Index I/O Port plus 1, if +// your Data I/O Port is not that, please modify below +// "++IoBase16". +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteIo8IdxData ( + IN UINT16 IoBase16, + IN UINT8 RegIdx8, + IN UINT8 Value8 ) +{ + IoWrite8( IoBase16, RegIdx8 ); + IoWrite8( ++IoBase16, Value8 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RwIo8IdxData +// +// Description: This function reads an 8bit value from a specific I/O +// Index/Data port, then applies Set/Reset masks and writes +// it back. +// +// Input: IoBase16 - A 16 Bit I/O Address for Index I/O Port +// RegIdx8 - An 8 Bit Register Index +// SetBit8 - Mask of 8bits to set (1 = Set) +// ResetBit8 - Mask of 8bits to reset (1 = Reset) +// +// Output: None +// +// Notes: The default Data I/O Port is the Index I/O Port plus 1, if +// your Data I/O Port is not that, please modify IoRead8IdxData +// and IoWrite8IdxData's "++IoBase16". +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID RwIo8IdxData ( + IN UINT16 IoBase16, + IN UINT8 RegIdx8, + IN UINT8 SetBit8, + IN UINT8 ResetBit8 ) +{ + UINT8 Buffer8 ; + + Buffer8 = ReadIo8IdxData( IoBase16, RegIdx8 ) & ~ResetBit8 | SetBit8; + WriteIo8IdxData( IoBase16, RegIdx8, Buffer8 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WriteIo8S3 +// +// Description: This function writes an 8bit value to a specific I/O port +// and writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBaseReg16 - A 16 Bit I/O Port Address +// Value8 - An 8 Bit Value to write. +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteIo8S3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBaseReg16, + IN UINT8 Value8 ) +{ + IoWrite8( IoBaseReg16, Value8 ); + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint8, \ + IoBaseReg16, \ + 1, \ + &Value8 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WriteIo16S3 +// +// Description: This function writes a 16bit value to a specific I/O port +// and writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBaseReg16 - A 16 Bit I/O Port Address +// Value16 - A 16 Bit Value to write. +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteIo16S3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBaseReg16, + IN UINT16 Value16 ) +{ + IoWrite16( IoBaseReg16, Value16 ); + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint16,\ + IoBaseReg16, \ + 1, \ + &Value16 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WriteIo32S3 +// +// Description: This function writes a 32bit value to a specific I/O port +// and writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBaseReg16 - A 16 Bit I/O Port Address +// Value32 - a 32 Bit Value to write. +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteIo32S3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBaseReg16, + IN UINT32 Value32 ) +{ + IoWrite32( IoBaseReg16, Value32 ); + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint32,\ + IoBaseReg16, \ + 1, \ + &Value32 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RwIo8S3 +// +// Description: This function reads an 8bit value from a specific I/O port, +// then applies Set/Reset masks, and writes it back, then +// writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBaseReg16 - A 16 Bit I/O Port Address +// SetBit8 - Mask of 8bits to set (1 = Set) +// ResetBit8 - Mask of 8bits to reset (1 = Reset) +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID RwIo8S3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBaseReg16, + IN UINT8 SetBit8, + IN UINT8 ResetBit8 ) +{ + + RW_IO8( IoBaseReg16, SetBit8, ResetBit8 ); + + ResetBit8 = ~ResetBit8; + + BOOT_SCRIPT_S3_IO_READ_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint8, \ + IoBaseReg16, \ + &SetBit8, \ + &ResetBit8 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RwIo16S3 +// +// Description: This function reads a 16bit value from a specific I/O port, +// then applies Set/Reset masks, and writes it back, then +// writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBaseReg16 - A 16 Bit I/O Port Address +// SetBit16 - Mask of 16bits to set (1 = Set) +// ResetBit16 - Mask of 16bits to reset (1 = Reset) +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID RwIo16S3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBaseReg16, + IN UINT16 SetBit16, + IN UINT16 ResetBit16 ) +{ + RW_IO16( IoBaseReg16, SetBit16, ResetBit16 ); + + ResetBit16 = ~ResetBit16; + + BOOT_SCRIPT_S3_IO_READ_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint16, \ + IoBaseReg16, \ + &SetBit16, \ + &ResetBit16 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RwIo32S3 +// +// Description: This function reads a 32bit value from a specific I/O port, +// then applies Set/Reset masks, and writes it back, then +// writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBaseReg16 - A 16 Bit I/O Port Address +// SetBit32 - Mask of 32bits to set (1 = Set) +// ResetBit32 - Mask of 32bits to reset (1 = Reset) +// +// Output: None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID RwIo32S3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBaseReg16, + IN UINT32 SetBit32, + IN UINT32 ResetBit32 ) +{ + RW_IO32( IoBaseReg16, SetBit32, ResetBit32 ); + + ResetBit32 = ~ResetBit32; + + BOOT_SCRIPT_S3_IO_READ_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint32, \ + IoBaseReg16, \ + &SetBit32, \ + &ResetBit32 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WriteIo8IdxDataS3 +// +// Description: This function writes an 8bit value to a specific I/O +// Index/Data ports and writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBase16 - A 16 Bit I/O Address for Index I/O Port +// RegIdx8 - An 8 Bit Register Index +// Value8 - An 8 Bit Value to write. +// +// Output: None +// +// Notes: The default Data I/O Port is the Index I/O Port plus 1, if +// your Data I/O Port is not that, please modify below +// "IoBase16+1". +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteIo8IdxDataS3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBase16, + IN UINT8 IoReg8, + IN UINT8 Value8 ) +{ + WriteIo8S3(mBootScriptSave, IoBase16, IoReg8); + WriteIo8S3(mBootScriptSave, IoBase16 + 1, Value8); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RwIo8IdxDataS3 +// +// Description: This function reads an 8bit value from a specific I/O +// Index/Data ports, then applies Set/Reset masks, and writes +// it back. Also writes a copy to Boot Script Table. +// +// Input: *mBootScriptSave - Pointer to Boot Script Save Protocal +// IoBase16 - A 16 Bit I/O Address for Index I/O Port +// RegIdx8 - An 8 Bit Register Index +// SetBit8 - Mask of 8bits to set (1 = Set) +// ResetBit8 - Mask of 8bits to reset (1 = Reset) +// +// Output: An 8Bit data read from the specific Index/Data I/O port +// after appling Set/Reset masks. +// +// Notes: The default Data I/O Port is the Index I/O Port plus 1, if +// your Data I/O Port is not that, please modify below +// "IoBase16+1" and IoWrite8IdxData's "++IoBase16". +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID RwIo8IdxDataS3 ( + IN AMI_S3_SAVE_PROTOCOL *mBootScriptSave, + IN UINT16 IoBase16, + IN UINT8 IoReg8, + IN UINT8 SetBit8, + IN UINT8 ResetBit8 ) +{ + RwIo8IdxData(IoBase16, IoReg8, SetBit8, ResetBit8); + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint8,\ + IoBase16, \ + 1, \ + &IoReg8 ); + ResetBit8 = ~ResetBit8; + BOOT_SCRIPT_S3_IO_READ_WRITE_MACRO( mBootScriptSave, \ + EfiBootScriptWidthUint8, \ + IoBase16 + 1, \ + &SetBit8, \ + &ResetBit8 ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_CmosRead +// +// Description: Read the RTC value at the given Index. +// +// Input: Index - RTC Index +// +// Output: RTC Value read from the provided Index +// +// Notes: Here is the control flow of this function: +// 1. Read port 0x70 (RTC Index Register) to get bit 7. +// Bit 7 is the NMI bit-it should not be changed. +// 2. Set Index with the NMI bit setting. +// 3. Output 0x70 with the Index and NMI bit setting. +// 4. Read 0x71 for Data. Getting Dec when appropriate. +// 5. Return the Data. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 SBLib_CmosRead ( + IN UINT8 Index ) +{ + return ReadCmos(Index); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SBLib_CmosWrite +// +// Description: Write the RTC value at the given Index. +// +// Input: Index - RTC Index +// Value - Value to write +// +// Output: None +// +// Notes: Here is the control flow of this function: +// 1. Read port 0x70 (RTC Index Register) to get bit 7. +// Bit 7 is the NMI bit-it should not be changed. +// 2. Set Index with the NMI bit setting. +// 3. Output 0x70 with the Index. Switch to BCD when needed. +// 4. Write the data to 0x71. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SBLib_CmosWrite ( + IN UINT8 Index, + IN UINT8 Value ) +{ + WriteCmos(Index, Value); +} + +PCH_SERIES +EFIAPI +GetPchSeries ( + VOID + ) +/** + + Return Pch Series + + @param[in] None + + @retval PCH_SERIES Pch Series + +**/ +{ + UINT16 LpcDeviceId; + UINT32 PchSeries; + + LpcDeviceId = READ_PCI16_SB(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; + } + + return PchSeries; +} + +UINT8 +EFIAPI +GetPchMaxPciePortNum ( + VOID + ) +/** + + Get Pch Maximum Pcie Root Port Number + + @param[in] None + + @retval Pch Maximum Pcie Root Port Number + +**/ +{ + 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; + } +} + +UINT8 +EFIAPI +GetPchMaxSataPortNum ( + VOID + ) +/** + + Get Pch Maximum Sata Port Number + + @param[in] None + + @retval Pch Maximum Sata Port Number + +**/ +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + switch (PchSeries) { + case PchLp: + return LPTLP_AHCI_MAX_PORTS; + + case PchH: + return LPTH_AHCI_MAX_PORTS; + + default: + return 0; + } +} + +UINT8 +EFIAPI +GetPchUsbMaxPhysicalPortNum ( + VOID + ) +/** + + Get Pch Usb Maximum Physical Port Number + + @param[in] None + + @retval Pch Usb Maximum Physical Port Number + +**/ +{ + 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; + } +} + +UINT8 +EFIAPI +GetPchXhciMaxUsb3PortNum ( + VOID + ) +/** + + Get Pch Maximum Usb3 Port Number of XHCI Controller + + @param[in] None + + @retval Pch Maximum Usb3 Port Number of XHCI Controller + +**/ +{ + 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; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetPchEhciMaxControllerNum +// +// Description: Get Pch Maximum EHCI Controller Number +// +// Input: None +// +// Output: Pch Maximum EHCI Controller Number +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +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; + } +} + +UINT32 DummyVerbTable[] = { + // + // Dummy Verb Table + // + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF +}; + +#if defined(HPET_APIC_INTERRUPT_MODE) && (HPET_APIC_INTERRUPT_MODE != 0) +//---------------------------------------------------------------------------- +// Generic IO APIC routine. +//---------------------------------------------------------------------------- +UINT8 gBspLocalApicID = 0; +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicBase +// +// Description: This routine returns a structure pointer to the I/O APIC. +// +// Input: None +// +// Output: IO_APIC structure. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +struct IO_APIC* IoApicBase( VOID ) +{ + static UINT32 IoApicAddr = 0; + if (IoApicAddr == 0 || IoApicAddr == -1) { + // This value may need to read from chipset registers. + IoApicAddr = APCB; + } + + return (struct IO_APIC*)IoApicAddr; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicWrite +// +// Description: This function writes a 32bits data to the register of +// I/O APIC. +// +// Input: UINT8 Reg - The register offset to be written. +// UINT32 Value - A 32bits data will be written to the register +// of I/O APIC. +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IoApicWrite ( + IN UINT8 Reg, + IN UINT32 Value ) +{ + struct IO_APIC *IoApicStruct = IoApicBase(); + + MMIO_WRITE8((UINT64)&IoApicStruct->Index, Reg); + MMIO_WRITE32((UINT64)&IoApicStruct->Data, Value); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicRead +// +// Description: This function reads a 32bits data from the register of +// I/O APIC. +// +// Input: UINT8 Reg - the register offset to be read. +// +// Output: UINT32 - A 32bits data read from the register of I/O APIC. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 IoApicRead ( + IN UINT8 Reg ) +{ + struct IO_APIC *IoApicStruct = IoApicBase(); + + MMIO_WRITE8((UINT64)&IoApicStruct->Index, Reg); + return MMIO_READ32((UINT64)&IoApicStruct->Data); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicEnableIrq +// +// Description: This function enables the specific interrupt pin of I/O APIC. +// +// Input: UINT8 Irq - The pin number of I/O APIC +// BOOLEAN LevelTriggered - Trigger mechanism (level or edge) +// for this INT pin. +// BOOLEAN Polarity - Specifies the polarity of the INT pin. +// (Active High or Active Low) +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IoApicEnableIrq ( + IN UINT8 Irq, + IN BOOLEAN LevelTriggered, + IN BOOLEAN Polarity ) +{ + IO_APIC_ROUTE_ENTRY ApicEntry; + union ENTRY_UNION Eu = {{0, 0}}; + + ApicEntry.DestMode = 0; // 0: physical + ApicEntry.Mask = 0; // 0 : enable + ApicEntry.Dest = gBspLocalApicID; // suppose the BSP handle interrupt. + ApicEntry.DeliveryMode = 0; // 000: FIXED + ApicEntry.Polarity = (Polarity) ? 1 : 0; + ApicEntry.Trigger = (LevelTriggered) ? 1 : 0; + ApicEntry.Vector = MASTER_INTERRUPT_BASE + Irq; + + Eu.Entry = ApicEntry; + IoApicWrite(IO_APIC_REDIR_TABLE_HIGH + 2 * Irq, Eu.W2); + IoApicWrite(IO_APIC_REDIR_TABLE_LOW + 2 * Irq, Eu.W1); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicDisableIrq +// +// Description: This function disables the specific interrupt pin of I/O APIC. +// +// Input: UINT8 Irq - The pin number of I/O APIC +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IoApicDisableIrq ( + IN UINT8 Irq ) +{ + union ENTRY_UNION Eu = {{0, 0}}; + + Eu.W1 = IoApicRead(IO_APIC_REDIR_TABLE_LOW + 2 * Irq); + Eu.W2 = IoApicRead(IO_APIC_REDIR_TABLE_HIGH + 2 * Irq); + Eu.Entry.Mask = 1; + IoApicWrite(IO_APIC_REDIR_TABLE_LOW + 2 * Irq, Eu.W1); + IoApicWrite(IO_APIC_REDIR_TABLE_HIGH + 2 * Irq, Eu.W2); + IoApicEoi(Irq); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicMaskIrq +// +// Description: This routine masks the specific interrupt pin of I/O APIC. +// +// Input: UINT8 Irq - The pin number of I/O APIC +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IoApicMaskIrq ( + IN UINT8 Irq ) +{ + union ENTRY_UNION Eu = {{0, 0}}; + + Eu.W1 = IoApicRead(IO_APIC_REDIR_TABLE_LOW + 2 * Irq); + Eu.Entry.Mask = 1; + IoApicWrite(IO_APIC_REDIR_TABLE_LOW + 2 * Irq, Eu.W1); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicUnmaskIrq +// +// Description: This routine unmasks the specific interrupt pin of I/O APIC. +// +// Input: UINT8 Irq - The pin number of I/O APIC +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IoApicUnmaskIrq ( + IN UINT8 Irq ) +{ + union ENTRY_UNION Eu = {{0, 0}}; + + Eu.W1 = IoApicRead(IO_APIC_REDIR_TABLE_LOW + 2 * Irq); + Eu.Entry.Mask = 0; + IoApicWrite(IO_APIC_REDIR_TABLE_LOW + 2 * Irq, Eu.W1); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IoApicEoi +// +// Description: This routine issues an EOI to the specific pin of I/O APIC. +// +// Input: UINT8 Irq - The pin number of I/O APIC +// +// Output: EFI_SUCCESS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IoApicEoi ( + IN UINT8 Irq ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Vector = MASTER_INTERRUPT_BASE + Irq; + struct IO_APIC *IoApicStruct = IoApicBase(); + UINT32 Isr = 0; + union ENTRY_UNION Eu = {{0, 0}}; + + do { + MMIO_WRITE32((UINT64)&IoApicStruct->Eoi, Vector); + Eu.W1 = IoApicRead(IO_APIC_REDIR_TABLE_LOW + 2 * Irq); + } while (Eu.Entry.Irr); + + do { + MMIO_WRITE32(LOCAL_APIC_BASE + APIC_EOI_REGISTER, Vector); + Isr = MMIO_READ32(LOCAL_APIC_BASE + ISR_REG (Vector)); + } while (Isr & ISR_BIT(Vector)); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetHpetApicPin +// +// Description: This routine gets the pin number of I/O APIC for HPET. +// +// Input: None +// +// Output: UINT8 Irq - The pin number of I/O APIC for HPET. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 GetHpetApicPin (VOID) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT8 Irq = 0; + + volatile HPET_TIMER_CONFIGURATION_REGISTER TimerConfiguration; + + TimerConfiguration.Uint64 = MMIO_READ64( HPET_BASE_ADDRESS + HPET_TIMER_CONFIGURATION_OFFSET + HPET_OFFSET * HPET_TIMER_STRIDE ); + Irq = TimerConfiguration.Bits.InterruptRoute; + + return Irq; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: IsHpetApicEnable +// +// Description: This routine checks the pin of I/O APIC for HPET is enabled or +// not. +// +// Input: None +// +// Output: TRUE - The pin of I/O APIC for HPET is enabled +// FALSE - The pin of I/O APIC for HPET is disabled +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN IsHpetApicEnable (VOID) +{ + union ENTRY_UNION Eu = {{0, 0}}; + UINT8 Irq; + + Irq = GetHpetApicPin(); + + Eu.W1 = IoApicRead(IO_APIC_REDIR_TABLE_LOW + 2 * Irq); + + return (Eu.Entry.Mask) ? FALSE : TRUE; +} +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* |