QuarkSocPkg: Add new package for Quark SoC X1000

Changes for V4
==============
1) Remove Unicode character from C source file
2) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode
   from QuarkPlatformPkg commit to QuarkSocPkg commit

Changes for V2
==============
1) Sync with new APIs in SmmCpuFeaturesLib class
2) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg
3) Remove PCI serial driver from QuarkSocPkg
4) Apply optimizations to MtrrLib from MtrrLib in UefiCpuPkg
5) Convert all UNI files to utf-8
6) Replace tabs with spaces and remove trailing spaces
7) Add License.txt

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19286 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Michael Kinney
2015-12-15 19:22:23 +00:00
committed by mdkinney
parent 46ff196fde
commit 9b6bbcdbfd
176 changed files with 54761 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
/** @file
File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
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 "QNCSmmHelpers.h"
CONST QNC_SMM_SOURCE_DESC GPI_SOURCE_DESC = {
QNC_SMM_NO_FLAGS,
{
{
{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_GPIO
},
NULL_BIT_DESC_INITIALIZER
},
{
{
{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_GPIO
}
}
};

View File

@@ -0,0 +1,555 @@
/** @file
This driver is responsible for the registration of child drivers
and the abstraction of the QNC SMI sources.
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 "QNCSmmHelpers.h"
//
// Help handle porting bit shifts to IA-64.
//
#define BIT_ZERO 0x00000001
VOID
QNCSmmPublishDispatchProtocols(
VOID
)
{
UINTN Index;
EFI_STATUS Status;
//
// Install protocol interfaces.
//
for (Index = 0; Index < NUM_PROTOCOLS; Index++) {
Status = gSmst->SmmInstallProtocolInterface (
&mPrivateData.InstallMultProtHandle,
mPrivateData.Protocols[Index].Guid,
EFI_NATIVE_INTERFACE,
&mPrivateData.Protocols[Index].Protocols.Generic
);
ASSERT_EFI_ERROR (Status);
}
}
EFI_STATUS
QNCSmmInitHardware(
VOID
)
/*++
Routine Description:
Initialize bits that aren't necessarily related to an SMI source.
Dependencies:
gSmst - SMM System Table; contains an entry for SMM CPU IO
Returns:
EFI_SUCCESS. Asserts, otherwise.
--*/
{
EFI_STATUS Status;
//
// Clear all SMIs
//
QNCSmmClearSmi();
Status = QNCSmmEnableGlobalSmiBit ();
ASSERT_EFI_ERROR (Status);
//
// Be *really* sure to clear all SMIs
//
QNCSmmClearSmi ();
return EFI_SUCCESS;
}
EFI_STATUS
QNCSmmEnableGlobalSmiBit (
VOID
)
/*++
Routine Description:
Enables the QNC 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.
Arguments:
None
Returns:
EFI_SUCCESS.
Asserts, otherwise.
--*/
{
UINT32 NewValue;
//
// Enable SMI globally
//
NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
NewValue |= SMI_EN;
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
return EFI_SUCCESS;
}
EFI_STATUS
QNCSmmClearSmi(
VOID
)
/*++
Routine Description:
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.
Returns:
EFI_SUCCESS.
Asserts, otherwise.
--*/
{
BOOLEAN EosSet;
BOOLEAN SciEn;
UINT32 Pm1Cnt = 0;
UINT16 Pm1Sts = 0;
UINT32 Gpe0Sts = 0;
UINT32 SmiSts = 0;
//
// Determine whether an ACPI OS is present (via the SCI_EN bit)
//
Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN);
if (SciEn == FALSE) {
//
// Clear any SMIs that double as SCIs (when SCI_EN==0)
//
Pm1Sts = (B_QNC_PM1BLK_PM1S_WAKE | B_QNC_PM1BLK_PM1S_PCIEWSTS | B_QNC_PM1BLK_PM1S_RTC | B_QNC_PM1BLK_PM1S_GLOB | B_QNC_PM1BLK_PM1S_TO);
Gpe0Sts = B_QNC_GPE0BLK_GPE0S_ALL;
IoOr16((PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S), Pm1Sts);
IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S), Gpe0Sts);
}
//
// Clear all SMIs that are unaffected by SCI_EN
//
SmiSts = IoRead32((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
SmiSts |= B_QNC_GPE0BLK_SMIS_ALL;
IoWrite32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), SmiSts);
//
// Try to clear the EOS bit. ASSERT on an error
//
EosSet = QNCSmmSetAndCheckEos();
ASSERT (EosSet);
return EFI_SUCCESS;
}
BOOLEAN
QNCSmmSetAndCheckEos(
VOID
)
{
//
// Reset the QNC to generate subsequent SMIs
//
IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
return TRUE;
}
BOOLEAN
QNCSmmGetSciEn(
)
{
BOOLEAN SciEn;
UINT32 Pm1Cnt;
//
// Determine whether an ACPI OS is present (via the SCI_EN bit)
//
Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN);
return SciEn;
}
//
// These may or may not need to change w/ the QNC version; they're highly IA-32 dependent, though.
//
BOOLEAN
ReadBitDesc (
CONST QNC_SMM_BIT_DESC *BitDesc
)
{
UINT64 Register;
UINT32 PciBus;
UINT32 PciDev;
UINT32 PciFun;
UINT32 PciReg;
BOOLEAN BitWasOne;
ASSERT (BitDesc != NULL );
ASSERT (!IS_BIT_DESC_NULL( *BitDesc ) );
Register = 0;
BitWasOne = FALSE;
switch (BitDesc->Reg.Type) {
case ACPI_ADDR_TYPE:
//
// Double check that we correctly read in the acpi base address
//
ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1) );
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) IoRead8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);
break;
case 2:
Register = (UINT64) IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);
break;
case 4:
Register = (UINT64) IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);
break;
default:
//
// Unsupported or invalid register size
//
ASSERT (FALSE );
break;
};
if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {
BitWasOne = TRUE;
} else {
BitWasOne = FALSE;
}
break;
case GPE_ADDR_TYPE:
//
// Double check that we correctly read in the gpe base address
//
ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1) );
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) IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);
break;
case 2:
Register = (UINT64) IoRead16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);
break;
case 4:
Register = (UINT64) IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);
break;
default:
//
// Unsupported or invalid register size
//
ASSERT (FALSE );
break;
};
if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {
BitWasOne = TRUE;
} else {
BitWasOne = FALSE;
}
break;
case MEMORY_MAPPED_IO_ADDRESS_TYPE:
//
// Read the register, and it with the bit to read
//
//
// This code does not support reads greater then 64 bits
//
ASSERT (BitDesc->SizeInBytes <= 8);
CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes);
Register &= LShiftU64 (BIT0, BitDesc->Bit);
if (Register) {
BitWasOne = TRUE;
} else {
BitWasOne = FALSE;
}
break;
case PCI_ADDR_TYPE:
PciBus = BitDesc->Reg.Data.pci.Fields.Bus;
PciDev = BitDesc->Reg.Data.pci.Fields.Dev;
PciFun = BitDesc->Reg.Data.pci.Fields.Fnc;
PciReg = BitDesc->Reg.Data.pci.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) PciRead8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));
break;
case 2:
Register = (UINT64) PciRead16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));
break;
case 4:
Register = (UINT64) PciRead32 (PCI_LIB_ADDRESS (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;
}
VOID
WriteBitDesc (
CONST QNC_SMM_BIT_DESC *BitDesc,
CONST BOOLEAN ValueToWrite
)
{
UINT64 Register;
UINT64 AndVal;
UINT64 OrVal;
UINT32 PciBus;
UINT32 PciDev;
UINT32 PciFun;
UINT32 PciReg;
ASSERT (BitDesc != NULL);
ASSERT (!IS_BIT_DESC_NULL(*BitDesc));
AndVal = ~(BIT_ZERO << (BitDesc->Bit));
OrVal = ((UINT32)ValueToWrite) << (BitDesc->Bit);
switch (BitDesc->Reg.Type) {
case ACPI_ADDR_TYPE:
//
// Double check that we correctly read in the acpi base address
//
ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1));
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:
IoAndThenOr8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT8)AndVal, (UINT8)OrVal);
break;
case 2:
IoAndThenOr16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT16)AndVal, (UINT16)OrVal);
break;
case 4:
IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT32)AndVal, (UINT32)OrVal);
break;
default:
//
// Unsupported or invalid register size
//
ASSERT (FALSE );
break;
};
break;
case GPE_ADDR_TYPE:
//
// Double check that we correctly read in the gpe base address
//
ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1));
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:
IoAndThenOr8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT8)AndVal, (UINT8)OrVal);
break;
case 2:
IoAndThenOr16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT16)AndVal, (UINT16)OrVal);
break;
case 4:
IoAndThenOr32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT32)AndVal, (UINT32)OrVal);
break;
default:
//
// Unsupported or invalid register size
//
ASSERT (FALSE );
break;
};
break;
case MEMORY_MAPPED_IO_ADDRESS_TYPE:
//
// Read the register, or it with the bit to set, then write it back.
//
//
// This code does not support writes greater then 64 bits
//
ASSERT (BitDesc->SizeInBytes <= 8);
CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes);
Register &= AndVal;
Register |= OrVal;
CopyMem (BitDesc->Reg.Data.Mmio, &Register, BitDesc->SizeInBytes);
break;
case PCI_ADDR_TYPE:
PciBus = BitDesc->Reg.Data.pci.Fields.Bus;
PciDev = BitDesc->Reg.Data.pci.Fields.Dev;
PciFun = BitDesc->Reg.Data.pci.Fields.Fnc;
PciReg = BitDesc->Reg.Data.pci.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:
PciAndThenOr8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT8) AndVal, (UINT8) OrVal);
break;
case 2:
PciAndThenOr16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT16) AndVal, (UINT16) OrVal);
break;
case 4:
PciAndThenOr32 (PCI_LIB_ADDRESS (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;
};
}

