/** @file Copyright (c) 2013-2015 Intel Corporation. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ // // Include common header file for this module. // #include "CommonHeader.h" #include "QNCSmm.h" #include "QNCSmmHelpers.h" // // #define BIT_ZERO 0x00000001 // CONST UINT32 BIT_ZERO = 0x00000001; // // ///////////////////////////////////////////////////////////////////////////// // SUPPORT / HELPER FUNCTIONS (QNC version-independent) // BOOLEAN CompareEnables ( CONST IN QNC_SMM_SOURCE_DESC *Src1, CONST IN QNC_SMM_SOURCE_DESC *Src2 ) /*++ Routine Description: GC_TODO: Add function description Arguments: Src1 - GC_TODO: add argument description Src2 - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { 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; } BOOLEAN CompareStatuses ( CONST IN QNC_SMM_SOURCE_DESC *Src1, CONST IN QNC_SMM_SOURCE_DESC *Src2 ) /*++ Routine Description: GC_TODO: Add function description Arguments: Src1 - GC_TODO: add argument description Src2 - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { 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; } BOOLEAN CompareSources ( CONST IN QNC_SMM_SOURCE_DESC *Src1, CONST IN QNC_SMM_SOURCE_DESC *Src2 ) /*++ Routine Description: GC_TODO: Add function description Arguments: Src1 - GC_TODO: add argument description Src2 - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2)); } BOOLEAN SourceIsActive ( CONST IN QNC_SMM_SOURCE_DESC *Src ) /*++ Routine Description: GC_TODO: Add function description Arguments: Src - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { BOOLEAN IsActive; UINTN loopvar; BOOLEAN SciEn; IsActive = TRUE; SciEn = QNCSmmGetSciEn (); if ((Src->Flags & QNC_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; } VOID QNCSmmEnableSource ( CONST QNC_SMM_SOURCE_DESC *SrcDesc ) /*++ Routine Description: GC_TODO: Add function description Arguments: SrcDesc - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { 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); } } QNCSmmClearSource (SrcDesc); } VOID QNCSmmDisableSource ( CONST QNC_SMM_SOURCE_DESC *SrcDesc ) /*++ Routine Description: GC_TODO: Add function description Arguments: SrcDesc - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { UINTN loopvar; for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) { if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) { WriteBitDesc (&SrcDesc->En[loopvar], 0); } } } VOID QNCSmmClearSource ( CONST QNC_SMM_SOURCE_DESC *SrcDesc ) /*++ Routine Description: GC_TODO: Add function description Arguments: SrcDesc - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { UINTN loopvar; BOOLEAN ValueToWrite; ValueToWrite = ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE; for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) { if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) { WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite); } } } VOID QNCSmmClearSourceAndBlock ( CONST QNC_SMM_SOURCE_DESC *SrcDesc ) // GC_TODO: function comment should start with '/*++' /* Sets the source to a 1 or 0 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). */ // GC_TODO: function comment should end with '--*/' // GC_TODO: function comment is missing 'Routine Description:' // GC_TODO: function comment is missing 'Arguments:' // GC_TODO: function comment is missing 'Returns:' // GC_TODO: SrcDesc - add argument and description to function comment { UINTN loopvar; BOOLEAN IsSet; BOOLEAN ValueToWrite; ValueToWrite = ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE; for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) { if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) { // // Write the bit // WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite); // // 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. // } } } }