summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.cif24
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.dxs43
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.inf104
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.mak115
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.sdl102
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmm.h727
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmCore.c891
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmGpi.c101
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c317
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.h155
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmIchn.c2425
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c519
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPowerButton.c104
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSw.c87
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSx.c975
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmUsb.c300
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.c820
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.h128
18 files changed, 7937 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.cif b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.cif
new file mode 100644
index 0000000..51c2e34
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.cif
@@ -0,0 +1,24 @@
+<component>
+ name = "PchSmiDispatcher"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\LynxPoint\PchSmiDispatcher\Smm"
+ RefName = "PchSmiDispatcher"
+[files]
+"PchSmiDispatcher.sdl"
+"PchSmiDispatcher.mak"
+"PchSmm.h"
+"PchSmmCore.c"
+"PchSmmHelpers.h"
+"PchSmmHelpers.c"
+"PchxSmmHelpers.h"
+"PchxSmmHelpers.c"
+"PchSmmUsb.c"
+"PchSmmGpi.c"
+"PchSmmPowerButton.c"
+"PchSmmSw.c"
+"PchSmmSx.c"
+"PchSmmIchn.c"
+"PchSmmPeriodicTimer.c"
+"PchSmiDispatcher.dxs"
+"PchSmiDispatcher.inf"
+<endComponent>
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.dxs b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.dxs
new file mode 100644
index 0000000..e0f4908
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.dxs
@@ -0,0 +1,43 @@
+/** @file
+ Dispatch dependency expression file for the PchSmmDispatcher driver.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (SmmBase)
+#include EFI_PROTOCOL_CONSUMER(PciRootBridgeIo)
+#endif
+
+DEPENDENCY_START
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.inf b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
new file mode 100644
index 0000000..a251b73
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
@@ -0,0 +1,104 @@
+## @file
+# Component description file for the Pch SMI Dispatch Handlers module
+#
+#@copyright
+# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+
+[defines]
+BASE_NAME = PchSmiDispatcher
+FILE_GUID = B0D6ED53-B844-43f5-BD2F-61095264E77E
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ PchSmm.h
+ PchSmmCore.c
+ PchSmmHelpers.h
+ PchSmmHelpers.c
+ PchxSmmHelpers.h
+ PchxSmmHelpers.c
+ PchSmmUsb.c
+ PchSmmGpi.c
+ PchSmmPowerButton.c
+ PchSmmSw.c
+ PchSmmSx.c
+ PchSmmIchn.c
+ PchSmmPeriodicTimer.c
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueSmmDriverEntryPoint.c
+
+[libraries.common]
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueUefiDevicePathLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueBasePciLibPciExpress
+ EdkFrameworkProtocolLib
+ EdkProtocolLib
+ $(PROJECT_PCH_FAMILY)ProtocolLib
+ PchPlatformLib
+ EdkIIGlueSmmFirmwarePerformanceLib
+
+[libraries.ia32,libraries.x64]
+
+[includes.common]
+ .
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PchSmiDispatcher.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InitializePchSmmDispatcher
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
+
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.mak b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.mak
new file mode 100644
index 0000000..d4308f8
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.mak
@@ -0,0 +1,115 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSmiDispatcher/PchSmiDispatcher.mak 3 6/24/13 6:08a Scottyang $
+#
+# $Revision: 3 $
+#
+# $Date: 6/24/13 6:08a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSmiDispatcher/PchSmiDispatcher.mak $
+#
+# 3 6/24/13 6:08a Scottyang
+# [TAG] EIP127297
+# [Category] Improvement
+# [Description] Update PCH RC 1.6.0.
+# [Files] SB.sd, SBDxe.c, ..\ReferenceCode\Chipset\LynxPoint\*.*
+#
+# 2 2/24/12 2:14a Victortu
+# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00.
+#
+# 1 2/08/12 8:54a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+
+#---------------------------------------------------------------------------
+# Create PchSmiDispatcher Driver
+#---------------------------------------------------------------------------
+EDK : PchSmiDispatcher
+PchSmiDispatcher : $(BUILD_DIR)\PchSmiDispatcher.mak PchSmiDispatcherBin
+
+
+$(BUILD_DIR)\PchSmiDispatcher.mak : $(PchSmiDispatcher_DIR)\$(@B).cif $(PchSmiDispatcher_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PchSmiDispatcher_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PchSmiDispatcher_INCLUDES=\
+ $(INTEL_PCH_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+
+PchSmiDispatcher_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializePchSmmDispatcher"\
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+
+PchSmiDispatcher_LIB_LINKS =\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiDevicePathLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(PchPlatformSmmLib_LIB)\
+ $(EdkIIGlueSmmFirmwarePerformanceLib_LIB)\
+ $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+
+PchSmiDispatcherBin: $(COMPILERSTUB) $(PchSmiDispatcher_LIB_LINKS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PchSmiDispatcher.mak all \
+ "MY_INCLUDES=$(PchSmiDispatcher_INCLUDES)" \
+ "MY_DEFINES=$(PchSmiDispatcher_DEFINES)" \
+ GUID=B0D6ED53-B844-43f5-BD2F-61095264E77E\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER\
+ EDKIIModule=SMMDRIVER\
+ DEPEX1=$(PchSmiDispatcher_DIR)\PchSmiDispatcher.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.sdl b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.sdl
new file mode 100644
index 0000000..93c2ae0
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmiDispatcher.sdl
@@ -0,0 +1,102 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSmiDispatcher/PchSmiDispatcher.sdl 3 12/30/13 5:10a Barretlin $
+#
+# $Revision: 3 $
+#
+# $Date: 12/30/13 5:10a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSmiDispatcher/PchSmiDispatcher.sdl $
+#
+# 3 12/30/13 5:10a Barretlin
+# [TAG] EIP145008
+# [Category] Improvement
+# [Description] Force Power button event phase always as entry to avoid
+# some power button issue
+# [Files] PchSmiDispatcher.sdl PchSmmPowerButton.c
+#
+# 2 4/25/12 9:22a 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
+#
+# 1 2/08/12 8:54a Yurenlai
+# Intel Lynx Point/SB eChipset initially releases.
+#
+#*************************************************************************
+TOKEN
+ Name = "PchSmiDispatcher_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PchSmiDispatcher support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "INTEL_RC_SMI_DISPATCHER_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "FORCE_PWB_PHASE_AS_ENTRY"
+ Value = "1"
+ Help = "Force Power button event phase always as entry to avoid some power button issue. EIP145008"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+PATH
+ Name = "PchSmiDispatcher_DIR"
+ Help = "PchSmiDispatcher file source directory"
+End
+
+MODULE
+ Help = "Includes PchSmiDispatcher.mak to Project"
+ File = "PchSmiDispatcher.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PchSmiDispatcher.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmm.h b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmm.h
new file mode 100644
index 0000000..864615b
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmm.h
@@ -0,0 +1,727 @@
+/** @file
+ Prototypes and defines for the PCH SMM Dispatcher.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#ifndef PCH_SMM_H
+#define PCH_SMM_H
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+
+#include "EdkIIGlueDxe.h"
+
+//
+// Driver Consumed Protocol Prototypes
+//
+//
+// Used during initialization
+//
+#include EFI_PROTOCOL_DEPENDENCY (PciRootBridgeIo)
+#include EFI_PROTOCOL_CONSUMER (LoadedImage)
+//
+// Used during SMI dispatch
+//
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+#include EFI_PROTOCOL_CONSUMER (SmmControl)
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORTED PROTOCOLS
+//
+#include EFI_PROTOCOL_PRODUCER (SmmUsbDispatch)
+#include EFI_PROTOCOL_PRODUCER (SmmSxDispatch)
+#include EFI_PROTOCOL_PRODUCER (SmmSwDispatch)
+#include EFI_PROTOCOL_PRODUCER (SmmGpiDispatch)
+#include EFI_PROTOCOL_PRODUCER (SmmIchnDispatch)
+#include EFI_PROTOCOL_PRODUCER (SmmIchnDispatchEx)
+#include EFI_PROTOCOL_PRODUCER (SmmPowerButtonDispatch)
+#include EFI_PROTOCOL_PRODUCER (SmmPeriodicTimerDispatch)
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#endif
+///
+/// Define an enumeration for all the supported protocols
+///
+typedef enum {
+ UsbType,
+ SxType,
+ SwType,
+ GpiType,
+ IchnType,
+ IchnExType,
+ PowerButtonType,
+ PeriodicTimerType,
+ PchSmmProtocolTypeMax
+} PCH_SMM_PROTOCOL_TYPE;
+
+///
+/// SPECIFYING A REGISTER
+/// We want a general way of referring to addresses. For this case, we'll only
+/// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+/// However, it's interesting to consider what it would take to support other types
+/// of addresses. To address Will's concern, I think it prudent to accommodate it
+/// early on in the design.
+///
+/// Addresses we need to consider:
+///
+/// Type: Required:
+/// I/O Yes
+/// ACPI (special case of I/O) Only if we want to
+/// TCO (special case of ACPI) Only if we want to
+/// GPIO (special case of I/O) Only if we want to
+/// Memory (or Memory Mapped I/O) Only if we want to
+/// PCIE Yes, for BiosWp
+///
+typedef enum {
+ ///
+ /// IO_ADDR_TYPE, /// unimplemented
+ ///
+ ACPI_ADDR_TYPE,
+ GPIO_ADDR_TYPE,
+ ///
+ /// MEMORY_ADDR_TYPE, /// unimplemented
+ ///
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCIE_ADDR_TYPE,
+ NUM_ADDR_TYPES, ///< count of items in this enum
+ PCH_SMM_ADDR_TYPE_NULL = -1 ///< sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32. Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes. This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR GPIO_ADDR;
+typedef IO_ADDR ACPI_ADDR; ///< can omit
+typedef IO_ADDR TCO_ADDR; ///< can omit
+typedef UINTN MEM_ADDR;
+typedef MEM_ADDR *MEMORY_MAPPED_IO_ADDRESS;
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT8 Reg;
+ UINT8 Fnc;
+ UINT8 Dev;
+ UINT8 Bus;
+ } Fields;
+} PCIE_ADDR;
+
+typedef struct {
+ ADDR_TYPE Type;
+ union {
+ ///
+ /// used to initialize during declaration/definition
+ ///
+ UINT32 raw;
+
+ ///
+ /// used to access useful data
+ ///
+ IO_ADDR io;
+ ACPI_ADDR acpi;
+ TCO_ADDR tco;
+ GPIO_ADDR gpio;
+ MEM_ADDR mem;
+ MEMORY_MAPPED_IO_ADDRESS Mmio;
+ PCIE_ADDR pcie;
+
+ } Data;
+
+} PCH_SMM_ADDRESS;
+
+///
+/// SPECIFYING BITS WITHIN A REGISTER
+/// Here's a struct that helps us specify a source or enable bit.
+///
+typedef struct {
+ PCH_SMM_ADDRESS Reg;
+ UINT8 SizeInBytes; ///< of the register
+ UINT8 Bit;
+} PCH_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused. It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc) ((BitDesc).Reg.Type == PCH_SMM_ADDR_TYPE_NULL) ///< "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = PCH_SMM_ADDR_TYPE_NULL) ///< will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+ { \
+ { \
+ PCH_SMM_ADDR_TYPE_NULL, \
+ { \
+ 0 \
+ } \
+ }, \
+ 0, 0 \
+ }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS 2
+#define NUM_STS_BITS 1
+
+//
+// Flags
+//
+typedef UINT8 PCH_SMM_SOURCE_FLAGS;
+
+//
+// Flags required today
+//
+#define PCH_SMM_NO_FLAGS 0
+#define PCH_SMM_SCI_EN_DEPENDENT 1
+
+//
+// Flags that might be required tomorrow
+//
+///
+/// #define PCH_SMM_CLEAR_WITH_ONE 2 /// may need to support bits that clear by writing 0
+/// #define PCH_SMM_MULTIBIT_FIELD 3 /// may need to support status/enable fields 2 bits wide
+///
+typedef struct {
+ PCH_SMM_SOURCE_FLAGS Flags;
+ PCH_SMM_BIT_DESC En[NUM_EN_BITS];
+ PCH_SMM_BIT_DESC Sts[NUM_STS_BITS];
+} PCH_SMM_SOURCE_DESC;
+//
+// 31 bytes, I think
+//
+#define NULL_SOURCE_DESC_INITIALIZER \
+ { \
+ PCH_SMM_NO_FLAGS, \
+ { \
+ NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ NULL_BIT_DESC_INITIALIZER \
+ } \
+ }
+
+///
+/// CHILD CONTEXTS
+/// To keep consistent w/ the architecture, we'll need to provide the context
+/// to the child when we call its callback function. After talking with Will,
+/// we agreed that we'll need functions to "dig" the context out of the hardware
+/// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+/// contexts to prevent unnecessary dispatches. I'd like a general type for these
+/// "GetContext" functions, so I'll need a union of all the protocol contexts for
+/// our internal use:
+///
+typedef union {
+ //
+ // (in no particular order)
+ //
+ EFI_SMM_ICHN_DISPATCH_CONTEXT Ichn;
+ EFI_SMM_ICHN_DISPATCH_EX_CONTEXT IchnEx;
+ EFI_SMM_SX_DISPATCH_CONTEXT Sx;
+ EFI_SMM_PERIODIC_TIMER_DISPATCH_CONTEXT PeriodicTimer;
+ EFI_SMM_SW_DISPATCH_CONTEXT Sw;
+ EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT PowerButton;
+ EFI_SMM_USB_DISPATCH_CONTEXT Usb;
+ EFI_SMM_GPI_DISPATCH_CONTEXT Gpi;
+} PCH_SMM_CONTEXT;
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+///
+/// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+/// Assumption: We don't need to pass in an enumeration for the protocol because each
+/// GET_CONTEXT function is written for only one protocol.
+/// We also need a function to compare contexts to see if the child should be dispatched
+///
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+ IN DATABASE_RECORD * Record,
+ OUT PCH_SMM_CONTEXT * Context
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+ IN PCH_SMM_CONTEXT * Context1,
+ IN PCH_SMM_CONTEXT * Context2
+ );
+
+///
+/// Finally, every protocol will require a "Get Context" and "Compare Context" call, so
+/// we may as well wrap that up in a table, too.
+///
+typedef struct {
+ GET_CONTEXT GetContext;
+ CMP_CONTEXT CmpContext;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS ContextFunctions[PchSmmProtocolTypeMax];
+
+///
+/// MAPPING CONTEXT TO BIT DESCRIPTIONS
+/// I'd like to have a general approach to mapping contexts to bit descriptions.
+/// Sometimes, we'll find that we can use table lookups or constant assignments;
+/// other times, we'll find that we'll need to use a function to perform the mapping.
+/// If we define a macro to mask that process, we'll never have to change the code.
+/// I don't know if this is desirable or not -- if it isn't, then we can get rid
+/// of the macros and just use function calls or variable assignments. Doesn't matter
+/// to me.
+/// Mapping complex contexts requires a function
+///
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[out] SrcDesc The source description that corresponds to the given context.
+
+ @retval None
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+ @retval None
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern const PCH_SMM_SOURCE_DESC SW_SOURCE_DESC;
+extern const PCH_SMM_SOURCE_DESC SX_SOURCE_DESC;
+extern const PCH_SMM_SOURCE_DESC POWER_BUTTON_SOURCE_DESC;
+
+//
+// With the changes we've made to the protocols, we can now use table
+// lookups for the following protocols:
+//
+#define NUM_SUPPORTED_GPIS 16
+extern const PCH_SMM_SOURCE_DESC LPTH_GPI_SOURCE_DESC[NUM_SUPPORTED_GPIS];
+extern const PCH_SMM_SOURCE_DESC LPTLP_GPI_SOURCE_DESC[NUM_SUPPORTED_GPIS];
+
+extern PCH_SMM_SOURCE_DESC ICHN_H_SOURCE_DESCS[NUM_ICHN_TYPES];
+extern PCH_SMM_SOURCE_DESC ICHN_LP_SOURCE_DESCS[NUM_ICHN_TYPES];
+extern PCH_SMM_SOURCE_DESC ICHN_EX_SOURCE_DESCS[IchnExTypeMAX - IchnExPciExpress];
+
+///
+/// For PCHx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+///
+#define MAXIMUM_SWI_VALUE 0xFF
+
+///
+/// GENERALIZING THE CALLBACK
+/// All SmmXxxDispatch callbacks have the same form:
+///
+/// VOID Callback( EFI_HANDLE, EFI_SMM_Xxx_DISPATCH_CONTEXT )
+/// We need a typedef that'll allow us to call any callback
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CALLBACK) (
+ IN EFI_HANDLE Handle,
+ IN PCH_SMM_CONTEXT * Context
+ );
+
+///
+/// Open: Need to make sure this kind of type cast will actually work.
+/// May need an intermediate form w/ two VOID* arguments. I'll figure
+/// that out when I start compiling.
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CLEAR_SOURCE) (
+ PCH_SMM_SOURCE_DESC * SrcDesc
+ );
+
+///
+/// "DATABASE" RECORD
+/// Linked list data structures
+///
+#define DATABASE_RECORD_SIGNATURE EFI_SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ ///
+ /// Status and Enable bit description
+ ///
+ PCH_SMM_SOURCE_DESC SrcDesc;
+
+ ///
+ /// Callback function
+ ///
+ PCH_SMM_CALLBACK Callback;
+ PCH_SMM_CONTEXT ChildContext;
+
+ ///
+ /// Special handling hooks -- init them to NULL if unused/unneeded
+ ///
+ PCH_SMM_CLEAR_SOURCE ClearSource; ///< needed for SWSMI timer
+
+ ///
+ /// Functions required to make callback code general
+ ///
+ CONTEXT_FUNCTIONS ContextFunctions;
+
+ ///
+ /// The protocol that this record dispatches
+ ///
+ PCH_SMM_PROTOCOL_TYPE ProtocolType;
+
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record) CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+
+///
+/// HOOKING INTO THE ARCHITECTURE
+///
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_REGISTER) (
+ IN VOID **This,
+ IN VOID *DispatchFunction,
+ IN VOID *DispatchContext,
+ OUT EFI_HANDLE * DispatchHandle
+ );
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_UNREGISTER) (
+ IN VOID **This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+///
+/// Define a memory "stamp" equivalent in size and function to most of the protocols
+///
+typedef struct {
+ PCH_SMM_GENERIC_REGISTER Register;
+ PCH_SMM_GENERIC_UNREGISTER Unregister;
+ UINTN Extra1;
+ UINTN Extra2; ///< may not need this one
+} PCH_SMM_GENERIC_PROTOCOL;
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+PchSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN PCH_SMM_CALLBACK DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ );
+
+typedef union {
+ PCH_SMM_GENERIC_PROTOCOL Generic;
+
+ EFI_SMM_USB_DISPATCH_PROTOCOL Usb;
+ EFI_SMM_SX_DISPATCH_PROTOCOL Sx;
+ EFI_SMM_SW_DISPATCH_PROTOCOL Sw;
+ EFI_SMM_GPI_DISPATCH_PROTOCOL Gpi;
+ EFI_SMM_ICHN_DISPATCH_PROTOCOL Ichn;
+ EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL IchnEx;
+ EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL PowerButton;
+ EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL PeriodicTimer;
+} PCH_SMM_PROTOCOL;
+
+///
+/// Define a structure to help us identify the generic protocol
+///
+#define PROTOCOL_SIGNATURE EFI_SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+ UINTN Signature;
+
+ PCH_SMM_PROTOCOL_TYPE Type;
+ PCH_SMM_PROTOCOL Protocols;
+} PCH_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+ CR ( \
+ _generic, \
+ PCH_SMM_QUALIFIED_PROTOCOL, \
+ Protocols, \
+ PROTOCOL_SIGNATURE \
+ )
+
+///
+/// Create private data for the protocols that we'll publish
+///
+typedef struct {
+ LIST_ENTRY CallbackDataBase;
+ EFI_HANDLE InstallMultProtHandle;
+ PCH_SMM_QUALIFIED_PROTOCOL Protocols[PchSmmProtocolTypeMax];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA mPrivateData;
+extern EFI_SMM_SYSTEM_TABLE *mSmst;
+extern UINT32 mAcpiBaseAddr;
+extern UINT32 mGpioBaseAddr;
+extern EFI_SMM_BASE_PROTOCOL *mSmmBase;
+
+/**
+ Get the Software Smi value
+
+ @param[in] Record No use
+ @param[out] Context The context that includes Software Smi value to be filled
+
+ @retval None
+**/
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether software SMI value of two contexts match
+
+ @param[in] Context1 Context 1 that includes software SMI value 1
+ @param[in] Context2 Context 2 that includes software SMI value 2
+
+ @retval FALSE Software SMI value match
+ @retval TRUE Software SMI value don't match
+**/
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+ @retval None
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+ @retval None.
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ );
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+
+ @param[in] None
+
+ @retval None.
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ );
+
+/**
+ Clear the SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchSmmIchnClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Fix the base address of the source regs and status regs.
+ Since Base should get from register filled by platform modules already.
+
+ @param[in] None.
+
+ @retval None.
+**/
+VOID
+PchSmmIchnFixSourceBase (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmCore.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmCore.c
new file mode 100644
index 0000000..89100d5
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmCore.c
@@ -0,0 +1,891 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+// AMI_OVERRIDE, GPIO_ROUT >>>
+#include "Token.h"
+// AMI_OVERRIDE, GPIO_ROUT <<<
+
+///
+/// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/// MODULE / GLOBAL DATA
+///
+/// Module variables used by the both the main dispatcher and the source dispatchers
+/// Declared in PchSmmSources.h
+///
+EFI_SMM_SYSTEM_TABLE *mSmst;
+UINT32 mAcpiBaseAddr;
+UINT32 mGpioBaseAddr;
+EFI_SMM_BASE_PROTOCOL *mSmmBase;
+//
+// The reserved mmio address can only be used in Sx handler
+// it's not reserved in ACPI.
+//
+EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+
+PRIVATE_DATA mPrivateData = { ///< for the structure
+ {
+ NULL
+ }, ///< CallbackDataBase linked list head
+ NULL, ///< EFI handle returned when calling InstallMultipleProtocolInterfaces
+ { ///< protocol arrays
+ ///
+ /// elements within the array
+ ///
+ {
+ PROTOCOL_SIGNATURE,
+ UsbType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SxType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SwType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) MAXIMUM_SWI_VALUE
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ GpiType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) NUM_SUPPORTED_GPIS
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ IchnType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ IchnExType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PowerButtonType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PeriodicTimerType,
+ {
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) PchSmmPeriodicTimerDispatchGetNextShorterInterval
+ }
+ },
+ }
+};
+
+CONTEXT_FUNCTIONS mContextFunctions[PchSmmProtocolTypeMax] = {
+ {
+ NULL,
+ NULL
+ },
+ {
+ SxGetContext,
+ SxCmpContext
+ },
+ {
+ SwGetContext,
+ SwCmpContext
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ PowerButtonGetContext,
+ PowerButtonCmpContext
+ },
+ {
+ PeriodicTimerGetContext,
+ PeriodicTimerCmpContext
+ },
+};
+
+///
+/// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/// PROTOTYPES
+///
+/// Functions use only in this file
+///
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ );
+
+///
+/// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/// FUNCTIONS
+///
+/// Driver entry point
+///
+
+/**
+ Initializes the PCH SMM Dispatcher
+
+ @param[in] ImageHandle Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PchSmmDispatcher Initialization completed.
+**/
+EFI_STATUS
+EFIAPI
+InitializePchSmmDispatcher (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Locate SMM Base Protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+ ///
+ /// Initialize our module variables
+ ///
+ Status = mSmmBase->GetSmstLocation (mSmmBase, &mSmst);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ PERF_START_EX (ImageHandle, L"SmmModule", NULL, AsmReadTsc(), 8);
+
+ ///
+ /// Access ACPI Base Addresses Register
+ ///
+ mAcpiBaseAddr = (UINT32) (MmioRead16 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_ACPI_BASE)
+ ) & B_PCH_LPC_ACPI_BASE_BAR);
+ ASSERT (mAcpiBaseAddr != 0);
+
+ ///
+ /// Access GPIO Base Addresses Register
+ ///
+ mGpioBaseAddr = (UINT32) (MmioRead16 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_GPIO_BASE)
+ ) & B_PCH_LPC_GPIO_BASE_BAR);
+ ASSERT (mGpioBaseAddr != 0);
+
+ ///
+ /// Fix the ICHN_SOURCE_DESCS base, in order to obtain independence with platform.
+ ///
+ PchSmmIchnFixSourceBase ();
+
+ PchSmmPublishDispatchProtocols ();
+
+ ///
+ /// Register a callback function to handle subsequent SMIs. This callback
+ /// will be called by SmmCoreDispatcher.
+ ///
+//AMI_OVERRIDE Support SMM2>>
+ mSmmBase->RegisterCallback (mSmmBase, ImageHandle, PchSmmCoreDispatcher, TRUE, FALSE);
+//AMI_OVERRIDE Support SMM2<<
+
+ ///
+ /// Initialize Callback DataBase
+ ///
+ InitializeListHead (&mPrivateData.CallbackDataBase);
+
+ ///
+ /// Enable SMIs on the PCH now that we have a callback
+ ///
+ PchSmmInitHardware ();
+
+ mResvMmioBaseAddr = 0x0ffffffff;
+#ifndef AMI_OVERRIDE_FOR_PCH
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 16, // 2^16: 64K Alignment
+ 0x10000, // 64K Length
+ &mResvMmioBaseAddr,
+ ImageHandle,
+ NULL
+ );
+#else
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchBottomUp,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 16, // 2^16: 64K Alignment
+ 0x10000, // 64K Length
+ &mResvMmioBaseAddr,
+ ImageHandle,
+ NULL
+ );
+#endif
+ ASSERT_EFI_ERROR (Status);
+ DEBUG((EFI_D_INFO,"mResvMmioBaseAddr %x\n", mResvMmioBaseAddr));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check the Fed SwSmiInputValue to see if there is a duplicated one in the database
+
+ @param[in] FedSwSmiInputValue Fed SwSmiInputValue
+
+ @retval EFI_SUCCESS There is no duplicated SwSmiInputValue
+ @retval EFI_INVALID_PARAMETER There is a duplicated SwSmiInputValue
+**/
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+ UINTN FedSwSmiInputValue
+ )
+{
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ if (RecordInDb->ProtocolType == SwType) {
+ if (RecordInDb->ChildContext.Sw.SwSmiInputValue == FedSwSmiInputValue) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+PchSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN PCH_SMM_CALLBACK DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ PCH_SMM_QUALIFIED_PROTOCOL *Qualified;
+ PCH_SMM_SOURCE_DESC NullSourceDesc = NULL_SOURCE_DESC_INITIALIZER;
+ PCH_SERIES PchSeries;
+ UINTN Index;
+
+ PchSeries = GetPchSeries();
+ Index = 0;
+ ///
+ /// Create database record and add to database
+ ///
+ if (mSmst == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = mSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ///
+ /// Gather information about the registration request
+ ///
+ Record->Callback = DispatchFunction;
+ Record->ChildContext = *DispatchContext;
+
+ Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+ Record->ProtocolType = Qualified->Type;
+
+ Record->ContextFunctions = mContextFunctions[Qualified->Type];
+ ///
+ /// Perform linked list housekeeping
+ ///
+ Record->Signature = DATABASE_RECORD_SIGNATURE;
+
+ switch (Qualified->Type) {
+ ///
+ /// By the end of this switch statement, we'll know the
+ /// source description the child is registering for
+ ///
+ case UsbType:
+ ///
+ /// Check the validity of Context Type
+ ///
+ if ((Record->ChildContext.Usb.Type < UsbLegacy) || (Record->ChildContext.Usb.Type > UsbWake)) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ MapUsbToSrcDesc (DispatchContext, &(Record->SrcDesc));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case SxType:
+ ///
+ /// Check the validity of Context Type and Phase
+ ///
+ if ((Record->ChildContext.Sx.Type < SxS0) ||
+ (Record->ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+ (Record->ChildContext.Sx.Phase < SxEntry) ||
+ (Record->ChildContext.Sx.Phase >= EfiMaximumPhase)
+ ) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (&SX_SOURCE_DESC), sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case SwType:
+ ///
+ /// Check the validity of Context Value
+ ///
+ if (Record->ChildContext.Sw.SwSmiInputValue > MAXIMUM_SWI_VALUE) {
+ goto Error;
+ }
+
+ if (EFI_ERROR (SmiInputValueDuplicateCheck (Record->ChildContext.Sw.SwSmiInputValue))) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (&SW_SOURCE_DESC), sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case GpiType:
+ Index = Record->ChildContext.Gpi.GpiNum;
+ if (PchSeries == PchH) {
+ Index -= V_PCH_LPTH_ALT_GP_SMI_GPIBASE;
+ if (Index >= S_PCH_LPTH_ALT_GP_SMI_GPISIZE) {
+ goto Error;
+ }
+ } else if (PchSeries == PchLp) {
+ Index -= V_PCH_LPTLP_ALT_GP_SMI_GPIBASE;
+ if (Index >= S_PCH_LPTLP_ALT_GP_SMI_GPISIZE) {
+ goto Error;
+ }
+ } else {
+ goto Error;
+ }
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ if (PchSeries == PchH) {
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(LPTH_GPI_SOURCE_DESC[Index]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ } else if (PchSeries == PchLp) {
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(LPTLP_GPI_SOURCE_DESC[Index]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ }
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case IchnType:
+ ///
+ /// Check the validity of Context Type
+ ///
+ if (Record->ChildContext.Ichn.Type >= NUM_ICHN_TYPES) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ if (PchSeries == PchLp) {
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(ICHN_LP_SOURCE_DESCS[Record->ChildContext.Ichn.Type]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ } else if (PchSeries == PchH) {
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(ICHN_H_SOURCE_DESCS[Record->ChildContext.Ichn.Type]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ }
+ Record->ClearSource = PchSmmIchnClearSource;
+ break;
+
+ case IchnExType:
+ ///
+ /// Check the validity of Context Type
+ ///
+ if ((Record->ChildContext.IchnEx.Type < IchnExPciExpress) || (Record->ChildContext.IchnEx.Type >= IchnExTypeMAX)) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(ICHN_EX_SOURCE_DESCS[Record->ChildContext.IchnEx.Type - IchnExPciExpress]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ Record->ClearSource = NULL;
+ break;
+
+ case PowerButtonType:
+ ///
+ /// Check the validity of Context Phase
+ ///
+ if ((Record->ChildContext.PowerButton.Phase < PowerButtonEntry) ||
+ (Record->ChildContext.PowerButton.Phase > PowerButtonExit)
+ ) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) &POWER_BUTTON_SOURCE_DESC, sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case PeriodicTimerType:
+ ///
+ /// Check the validity of timer value
+ ///
+ if (DispatchContext->PeriodicTimer.SmiTickInterval <= 0) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ MapPeriodicTimerToSrcDesc (DispatchContext, &(Record->SrcDesc));
+ Record->ClearSource = PchSmmPeriodicTimerClearSource;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (CompareSources (&Record->SrcDesc, &NullSourceDesc)) {
+ goto Error;
+ }
+
+ if (Record->ClearSource == NULL) {
+ ///
+ /// Clear the SMI associated w/ the source using the default function
+ ///
+ PchSmmClearSource (&Record->SrcDesc);
+ } else {
+ ///
+ /// This source requires special handling to clear
+ ///
+ Record->ClearSource (&Record->SrcDesc);
+ }
+
+ PchSmmEnableSource (&Record->SrcDesc);
+
+// AMI_OVERRIDE, GPIO_ROUT >>>
+// Added GPIO_ROUT (B0:D31:F0 Reg#B8h) initialization for GPI SMI register.
+{
+ UINT32 GpioRout;
+ UINT32 GpioSmiRout;
+
+ if (Qualified->Type == GpiType) {
+ if (PchSeries == PchH) {
+ GpioRout = (UINT32) (MmioRead32 ( \
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH, \
+ PCI_DEVICE_NUMBER_PCH_LPC, \
+ PCI_FUNCTION_NUMBER_PCH_LPC, \
+ R_PCH_LPC_GPI_ROUT)\
+ ));
+
+ GpioRout &= ~(3 << (Record->ChildContext.Gpi.GpiNum * 2));
+ GpioRout |= (1 << (Record->ChildContext.Gpi.GpiNum * 2));
+
+ MmioWrite32 ( \
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH, \
+ PCI_DEVICE_NUMBER_PCH_LPC, \
+ PCI_FUNCTION_NUMBER_PCH_LPC,\
+ R_PCH_LPC_GPI_ROUT), \
+ GpioRout\
+ );
+ }else if(PchSeries == PchLp){
+ if( Record->ChildContext.Gpi.GpiNum >= 32 && Record->ChildContext.Gpi.GpiNum < 48){
+ GpioRout = IoRead32(GPIO_BASE_ADDRESS + R_PCH_LP_LPC_GPI_ROUT1);
+ GpioSmiRout = IoRead32(GPIO_BASE_ADDRESS + R_PCH_LPTLP_ALT_GP_SMI_EN);
+
+ GpioRout |= (1 << (Record->ChildContext.Gpi.GpiNum - 32));
+ GpioSmiRout |= (1 << (Record->ChildContext.Gpi.GpiNum - 32));
+
+ IoWrite32((GPIO_BASE_ADDRESS + R_PCH_LP_LPC_GPI_ROUT1),GpioRout);
+ IoWrite32((GPIO_BASE_ADDRESS + R_PCH_LPTLP_ALT_GP_SMI_EN),GpioSmiRout);
+ }
+ }
+ }
+}
+// AMI_OVERRIDE, GPIO_ROUT <<<
+
+ ///
+ /// Child's handle will be the address linked list link in the record
+ ///
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+
+Error:
+ Status = mSmst->SmmFreePool (Record);
+ ///
+ /// DEBUG((EFI_D_ERROR,"Free pool status %d\n", Status ));
+ ///
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ )
+{
+ ///
+ /// BOOLEAN SafeToDisable;
+ ///
+ DATABASE_RECORD *RecordToDelete;
+
+ ///
+ /// DATABASE_RECORD *RecordInDb;
+ /// EFI_LIST_NODE *LinkInDb;
+ ///
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ ///
+ /// Take the entry out of the linked list
+ ///
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+
+ ///
+ /// See if we can disable the source, reserved for future use since this might
+ /// not be the only criteria to disable
+ ///
+ /// SafeToDisable = TRUE;
+ /// LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ /// while(!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ /// RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ /// if (CompareEnables (&RecordToDelete->SrcDesc, &RecordInDb->SrcDesc)) {
+ /// SafeToDisable = FALSE;
+ /// break;
+ /// }
+ /// LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ /// }
+ /// if (SafeToDisable) {
+ /// PchSmmDisableSource( &Record->SrcDesc );
+ /// }
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ The callback function to handle subsequent SMIs. This callback will be called by SmmCoreDispatcher.
+
+ @param[in] SmmImageHandle Not used
+ @param[in, out] CommunicationBuffer Not used
+ @param[in, out] SourceSize Not used
+
+ @retval EFI_SUCCESS Function successfully completed
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ ///
+ /// Used to prevent infinite loops
+ ///
+ UINTN EscapeCount;
+
+ BOOLEAN ContextsMatch;
+ BOOLEAN EosSet;
+ BOOLEAN SxChildWasDispatched;
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ DATABASE_RECORD *RecordToExhaust;
+ LIST_ENTRY *LinkToExhaust;
+
+ PCH_SMM_CONTEXT Context;
+
+ EFI_STATUS Status;
+
+ PCH_SMM_SOURCE_DESC ActiveSource = NULL_SOURCE_DESC_INITIALIZER;
+
+ EscapeCount = 100;
+ ContextsMatch = FALSE;
+ EosSet = FALSE;
+ SxChildWasDispatched = FALSE;
+ Status = EFI_SUCCESS;
+
+ if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+ ///
+ /// We have children registered w/ us -- continue
+ ///
+ while ((!EosSet) && (EscapeCount > 0)) {
+ EscapeCount--;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ ///
+ /// look for the first active source
+ ///
+ if (!SourceIsActive (&RecordInDb->SrcDesc)) {
+ ///
+ /// Didn't find the source yet, keep looking
+ ///
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+ ///
+ /// if it's the last one, try to clear EOS
+ ///
+ if (IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ EosSet = PchSmmSetAndCheckEos ();
+ }
+ } else {
+ ///
+ /// We found a source. If this is a sleep type, we have to go to
+ /// appropriate sleep state anyway.No matter there is sleep child or not
+ ///
+ if (RecordInDb->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ ///
+ /// "cache" the source description and don't query I/O anymore
+ ///
+ CopyMem ((VOID *) &ActiveSource, (VOID *) &(RecordInDb->SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+ LinkToExhaust = LinkInDb;
+
+ ///
+ /// exhaust the rest of the queue looking for the same source
+ ///
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+ RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+ ///
+ /// RecordToExhaust->Link might be removed (unregistered) by Callback function, and then the
+ /// system will hang in ASSERT() while calling GetNextNode().
+ /// To prevent the issue, we need to get next record in DB here (before Callback function).
+ ///
+ LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+
+ if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+ ///
+ /// These source descriptions are equal, so this callback should be
+ /// dispatched.
+ ///
+ if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+ ///
+ /// This child requires that we get a calling context from
+ /// hardware and compare that context to the one supplied
+ /// by the child.
+ ///
+ ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+ ///
+ /// Make sure contexts match before dispatching event to child
+ ///
+ RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+ ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+ } else {
+ ///
+ /// This child doesn't require any more calling context beyond what
+ /// it supplied in registration. Simply pass back what it gave us.
+ ///
+ ASSERT (RecordToExhaust->Callback != NULL);
+ Context = RecordToExhaust->ChildContext;
+ ContextsMatch = TRUE;
+ }
+
+ if (ContextsMatch) {
+
+ ASSERT (RecordToExhaust->Callback != NULL);
+ PERF_START_EX (NULL, L"SmmFunction", NULL, AsmReadTsc(), RecordToExhaust->ProtocolType);
+ RecordToExhaust->Callback ((EFI_HANDLE) & RecordToExhaust->Link, &Context);
+ PERF_END_EX (NULL, L"SmmFunction", NULL, AsmReadTsc(), RecordToExhaust->ProtocolType);
+ if (RecordToExhaust->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ }
+ }
+ }
+
+ if (RecordInDb->ClearSource == NULL) {
+ ///
+ /// Clear the SMI associated w/ the source using the default function
+ ///
+ PchSmmClearSource (&ActiveSource);
+ } else {
+ ///
+ /// This source requires special handling to clear
+ ///
+ RecordInDb->ClearSource (&ActiveSource);
+ }
+ ///
+ /// Also, try to clear EOS
+ ///
+ EosSet = PchSmmSetAndCheckEos ();
+ ///
+ /// Queue is empty, reset the search
+ ///
+ break;
+ }
+ }
+ }
+ }
+ ///
+ /// If you arrive here, there are two possible reasons:
+ /// (1) you've got problems with clearing the SMI status bits in the
+ /// ACPI table. If you don't properly clear the SMI bits, then you won't be able to set the
+ /// EOS bit. If this happens too many times, the loop exits.
+ /// (2) there was a SMM communicate for callback messages that was received prior
+ /// to this driver.
+ /// If there is an asynchronous SMI that occurs while processing the Callback, let
+ /// all of the drivers (including this one) have an opportunity to scan for the SMI
+ /// and handle it.
+ /// If not, we don't want to exit and have the foreground app. clear EOS without letting
+ /// these other sources get serviced.
+ ///
+ /// This assert is not valid with CSM legacy solution because it generates software SMI
+ /// to test for legacy USB support presence.
+ /// This may not be illegal, so we cannot assert at this time.
+ ///
+ /// ASSERT (EscapeCount > 0);
+ ///
+ if (SxChildWasDispatched) {
+ ///
+ /// A child of the SmmSxDispatch protocol was dispatched during this call;
+ /// put the system to sleep.
+ ///
+ PchSmmSxGoToSleep ();
+ }
+
+ return Status;
+
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmGpi.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmGpi.c
new file mode 100644
index 0000000..e9b16f9
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmGpi.c
@@ -0,0 +1,101 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "PchSmmHelpers.h"
+
+#define LPTH_GPI_INIT_ELEMENT(num) { \
+ PCH_SMM_NO_FLAGS, \
+ { \
+ { \
+ { \
+ ACPI_ADDR_TYPE, R_PCH_LPTH_ALT_GP_SMI_EN \
+ }, \
+ S_PCH_LPTH_ALT_GP_SMI_EN, num, \
+ }, \
+ NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ { \
+ { \
+ ACPI_ADDR_TYPE, R_PCH_LPTH_ALT_GP_SMI_STS \
+ }, \
+ S_PCH_LPTH_ALT_GP_SMI_STS, (num), \
+ }, \
+ } \
+ }
+
+#define LPTLP_GPI_INIT_ELEMENT(num) { \
+ PCH_SMM_NO_FLAGS, \
+ { \
+ { \
+ { \
+ GPIO_ADDR_TYPE, R_PCH_LPTLP_ALT_GP_SMI_EN \
+ }, \
+ S_PCH_LPTLP_ALT_GP_SMI_EN, num, \
+ }, \
+ NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ { \
+ { \
+ GPIO_ADDR_TYPE, R_PCH_LPTLP_ALT_GP_SMI_STS \
+ }, \
+ S_PCH_LPTLP_ALT_GP_SMI_STS, (num), \
+ }, \
+ } \
+ }
+
+const PCH_SMM_SOURCE_DESC LPTH_GPI_SOURCE_DESC[NUM_SUPPORTED_GPIS] = {
+ LPTH_GPI_INIT_ELEMENT(0),
+ LPTH_GPI_INIT_ELEMENT(1),
+ LPTH_GPI_INIT_ELEMENT(2),
+ LPTH_GPI_INIT_ELEMENT(3),
+ LPTH_GPI_INIT_ELEMENT(4),
+ LPTH_GPI_INIT_ELEMENT(5),
+ LPTH_GPI_INIT_ELEMENT(6),
+ LPTH_GPI_INIT_ELEMENT(7),
+ LPTH_GPI_INIT_ELEMENT(8),
+ LPTH_GPI_INIT_ELEMENT(9),
+ LPTH_GPI_INIT_ELEMENT(10),
+ LPTH_GPI_INIT_ELEMENT(11),
+ LPTH_GPI_INIT_ELEMENT(12),
+ LPTH_GPI_INIT_ELEMENT(13),
+ LPTH_GPI_INIT_ELEMENT(14),
+ LPTH_GPI_INIT_ELEMENT(15),
+};
+
+const PCH_SMM_SOURCE_DESC LPTLP_GPI_SOURCE_DESC[NUM_SUPPORTED_GPIS] = {
+ LPTLP_GPI_INIT_ELEMENT(0),
+ LPTLP_GPI_INIT_ELEMENT(1),
+ LPTLP_GPI_INIT_ELEMENT(2),
+ LPTLP_GPI_INIT_ELEMENT(3),
+ LPTLP_GPI_INIT_ELEMENT(4),
+ LPTLP_GPI_INIT_ELEMENT(5),
+ LPTLP_GPI_INIT_ELEMENT(6),
+ LPTLP_GPI_INIT_ELEMENT(7),
+ LPTLP_GPI_INIT_ELEMENT(8),
+ LPTLP_GPI_INIT_ELEMENT(9),
+ LPTLP_GPI_INIT_ELEMENT(10),
+ LPTLP_GPI_INIT_ELEMENT(11),
+ LPTLP_GPI_INIT_ELEMENT(12),
+ LPTLP_GPI_INIT_ELEMENT(13),
+ LPTLP_GPI_INIT_ELEMENT(14),
+ LPTLP_GPI_INIT_ELEMENT(15),
+};
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c
new file mode 100644
index 0000000..062f518
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c
@@ -0,0 +1,317 @@
+/** @file
+ Helper functions for PCH SMM dispatcher.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSmmHelpers.h"
+
+///
+/// #define BIT_ZERO 0x00000001
+///
+const UINT32 BIT_ZERO = 0x00000001;
+
+///
+/// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+///
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ const IN PCH_SMM_SOURCE_DESC *Src1,
+ const IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN loopvar;
+
+ IsEqual = TRUE;
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->En[loopvar].Bit != Src2->En[loopvar].Bit ||
+ Src1->En[loopvar].Reg.Type != Src2->En[loopvar].Reg.Type ||
+ Src1->En[loopvar].Reg.Data.raw != Src2->En[loopvar].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ const IN PCH_SMM_SOURCE_DESC *Src1,
+ const IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN loopvar;
+
+ IsEqual = TRUE;
+
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->Sts[loopvar].Bit != Src2->Sts[loopvar].Bit ||
+ Src1->Sts[loopvar].Reg.Type != Src2->Sts[loopvar].Reg.Type ||
+ Src1->Sts[loopvar].Reg.Data.raw != Src2->Sts[loopvar].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ const IN PCH_SMM_SOURCE_DESC *Src1,
+ const IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ const IN PCH_SMM_SOURCE_DESC *Src
+ )
+{
+ BOOLEAN IsActive;
+ UINTN loopvar;
+
+ BOOLEAN SciEn;
+
+ IsActive = TRUE;
+
+ SciEn = PchSmmGetSciEn ();
+
+ if ((Src->Flags & PCH_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+ ///
+ /// This source is dependent on SciEn, and SciEn == 1. An ACPI OS is present,
+ /// so we shouldn't do anything w/ this source until SciEn == 0.
+ ///
+ IsActive = FALSE;
+
+ } else {
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+
+ if (!IS_BIT_DESC_NULL (Src->En[loopvar])) {
+
+ if (ReadBitDesc (&Src->En[loopvar]) == 0) {
+ IsActive = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+
+ }
+ }
+
+ if (IsActive) {
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+
+ if (!IS_BIT_DESC_NULL (Src->Sts[loopvar])) {
+
+ if (ReadBitDesc (&Src->Sts[loopvar]) == 0) {
+ IsActive = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+
+ }
+ }
+ }
+ }
+
+ return IsActive;
+}
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmEnableSource (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN loopvar;
+
+ ///
+ /// Set enables to 1 by writing a 1
+ ///
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {
+ WriteBitDesc (&SrcDesc->En[loopvar], 1, FALSE);
+ }
+ }
+ ///
+ /// Clear statuses to 0 by writing a 1
+ ///
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
+ WriteBitDesc (&SrcDesc->Sts[loopvar], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmDisableSource (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN loopvar;
+
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {
+ WriteBitDesc (&SrcDesc->En[loopvar], 0, FALSE);
+ }
+ }
+}
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmClearSource (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN loopvar;
+
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
+ WriteBitDesc (&SrcDesc->Sts[loopvar], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN loopvar;
+ BOOLEAN IsSet;
+
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
+ ///
+ /// Write the bit
+ ///
+ WriteBitDesc (&SrcDesc->Sts[loopvar], 1, TRUE);
+
+ ///
+ /// Don't return until the bit actually clears.
+ ///
+ IsSet = TRUE;
+ while (IsSet) {
+ IsSet = ReadBitDesc (&SrcDesc->Sts[loopvar]);
+ ///
+ /// IsSet will eventually clear -- or else we'll have
+ /// an infinite loop.
+ ///
+ }
+ }
+ }
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.h b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.h
new file mode 100644
index 0000000..24ef5f8
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.h
@@ -0,0 +1,155 @@
+/** @file
+ Helper functions for PCH SMM
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef PCH_SMM_HELPERS_H
+#define PCH_SMM_HELPERS_H
+
+#include "PchSmm.h"
+#include "PchxSmmHelpers.h"
+
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+//
+
+/**
+ Publish SMI Dispatch protocols.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ );
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ const IN PCH_SMM_SOURCE_DESC *Src1,
+ const IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ const IN PCH_SMM_SOURCE_DESC *Src1,
+ const IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ const IN PCH_SMM_SOURCE_DESC *Src1,
+ const IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ const IN PCH_SMM_SOURCE_DESC *Src
+ );
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmEnableSource (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmDisableSource (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmClearSource (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ const PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmIchn.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmIchn.c
new file mode 100644
index 0000000..5ecb7d3
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmIchn.c
@@ -0,0 +1,2425 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Ichn dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "PchSmmHelpers.h"
+
+#define PCH_RCRB_BASE_NEED_FIX 0
+
+PCH_SMM_SOURCE_DESC ICHN_H_SOURCE_DESCS[NUM_ICHN_TYPES] = {
+ ///
+ /// IchnMch
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_DMISMI
+ }
+ }
+ },
+ ///
+ /// IchnPme
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0a_EN
+ },
+ S_PCH_ACPI_GPE0a_EN,
+ N_PCH_ACPI_GPE0a_EN_PME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0a_STS
+ },
+ S_PCH_ACPI_GPE0a_STS,
+ N_PCH_ACPI_GPE0a_STS_PME
+ }
+ }
+ },
+ ///
+ /// IchnRtcAlarm
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_EN
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_RTC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_STS
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_RTC
+ }
+ }
+ },
+ ///
+ /// IchnRingIndicate
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0a_EN
+ },
+ S_PCH_ACPI_GPE0a_EN,
+ N_PCH_ACPI_GPE0a_EN_RI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0a_STS
+ },
+ S_PCH_ACPI_GPE0a_STS,
+ N_PCH_ACPI_GPE0a_STS_RI
+ }
+ }
+ },
+ ///
+ /// IchnAc97Wake
+ /// ICH8M has removed AC97 but IchnAc97Wake is the enumed index reserved in framework SmmIchnDispatch protocol,
+ /// we just fill in invalid initializer and not use it.
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnSerialIrq
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SERIRQ
+ }
+ }
+ },
+ ///
+ /// IchnY2KRollover
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NEWCENTURY
+ }
+ }
+ },
+ ///
+ /// IchnTcoTimeout
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_TIMEOUT
+ }
+ }
+ },
+ ///
+ /// IchnOsTco
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_SW_TCO_SMI
+ }
+ }
+ },
+ ///
+ /// IchnNmi
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_CNT)
+ },
+ S_PCH_TCO1_CNT,
+ N_PCH_TCO_CNT_NMI2SMI_EN
+ }
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NMI2SMI
+ }
+ }
+ },
+ ///
+ /// IchnIntruderDetect
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO2_CNT)
+ },
+ S_PCH_TCO2_CNT,
+ N_PCH_TCO2_CNT_INTRD_SEL
+ }
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO2_STS)
+ },
+ S_PCH_TCO2_STS,
+ N_PCH_TCO2_STS_INTRD_DET
+ }
+ }
+ },
+ ///
+ /// IchnBiosWp
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 8) |
+ R_PCH_LPC_BIOS_CNTL
+ )
+ },
+ S_PCH_LPC_BIOS_CNTL,
+ N_PCH_LPC_BIOS_CNTL_BLE
+ }
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_BIOSWR
+ }
+ }
+ },
+ ///
+ /// IchnMcSmi
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_MCSMI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MCSMI
+ }
+ }
+ },
+ ///
+ /// IchnPmeB0
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0a_EN
+ },
+ S_PCH_ACPI_GPE0a_EN,
+ N_PCH_ACPI_GPE0a_EN_PME_B0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0a_STS
+ },
+ S_PCH_ACPI_GPE0a_STS,
+ N_PCH_ACPI_GPE0a_STS_PME_B0
+ }
+ }
+ },
+ ///
+ /// IchnThrmSts (THRM# signal no longer existed in PCH)
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnSmBus
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SMBUS
+ }
+ }
+ },
+ ///
+ /// IchnIntelUsb2
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_INTEL_USB2
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_INTEL_USB2
+ }
+ }
+ },
+ ///
+ /// IchnMonSmi7
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnMonSmi6
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnMonSmi5
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnMonSmi4
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap13
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap12, KBC_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 12
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap11
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap10
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap9, PIRQDH_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 9
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap8, PIRQCG_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 8
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap7, PIRQBF_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 7
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap6, PIRQAE_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 6
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap5
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap3
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap2
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap1
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap0, IDE_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 0
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 3 monitor,
+ /// The "PCH_RCRB_BASE_NEED_FIX" should be fixed since the RCRB base should get from the RCBA register filled by platform module.
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_3
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 3
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 2 monitor
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_2
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 2
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 1 monitor
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_1
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 1
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 0 monitor
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_0
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 0
+ }
+ }
+ }
+};
+
+PCH_SMM_SOURCE_DESC ICHN_LP_SOURCE_DESCS[NUM_ICHN_TYPES] = {
+ ///
+ /// IchnMch
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_DMISMI
+ }
+ }
+ },
+ ///
+ /// IchnPme
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0_EN_127_96
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_PME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0_STS_127_96
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_PME
+ }
+ }
+ },
+ ///
+ /// IchnRtcAlarm
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_EN
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_RTC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_STS
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_RTC
+ }
+ }
+ },
+ ///
+ /// IchnRingIndicate
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0_EN_127_96
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_RI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0_STS_127_96
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_RI
+ }
+ }
+ },
+ ///
+ /// IchnAc97Wake
+ /// ICH8M has removed AC97 but IchnAc97Wake is the enumed index reserved in framework SmmIchnDispatch protocol,
+ /// we just fill in invalid initializer and not use it.
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnSerialIrq
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SERIRQ
+ }
+ }
+ },
+ ///
+ /// IchnY2KRollover
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NEWCENTURY
+ }
+ }
+ },
+ ///
+ /// IchnTcoTimeout
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_TIMEOUT
+ }
+ }
+ },
+ ///
+ /// IchnOsTco
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_SW_TCO_SMI
+ }
+ }
+ },
+ ///
+ /// IchnNmi
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_CNT)
+ },
+ S_PCH_TCO1_CNT,
+ N_PCH_TCO_CNT_NMI2SMI_EN
+ }
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NMI2SMI
+ }
+ }
+ },
+ ///
+ /// IchnIntruderDetect
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO2_CNT)
+ },
+ S_PCH_TCO2_CNT,
+ N_PCH_TCO2_CNT_INTRD_SEL
+ }
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO2_STS)
+ },
+ S_PCH_TCO2_STS,
+ N_PCH_TCO2_STS_INTRD_DET
+ }
+ }
+ },
+ ///
+ /// IchnBiosWp
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 8) |
+ R_PCH_LPC_BIOS_CNTL
+ )
+ },
+ S_PCH_LPC_BIOS_CNTL,
+ N_PCH_LPC_BIOS_CNTL_BLE
+ }
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ (PCH_TCO_BASE + R_PCH_TCO1_STS)
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_BIOSWR
+ }
+ }
+ },
+ ///
+ /// IchnMcSmi
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_MCSMI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MCSMI
+ }
+ }
+ },
+ ///
+ /// IchnPmeB0
+ ///
+ {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0_EN_127_96
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_PME_B0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_GPE0_STS_127_96
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_PME_B0
+ }
+ }
+ },
+ ///
+ /// IchnThrmSts (THRM# signal no longer existed in PCH)
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnSmBus
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SMBUS
+ }
+ }
+ },
+ ///
+ /// IchnIntelUsb2
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_INTEL_USB2
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_INTEL_USB2
+ }
+ }
+ },
+ ///
+ /// IchnMonSmi7
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnMonSmi6
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnMonSmi5
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnMonSmi4
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap13
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap12, KBC_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 12
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap11
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap10
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap9, PIRQDH_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 9
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap8, PIRQCG_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 8
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap7, PIRQBF_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 7
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap6, PIRQAE_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 6
+ }
+ }
+ },
+ ///
+ /// IchnDevTrap5
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap3
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap2
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap1
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ NULL_BIT_DESC_INITIALIZER
+ }
+ },
+ ///
+ /// IchnDevTrap0, IDE_ACT_STS
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_DEVACT_STS
+ },
+ S_PCH_DEVACT_STS,
+ 0
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 3 monitor,
+ /// The "PCH_RCRB_BASE_NEED_FIX" should be fixed since the RCRB base should get from the RCBA register filled by platform module.
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_3
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 3
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 2 monitor
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_2
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 2
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 1 monitor
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_1
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 1
+ }
+ }
+ },
+ ///
+ /// PCH I/O Trap register 0 monitor
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_IO_TRAP_0
+ },
+ 8,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCH_RCRB_BASE_NEED_FIX + R_PCH_RCRB_TRSR
+ },
+ 1,
+ 0
+ }
+ }
+ }
+};
+
+PCH_SMM_SOURCE_DESC ICHN_EX_SOURCE_DESCS[IchnExTypeMAX - IchnExPciExpress] = {
+ ///
+ /// IchnExPciExpress
+ ///
+ NULL_SOURCE_DESC_INITIALIZER,
+ ///
+ /// IchnExMonitor
+ ///
+ NULL_SOURCE_DESC_INITIALIZER,
+ ///
+ /// IchnExSpi
+ ///
+ NULL_SOURCE_DESC_INITIALIZER,
+ ///
+ /// IchnExQRT
+ ///
+ NULL_SOURCE_DESC_INITIALIZER,
+ ///
+ /// IchnExGpioUnlock
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_GPIO_UNLOCK
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_UNLOCK
+ }
+ }
+ },
+ ///
+ /// IchnExTmrOverflow
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_EN
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_TMROF
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_STS
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_TMROF
+ }
+ }
+ },
+ ///
+ /// IchnExPcie0Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie1Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie2Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie3Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie4Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie5Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie6Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie7Hotplug
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ }
+ },
+ ///
+ /// IchnExPcie0LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie1LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie2LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie3LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie4LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie5LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie6LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ },
+ ///
+ /// IchnExPcie7LinkActive
+ ///
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8 << 8) |
+ R_PCH_PCIE_MPC
+ )
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16) |
+ (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8 << 8) |
+ R_PCH_PCIE_SMSCS
+ )
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ }
+ }
+};
+
+///
+/// TCO_STS bit that needs to be cleared
+///
+PCH_SMM_SOURCE_DESC TCO_STS = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+ }
+};
+
+/**
+ Clear the SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchSmmIchnClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ if ((
+ (SrcDesc->Sts[0].Reg.Data.acpi == PCH_TCO_BASE + R_PCH_TCO1_STS) &&
+ (SrcDesc->Sts[0].Bit == N_PCH_TCO1_STS_NEWCENTURY)
+ ) ||
+ (
+ (SrcDesc->Sts[0].Reg.Data.acpi == PCH_TCO_BASE + R_PCH_TCO2_STS) &&
+ (SrcDesc->Sts[0].Bit == N_PCH_TCO2_STS_INTRD_DET)
+ )
+ ) {
+ ///
+ /// This is the Y2K rollover bit and requires special handling
+ ///
+ PchSmmClearSourceAndBlock (SrcDesc);
+ } else {
+ PchSmmClearSource (SrcDesc);
+ }
+ ///
+ /// Any TCO-based status bits require special handling.
+ /// SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ ///
+ PchSmmClearSource (&TCO_STS);
+}
+
+/**
+ Fix the base address of the source regs and status regs.
+ Since Base should get from register filled by platform modules already.
+
+ @param[in] None.
+
+ @retval None.
+**/
+VOID
+PchSmmIchnFixSourceBase (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries();
+ ///
+ /// We need to fix the IoTrap item's RCRB base,
+ ///
+ if (PchSeries == PchLp) {
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap3].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_3);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap3].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap2].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_2);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap2].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap1].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_1);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap1].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap0].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_0);
+ ICHN_LP_SOURCE_DESCS[IchnIoTrap0].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ } else if (PchSeries == PchH) {
+ ICHN_H_SOURCE_DESCS[IchnIoTrap3].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_3);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap3].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap2].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_2);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap2].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap1].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_1);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap1].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap0].En[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_IO_TRAP_0);
+ ICHN_H_SOURCE_DESCS[IchnIoTrap0].Sts[0].Reg.Data.mem = (MEM_ADDR) (PCH_RCRB_BASE + R_PCH_RCRB_TRSR);
+ }
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
new file mode 100644
index 0000000..ee554f7
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
@@ -0,0 +1,519 @@
+/** @file
+ File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSmmHelpers.h"
+
+typedef enum {
+ PERIODIC_TIMER= 0,
+ SWSMI_TIMER,
+ NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL {
+ UINT64 Interval;
+ UINT8 AssociatedTimer;
+} TIMER_INTERVAL;
+
+#define NUM_INTERVALS 8
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s 640000000 ///< 64 s
+#define TIME_32s 320000000 ///< 32 s
+#define TIME_16s 160000000 ///< 16 s
+#define TIME_8s 80000000 ///< 8 s
+#define TIME_64ms 640000 ///< 64 ms
+#define TIME_32ms 320000 ///< 32 ms
+#define TIME_16ms 160000 ///< 16 ms
+#define TIME_1_5ms 15000 ///< 1.5 ms
+
+typedef enum {
+ INDEX_TIME_64s = 0,
+ INDEX_TIME_32s,
+ INDEX_TIME_16s,
+ INDEX_TIME_8s,
+ INDEX_TIME_64ms,
+ INDEX_TIME_32ms,
+ INDEX_TIME_16ms,
+ INDEX_TIME_1_5ms,
+ INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+static TIMER_INTERVAL mSmmPeriodicTimerIntervals[NUM_INTERVALS] = {
+ {
+ TIME_64s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_32s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_16s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_8s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_64ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_32ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_16ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_1_5ms,
+ SWSMI_TIMER
+ },
+};
+
+typedef struct _TIMER_INFO {
+ UINTN NumChildren; ///< number of children using this timer
+ UINT64 MinReqInterval; ///< minimum interval required by children
+ UINTN CurrentSetting; ///< interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+TIMER_INFO mTimers[NUM_TIMERS];
+
+PCH_SMM_SOURCE_DESC mTIMER_SOURCE_DESCS[NUM_TIMERS] = {
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_PERIODIC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PERIODIC
+ }
+ }
+ },
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_SWSMI_TMR
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SWSMI_TMR
+ }
+ }
+ }
+};
+
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ VOID
+ );
+
+/**
+ Convert the dispatch context to the timer interval, this function will assert if then either:
+ (1) The context contains an invalid interval
+ (2) The timer interval table is corrupt
+
+ @param[in] DispatchContext The pointer to the Dispatch Context
+
+ @retval TIMER_INTERVAL The timer interval of input dispatch context
+**/
+TIMER_INTERVAL *
+ContextToTimerInterval (
+ IN PCH_SMM_CONTEXT *DispatchContext
+ )
+{
+ UINTN loopvar;
+
+ ///
+ /// Determine which timer this child is using
+ ///
+ for (loopvar = 0; loopvar < NUM_INTERVALS; loopvar++) {
+ if (((DispatchContext->PeriodicTimer.SmiTickInterval == 0) &&
+ (DispatchContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+ (DispatchContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)) {
+ return &mSmmPeriodicTimerIntervals[loopvar];
+ }
+ }
+ ///
+ /// If this assertion fires, then either:
+ /// (1) the context contains an invalid interval
+ /// (2) the timer interval table is corrupt
+ ///
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+ @retval None
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ///
+ /// Figure out which timer the child is requesting and
+ /// send back the source description
+ ///
+ TimerInterval = ContextToTimerInterval (DispatchContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ CopyMem (
+ (VOID *) SrcDesc,
+ (VOID *) (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+
+ ///
+ /// Program the value of the interval into hardware
+ ///
+ PchSmmPeriodicTimerProgramTimers ();
+}
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *HwContext
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+ ///
+ /// Ignore the hardware context. It's not required for this protocol.
+ /// Instead, just increment the child's context.
+ /// Update the elapsed time w/ the data from our tables
+ ///
+ Record->ChildContext.PeriodicTimer.ElapsedTime += TimerInterval->Interval;
+ *HwContext = Record->ChildContext;
+}
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *HwContext,
+ IN PCH_SMM_CONTEXT *ChildContext
+ )
+{
+
+ if (ChildContext->PeriodicTimer.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+ ///
+ /// This child should be dispatched
+ /// Need reset ElapsedTime, or SMI handler will be invoked during SmiTickInterval instead of Period.
+ ///
+ ChildContext->PeriodicTimer.ElapsedTime = 0;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ VOID
+ )
+{
+ UINT16 GenPmCon1;
+ UINT8 GenPmCon3;
+ SUPPORTED_TIMER Timer;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ UINTN PciD31F0RegBase;
+ TIMER_INTERVAL *TimerInterval;
+
+ PciD31F0RegBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0
+ );
+ ///
+ /// Find the minimum required interval for each timer
+ ///
+ for (Timer = 0; Timer < NUM_TIMERS; Timer++) {
+ mTimers[Timer].MinReqInterval = ~ (UINT64) 0x0;
+ mTimers[Timer].NumChildren = 0;
+ }
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ ///
+ /// This child is registerd with the PeriodicTimer protocol
+ ///
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ Timer = TimerInterval->AssociatedTimer;
+ if (Timer < 0 || Timer >= NUM_TIMERS) {
+ ASSERT (FALSE);
+ EFI_DEADLOOP ();
+ }
+
+ if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+ mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+ }
+
+ mTimers[Timer].NumChildren++;
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ ///
+ /// Program the hardware
+ ///
+ if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+ GenPmCon1 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1);
+
+ GenPmCon1 &= ~B_PCH_LPC_GEN_PMCON_PER_SMI_SEL;
+ switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+ case TIME_64s:
+ GenPmCon1 |= V_PCH_LPC_GEN_PMCON_PER_SMI_64S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+ break;
+
+ case TIME_32s:
+ GenPmCon1 |= V_PCH_LPC_GEN_PMCON_PER_SMI_32S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+ break;
+
+ case TIME_16s:
+ GenPmCon1 |= V_PCH_LPC_GEN_PMCON_PER_SMI_16S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+ break;
+
+ case TIME_8s:
+ GenPmCon1 |= V_PCH_LPC_GEN_PMCON_PER_SMI_8S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1, GenPmCon1);
+
+ ///
+ /// Restart the timer here, just need to clear the SMI
+ ///
+ PchSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ } else {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ }
+
+ if (mTimers[SWSMI_TIMER].NumChildren > 0) {
+ ///
+ /// ICH9, ICH10 and PCH share the same bit positions for SW SMI Rate settings
+ ///
+ GenPmCon3 = MmioRead8 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3);
+ GenPmCon3 &= ~B_PCH_LPC_GEN_PMCON_SWSMI_RTSL;
+ switch (mTimers[SWSMI_TIMER].MinReqInterval) {
+ case TIME_64ms:
+ GenPmCon3 |= V_PCH_LPC_GEN_PMCON_SWSMI_RTSL_64MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_64ms;
+ break;
+
+ case TIME_32ms:
+ GenPmCon3 |= V_PCH_LPC_GEN_PMCON_SWSMI_RTSL_32MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_32ms;
+ break;
+
+ case TIME_16ms:
+ GenPmCon3 |= V_PCH_LPC_GEN_PMCON_SWSMI_RTSL_16MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_16ms;
+ break;
+
+ case TIME_1_5ms:
+ GenPmCon3 |= V_PCH_LPC_GEN_PMCON_SWSMI_RTSL_1_5MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// SWSMI_RATE_SEL BIT (D31:F0:A4h[7:6]) bits are in RTC well
+ ///
+ MmioWrite8 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, GenPmCon3);
+
+ ///
+ /// Restart the timer here, need to disable, clear, then enable to restart this timer
+ ///
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ PchSmmClearSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ PchSmmEnableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ } else {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ }
+}
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ )
+{
+ TIMER_INTERVAL *IntervalPointer;
+
+ ASSERT (SmiTickInterval != NULL);
+
+ IntervalPointer = (TIMER_INTERVAL *) *SmiTickInterval;
+
+ if (IntervalPointer == NULL) {
+ ///
+ /// The first time child requesting an interval
+ ///
+ IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+ } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1]) {
+ ///
+ /// At end of the list
+ ///
+ IntervalPointer = NULL;
+ } else {
+ if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+ (IntervalPointer < &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1])
+ ) {
+ ///
+ /// Get the next interval in the list
+ ///
+ IntervalPointer++;
+ } else {
+ ///
+ /// Input is out of range
+ ///
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (IntervalPointer != NULL) {
+ *SmiTickInterval = &IntervalPointer->Interval;
+ } else {
+ *SmiTickInterval = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+ @retval None.
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmPeriodicTimerProgramTimers ();
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPowerButton.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPowerButton.c
new file mode 100644
index 0000000..e172808
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmPowerButton.c
@@ -0,0 +1,104 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Power Button dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "Token.h"
+#include "PchSmmHelpers.h"
+
+const PCH_SMM_SOURCE_DESC POWER_BUTTON_SOURCE_DESC = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_EN
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_PWRBTN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_ACPI_PM1_STS
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_PWRBTN
+ }
+ }
+};
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT16 GenPmCon1;
+
+ GenPmCon1 = MmioRead16 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_GEN_PMCON_1)
+ );
+
+ if ((GenPmCon1 & B_PCH_LPC_GEN_PMCON_PWRBTN_LVL) != 0) {
+ Context->PowerButton.Phase = PowerButtonExit;
+ } else {
+ Context->PowerButton.Phase = PowerButtonEntry;
+ }
+
+// AMI_OVERRIDE, EIP145008, forced PowerButton.Phase as PowerButtonEntry.>>>
+#if defined FORCE_PWB_PHASE_AS_ENTRY && FORCE_PWB_PHASE_AS_ENTRY == 1
+ Context->PowerButton.Phase = PowerButtonEntry;
+#endif
+// AMI_OVERRIDE, EIP145008, forced PowerButton.Phase as PowerButtonEntry.<<<
+}
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->PowerButton.Phase == Context2->PowerButton.Phase);
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSw.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSw.c
new file mode 100644
index 0000000..9a20df3
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSw.c
@@ -0,0 +1,87 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "PchSmmHelpers.h"
+
+const PCH_SMM_SOURCE_DESC SW_SOURCE_DESC = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_APMC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_APM
+ }
+ }
+};
+
+/**
+ Get the Software Smi value
+
+ @param[in] Record No use
+ @param[out] Context The context that includes Software Smi value to be filled
+
+ @retval None
+**/
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT8 ApmCnt;
+
+ ApmCnt = IoRead8 ((UINTN) R_PCH_APM_CNT);
+
+ Context->Sw.SwSmiInputValue = ApmCnt;
+}
+
+/**
+ Check whether software SMI value of two contexts match
+
+ @param[in] Context1 Context 1 that includes software SMI value 1
+ @param[in] Context2 Context 2 that includes software SMI value 2
+
+ @retval FALSE Software SMI value match
+ @retval TRUE Software SMI value don't match
+**/
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue);
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSx.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSx.c
new file mode 100644
index 0000000..3f7e3e2
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmSx.c
@@ -0,0 +1,975 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSmmHelpers.h"
+
+extern EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+///
+/// Maximum loop time for GbE status check
+///
+#define GBE_MAX_LOOP_TIME 4000
+
+const PCH_SMM_SOURCE_DESC SX_SOURCE_DESC = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_ON_SLP_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ON_SLP_EN
+ }
+ }
+};
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+ @retval None
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT32 Pm1Cnt;
+
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ ///
+ /// By design, the context phase will always be ENTRY
+ ///
+ Context->Sx.Phase = SxEntry;
+
+ ///
+ /// Map the PM1_CNT register's SLP_TYP bits to the context type
+ ///
+ switch (Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) {
+ case V_PCH_ACPI_PM1_CNT_S0:
+ Context->Sx.Type = SxS0;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S1:
+ Context->Sx.Type = SxS1;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S3:
+ Context->Sx.Type = SxS3;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S4:
+ Context->Sx.Type = SxS4;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S5:
+ Context->Sx.Type = SxS5;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sx.Type == Context2->Sx.Type);
+}
+
+/**
+ Check ready flag to see if writing to MDIC is done.
+
+ @param[in] GbEBar GbE Memory Base Address Register
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_TIMEOUT Checking flag time out.
+**/
+EFI_STATUS
+CheckReadyFlag (
+ UINT32 GbEBar
+ )
+{
+ UINT32 ReadyFlag;
+ UINT32 LoopTime;
+
+ ReadyFlag = 0;
+
+ for (LoopTime = 0; LoopTime < GBE_MAX_LOOP_TIME; LoopTime++) {
+ ReadyFlag = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR3) & B_PCH_MBARA_GBECSR3_RB;
+
+ if (ReadyFlag) {
+ break;
+ }
+
+ PchPmTimerStall (10);
+ }
+
+ if (LoopTime >= GBE_MAX_LOOP_TIME) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PCH BIOS Spec Rev 0.5.0 Section 10.5
+ Additional Internal GbE Controller special cases WOL Support
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GbES02SxWorkaround (
+ VOID
+ )
+{
+ UINTN PciD25F0RegBase;
+ UINTN PciD31F0RegBase;
+ UINT32 GbEBar;
+ UINT32 GbEBarB;
+ UINT16 CmdReg;
+ UINT32 RAL0;
+ UINT32 RAH0;
+ UINT32 PhyCtrl;
+ UINT32 ExtCnfCtrl;
+ UINT32 Buffer;
+ UINT32 LoopTime;
+ UINT32 RootComplexBar;
+ UINT32 PchGpioBase;
+ EFI_STATUS Status;
+
+ PciD25F0RegBase = MmPciAddress (
+ 0,
+ PCI_BUS_NUMBER_PCH_LAN,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN,
+ 0
+ );
+ PciD31F0RegBase = MmPciAddress (
+ 0,
+ 0,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0
+ );
+ RootComplexBar = PCH_RCRB_BASE;
+ PchGpioBase = (MmioRead32 (PciD31F0RegBase + R_PCH_LPC_GPIO_BASE)) &~BIT0;
+ GbEBar = 0;
+ GbEBarB = 0;
+ CmdReg = 0;
+ Buffer = 0;
+
+ if (((MmioRead16 (RootComplexBar + R_PCH_RCRB_BUC)) & BIT5) == 0) {
+ ///
+ /// System BIOS requires to program the registers listed below for internal GbE to function upon S0 to S3,4,5 transition
+ /// (When ME off and GbE device in D0)
+ ///
+ /// Note: Time out should be applied for MBARA + Offset 20h[28] verification to avoid non respond loop. Upon time out,
+ /// system BIOS is required to clear MBARA + Offset F00h [5] = 0b before exiting the WA.
+ ///
+ /// Check if GbE device is in D0 state
+ ///
+ if ((MmioRead16 (PciD25F0RegBase + R_PCH_LAN_PMCS) & (UINT16) B_PCH_LAN_PMCS_PS) == (UINT16) V_PCH_LAN_PMCS_PS0) {
+ GbEBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A);
+ ///
+ /// Step 1
+ /// If MBARA + Offset 5800h [0] = 1b then proceed the steps below
+ ///
+ if (MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR9) & B_PCH_MBARA_GBECSR9_APME) {
+ ///
+ /// Step 2
+ /// System BIOS perform read to MBARA + Offset 5400h [31:0], MBARA + Offset 5404h [31:0]
+ /// and MBARA + Offset F00h [31:0]
+ ///
+ RAL0 = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR7);
+ RAH0 = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR8);
+ ExtCnfCtrl = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR5);
+ ///
+ /// Step 3
+ /// Ensure that MBARA + Offset F00h [5] = 1b
+ /// a. Set MBARA + Offset F00h [31:0] value with the value read in step 2 or with 0x20 (set bit 5)
+ /// b. Read MBARA + Offset F00h
+ /// c. If MBARA + Offset F00h [5] = 1b (true) continue else wait X Sec and go back to step 3.b for Y times
+ /// (X*Y totals to ~200mSec) if false - exit flow by jumping to step 32.
+ ///
+ MmioWrite32 (GbEBar + R_PCH_MBARA_GBECSR5, ExtCnfCtrl | B_PCH_MBARA_GBECSR5_SWFLAG);
+
+ for (LoopTime = 0; LoopTime < GBE_MAX_LOOP_TIME; LoopTime++) {
+ ExtCnfCtrl = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR5);
+
+ if (ExtCnfCtrl & B_PCH_MBARA_GBECSR5_SWFLAG) {
+ break;
+ }
+
+ PchPmTimerStall (50);
+ }
+
+ if (LoopTime >= GBE_MAX_LOOP_TIME) {
+ goto ExitGbEWa;
+ }
+ ///
+ /// Step 4
+ /// If MBARA + Offset 5B54h [15] = 1b then jump to Step 10
+ ///
+ if ((MmioRead32 (GbEBar + 0x5B54) & BIT15) != BIT15) {
+ ///
+ /// Step 5
+ /// If MBARA + Offset F10h [2] = 1b, then set MBARA + Offset F10h[1] = 1b. Else clear MBARA + Offset F10h[1] = 0b
+ ///
+ if (MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR6) & B_PCH_MBARA_GBECSR6_LPLUND) {
+ MmioOr32 (GbEBar + R_PCH_MBARA_GBECSR6, (UINT32) B_PCH_MBARA_GBECSR6_LPLUD);
+ } else {
+ MmioAnd32 (GbEBar + R_PCH_MBARA_GBECSR6, (UINT32)~B_PCH_MBARA_GBECSR6_LPLUD);
+ }
+ ///
+ /// Step 6
+ /// Set MBARA + Offset 20h = 0x043f0000. Verify MBARA + Offset 20h[28] = 1b
+ ///
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x043f0000);
+
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+ ///
+ /// Step 7
+ /// Wait 4 mSec
+ ///
+ PchPmTimerStall (4 * 1000);
+ ///
+ /// Step 8
+ /// Set MBARA + Offset 20h = 0x04390000 or with 0x400 or with 0x40 if MBARA + Offset F10h [3] = 1b
+ /// or with 0x04 if MBARA + Offset F10h [2] = 1b
+ ///
+ Buffer = 0x04390000 | 0x400;
+ if (MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR6) & B_PCH_MBARA_GBECSR6_GbE_DIS) {
+ Buffer |= 0x40;
+ }
+
+ if (MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR6) & B_PCH_MBARA_GBECSR6_LPLUND) {
+ Buffer |= 0x04;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), Buffer);
+ ///
+ /// Step 9
+ /// Verify MBARA + Offset 20h[28] = 1b
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+ }
+ ///
+ /// Step 10
+ /// Set MBARA + Offset 20h = 0x043f6400
+ ///
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x043f6400);
+ ///
+ /// Step 11
+ /// Wait 4 mSec
+ ///
+ PchPmTimerStall (4 * 1000);
+ ///
+ /// Step 12
+ /// Set MBARA + Offset F10h [6] = 1b (read modify write)
+ ///
+ PhyCtrl = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR6);
+ MmioWrite32 (GbEBar + R_PCH_MBARA_GBECSR6, PhyCtrl | B_PCH_MBARA_GBECSR6_GGD);
+ ///
+ /// Step 13
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4310010
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310010);
+ ///
+ /// Step 14
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4320000 or with
+ /// the least significant word of MBARA + offset 5400 that read in step 2
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), (0x4320000 | (RAL0 & 0x0000FFFF)));
+ ///
+ /// Step 15
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4310011
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310011);
+ ///
+ /// Step 16
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4320000 or with
+ /// the most significant word of MBARA + offset 5400 that read in step 2
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), (0x4320000 | (RAL0 >> 16)));
+ ///
+ /// Step 17
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4310012
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310012);
+ ///
+ /// Step 18
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4320000 or with
+ /// the least significant word of MBARA + offset 5404 that read in step 2
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), (0x4320000 | (RAH0 & B_PCH_MBARA_GBECSR8_RAH)));
+ ///
+ /// Step 19
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4310013
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310013);
+ ///
+ /// Step 20
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4328000
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4328000);
+ ///
+ /// Step 21
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4310001
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310001);
+ ///
+ /// Step 22
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x8320000
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x8320000);
+ ///
+ /// Step 23
+ /// Verify MBARA + Offset 20h[28] = 1b, TEMP[15:0] = MBARA + Offset 20h [15:0]
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ Buffer = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR3) & B_PCH_MBARA_GBECSR3_DATA;
+ ///
+ /// Step 24
+ /// Set MBARA + Offset 20h = 0x4320000 or TEMP[15:0] or 0x0001
+ ///
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4320000 | Buffer | 0x0001);
+ ///
+ /// Step 25
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x43f6460
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x43f6460);
+ ///
+ /// Step 26
+ /// Wait 4 mSec
+ ///
+ PchPmTimerStall (4 * 1000);
+ ///
+ /// Step 27
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x4310042
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310042);
+ ///
+ /// Step 28
+ /// Verify MBARA + Offset 20h[28] = 1b.
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x43F6020);
+
+ ///
+ /// Step 29
+ /// Wait 4 mSec
+ ///
+ PchPmTimerStall (4 * 1000);
+
+ ///
+ /// Step 30
+ /// Verify MBARA + Offset 20h[28] = 1b, set MBARA + Offset 20h = 0x8310000
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x8310000);
+ ///
+ /// Step 31
+ /// Verify MBARA + Offset 20h[28] = 1b, TEMP[15:0] = MBARA + 20[15:0]
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ Buffer = MmioRead32 (GbEBar + R_PCH_MBARA_GBECSR3) & 0x0000FFFF;
+
+ ///
+ /// Step 32
+ /// Verify MBARA + 20h[28] = 1b, set MBARA + 20h = 4310000h or with the TEMP[15:0] or with 10h
+ ///
+ Status = CheckReadyFlag (GbEBar);
+ if (EFI_ERROR (Status)) {
+ goto ExitGbEWa;
+ }
+
+ExitGbEWa:
+
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR3), 0x4310000 | Buffer | 0x10);
+ ///
+ /// Step 33
+ /// Verify MBARA + Offset 20h[28] = 1b
+ ///
+ Status = CheckReadyFlag (GbEBar);
+
+ ///
+ /// Step 34
+ /// Clear MBARA + Offset F00h [5] = 0b (read modify write)
+ ///
+ MmioWrite32 ((GbEBar + R_PCH_MBARA_GBECSR5), (ExtCnfCtrl & (UINT32) (~BIT5)));
+
+ }
+ }
+ }
+}
+
+typedef struct {
+ UINT8 Device;
+ UINT8 Function;
+} USB_CONTROLLER;
+
+/**
+ PCH BIOS Spec Rev 0.5.0, Section 12.10.1
+ Additional Programming Requirements prior to enter
+ S4/S5
+
+ @param[in] None
+
+ @retval None
+**/
+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 (0, 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.
+ ///
+ MmioOr16 (
+ 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)) {
+ MmioAnd32 (UsbBar + R_PCH_EHCI_USB2CMD, (UINT32)~(B_PCH_EHCI_USB2CMD_ASE | B_PCH_EHCI_USB2CMD_PSE));
+ MmioOr32 (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)) {
+ MmioOr32 (UsbBar + R_PCH_EHCI_PORTSC0, R_PCH_EHCI_PORTSC0_SUSPEND);
+ }
+ ///
+ /// Step 8
+ /// Set delay of 25ms
+ ///
+ PchPmTimerStall (25 * 1000);
+ ///
+ /// Step 9
+ /// Clear "Run/Stop (RS)" bit, MEM_BASE + offset 20h [0] = 0b.
+ ///
+ MmioAnd32 (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
+ ///
+ }
+ }
+}
+
+/**
+ Additional xHCI Controller Configurations Prior to Entering S3/S4/S5
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+XhciSxWorkaround (
+ VOID
+ )
+{
+ UINT32 RootComplexBar;
+ UINTN XhciPciMmBase;
+ UINT8 OrgCmdByte;
+ UINT32 OrgMmioAddr;
+ UINT32 OrgMmioHAddr;
+ UINT8 OrgPwrSts;
+ PCH_SERIES PchSeries;
+ UINT32 XhciMmioBase;
+ UINT32 PortScOffset[4];
+ UINT32 Data32;
+ UINT32 Index;
+ UINT32 ResetMask;
+
+ PchSeries = GetPchSeries();
+
+ RootComplexBar = PCH_RCRB_BASE;
+ ///
+ /// Check if XHCI controller is enabled
+ ///
+ if ((MmioRead32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS) & (UINT32) B_PCH_RCRB_FUNC_DIS_XHCI) != 0) {
+ return;
+ }
+ XhciPciMmBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI,
+ 0
+ );
+
+ //
+ // Save Cmd and XhciBar and PwrSts registers
+ //
+ OrgCmdByte = MmioRead8 (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER);
+ OrgMmioAddr = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & 0xFFFF0000;
+ OrgMmioHAddr = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4);
+ OrgPwrSts = MmioRead8 (XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS);
+ //
+ // Bring device back to D0
+ //
+ MmioAnd8 (XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS, (UINT8)~(B_PCH_XHCI_PWR_CNTL_STS_PWR_STS));
+ //
+ // Use the reserved MMIO
+ // Clear MSE before changing MMIO address
+ //
+ MmioAnd8 (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, (UINT8)~(B_PCH_XHCI_COMMAND_BME | B_PCH_XHCI_COMMAND_MSE));
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, (UINT32)mResvMmioBaseAddr);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4, 0);
+ XhciMmioBase = (UINT32)mResvMmioBaseAddr;
+ //
+ // Set MSE
+ //
+ MmioOr8 (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, (B_PCH_XHCI_COMMAND_BME | B_PCH_XHCI_COMMAND_MSE));
+
+ //
+ // XHC W/A for LPT-LP
+ // Clear PCI CFG offset 0xB0[14:13] for LPT-LP
+ // Clear MMIO Offset 0x816C[14]
+ // Clear MMIO Offset 0x816C[2]
+ // Wait until all SS ports are out of polling
+ // For each SS port which is disconnected (i.e. PORTS.PLS=5h) and CSC=0
+ // Issue Warm Port Reset
+ // Wait 101ms
+ // Write '1' to all Port Change Status bits if reset
+ // Set MMIO Offset 0x80E0[15]
+ //
+ // For PCH H and LP
+ // Clear MMIO Offset 0x8154[31]
+ //
+ if (PchSeries == PchLp) {
+ //
+ // Clear PCI CFG offset 0xB0[14:13] for LPT-LP
+ //
+ MmioAnd32 (XhciPciMmBase + 0xB0, (UINT32)~(BIT14 | BIT13));
+ //
+ // Clear MMIO Offset 0x816C[14]
+ // Clear MMIO Offset 0x816C[2]
+ //
+ MmioAnd32 (XhciMmioBase + 0x816C, (UINT32)~(BIT14 | BIT2));
+
+ PortScOffset[0] = R_PCH_LP_XHCI_PORTSC1USB3;
+ PortScOffset[1] = R_PCH_LP_XHCI_PORTSC2USB3;
+ PortScOffset[2] = R_PCH_LP_XHCI_PORTSC3USB3;
+ PortScOffset[3] = R_PCH_LP_XHCI_PORTSC4USB3;
+ //
+ // Wait until all ports are out of polling (PP=1, PLS=7)
+ //
+ for (Index = 0; Index < 4; Index++) {
+ Data32 = MmioRead32 (XhciMmioBase + PortScOffset[Index]);
+ //
+ // Check if PLS = 7, and PP = 1
+ //
+ while ((Data32 & B_PCH_XHCI_PORTSCXUSB3_PLS) == V_PCH_XHCI_PORTSCXUSB3_PLS_POLLING)
+ {
+ PchPmTimerStall (10);
+ Data32 = MmioRead32 (XhciMmioBase + PortScOffset[Index]);
+ }
+ }
+ ResetMask = 0;
+ for (Index = 0; Index < 4; Index++) {
+ Data32 = MmioRead32 (XhciMmioBase + PortScOffset[Index]);
+ //
+ // If Port X is Disconnected (i.e. PORTS.PLS=5h) AND PORTSC{X}.CSC=0
+ // Check if PLS = 5, CSC = 0, and PP = 1
+ //
+ if (((Data32 & B_PCH_XHCI_PORTSCXUSB3_PLS) == V_PCH_XHCI_PORTSCXUSB3_PLS_RXDETECT) &&
+ ((Data32 & B_PCH_XHCI_PORTSCXUSB3_CSC) == 0))
+ {
+ //
+ // Issue Warm Port Reset
+ //
+ ResetMask |= (1 << Index);
+ Data32 &= (UINT32)~(B_PCH_XHCI_PORTSCXUSB3_PED);
+ Data32 |= B_PCH_XHCI_PORTSCXUSB3_WPR;
+ MmioWrite32 (XhciMmioBase + PortScOffset[Index], Data32);
+ }
+ }
+
+ if (ResetMask != 0) {
+ //
+ // Wait 101ms to ensure reset completed
+ //
+ PchPmTimerStall (101 * 1000);
+
+ for (Index = 0; Index < 4; ++Index) {
+ if (ResetMask & (1 << Index)) {
+ Data32 = MmioRead32 (XhciMmioBase + PortScOffset[Index]);
+ Data32 &= (UINT32)~(B_PCH_XHCI_PORTSCXUSB3_PED);
+ //
+ // Write '1' to All Port Change Status
+ //
+ Data32 |= (B_PCH_XHCI_PORTSCXUSB3_CEC |
+ B_PCH_XHCI_PORTSCXUSB3_PLC |
+ B_PCH_XHCI_PORTSCXUSB3_PRC |
+ B_PCH_XHCI_PORTSCXUSB3_OCC |
+ B_PCH_XHCI_PORTSCXUSB3_WRC |
+ B_PCH_XHCI_PORTSCXUSB3_PEC |
+ B_PCH_XHCI_PORTSCXUSB3_CSC);
+ MmioWrite32 (XhciMmioBase + PortScOffset[Index], Data32);
+ }
+ }
+ }
+
+ //
+ // Set MMIO Offset 0x80E0[15]
+ //
+ MmioOr32 (XhciMmioBase + 0x80E0, BIT15);
+ }
+ //
+ // Clear MMIO Offset 0x8154[31]
+ //
+ MmioAnd32 (XhciMmioBase + 0x8154, (UINT32)~BIT31);
+
+ //
+ // Restore Cmd and XhciBar and PwrSts registers
+ //
+ MmioAnd8 (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, (UINT8)~(B_PCH_XHCI_COMMAND_BME | B_PCH_XHCI_COMMAND_MSE));
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4, OrgMmioHAddr);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, OrgMmioAddr);
+ MmioWrite8 (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, OrgCmdByte);
+
+ ///
+ /// Set D3hot state - 11b
+ ///
+ MmioOr16 ((XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS), (UINT16) 0x3);
+
+ ///
+ /// Set "PME Enable" bit of PWR_CNTL_STS register, D20:F0:74h[8] = 1h
+ ///
+ MmioOr16 ((XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS), (UINT16) (B_PCH_XHCI_PWR_CNTL_STS_PME_EN));
+
+}
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+
+ @param[in] None
+
+ @retval None.
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ )
+{
+ UINT32 Pm1Cnt;
+ UINT32 RootComplexBar;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries();
+ RootComplexBar = PCH_RCRB_BASE;
+
+ ///
+ /// Flush cache into memory before we go to sleep. It is necessary for S3 sleep
+ /// because we may update memory in SMM Sx sleep handlers -- the updates are in cache now
+ ///
+ AsmWbinvd ();
+
+ ///
+ /// Disable SMIs
+ ///
+ PchSmmClearSource (&SX_SOURCE_DESC);
+ PchSmmDisableSource (&SX_SOURCE_DESC);
+
+ ///
+ /// Get Power Management 1 Control Register Value
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 12.10.1
+ /// Additional Programming Requirements prior to enter S4/S5
+ ///
+ if (((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) ||
+ ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S5)) {
+ UsbS02SxWorkaround ();
+ }
+
+ if (((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) ||
+ ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) ||
+ ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S5)) {
+ XhciSxWorkaround ();
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 Section 10.6
+ /// Additional Internal GbE Controller special cases WOL Support
+ ///
+ GbES02SxWorkaround ();
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 Section 10.6 Additional GbE based wake events
+ /// The GPIO[27] is used as a wake pin when the GbE controller is enabled.
+ /// The System BIOS should enable this as wake event by setting the GPIO[27]
+ /// Enable bit (GP27_EN PMBASE + 2Ch[3]). Unlike other wake events the System
+ /// BIOS does not need to clear the corresponding GPIO[27] Status bit
+ /// (GP27_STS PMBASE + 24h[3]) as the bit will be cleared by the hardware.
+ ///
+ /// RCBA + 0x3334 [0] will be 1b while PchDeepSx is enabled and GP27 is
+ /// reuqired to wake up the system from PchDeepSx.
+ ///
+ if ((MmioRead32 (RootComplexBar + 0x3334) & (UINT32) BIT0) != 0) {
+ if (PchSeries == PchLp) {
+ IoOr32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_EN_127_96), (UINT32) B_PCH_ACPI_GPE0_EN_127_96_GP27);
+ } else if (PchSeries == PchH) {
+ IoOr32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0b_EN), (UINT32) B_PCH_ACPI_GPE0b_EN_GP27);
+ }
+ }
+ }
+
+ ///
+ /// Record S3 suspend performance data
+ ///
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
+ ///
+ /// Report status code before goto S3 sleep
+ ///
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_END);
+
+ ///
+ /// Flush cache into memory before we go to sleep.
+ ///
+ AsmWbinvd ();
+ }
+
+ ///
+ /// Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
+ ///
+ Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT), Pm1Cnt);
+
+ ///
+ /// Should only proceed if wake event is generated.
+ ///
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S1) {
+ while (((IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS))) & B_PCH_ACPI_PM1_STS_WAK) == 0x0);
+ } else {
+ EFI_DEADLOOP ();
+ }
+ ///
+ /// The system just went to sleep. If the sleep state was S1, then code execution will resume
+ /// here when the system wakes up.
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == 0) {
+ ///
+ /// An ACPI OS isn't present, clear the sleep information
+ ///
+ Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SLP_TYP;
+ Pm1Cnt |= V_PCH_ACPI_PM1_CNT_S0;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT), Pm1Cnt);
+ }
+
+ PchSmmClearSource (&SX_SOURCE_DESC);
+ PchSmmEnableSource (&SX_SOURCE_DESC);
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmUsb.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmUsb.c
new file mode 100644
index 0000000..8f24ff5
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmUsb.c
@@ -0,0 +1,300 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#include "PchSmmHelpers.h"
+
+PCH_SMM_SOURCE_DESC mUSB2_WAKE = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_INTEL_USB2
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_INTEL_USB2
+ }
+ }
+};
+
+PCH_SMM_SOURCE_DESC mUSB1_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB
+ }
+ }
+};
+
+PCH_SMM_SOURCE_DESC mUSB2_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB2
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB2
+ }
+ }
+};
+
+PCH_SMM_SOURCE_DESC mUSB3_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_EN
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB3
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ R_PCH_SMI_STS
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB3
+ }
+ }
+};
+
+typedef enum {
+ PchUsbControllerLpc0 = 0,
+ PchUsbControllerEhci1,
+ PchUsbControllerEhci2,
+ PchUsbControllerXhci,
+ PchUsbControllerTypeMax
+} PCH_USB_CONTROLLER_TYPE;
+
+typedef struct {
+ UINT8 Function;
+ UINT8 Device;
+ PCH_USB_CONTROLLER_TYPE UsbConType;
+} USB_CONTROLLER;
+
+USB_CONTROLLER mUsbControllersMap[] = {
+ {
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PchUsbControllerLpc0
+ },
+ {
+ PCI_FUNCTION_NUMBER_PCH_EHCI,
+ PCI_DEVICE_NUMBER_PCH_USB,
+ PchUsbControllerEhci1
+ },
+ {
+ PCI_FUNCTION_NUMBER_PCH_EHCI2,
+ PCI_DEVICE_NUMBER_PCH_USB_EXT,
+ PchUsbControllerEhci2
+ },
+ {
+ PCI_FUNCTION_NUMBER_PCH_XHCI,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PchUsbControllerXhci
+ }
+};
+
+/**
+ Find the handle that best matches the input Device Path and return the USB controller type
+
+ @param[in] DevicePath Pointer to the device Path table
+ @param[out] Controller Returned with the USB controller type of the input device path
+
+ @retval EFI_SUCCESS Find the handle that best matches the input Device Path
+ @exception EFI_UNSUPPORTED Invalid device Path table or can't find any match USB device path
+ PCH_USB_CONTROLLER_TYPE The USB controller type of the input
+ device path
+**/
+EFI_STATUS
+DevicePathToSupportedController (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT PCH_USB_CONTROLLER_TYPE *Controller
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ ACPI_HID_DEVICE_PATH *AcpiNode;
+ PCI_DEVICE_PATH *PciNode;
+ EFI_DEVICE_PATH_PROTOCOL *RemaingDevicePath;
+ UINT8 UsbIndex;
+ ///
+ /// Find the handle that best matches the Device Path. If it is only a
+ /// partial match the remaining part of the device path is returned in
+ /// RemainingDevicePath.
+ ///
+ RemaingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &DevicePath,
+ &DeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DevicePath = RemaingDevicePath;
+
+ ///
+ /// Get first node: Acpi Node
+ ///
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
+
+ if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
+ AcpiNode->Header.SubType != ACPI_DP ||
+ DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
+ AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
+ AcpiNode->UID != 0
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// Get the next node: Pci Node
+ ///
+ RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
+ PciNode = (PCI_DEVICE_PATH *) RemaingDevicePath;
+ if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
+ PciNode->Header.SubType != HW_PCI_DP ||
+ DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (USB_CONTROLLER); UsbIndex++) {
+ if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
+ (PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
+ *Controller = mUsbControllersMap[UsbIndex].UsbConType;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[in] SrcDesc The source description that corresponds to the given context.
+
+ @retval None.
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PCH_USB_CONTROLLER_TYPE Controller;
+ EFI_STATUS Status;
+
+ Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
+ ///
+ /// Either the device path passed in by the child is incorrect or
+ /// the ones stored here internally are incorrect.
+ ///
+ ASSERT_EFI_ERROR (Status);
+
+ switch (Context->Usb.Type) {
+ case UsbLegacy:
+ switch (Controller) {
+ case PchUsbControllerLpc0:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB1_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ case PchUsbControllerEhci1:
+ case PchUsbControllerEhci2:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB2_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ case PchUsbControllerXhci:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB3_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case UsbWake:
+ switch (Controller) {
+ case PchUsbControllerEhci1:
+ case PchUsbControllerEhci2:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB2_WAKE), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.c b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.c
new file mode 100644
index 0000000..f6513a7
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.c
@@ -0,0 +1,820 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchSmmHelpers.h"
+
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO 0x00000001
+
+/**
+ Publish SMI Dispatch protocols.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Install protocol interfaces.
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mPrivateData.InstallMultProtHandle,
+ &gEfiSmmGpiDispatchProtocolGuid,
+ &mPrivateData.Protocols[GpiType].Protocols.Gpi,
+ &gEfiSmmSxDispatchProtocolGuid,
+ &mPrivateData.Protocols[SxType].Protocols.Sx,
+ &gEfiSmmSwDispatchProtocolGuid,
+ &mPrivateData.Protocols[SwType].Protocols.Sw,
+ &gEfiSmmIchnDispatchProtocolGuid,
+ &mPrivateData.Protocols[IchnType].Protocols.Ichn,
+ &gEfiSmmIchnDispatchExProtocolGuid,
+ &mPrivateData.Protocols[IchnExType].Protocols.IchnEx,
+ &gEfiSmmPowerButtonDispatchProtocolGuid,
+ &mPrivateData.Protocols[PowerButtonType].Protocols.PowerButton,
+ &gEfiSmmPeriodicTimerDispatchProtocolGuid,
+ &mPrivateData.Protocols[PeriodicTimerType].Protocols.PeriodicTimer,
+ &gEfiSmmUsbDispatchProtocolGuid,
+ &mPrivateData.Protocols[UsbType].Protocols.Usb,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Clear all SMIs
+ ///
+ PchSmmClearSmi ();
+
+ Status = PchSmmEnableGlobalSmiBit ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Be *really* sure to clear all SMIs
+ ///
+ PchSmmClearSmi ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Set the "global smi enable" bit
+ ///
+ SmiEn |= B_PCH_SMI_EN_GBL_SMI;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ )
+{
+ BOOLEAN EosSet;
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+ UINT16 Pm1Sts;
+ UINT32 Gpe0Sts;
+ UINT32 Gpe0aStsLow;
+ UINT32 Gpe0bStsHigh;
+ UINT32 SmiSts;
+ UINT32 AltGpiSmiSts;
+ UINT16 DevActSts;
+ UINT16 Tco1Sts;
+ UINT16 Tco2Sts;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries();
+ Gpe0Sts = 0;
+ Gpe0aStsLow = 0;
+ Gpe0bStsHigh = 0;
+ AltGpiSmiSts = 0;
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+ if (!SciEn) {
+ ///
+ /// Clear any SMIs that double as SCIs (when SCI_EN==0)
+ ///
+ Pm1Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS));
+ if (PchSeries == PchLp) {
+ Gpe0Sts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96));
+ } else if (PchSeries == PchH) {
+ Gpe0aStsLow = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS));
+ Gpe0bStsHigh = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0b_STS));
+ }
+
+ Pm1Sts |=
+ (
+ B_PCH_ACPI_PM1_STS_WAK |
+ B_PCH_ACPI_PM1_STS_PRBTNOR |
+ B_PCH_ACPI_PM1_STS_RTC |
+ B_PCH_ACPI_PM1_STS_PWRBTN |
+ B_PCH_ACPI_PM1_STS_GBL |
+ B_PCH_ACPI_PM1_STS_TMROF
+ );
+
+ if (PchSeries == PchLp) {
+ Gpe0Sts |=
+ (
+ B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
+ B_PCH_ACPI_GPE0_STS_127_96_PME |
+ B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
+ B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
+ B_PCH_ACPI_GPE0_STS_127_96_RI |
+ B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
+ B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
+ B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
+ B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
+ B_PCH_ACPI_GPE0_STS_127_96_GP27
+ );
+ } else if (PchSeries == PchH) {
+ Gpe0aStsLow |=
+ (
+ B_PCH_ACPI_GPE0a_STS_PME_B0 |
+ B_PCH_ACPI_GPE0a_STS_PME |
+ B_PCH_ACPI_GPE0a_STS_BATLOW |
+ B_PCH_ACPI_GPE0a_STS_PCI_EXP |
+ B_PCH_ACPI_GPE0a_STS_RI |
+ B_PCH_ACPI_GPE0a_STS_SMB_WAK |
+ B_PCH_ACPI_GPE0a_STS_TC0SCI |
+ B_PCH_ACPI_GPE0a_STS_HOT_PLUG |
+ B_PCH_ACPI_GPE0a_STS_BATLOW
+ );
+
+ Gpe0bStsHigh |= (B_PCH_ACPI_GPE0b_STS_GP27);
+ }
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS), (UINT16) Pm1Sts);
+ if (PchSeries == PchLp) {
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96), (UINT32) Gpe0Sts);
+ } else if (PchSeries == PchH) {
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS), (UINT32) Gpe0aStsLow);
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0b_STS), (UINT32) Gpe0bStsHigh);
+ }
+ }
+ ///
+ /// Clear all SMIs that are unaffected by SCI_EN
+ ///
+ if (PchSeries == PchLp) {
+ AltGpiSmiSts = IoRead32 ((UINTN) (mGpioBaseAddr + R_PCH_LPTLP_ALT_GP_SMI_STS));
+ } else if (PchSeries == PchH) {
+ AltGpiSmiSts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_LPTH_ALT_GP_SMI_STS));
+ }
+ SmiSts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
+ DevActSts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS));
+ Tco1Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + PCH_TCO_BASE + R_PCH_TCO1_STS));
+ Tco2Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + PCH_TCO_BASE + R_PCH_TCO2_STS));
+
+ SmiSts |=
+ (
+ B_PCH_SMI_STS_SMBUS |
+ B_PCH_SMI_STS_PERIODIC |
+ B_PCH_SMI_STS_TCO |
+ B_PCH_SMI_STS_MCSMI |
+ B_PCH_SMI_STS_SWSMI_TMR |
+ B_PCH_SMI_STS_APM |
+ B_PCH_SMI_STS_ON_SLP_EN |
+ B_PCH_SMI_STS_BIOS
+ );
+ AltGpiSmiSts |= 0xFFFF;
+ DevActSts |=
+ (
+ B_PCH_DEVACT_STS_KBC |
+ B_PCH_DEVACT_STS_PIRQDH |
+ B_PCH_DEVACT_STS_PIRQCG |
+ B_PCH_DEVACT_STS_PIRQBF |
+ B_PCH_DEVACT_STS_PIRQAE
+ );
+ Tco1Sts |=
+ (
+ B_PCH_TCO1_STS_DMISERR |
+ B_PCH_TCO1_STS_DMISMI |
+ B_PCH_TCO1_STS_DMISCI |
+ B_PCH_TCO1_STS_BIOSWR |
+ B_PCH_TCO1_STS_NEWCENTURY |
+ B_PCH_TCO1_STS_TIMEOUT |
+ B_PCH_TCO1_STS_TCO_INT |
+ B_PCH_TCO1_STS_SW_TCO_SMI
+ );
+ if(PchSeries == PchLp){
+ IoWrite32 ((UINTN) (mGpioBaseAddr + R_PCH_LPTLP_ALT_GP_SMI_STS), AltGpiSmiSts);
+ } else if (PchSeries == PchH) {
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_LPTH_ALT_GP_SMI_STS), (UINT16)AltGpiSmiSts);
+ }
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + PCH_TCO_BASE + R_PCH_TCO1_STS), Tco1Sts);
+
+ Tco2Sts |= B_PCH_TCO2_STS_SECOND_TO;
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + PCH_TCO_BASE + R_PCH_TCO2_STS), Tco2Sts);
+
+ Tco2Sts |= (B_PCH_TCO2_STS_SMLINK_SLV_SMI | B_PCH_TCO2_STS_BOOT | B_PCH_TCO2_STS_INTRD_DET);
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + PCH_TCO_BASE + R_PCH_TCO2_STS), Tco2Sts);
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS), SmiSts);
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS), DevActSts);
+
+ ///
+ /// Try to clear the EOS bit. ASSERT on an error
+ ///
+ EosSet = PchSmmSetAndCheckEos ();
+ ASSERT (EosSet);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+ @param[in] None
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Reset the PCH to generate subsequent SMIs
+ ///
+ SmiEn |= B_PCH_SMI_EN_EOS;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
+
+ ///
+ /// Double check that the assert worked
+ ///
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Return TRUE if EOS is set correctly
+ ///
+ if ((SmiEn & B_PCH_SMI_EN_EOS) == 0) {
+ ///
+ /// EOS was not set to a 1; this is an error
+ ///
+ return FALSE;
+ } else {
+ ///
+ /// EOS was correctly set to a 1
+ ///
+ return TRUE;
+ }
+}
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+ @param[in] None
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ )
+{
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+
+ return SciEn;
+}
+
+/**
+ Read a specifying bit with the register
+ These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ const PCH_SMM_BIT_DESC *BitDesc
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegSize;
+ BOOLEAN BitWasOne;
+ UINTN ShiftCount;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+ ShiftCount = 0;
+ BitWasOne = FALSE;
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case GPIO_ADDR_TYPE:
+ if(BitDesc->Reg.Type == ACPI_ADDR_TYPE){
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.gpio;
+ BaseAddr = mGpioBaseAddr;
+ }
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Double check that we correctly read in the acpi base address
+ ///
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ShiftCount = BitDesc->Bit;
+ ///
+ /// As current CPU Smm Io can only support at most
+ /// 32-bit read/write,if Operation is 64 bit,
+ /// we do a 32 bit operation according to BitDesc->Bit
+ ///
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ ///
+ /// If the operation is for high 32 bits
+ ///
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+ ShiftCount -= 32;
+ }
+ }
+
+ Status = mSmst->SmmIo.Io.Read (
+ &mSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ ///
+ /// Read the register, and it with the bit to read
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ Register = (UINT64) MmioRead8 (MmPciAddress (0, PciBus, PciDev, PciFun, PciReg));
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 (MmPciAddress (0, PciBus, PciDev, PciFun, PciReg));
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 (MmPciAddress (0, PciBus, PciDev, PciFun, PciReg));
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ default:
+ ///
+ /// This address type is not yet implemented
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ return BitWasOne;
+}
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+ @retval None
+**/
+VOID
+WriteBitDesc (
+ const PCH_SMM_BIT_DESC *BitDesc,
+ const BOOLEAN ValueToWrite,
+ const BOOLEAN WriteClear
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT64 AndVal;
+ UINT64 OrVal;
+ UINT32 RegSize;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
+ }
+
+ OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case GPIO_ADDR_TYPE:
+ if(BitDesc->Reg.Type == ACPI_ADDR_TYPE){
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.gpio;
+ BaseAddr = mGpioBaseAddr;
+ }
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Double check that we correctly read in the acpi base address
+ ///
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ///
+ /// As current CPU Smm Io can only support at most
+ /// 32-bit read/write,if Operation is 64 bit,
+ /// we do a 32 bit operation according to BitDesc->Bit
+ ///
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ ///
+ /// If the operation is for high 32 bits
+ ///
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
+ }
+
+ OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
+ }
+ }
+
+ Status = mSmst->SmmIo.Io.Read (
+ &mSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Register &= AndVal;
+ Register |= OrVal;
+
+ Status = mSmst->SmmIo.Io.Write (
+ &mSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ ///
+ /// Read the register, or it with the bit to set, then write it back.
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register &= AndVal;
+ Register |= OrVal;
+ ///
+ /// Read the register, or it with the bit to set, then write it back.
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ MmioWrite8 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8) Register);
+ break;
+
+ case 2:
+ MmioWrite16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) Register);
+ break;
+
+ case 4:
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+ break;
+
+ case 8:
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized -- check your assignments
+ /// to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ MmioAndThenOr8 (MmPciAddress (0, PciBus, PciDev, PciFun, PciReg), (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ MmioAndThenOr16 (MmPciAddress (0, PciBus, PciDev, PciFun, PciReg), (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ MmioAndThenOr32 (MmPciAddress (0, PciBus, PciDev, PciFun, PciReg), (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ default:
+ ///
+ /// This address type is not yet implemented
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.h b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.h
new file mode 100644
index 0000000..ead184c
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchxSmmHelpers.h
@@ -0,0 +1,128 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _PCHX_SMM_HELPERS_H_
+#define _PCHX_SMM_HELPERS_H_
+
+#include "PchSmm.h"
+#include "PchPlatformLib.h"
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ );
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ );
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+ @param[in] None
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ );
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+ @param[in] None
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ );
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+ @param[in] None
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ );
+
+/**
+ Read a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ const PCH_SMM_BIT_DESC *BitDesc
+ );
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+ @retval None
+**/
+VOID
+WriteBitDesc (
+ const PCH_SMM_BIT_DESC *BitDesc,
+ const BOOLEAN ValueToWrite,
+ const BOOLEAN WriteClear
+ );
+
+#endif