View File

@@ -0,0 +1,430 @@
/** @file
File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
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 "QNCSmmHelpers.h"
typedef enum {
PERIODIC_TIMER = 0,
NUM_TIMERS
} SUPPORTED_TIMER;
typedef struct _TIMER_INTERVAL
{
UINT64 Interval;
UINT8 AssociatedTimer;
} TIMER_INTERVAL;
//
// 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 */
// PMCW (GPE+28h) [2:0] Periodic SMI Rate selection
// 000 1.5ms
// 001 16ms
// 010 32ms
// 011 64ms
// 100 8s
// 101 16s
// 110 32s
// 111 64s
typedef enum {
INDEX_TIME_1_5ms = 0,
INDEX_TIME_16ms,
INDEX_TIME_32ms,
INDEX_TIME_64ms,
INDEX_TIME_8s,
INDEX_TIME_16s,
INDEX_TIME_32s,
INDEX_TIME_64s,
INDEX_TIME_MAX
} TIMER_INTERVAL_INDEX;
TIMER_INTERVAL mSmmPeriodicTimerIntervals[INDEX_TIME_MAX] = {
{TIME_1_5ms, PERIODIC_TIMER},
{TIME_16ms, PERIODIC_TIMER},
{TIME_32ms, PERIODIC_TIMER},
{TIME_64ms, PERIODIC_TIMER},
{ TIME_8s, PERIODIC_TIMER },
{TIME_16s, PERIODIC_TIMER},
{TIME_32s, PERIODIC_TIMER},
{TIME_64s, PERIODIC_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];
QNC_SMM_SOURCE_DESC mTIMER_SOURCE_DESCS[NUM_TIMERS] = {
{
QNC_SMM_NO_FLAGS,
{
{{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SWT},
NULL_BIT_DESC_INITIALIZER
},
{
{{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SWT}
}
}
};
VOID
QNCSmmPeriodicTimerProgramTimers(
VOID
);
TIMER_INTERVAL *
ContextToTimerInterval (
IN QNC_SMM_CONTEXT *RegisterContext
)
{
UINTN loopvar;
//
// Determine which timer this child is using
//
for (loopvar = 0; loopvar < INDEX_TIME_MAX; loopvar++) {
if (((RegisterContext->PeriodicTimer.SmiTickInterval == 0) && (RegisterContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
(RegisterContext->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;
}
EFI_STATUS
MapPeriodicTimerToSrcDesc (
IN QNC_SMM_CONTEXT *RegisterContext,
OUT QNC_SMM_SOURCE_DESC *SrcDesc
)
{
TIMER_INTERVAL *TimerInterval;
//
// Figure out which timer the child is requesting and
// send back the source description
//
TimerInterval = ContextToTimerInterval (RegisterContext);
if (TimerInterval == NULL) {
return EFI_INVALID_PARAMETER;
}
CopyMem (SrcDesc, &mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer], sizeof (QNC_SMM_SOURCE_DESC));;
//
// Program the value of the interval into hardware
//
QNCSmmPeriodicTimerProgramTimers ();
return EFI_SUCCESS;
}
VOID
PeriodicTimerGetContext (
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *HwContext
)
{
TIMER_INTERVAL *TimerInterval;
ASSERT (Record->ProtocolType == PeriodicTimerType);
TimerInterval = ContextToTimerInterval (&Record->ChildContext);
if (TimerInterval != NULL) {
//
// 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->CommBuffer.PeriodicTimer.ElapsedTime += TimerInterval->Interval;
*HwContext = Record->ChildContext;
}
}
BOOLEAN
PeriodicTimerCmpContext (
IN QNC_SMM_CONTEXT *HwContext,
IN QNC_SMM_CONTEXT *ChildContext
)
{
DATABASE_RECORD *Record;
Record = DATABASE_RECORD_FROM_CONTEXT (ChildContext);
if (Record->CommBuffer.PeriodicTimer.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
//
// This child should be dispatched
// The timer will be restarted on the "ClearSource" call.
//
return TRUE;
} else {
return FALSE;
}
}
VOID
PeriodicTimerGetBuffer (
IN DATABASE_RECORD * Record
)
{
//
// CommBuffer has been updated by PeriodicTimerGetContext, so return directly
//
return;
}
VOID
QNCSmmPeriodicTimerProgramTimers (
VOID
)
{
UINT32 GpePmcwValue;
SUPPORTED_TIMER Timer;
DATABASE_RECORD *RecordInDb;
LIST_ENTRY *LinkInDb;
TIMER_INTERVAL *TimerInterval;
//
// Find the minimum required interval for each timer
//
for (Timer = (SUPPORTED_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) {
Timer = (SUPPORTED_TIMER)((TIMER_INTERVAL *) (TimerInterval))->AssociatedTimer;
ASSERT (Timer >= 0 && Timer < NUM_TIMERS);
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
//
GpePmcwValue = 0;
if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
case TIME_64s:
GpePmcwValue = INDEX_TIME_64s;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
break;
case TIME_32s:
GpePmcwValue = INDEX_TIME_32s;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
break;
case TIME_16s:
GpePmcwValue = INDEX_TIME_16s;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
break;
case TIME_8s:
GpePmcwValue = INDEX_TIME_8s;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
break;
case TIME_64ms:
GpePmcwValue = INDEX_TIME_64ms;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64ms;
break;
case TIME_32ms:
GpePmcwValue = INDEX_TIME_32ms;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32ms;
break;
case TIME_16ms:
GpePmcwValue = INDEX_TIME_16ms;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16ms;
break;
case TIME_1_5ms:
GpePmcwValue = INDEX_TIME_1_5ms;
mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
break;
default:
ASSERT (FALSE);
break;
};
GpePmcwValue |= B_QNC_GPE0BLK_PMCW_PSE;
IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMCW), GpePmcwValue);
//
// Restart the timer here, just need to clear the SMI
//
QNCSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
} else {
QNCSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
}
}
EFI_STATUS
QNCSmmPeriodicTimerDispatchGetNextShorterInterval (
IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
IN OUT UINT64 **SmiTickInterval
)
/*++
Routine Description:
This services returns the next SMI tick period that is supported by the chipset.
The order returned is from longest to shortest interval period.
Arguments:
This - Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
SmiTickInterval - Pointer to pointer of the next shorter SMI interval period that is supported by the child.
Returns:
EFI_SUCCESS - The service returned successfully.
EFI_INVALID_PARAMETER - The parameter SmiTickInterval is invalid.
--*/
{
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[INDEX_TIME_MAX - 1]) {
//
// At end of the list
//
IntervalPointer = NULL;
} else {
if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
(IntervalPointer < &mSmmPeriodicTimerIntervals[INDEX_TIME_MAX - 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;
}
VOID
QNCSmmPeriodicTimerClearSource (
IN QNC_SMM_SOURCE_DESC *SrcDesc
)
/*++
Routine Description:
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.
Arguments:
SrcDesc - Pointer to the QNC_SMM_SOURCE_DESC instance.
Returns:
None.
--*/
{
DATABASE_RECORD *RecordInDb;
LIST_ENTRY *LinkInDb;
QNCSmmPeriodicTimerProgramTimers ();
//
// Reset Elapsed time
//
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 and Callback
// has been invoked, so reset the ElapsedTime to 0
//
if (RecordInDb->CommBuffer.PeriodicTimer.ElapsedTime >= RecordInDb->ChildContext.PeriodicTimer.Period) {
RecordInDb->CommBuffer.PeriodicTimer.ElapsedTime = 0;
}
}
LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
}
}

View File

@@ -0,0 +1,217 @@
/** @file
File to contain all the hardware specific stuff for the Smm QNCn dispatch protocol.
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 "QNCSmmHelpers.h"
QNC_SMM_SOURCE_DESC QNCN_SOURCE_DESCS[NUM_ICHN_TYPES] = {
// QNCnMch (0)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnPme (1)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnRtcAlarm (2)
{
QNC_SMM_NO_FLAGS,
{
{{ACPI_ADDR_TYPE, {R_QNC_PM1BLK_PM1E}}, S_QNC_PM1BLK_PM1E, N_QNC_PM1BLK_PM1E_RTC},
NULL_BIT_DESC_INITIALIZER
},
{
{{ACPI_ADDR_TYPE, {R_QNC_PM1BLK_PM1S}}, S_QNC_PM1BLK_PM1S, N_QNC_PM1BLK_PM1S_RTC}
}
},
// QNCnRingIndicate (3)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnAc97Wake (4)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnSerialIrq (5)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnY2KRollover (6)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnTcoTimeout (7)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnOsTco (8)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnNmi (9)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnIntruderDetect (10)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnBiosWp (11)
{
QNC_SMM_CLEAR_WITH_ZERO,
{
{
{
PCI_ADDR_TYPE,
{
(
(PCI_BUS_NUMBER_QNC << 24) |
(PCI_DEVICE_NUMBER_QNC_LPC << 16) |
(PCI_FUNCTION_NUMBER_QNC_LPC << 8) |
R_QNC_LPC_BIOS_CNTL
)
}
},
S_QNC_LPC_BIOS_CNTL,
N_QNC_LPC_BIOS_CNTL_BLE
},
NULL_BIT_DESC_INITIALIZER
},
{
{
{
PCI_ADDR_TYPE,
{
(
(PCI_BUS_NUMBER_QNC << 24) |
(PCI_DEVICE_NUMBER_QNC_LPC << 16) |
(PCI_FUNCTION_NUMBER_QNC_LPC << 8) |
R_QNC_LPC_BIOS_CNTL
)
}
},
S_QNC_LPC_BIOS_CNTL,
N_QNC_LPC_BIOS_CNTL_BIOSWE
}
}
},
// QNCnMcSmi (12)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnPmeB0 (13)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnThrmSts (14)
{
QNC_SMM_SCI_EN_DEPENDENT,
{
{{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_GPE0E}}, S_QNC_GPE0BLK_GPE0E, N_QNC_GPE0BLK_GPE0E_THRM},
NULL_BIT_DESC_INITIALIZER
},
{
{{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_GPE0S}}, S_QNC_GPE0BLK_GPE0S, N_QNC_GPE0BLK_GPE0S_THRM}
}
},
// QNCnSmBus (15)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnIntelUsb2 (16)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnMonSmi7 (17)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnMonSmi6 (18)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnMonSmi5 (19)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnMonSmi4 (20)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap13 (21)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap12 (22)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap11 (23)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap10 (24)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap9 (25)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap8 (26)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap7 (27)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap6 (28)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap5 (29)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap3 (30)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap2 (31)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap1 (32)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnDevTrap0 (33)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnIoTrap3 (34)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnIoTrap2 (35)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnIoTrap1 (36)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnIoTrap0 (37)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnPciExpress (38)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnMonitor (39)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnSpi (40)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnQRT (41)
NULL_SOURCE_DESC_INITIALIZER,
// QNCnGpioUnlock (42)
NULL_SOURCE_DESC_INITIALIZER
};
VOID
QNCSmmQNCnClearSource(
QNC_SMM_SOURCE_DESC *SrcDesc
)
{
QNCSmmClearSource (SrcDesc);
}

View File

@@ -0,0 +1,96 @@
/** @file
File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
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 "QNCSmmHelpers.h"
EFI_SMM_CPU_PROTOCOL *mSmmCpu = NULL;
CONST QNC_SMM_SOURCE_DESC SW_SOURCE_DESC = {
QNC_SMM_NO_FLAGS,
{
{
{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_APM
},
NULL_BIT_DESC_INITIALIZER
},
{
{
{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_APM
}
}
};
VOID
SwGetContext(
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *Context
)
{
Context->Sw.SwSmiInputValue = IoRead8 (R_APM_CNT);
}
BOOLEAN
SwCmpContext (
IN QNC_SMM_CONTEXT *Context1,
IN QNC_SMM_CONTEXT *Context2
)
{
return (BOOLEAN)( Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue );
}
VOID
SwGetBuffer (
IN DATABASE_RECORD * Record
)
{
EFI_STATUS Status;
UINTN Index;
UINTN CpuIndex;
EFI_SMM_SAVE_STATE_IO_INFO IoState;
//
// Locate SMM CPU protocol to retrieve the CPU save state
//
if (mSmmCpu == NULL) {
Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
ASSERT_EFI_ERROR (Status);
}
//
// Find the CPU which generated the software SMI
//
CpuIndex = 0;
for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
Status = mSmmCpu->ReadSaveState (
mSmmCpu,
sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
EFI_SMM_SAVE_STATE_REGISTER_IO,
Index,
&IoState
);
if (!EFI_ERROR (Status) && (IoState.IoPort == R_APM_CNT)) {
CpuIndex = Index;
break;
}
}
Record->CommBuffer.Sw.SwSmiCpuIndex = CpuIndex;
}

View File

@@ -0,0 +1,153 @@
/** @file
File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
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 "QNCSmmHelpers.h"
CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC = {
QNC_SMM_NO_FLAGS,
{
{
{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SLP
},
NULL_BIT_DESC_INITIALIZER
},
{
{
{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SLP
}
}
};
VOID
SxGetContext(
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *Context
)
{
UINT32 Pm1Cnt;
Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
//
// 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_QNC_PM1BLK_PM1C_SLPTP) {
case V_S0:
Context->Sx.Type = SxS0;
break;
case V_S3:
Context->Sx.Type = SxS3;
break;
case V_S4:
Context->Sx.Type = SxS4;
break;
case V_S5:
Context->Sx.Type = SxS5;
break;
default:
ASSERT (FALSE);
break;
};
}
BOOLEAN
SxCmpContext (
IN QNC_SMM_CONTEXT *Context1,
IN QNC_SMM_CONTEXT *Context2
)
{
return (BOOLEAN)(Context1->Sx.Type == Context2->Sx.Type);
}
VOID
QNCSmmSxGoToSleep(
VOID
)
/*++
Routine Description:
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.
Returns:
None.
--*/
{
UINT32 Pm1Cnt;
//
// 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
//
QNCSmmClearSource (&SX_SOURCE_DESC );
QNCSmmDisableSource (&SX_SOURCE_DESC);
//
// Clear Sleep Type Enable
//
IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIE, (UINT16)(~B_QNC_GPE0BLK_SMIE_SLP));
// clear sleep SMI status
IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, (UINT16)(S_QNC_GPE0BLK_SMIS));
//
// Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
//
Pm1Cnt = IoOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, B_QNC_PM1BLK_PM1C_SLPEN);
//
// 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 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
if ((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == 0) {
//
// An ACPI OS isn't present, clear the sleep information
//
Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SLPTP;
Pm1Cnt |= V_S0;
IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Pm1Cnt);
}
QNCSmmClearSource (&SX_SOURCE_DESC);
QNCSmmEnableSource (&SX_SOURCE_DESC);
}