summaryrefslogtreecommitdiff
path: root/Chipset/SB/SmiHandlerPorting.c
diff options
context:
space:
mode:
Diffstat (limited to 'Chipset/SB/SmiHandlerPorting.c')
-rw-r--r--Chipset/SB/SmiHandlerPorting.c1699
1 files changed, 1699 insertions, 0 deletions
diff --git a/Chipset/SB/SmiHandlerPorting.c b/Chipset/SB/SmiHandlerPorting.c
new file mode 100644
index 0000000..d0e55e1
--- /dev/null
+++ b/Chipset/SB/SmiHandlerPorting.c
@@ -0,0 +1,1699 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SmmChildDispatcher/SmiHandlerPorting.c 6 3/19/13 8:21a Scottyang $
+//
+// $Revision: 6 $
+//
+// $Date: 3/19/13 8:21a $
+//*************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SmmChildDispatcher/SmiHandlerPorting.c $
+//
+// 6 3/19/13 8:21a Scottyang
+// [TAG] EIP118158
+// [Category] Improvement
+// [Description] Correct SBLib_CmosRead () offset.
+// [Files] SmiHandlerPorting2.c, SBDxe.c, SBGeneric.c, SBSmm.c,
+// SmiHandlerPorting.c
+//
+// 5 11/06/12 8:10a Scottyang
+// [TAG] None
+// [Category] Improvement
+// [Description] Reduce function "GetPchSeries()".
+// [Files] SBPEI.c, SBDxe.c, SmiHandlerPorting.c, SmiHandlerPorting2.c
+//
+// 4 9/26/12 4:00a 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
+//
+// 3 7/27/12 6:15a Victortu
+// [TAG] None
+// [Category] Improvement
+// [Description] Update to support ULT Platform.
+// [Files] SB.H, SB.mak, SB.sdl, SB.sd, SBSetup.c,
+// AcpiModeEnable.c, SBDxe.c, SBPEI.c, SBSMI.c, SleepSmi.c,
+// SmiHandlerPorting.c, SmiHandlerPorting2.c, SBPPI.h, Pch.sdl
+//
+// 2 4/25/12 9:33a Victortu
+//
+// [TAG] None
+// [Category] Improvement
+// [Description] Reprogram SMM ChildDispatcher drivers.
+// [Files] SmiHandlerGeneric.c; SmiHandlerPorting.c;
+// SmiHandlerGeneric2.c; SmmChildDispatch2Main.c; SmmChildDispatcher2.mak;
+// SmmChildDispatcher2.sdl; SmmChildDispatch.h; SmmChildDispatchMain.c;
+// SmmChildDispatchProtocol.c; SmmChildDispatcher.dxs;
+// PchSmiDispatcher.sdl
+//
+// [TAG] EIP73033
+// [Category] Improvement
+// [Description] 'PciDevicePath' used in GetControllerType(),
+// conditionally not set.
+// [Files] SmiHandlerPorting.c; SmiHandlerPorting2.c
+//
+// 1 2/08/12 8:27a Yurenlai
+// Intel Lynx Point/SB eChipset initially releases.
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: SmiHandlerPorting.c
+//
+// Description: This file contains SMM Child Dispatcher porting functions
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+
+//---------------------------------------------------------------------------
+// Include(s)
+//---------------------------------------------------------------------------
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <AmiCspLib.h>
+#include <AmiSmm.h>
+#include "SmmChildDispatch.h"
+
+//---------------------------------------------------------------------------
+// Constant, Macro and Type Definition(s)
+//---------------------------------------------------------------------------
+// Constant Definition(s)
+
+// Macro Definition(s)
+
+// Type Definition(s)
+
+// Function Prototype(s)
+
+//---------------------------------------------------------------------------
+// Variable and External Declaration(s)
+//---------------------------------------------------------------------------
+// Variable Declaration(s)
+
+UINT64 gSupportedIntervals[] = {
+ // Porting required - put all available intervals here (in Nanoseconds)
+#if SWSMI_TIMER_INSTEAD
+ 15000, // 1.5ms
+ 160000, // 16 ms
+ 320000, // 32 ms
+ 640000, // 64 ms
+#else
+ 600000000, // 60 Seconds
+ 320000000, // 32 Seconds
+ 160000000, // 16 Seconds
+ 80000000, // 8 Seconds
+#endif
+
+ // Terminator record
+ 0
+};
+
+// GUID Definition(s)
+
+// Protocol Definition(s)
+
+// External Declaration(s)
+
+extern EFI_SMM_SYSTEM_TABLE *pSmst;
+
+// Function Definition(s)
+
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// All purpose SMI Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IsAcpi
+//
+// Description: This function determines if the system is in ACPI mode.
+//
+// Input: None
+//
+// Output: BOOLEAN
+// TRUE - It is in ACPI mode
+// FALSE - It is not in ACPI mode
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsAcpi (VOID)
+{
+ return (READ_IO16_PM(ACPI_IOREG_PM1_CNTL) & 1) ? TRUE : FALSE; // 0x04
+};
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IsMe
+//
+// Description: This function checks whether the specific SMI event is raised
+//
+// Input: CheckBitNo - The bit number for the specific SMI.
+//
+// Output: BOOLEAN
+// TRUE - It is the specific SMI event
+// FALSE - It is not the specific SMI event
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsMe (
+ IN UINT8 CheckBitNo )
+{
+ volatile UINT32 Buffer32 = READ_IO32_PM(ACPI_IOREG_SMI_EN); // 0x30
+
+ Buffer32 &= READ_IO32_PM(ACPI_IOREG_SMI_STS); // 0x34
+ return (Buffer32 & (UINT32)(1 << CheckBitNo)) ? TRUE : FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ClearAllSmi
+//
+// Description: This function clears all SMI's and issues an EOS (End of SMI).
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: If you are porting INTEL chipset and have to support SWSMI
+// Timer SMI, you must be unable to clear the SWSMI status in
+// this routine.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ClearAllSmi (VOID)
+{
+ // Porting Required. Program to clear ALL SMI status bit
+ if ( !IsAcpi() ) {
+ if (READ_IO16_PM(ACPI_IOREG_PM1_EN) & 0x400)
+ if (READ_IO16_PM(ACPI_IOREG_PM1_STS) & 0x400)
+ SBLib_CmosRead(0x0C);
+ WRITE_IO16_PM(ACPI_IOREG_PM1_STS, 0xcc31); // 0x00
+ if (GetPchSeries() == PchLp) {
+ WRITE_IO32_PM(ACPI_PCHLP_IOREG_GPE0_STS+0x0c, 0xffffffff); // 0x8C
+ WRITE_IO32(GPIO_BASE_ADDRESS + GP_IOREG_ALTGP_SMI_STS, 0xffffffff); // 0x50
+ } else {
+ WRITE_IO32_PM(ACPI_IOREG_GPE0_STS, 0xffffffff); // 0x20
+ WRITE_IO32_PM(ACPI_IOREG_GPE0_STS+4, 0xffffffff); // 0x24
+ WRITE_IO16_PM(ACPI_IOREG_ALTGP_SMI_STS, 0xffff); // 0x3A
+ }
+ WRITE_IO16_PM(ACPI_IOREG_DEVACT_STS, 0xffff); // 0x44
+ WRITE_IO16_TCO(TCO_IOREG_STS1, 0xffff); // 0x04
+ WRITE_IO16_TCO(TCO_IOREG_STS2, 0xfffe); // 0x06 (Except Intruder Det)
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0xffffffbf); // 0x34 (Except SWSMI)
+ if ((READ_IO16_TCO(TCO_IOREG_CNT1) & 0x300) == 0x300) { // 0x08
+ SET_IO16_TCO(TCO_IOREG_CNT1, 0x100); // Clear NMI_NOW if needed.
+ }
+ }
+ // EOS
+ SET_IO8_PM(ACPI_IOREG_SMI_EN, 0x02); // 0x30
+ if ((READ_IO8_PM(ACPI_IOREG_SMI_EN) & 0x02) == 0) {
+ // Reset GBL_SMI_EN
+ RESET_IO8_PM(ACPI_IOREG_SMI_EN, 0x01); // 0x30
+ // Set EOS Again
+ SET_IO8_PM(ACPI_IOREG_SMI_EN, 0x02); // 0x30
+ // Set GBL_SMI_EN
+ SET_IO8_PM(ACPI_IOREG_SMI_EN, 0x01); // 0x30
+ }
+}
+
+//---------------------------------------------------------------------------
+// SW SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SwSmiEnable
+//
+// Description: This function enables SW SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SwSmiEnable (VOID)
+{
+ // Porting required
+ SET_IO32_PM(ACPI_IOREG_SMI_EN, 0x20); // 0x30
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SwSmiDisable
+//
+// Description: This function disables SW SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SwSmiDisable (VOID)
+{
+ // Porting required
+ RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x20);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SwSmiClear
+//
+// Description: This function clears SW SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SwSmiClear (VOID)
+{
+ // Porting required
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x20); // 0x34
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SwSmiDetect
+//
+// Description: This function detects SW SMI event
+//
+// Input: *Type - Pointer to store SW SMI number
+//
+// Output: TRUE - SW SMI occured, FALSE otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN SwSmiDetect (
+ OUT UINT16 *Type )
+{
+ // Porting required
+ if ( IsMe(5) ) { // SW_SMI
+ *Type = IoRead8(SW_SMI_IO_ADDRESS);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GetEAX
+//
+// Description: This function returns EAX saved value from CPU that caused
+// SW SMI.
+//
+// Input: None
+//
+// Output: EAX saved value
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINTN GetEAX (VOID)
+{
+ // Porting required for different CPU
+ EFI_GUID SwSmiCpuTriggerGuid = SW_SMI_CPU_TRIGGER_GUID;
+ SW_SMI_CPU_TRIGGER *SwSmiCpuTrigger;
+ UINTN Cpu = pSmst->CurrentlyExecutingCpu - 1; // CPU #
+ EFI_SMM_CPU_SAVE_STATE *CpuSaveState;
+ UINT16 i;
+
+ for (i = 0; i < pSmst->NumberOfTableEntries; i++) {
+ if (guidcmp(&(pSmst->SmmConfigurationTable[i].VendorGuid), \
+ &SwSmiCpuTriggerGuid) == 0)
+ break;
+ }
+
+ // If found table, check for the CPU that caused the software Smi.
+ if (i != pSmst->NumberOfTableEntries)
+ {
+ SwSmiCpuTrigger = pSmst->SmmConfigurationTable[i].VendorTable;
+ Cpu = SwSmiCpuTrigger->Cpu;
+ }
+ CpuSaveState = pSmst->CpuSaveState;
+
+ return CpuSaveState[Cpu].Ia32SaveState.EAX;
+}
+
+//---------------------------------------------------------------------------
+// SX SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SxSmiEnable
+//
+// Description: This function enables SX SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SxSmiEnable (VOID)
+{
+ // Porting required
+ SET_IO32_PM(ACPI_IOREG_SMI_EN, 0x10); // 0x30
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SxSmiDisable
+//
+// Description: This function disables SX SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SxSmiDisable (VOID)
+{
+ // Porting required
+ RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x10); // 0x30
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SxSmiClear
+//
+// Description: This function clears SX SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SxSmiClear (VOID)
+{
+ // Porting required
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x10); // 0x34
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SxSmiDetect
+//
+// Description: This function detects SX SMI event
+//
+// Input: *Type - Pointer to store value of Sleep type
+//
+// Output: TRUE - SX SMI occured, FALSE otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN SxSmiDetect (
+ OUT UINT16 *Type )
+{
+ // Porting required
+ if (IsMe(4)) { // SLP_SMI
+ switch (READ_IO16_PM(ACPI_IOREG_PM1_CNTL) & (7 << 10)) { // SLP_TYP
+ case (0 << 10):
+ *Type = SxS0;
+ break;
+ case (1 << 10):
+ *Type = SxS1;
+ break;
+ case (5 << 10):
+ *Type = SxS3;
+ break;
+ case (6 << 10):
+ *Type = SxS4;
+ break;
+ case (7 << 10):
+ *Type = SxS5;
+ break;
+ default:
+ return FALSE; // Unknown Error.
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PutToSleep
+//
+// Description: Disable Smi sleep and put to sleep.
+//
+// Input: *Context - Pointer to Sleep SMI context
+//
+// Output: None
+//
+// Referrals: SxSmiDisable
+//
+// Notes: Here is the control flow of this function:
+// 1. Disable Smi sleep.
+// 2. Set to go to sleep if you want to sleep in SMI. otherwise
+// set IORestart to 0xFF in CPU SMM dump area.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID PutToSleep (
+ IN VOID *SxContext )
+{
+ EFI_SMM_CPU_SAVE_STATE *pCpuSaveState = pSmst->CpuSaveState;
+ UINTN Cpu = pSmst->CurrentlyExecutingCpu - 1;
+ UINT32 CacheFlush = 0;
+
+ SxSmiDisable(); // Disable sleep SMI.
+
+//#### if (SxContext->Type == SxS5)
+//#### SBLib_BeforeShutdown();
+
+#if ACPI_SLEEP_IN_SMM
+ SET_IO16_PM(ACPI_IOREG_PM1_CNTL, 0x2000); // Set to sleep.
+#else
+ CacheFlush = pCpuSaveState[Cpu].Ia32SaveState.IORestart;
+ pCpuSaveState[Cpu].Ia32SaveState.IORestart = 0xff;
+#endif
+
+}
+
+//---------------------------------------------------------------------------
+// Periodic timer SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TimerSmiEnable
+//
+// Description: This function enables Periodic timer SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TimerSmiEnable (VOID)
+{
+ // Porting required
+#if SWSMI_TIMER_INSTEAD
+ SET_IO32_PM(ACPI_IOREG_SMI_EN, 0x40); // 0x30
+#else
+ SET_IO32_PM(ACPI_IOREG_SMI_EN, 0x4000); // 0x30
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TimerSmiDisable
+//
+// Description: This function disables Periodic timer SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TimerSmiDisable (VOID)
+{
+ // Porting required
+#if SWSMI_TIMER_INSTEAD
+ RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x40); // 0x30
+#else
+ RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x4000); // 0x30
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TimerSmiClear
+//
+// Description: This function clears Periodic timer SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TimerSmiClear (VOID)
+{
+ // Porting required
+#if SWSMI_TIMER_INSTEAD
+ // SWSMI has to be disabled before clear the status
+ volatile UINT32 Buffer32 = READ_IO32_PM(ACPI_IOREG_SMI_EN); // 0x30
+ WRITE_IO32_PM(ACPI_IOREG_SMI_EN, Buffer32 & (UINT32)(~0x40)); // 0x30
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x40); // 0x34
+ WRITE_IO32_PM(ACPI_IOREG_SMI_EN, Buffer32); // 0x30
+#else
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x4000); // 0x34
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TimerSmiDetect
+//
+// Description: This function detects Periodic timer SMI event
+//
+// Input: *Type - Added for compatibility, not used
+//
+// Output: TRUE - Periodic timer SMI occured, FALSE otherwise
+//
+// Notes: Return TRUE if Timer SMI detected, Type ignored
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN TimerSmiDetect (
+ OUT UINT16 *Type )
+{
+ // Porting required
+ *Type = 0;
+#if SWSMI_TIMER_INSTEAD
+ return (IsMe(6)) ? TRUE : FALSE;
+#else
+ return (IsMe(14)) ? TRUE : FALSE;
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TimerSetInterval
+//
+// Description: This function programs Periodic timer to given interval
+//
+// Input: Interval - Interval to program
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TimerSetInterval (
+ IN UINT64 Interval )
+{
+ // Porting required
+ UINT16 RateIndex;
+ UINT16 AvailTimer = sizeof(gSupportedIntervals) / sizeof(UINT64) - 1;
+
+ TimerSmiDisable();
+ TimerSmiClear();
+
+ for (RateIndex = 0; RateIndex < AvailTimer ; RateIndex++)
+ if (Interval == gSupportedIntervals[RateIndex]) break;
+#if SWSMI_TIMER_INSTEAD
+ RW_PCI16_SB(SB_REG_GEN_PMCON_3, RateIndex << 6, 0xc0); // 0xA4
+#else
+ RW_PCI16_SB(SB_REG_GEN_PMCON_1, RateIndex, 3); // 0xA0
+#endif
+
+ TimerSmiEnable();
+}
+
+//---------------------------------------------------------------------------
+// Usb SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UsbSmiSet
+//
+// Description: This function enables/disables USB SMI based on given
+// Controller type
+//
+// Input: ControllerType - USB controller type variable
+//
+// Output: None
+//
+// Notes: This function implements logic as follows:
+// Two lowest bits of ControllerType:
+// 00 - both USB controllers smi are disabled
+// 01 - UHCI/OHCI enabled, EHCI - disabled
+// 10 - UHCI/OHCI disabled, EHCI - enabled
+// 11 - both USB controllers smi are enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID UsbSmiSet(
+ IN UINT16 ControllerType )
+{
+ // Porting required
+ switch (ControllerType & 3) {
+ case 0 :
+ RESET_PCI32_EHCI(EHCI_REG_SPECIAL_SMI, 1);
+ RESET_PCI32_EHCI2(EHCI_REG_SPECIAL_SMI, 1);
+ RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x60008); // 0x30
+ break;
+ case 1 :
+ RESET_PCI32_EHCI(EHCI_REG_SPECIAL_SMI, 1);
+ RESET_PCI32_EHCI2(EHCI_REG_SPECIAL_SMI, 1);
+ RW_IO32_PM(ACPI_IOREG_SMI_EN, 0x08, 0x60008); // 0x30
+ break;
+ case 2 :
+ RW_IO32_PM(ACPI_IOREG_SMI_EN, 0x60000, 0x60008); // 0x30
+ SET_PCI32_EHCI(EHCI_REG_SPECIAL_SMI, 1);
+ SET_PCI32_EHCI2(EHCI_REG_SPECIAL_SMI, 1);
+ break;
+ default:
+ SET_IO32_PM(ACPI_IOREG_SMI_EN, 0x60008); // 0x30
+ SET_PCI32_EHCI(EHCI_REG_SPECIAL_SMI, 1);
+ SET_PCI32_EHCI2(EHCI_REG_SPECIAL_SMI, 1);
+ break;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbSmiClear
+//
+// Description: This function clears USB SMI based on given Controller type
+//
+// Input: UINT16 ControllerType - USB controller type variable
+//
+// Output: None
+//
+// Notes: This function implements logic as follows:
+// Two lowest bits of ControllerType:
+// 00 - Nothing to do
+// 01 - Clear UHCI/OHCI USB SMI status
+// 10 - Clear EHCI USB SMI status
+// 11 - Clear UHCI/OHCI & EHCI USB SMI statuses
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID UsbSmiClear (
+ IN UINT16 ControllerType )
+{
+ // Porting required
+ switch (ControllerType & 3) {
+ case 0 :
+ break;
+ case 1 :
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x08); // 0x34
+ break;
+ case 2 :
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x20000); // 0x34
+ break;
+ default:
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x20008); // 0x34
+ break;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UsbSmiDetect
+//
+// Description: This function detects USB SMI event
+//
+// Input: *Type - Pointer to store USB controller type, source of event
+//
+// Output: TRUE - USB SMI occured, FALSE otherwise
+//
+// Notes: This function implements logic as follows:
+// *Type will be set to
+// 01 - If UHCI/OHCI USB SMI is occured
+// 02 - If EHCI USB SMI is occured
+// 03 - If UHCI/OHCI & EHCI USB SMI is occured
+// 00 - Nothing is occured and return FALSE
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN UsbSmiDetect (
+ OUT UINT16 *Type )
+{
+ // Porting required
+ *Type = 0;
+ if (IsMe(3)) *Type |= 1; // USB_SMI (USB 1.1)
+ if (IsMe(17)) *Type |= 2; // USB_SMI (USB 2.0)
+
+ return (*Type) ? TRUE : FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GetControllerType
+//
+// Description: This function returns USB controller type, based on given
+// device path
+//
+// Input: *Device - Pointer USB device path protocol
+//
+// Output: UINT16 - USB controller type
+//
+// Notes: The USB controller type will be retuened by the follow value:
+// 0 - If there is no matche.
+// 1 - It is an UHCI/OHCI (USB 1.1) controller
+// 2 - It is an EHCI (USB 2.0) controller
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetControllerType (
+ IN EFI_DEVICE_PATH_PROTOCOL *Device)
+{
+
+ // Porting required
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath = Device;
+ PCI_DEVICE_PATH *PciDevicePath = NULL; // [EIP73033]
+ UINT16 ControllerType = 0;
+
+ while (!isEndNode( DevicePath )) {
+ if ((DevicePath->Type == HARDWARE_DEVICE_PATH) && \
+ (DevicePath->SubType == HW_PCI_DP)) {
+ PciDevicePath = (PCI_DEVICE_PATH *) DevicePath;
+ break;
+ }
+ DevicePath = NEXT_NODE (DevicePath);
+ }
+
+ if ((PciDevicePath->Device == EHCI_DEV) || \
+ (PciDevicePath->Device == EHCI2_DEV)) {
+ if ((READ_MEM32_RCRB(0x3598) & 1) == 0) return 2; // RMH Enabled
+ ControllerType = 1;
+ if (PciDevicePath->Function == 0x07) ControllerType = 2;
+ }
+
+ return ControllerType;
+}
+
+//---------------------------------------------------------------------------
+// GPI SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GpiSmiSet
+//
+// Description: This function enables GPI SMI based on given bit field.
+//
+// Input: GpiEnableBit - GPI enabled bit field
+//
+// Output: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID GpiSmiSet (
+ IN UINT32 GpiEnableBit )
+{
+ // Porting required
+
+ UINT8 GpiNum = 0;
+ PCH_SERIES PchSeries = GetPchSeries();
+
+ if (PchSeries == PchLp) {
+ SET_IO32(GPIO_BASE_ADDRESS + GP_IOREG_ALTGP_SMI_EN, GpiEnableBit);
+ } else {
+ SET_IO16_PM(ACPI_IOREG_ALTGP_SMI_EN, (UINT16)GpiEnableBit);
+ }
+
+ while ((GpiEnableBit % 2) == 0) {
+ GpiEnableBit /= 2;
+ GpiNum++;
+ }
+
+ if (PchSeries == PchLp) {
+ //Only GPI[47:32] are capable of SMI# generation.
+ SET_IO16(GPIO_BASE_ADDRESS+GP_IOREG_GPI_ROUT2, (UINT16)GpiEnableBit);
+ } else {
+ RW_PCI32_SB(SB_REG_GPI_ROUT, 1 << (GpiNum * 2), 3 << (GpiNum * 2)); // 0xB8,
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GpiSmiReset
+//
+// Description: This function disables GPI SMI based on given bit field.
+//
+// Input: GpiDisableBit - GPI disabled bit field
+//
+// Output: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID GpiSmiReset (
+ IN UINT32 GpiDisableBit )
+{
+ // Porting required
+
+ UINT8 GpiNum = 0;
+ PCH_SERIES PchSeries = GetPchSeries();
+
+ if (PchSeries == PchLp) {
+ RESET_IO32(GPIO_BASE_ADDRESS + GP_IOREG_ALTGP_SMI_EN, GpiDisableBit);
+ } else {
+ RESET_IO16_PM(ACPI_IOREG_ALTGP_SMI_EN, (UINT16)GpiDisableBit);
+ }
+
+ while ((GpiDisableBit % 2) == 0) {
+ GpiDisableBit /= 2;
+ GpiNum++;
+ }
+
+ if (PchSeries == PchLp) {
+ //Only GPI[47:32] are capable of SMI# generation.
+ RESET_IO16(GPIO_BASE_ADDRESS+GP_IOREG_GPI_ROUT2, (UINT16)GpiDisableBit);
+ } else {
+ RESET_PCI32_SB(SB_REG_GPI_ROUT, 3 << (GpiNum * 2)); // 0xB8,
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GpiSmiClear
+//
+// Description: This function clears GPI SMI status based on given bit field
+//
+// Input: Type - GPI Disabled bit field
+//
+// Output: None
+//
+// Notes: All GPIs which correspondent bit in Type set to 1 should
+// be cleared
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID GpiSmiClear (
+ IN UINT32 GpiClearBit )
+{
+ // Porting required
+ if (GetPchSeries() == PchLp) {
+ WRITE_IO32(GPIO_BASE_ADDRESS + GP_IOREG_ALTGP_SMI_EN, GpiClearBit);
+ } else {
+ WRITE_IO16_PM(ACPI_IOREG_ALTGP_SMI_STS, (UINT16)GpiClearBit);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GpiSmiDetect
+//
+// Description: This function detects GPI SMI event
+//
+// Input: *Gpi - Pointer to store source of GPI SMI
+//
+// Output: TRUE - GPI SMI occured, FALSE otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN GpiSmiDetect (
+ OUT UINT32 *Gpi )
+{
+ // Porting required
+ if (GetPchSeries() == PchLp) {
+ *Gpi = READ_IO32(GPIO_BASE_ADDRESS + GP_IOREG_ALTGP_SMI_EN) & READ_IO32(GPIO_BASE_ADDRESS + GP_IOREG_ALTGP_SMI_STS);
+ } else {
+ *Gpi = READ_IO16_PM(ACPI_IOREG_ALTGP_SMI_EN) & READ_IO16_PM(ACPI_IOREG_ALTGP_SMI_STS);
+ }
+
+ return (*Gpi) ? TRUE : FALSE;
+}
+
+//---------------------------------------------------------------------------
+// Standby button SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SButtonSmiEnable
+//
+// Description: This function enables Standby button SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SButtonSmiEnable (VOID)
+{
+ // Porting required
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SButtonSmiDisable
+//
+// Description: This function disables Standby button SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SButtonSmiDisable (VOID)
+{
+ // Porting required
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SButtonSmiClear
+//
+// Description: This function clears Standby button SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SButtonSmiClear (VOID)
+{
+ // Porting required
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SButtonSmiDetect
+//
+// Description: This function detects Standby button SMI event
+//
+// Input: *Type - Pointer to store value of Standby button phase,
+// not used.
+//
+// Output: TRUE - Standby button SMI occured, FALSE otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN SButtonSmiDetect (
+ OUT UINT16 *Type )
+{
+ // Porting required
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+// Power button SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PButtonSmiEnable
+//
+// Description: This function enables Power button SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID PButtonSmiEnable (VOID)
+{
+ // Porting required
+ SET_IO16_PM(ACPI_IOREG_PM1_EN, 0x100);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PButtonSmiDisable
+//
+// Description: This function disables Power button SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID PButtonSmiDisable (VOID)
+{
+ // Porting required
+ RESET_IO16_PM(ACPI_IOREG_PM1_EN, 0x100);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PButtonSmiClear
+//
+// Description: This function clears Power button SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID PButtonSmiClear (VOID)
+{
+ // Porting required
+ WRITE_IO16_PM(ACPI_IOREG_PM1_STS, 0x100);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PButtonSmiDetect
+//
+// Description: This function detects Power button SMI event
+//
+// Input: *Type - pointer to store value of Power button phase
+// not used.
+//
+// Output: TRUE - Power button SMI occured, FALSE - otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN PButtonSmiDetect (
+ OUT UINT16 *Type )
+{
+ // Porting Required
+ UINT16 Buffer16;
+
+ if ( IsAcpi() ) {
+ return FALSE;
+ } else {
+ Buffer16 = READ_IO16_PM(ACPI_IOREG_PM1_STS) & \
+ READ_IO16_PM(ACPI_IOREG_PM1_EN) & 0x100;
+ return (Buffer16) ? TRUE : FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+// TCO SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TcoSmiSet
+//
+// Description: This function sets TCO functon based on given bit field .
+//
+// Input: TcoBitOffset - The offset of TCO bit will be set.
+//
+// Output: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TcoSmiSet (
+ IN UINT32 TcoBitOffset )
+{
+ UINT32 PchRcba = READ_PCI32_SB(SB_REG_RCBA);
+
+ // NMI2SMI_STS (TCOBASE+04h[0])
+ if (TcoBitOffset == 0) {
+ // Enable NMI by set Port 70h[7] = '0b'
+ SwitchAlternateAccessMode (TRUE);
+ RESET_IO8(CMOS_ADDR_PORT, BIT07);
+ SwitchAlternateAccessMode (FALSE);
+
+ // GBL_SMI_EN = 1
+ SET_IO8_PM(ACPI_IOREG_SMI_EN, BIT00);
+ // Set NMI2SMI_EN = '1b', TCO_BASE + 08h[9]
+ SET_IO16_TCO(TCO_IOREG_CNT1, BIT09);
+ }
+
+ // INTRD_DET (TCOBASE+06h[0])
+ if (TcoBitOffset == 16) {
+ // INTRD_SEL
+ RW_IO16_TCO(TCO_IOREG_STS2, BIT02, (BIT01 | BIT02));
+ }
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TcoSmiReset
+//
+// Description: This function resets TCO functon based on given bit field .
+//
+// Input: TcoBitOffset - The offset of TCO bit will be reset.
+//
+// Output: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TcoSmiReset (
+ IN UINT32 TcoBitOffset )
+{
+ // NMI2SMI_STS (TCOBASE+04h[0])
+ if (TcoBitOffset & BIT00) {
+ // Set NMI2SMI_EN = 0
+ RESET_IO16_TCO(TCO_IOREG_CNT1, BIT09);
+ }
+
+ // INTRD_DET (TCOBASE+06h[0])
+ if (TcoBitOffset & BIT16) {
+ // INTRD_SEL
+ RESET_IO16_TCO(TCO_IOREG_CNT2, (BIT01 | BIT02));
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TcoSmiEnable
+//
+// Description: This function enables TCO SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TcoSmiEnable (VOID)
+{
+ // Porting required
+ SET_IO32_PM(ACPI_IOREG_SMI_EN, 0x2000); // 0x30
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TcoSmiDisable
+//
+// Description: This function disables TCO SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TcoSmiDisable (VOID)
+{
+ // Porting required
+ RESET_IO32_PM(ACPI_IOREG_SMI_EN, 0x2000);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TcoSmiClear
+//
+// Description: This function clears TCO SMI and TCO statuses
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TcoSmiClear (VOID)
+{
+ // Porting required
+ WRITE_IO32_TCO(TCO_IOREG_STS1, (UINT32)SUPPORTED_TCOS); // 0x04
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x2000); // 0x34
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: TcoSmiDetect
+//
+// Description: This function detects TCO SMI event
+//
+// Input: *TcoStatus - Pointer to store TCO SMI status
+//
+// Output: TRUE - TCO SMI occured, FALSE otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN TcoSmiDetect (
+ OUT UINT32 *TcoStatus )
+{
+ // Porting required
+ if ( (IsMe(13)) || (READ_IO8_TCO(TCO_IOREG_STS1) & BIT00)) { // TCO_SMI
+ *TcoStatus = READ_IO32_TCO(TCO_IOREG_STS1); // 0x04
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+// I/O Trap SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IoTrapSmiSet
+//
+// Description: This function sets I/O Trap functon based on given the
+// context
+//
+// Input: IoTrapContext - Pointer to the context that I/O trap register
+// will be enabled.
+//
+// Output: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID IoTrapSmiSet (
+ IN EFI_SMM_IO_TRAP_DISPATCH_CONTEXT *IoTrapContext )
+{
+ // Porting required if needed.
+ UINT32 IoTrapAddr = RCRB_MMIO_IO_TRAP_0; // 0x1E80
+ UINT32 i;
+ UINT32 Buffer32 = 0;
+
+ // Find an available I/O trap register
+ for (i = 0; i < MAX_SUPPORTED_IOTRAP_REGS; i++) {
+ if ((READ_MEM32_RCRB(IoTrapAddr) & 1) == 0) break;
+ IoTrapAddr += 8;
+ }
+
+ IoTrapContext->TrapRegIndex = i;
+
+ if (IoTrapContext->Length < 4) IoTrapContext->Length = 4;
+ Buffer32 = IoTrapContext->Length;
+ for (i = 0; Buffer32 != 1; Buffer32 >>= 1, i++);
+ if (IoTrapContext->Length > (1 << i)) i++;
+
+ IoTrapContext->Length = 1 << i; // Length is always 2^n
+
+ Buffer32 = IoTrapContext->Address & 0xfffc;
+ Buffer32 |= ((IoTrapContext->Length - 1) & 0xfffc) << 16;
+ WRITE_MEM32_RCRB(IoTrapAddr, Buffer32);
+
+ Buffer32 = 0xf0;
+ if (IoTrapContext->TrapWidth == AccessWord) Buffer32 = 0x03;
+ if (IoTrapContext->TrapWidth == AccessDWord) Buffer32 = 0x0f;
+
+ if (IoTrapContext->TrapOpType == ReadWriteIoCycle) {
+ Buffer32 |= (1 << 17); // Both Read/Write Cycles.
+ } else {
+ if (IoTrapContext->TrapOpType == ReadIoCycle)
+ Buffer32 |= (1 << 16); // Read Cycle Only
+ }
+
+ WRITE_MEM32_RCRB(IoTrapAddr + 4, Buffer32);
+ SET_MEM32_RCRB(IoTrapAddr, 1); // Enable Trap and SMI.
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IoTrapSmiReset
+//
+// Description: This function resets I/O Trap functon based on given the
+// context
+//
+// Input: IoTrapContext - Pointer to the context that I/O trap register
+// will be disabled.
+//
+// Output: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID IoTrapSmiReset (
+ IN EFI_SMM_IO_TRAP_DISPATCH_CONTEXT *IoTrapContext )
+{
+ // Porting required if needed.
+ UINT32 IoTrapAddr = RCRB_MMIO_IO_TRAP_0 + IoTrapContext->TrapRegIndex * 8;
+
+ WRITE_MEM32_RCRB(IoTrapAddr, 0);
+ WRITE_MEM32_RCRB(IoTrapAddr + 4, 0);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IoTrapSmiEnable
+//
+// Description: This function enables I/O Trap SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID IoTrapSmiEnable (VOID)
+{
+ // Porting required if needed.
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IoTrapSmiDisable
+//
+// Description: This function disables I/O Trap SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID IoTrapSmiDisable (VOID)
+{
+ // Porting required if needed.
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IoTrapSmiClear
+//
+// Description: This function clears all I/O Trap SMI status.
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID IoTrapSmiClear (VOID)
+{
+ // Porting required
+ SET_MEM32_RCRB(RCRB_MMIO_TRSR, 0); // 0x1E00
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IoTrapSmiDetect
+//
+// Description: This function detects I/O Trap SMI event.
+//
+// Input: *IoTrapContext - Pointer to EFI_SMM_IO_TRAP_DISPATCH_CONTEXT
+//
+// Output: TRUE - I/O Trap SMI occured, the SMI context IoTrapContext
+// should be updated according to the traped H/W
+// information.
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IoTrapSmiDetect (
+ OUT EFI_SMM_IO_TRAP_DISPATCH_CONTEXT *IoTrapContext )
+{
+ UINT32 IoTrapStatus;
+ UINT32 Buffer32;
+
+ // Porting required
+ IoTrapStatus = READ_MEM32_RCRB(RCRB_MMIO_TRSR) & 15; // 0x1E00
+
+ if (IoTrapStatus) {
+
+ IoTrapContext->TrapRegIndex = 0;
+
+ while (IoTrapStatus != 1) {
+ IoTrapStatus >>= 1;
+ IoTrapContext->TrapRegIndex++;
+ }
+
+ Buffer32 = READ_MEM32_RCRB(RCRB_MMIO_TRCR); // 0x1E10
+ IoTrapContext->TrapAddress = Buffer32 & 0xfffc;
+ IoTrapContext->TrapOpType = (Buffer32 & 0x1000000) ? WriteIoCycle :
+ ReadIoCycle;
+ if (IoTrapContext->TrapOpType == WriteIoCycle)
+ IoTrapContext->TrapData = READ_MEM32_RCRB(RCRB_MMIO_TWDR);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+// BIOS Write SMI Handler Porting hooks
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: BiosWriteSmiEnable
+//
+// Description: This function enables BIOS write SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID BiosWriteSmiEnable (VOID)
+{
+ // Enable BIOSWE SMI if needed
+//#### SET_PCI8_SB(SB_REG_BIOS_CNTL, 2); // 0xDC
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: BiosWriteSmiDisable
+//
+// Description: This function disables BIOS write SMI
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID BiosWriteSmiDisable (VOID)
+{
+ // Disable BIOSWE SMI if possible.
+//#### RESET_PCI8_SB(SB_REG_BIOS_CNTL, 2); // 0xDC
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: BiosWriteSmiClear
+//
+// Description: This function clears BIOS write SMI status and disables
+// BIOS write function.
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID BiosWriteSmiClear (VOID)
+{
+ // Only clear BIOSWR_STS
+ WRITE_IO16_TCO(TCO_IOREG_STS1, 0x100); // 0x04
+ // Disable BIOS Write
+ RESET_PCI8_SB(SB_REG_BIOS_CNTL, 1); // 0xDC
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: BiosWriteSmiDetect
+//
+// Description: This function detects BIOS write SMI event
+//
+// Input: None
+//
+// Output: TRUE - BIOS Write SMI occured, FALSE otherwise
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN BiosWriteSmiDetect (VOID)
+{
+ // Check BIOS Lock Enable first.
+ if ((READ_PCI8_SB(SB_REG_BIOS_CNTL) & 2) == 0) return FALSE; // 0xDC
+
+ return (READ_IO16_TCO(TCO_IOREG_STS1) & 0x100) ? TRUE : FALSE; // 0x04
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SbSmiWorkaround
+//
+// Description: This hook is used for all south bridge workaround in SMI.
+//
+// Input: None
+//
+// Output: None
+//
+// Notes: Porting required
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SbSmiWorkaround (VOID)
+{
+ UINT8 DevNum8 = 0;
+ UINT32 BaseAddress;
+ UINT8 Offset;
+ UINT8 EndPort;
+
+ // Sighting #3306438
+ if ((READ_IO32_PM(ACPI_IOREG_SMI_EN) & 0x40000) == 0) return;
+ if ((READ_IO32_PM(ACPI_IOREG_SMI_STS) & 0x40000) == 0) return;
+
+ // Clear the SMI status
+ WRITE_IO32_PM(ACPI_IOREG_SMI_STS, 0x40000);
+
+ if (READ_PCI32_EHCI(EHCI_REG_VID) != 0xffffffff)
+ if ((READ_PCI32_EHCI(EHCI_REG_SPECIAL_SMI) & 0x10001) == 0x10001)
+ DevNum8 = EHCI_DEV;
+
+ if (READ_PCI32_EHCI2(EHCI_REG_VID) != 0xffffffff)
+ if ((READ_PCI32_EHCI2(EHCI_REG_SPECIAL_SMI) & 0x10001) == 0x10001)
+ DevNum8 = EHCI2_DEV;
+
+ if (DevNum8) {
+ // Clear HCReset SMI status
+ WRITE_PCI16(0, DevNum8, 0, EHCI_REG_SPECIAL_SMI + 2, 1);
+
+ BaseAddress = READ_PCI32(0, DevNum8, 0, EHCI_REG_MBASE_ADDR);
+ BaseAddress &= 0xfffffff0;
+ EndPort = (DevNum8 == EHCI2_DEV) ? 0x78 : 0x80;
+
+ for (Offset = 0x68; Offset <= EndPort; Offset += 4) {
+ // Ensure port ownerchip is not been claimed.
+ // Clear "Port Owner" bit, Port N Status and Control(PORTSC) [13],
+ // if it was set.
+ RESET_MEM8(BaseAddress + Offset + 1, 0x20);
+
+ // Set "Port Test Control" bit, PORTSC[19:16], to '1h'.
+ RW_MEM8(BaseAddress + Offset + 2, 0x01, 0x0f);
+
+ // Clear "Port Test Control" bit, PORTSC[19:16], to '0h'.
+ RESET_MEM8(BaseAddress + Offset + 2, 0x0f);
+ }
+ // Clear FC[5];
+ RESET_PCI16(0, DevNum8, 0, EHCI_REG_IR2, 0x20);
+ }
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************