summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchSmiDispatcher/Smm/PchSmmHelpers.c317
1 files changed, 317 insertions, 0 deletions
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.
+ ///
+ }
+ }
+ }
+}