mirror of https://github.com/acidanthera/audk.git
374 lines
7.5 KiB
C
374 lines
7.5 KiB
C
/** @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.
|
|
//
|
|
}
|
|
}
|
|
}
|
|
}
|