654 lines
17 KiB
C
654 lines
17 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
Copyright (c) 1992 Intel Corporation
|
||
All rights reserved
|
||
|
||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||
|
||
This software is supplied to Microsoft under the terms
|
||
of a license agreement with Intel Corporation and may not be
|
||
copied nor disclosed except in accordance with the terms
|
||
of that agreement.
|
||
|
||
Module Name:
|
||
|
||
pcmpdtct.c
|
||
|
||
Abstract:
|
||
|
||
This module detects an MPS system.
|
||
|
||
Author:
|
||
|
||
Ron Mosgrove (Intel) - Aug 1993.
|
||
|
||
Environment:
|
||
|
||
Kernel mode or from textmode setup.
|
||
|
||
Revision History:
|
||
Rajesh Shah (Intel) - Oct 1993. Added support for MPS table.
|
||
|
||
--*/
|
||
|
||
#ifndef _NTOS_
|
||
#include "halp.h"
|
||
#endif
|
||
|
||
#include "apic.inc"
|
||
#include "pcmp_nt.inc"
|
||
#include "stdio.h"
|
||
|
||
#if DEBUGGING
|
||
CHAR Cbuf[120];
|
||
VOID HalpDisplayConfigTable(VOID);
|
||
VOID HalpDisplayExtConfigTable(VOID);
|
||
VOID HalpDisplayBIOSSysCfg(struct SystemConfigTable *);
|
||
#define DBGMSG(a) HalDisplayString(a)
|
||
#else
|
||
#define DBGMSG(a)
|
||
#endif
|
||
|
||
#define DEBUG_MSG(a)
|
||
|
||
//
|
||
// The floating pointer structure defined by the MPS spec can reside
|
||
// anywhere in BIOS extended data area. These defines are used to search for
|
||
// the floating structure starting from physical address 639K(9f000+c00)
|
||
//
|
||
#define PCMP_TABLE_PTR_BASE 0x09f000
|
||
#define PCMP_TABLE_PTR_OFFSET 0x00000c00
|
||
|
||
extern struct HalpMpInfo HalpMpInfoTable;
|
||
|
||
UCHAR
|
||
ComputeCheckSum(
|
||
IN PUCHAR SourcePtr,
|
||
IN USHORT NumOfBytes
|
||
);
|
||
|
||
VOID
|
||
HalpUnmapVirtualAddress(
|
||
IN PVOID VirtualAddress,
|
||
IN ULONG NumberPages
|
||
);
|
||
|
||
struct FloatPtrStruct *
|
||
SearchFloatPtr (
|
||
ULONG PhysicalAddress,
|
||
ULONG ByteSize
|
||
);
|
||
|
||
struct FloatPtrStruct *
|
||
PcMpGetFloatingPtr (
|
||
VOID
|
||
);
|
||
|
||
struct PcMpTable *
|
||
GetPcMpTable (
|
||
VOID
|
||
);
|
||
|
||
|
||
struct PcMpTable *
|
||
MPS10_GetPcMpTablePtr (
|
||
VOID
|
||
);
|
||
|
||
struct PcMpTable *
|
||
MPS10_GetPcMpTable (
|
||
VOID
|
||
);
|
||
|
||
|
||
struct PcMpTable *
|
||
GetDefaultConfig (
|
||
IN ULONG Config
|
||
);
|
||
|
||
#ifdef SETUP
|
||
|
||
//
|
||
// A dummy pointer to a default MPS table. For setup, we can conserve
|
||
// space by not building default tables in our data area.
|
||
#define DEFAULT_MPS_INDICATOR 0xfefefefe
|
||
|
||
#define HalpUnmapVirtualAddress(a, b)
|
||
|
||
#endif //SETUP
|
||
|
||
#ifndef SETUP
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGELK,SearchFloatPtr)
|
||
#pragma alloc_text(PAGELK,PcMpGetFloatingPtr)
|
||
#pragma alloc_text(PAGELK,ComputeCheckSum)
|
||
#pragma alloc_text(PAGELK,GetPcMpTable)
|
||
#pragma alloc_text(PAGELK,MPS10_GetPcMpTablePtr)
|
||
#pragma alloc_text(PAGELK,MPS10_GetPcMpTable)
|
||
#pragma alloc_text(PAGELK,GetDefaultConfig)
|
||
#endif // ALLOC_PRAGMA
|
||
|
||
extern struct PcMpTable *PcMpDefaultTablePtrs[];
|
||
extern BOOLEAN HalpUse8254;
|
||
#endif // ndef SETUP
|
||
|
||
|
||
struct FloatPtrStruct *
|
||
SearchFloatPtr(
|
||
ULONG PhysicalAddress,
|
||
ULONG ByteSize
|
||
)
|
||
{
|
||
// Search for the MPS floating pointer structure starting from the
|
||
// physical address given.
|
||
|
||
USHORT Index, ParagraphLength;
|
||
UCHAR CheckSum;
|
||
struct FloatPtrStruct *VirtualAddress;
|
||
BOOLEAN CheckSumError;
|
||
PHYSICAL_ADDRESS physAddr = {0};
|
||
|
||
#ifdef DEBUGGING
|
||
sprintf(Cbuf, "SearchFloatPtr: Will search at physical address 0x%lx\n",
|
||
PhysicalAddress);
|
||
HalDisplayString(Cbuf);
|
||
#endif // DEBUGGING
|
||
|
||
// The MPS spec says that the floating pointer structure MUST be
|
||
// aligned at 16 byte boundaries. We can use this fact to search for
|
||
// the structure only at those boundaries. Assume that the input physical
|
||
// address to start search from is 16 byte aligned.
|
||
|
||
CheckSumError = FALSE;
|
||
for(Index = 0; Index < (ByteSize/sizeof(struct FloatPtrStruct)); Index++) {
|
||
|
||
physAddr.LowPart = PhysicalAddress + (Index * sizeof(struct FloatPtrStruct));
|
||
|
||
VirtualAddress = (struct FloatPtrStruct *)HalpMapPhysicalMemory64(
|
||
physAddr,
|
||
1
|
||
);
|
||
|
||
if (VirtualAddress == NULL) {
|
||
DEBUG_MSG ("SearchFloatPtr: Cannot map Physical address\n");
|
||
return (NULL);
|
||
}
|
||
|
||
if ( (*((PULONG)VirtualAddress) ) == MP_PTR_SIGNATURE) {
|
||
|
||
ParagraphLength =
|
||
((struct FloatPtrStruct *)VirtualAddress)->MpTableLength;
|
||
|
||
//
|
||
// Detected the floating structure signature. Check if the
|
||
// floating pointer structure checksum is valid.
|
||
//
|
||
|
||
CheckSum = ComputeCheckSum((PUCHAR)VirtualAddress,
|
||
(USHORT) (ParagraphLength*16) );
|
||
|
||
if (CheckSum == 0 ) {
|
||
|
||
// We have a valid floating pointer structure.
|
||
// Return a pointer to it.
|
||
|
||
DEBUG_MSG ("SearchFloatPtr: Found structure\n");
|
||
return((struct FloatPtrStruct *) VirtualAddress);
|
||
}
|
||
|
||
// Invalid structure. Continue searching.
|
||
CheckSumError = TRUE;
|
||
DEBUG_MSG ("SearchFloatPtr: Valid MP_PTR signature, invalid checksum\n");
|
||
}
|
||
|
||
//
|
||
// Give back the PTE.
|
||
//
|
||
|
||
HalpUnmapVirtualAddress(VirtualAddress, 1);
|
||
}
|
||
|
||
if (CheckSumError) {
|
||
FAILMSG (rgzMPPTRCheck);
|
||
}
|
||
|
||
return(NULL);
|
||
}
|
||
|
||
struct FloatPtrStruct *
|
||
PcMpGetFloatingPtr(
|
||
VOID)
|
||
{
|
||
ULONG EbdaSegmentPtr, BaseMemPtr;
|
||
ULONG EbdaPhysicalAdd = 0, ByteLength, BaseMemKb = 0;
|
||
struct FloatPtrStruct *FloatPtr = NULL;
|
||
PUCHAR zeroVirtual;
|
||
PHYSICAL_ADDRESS zeroPhysical;
|
||
|
||
// Search for the floating pointer structure in the order specified in
|
||
// MPS spec version 1.1.
|
||
|
||
// First, search for it in the first kilobyte in the Extended BIOS Data
|
||
// Area. The EBDA segment address is available at physical address 40:0E
|
||
|
||
zeroPhysical = HalpPtrToPhysicalAddress( (PVOID)0 );
|
||
zeroVirtual = HalpMapPhysicalMemory64( zeroPhysical, 1);
|
||
EbdaSegmentPtr = (ULONG)(zeroVirtual + EBDA_SEGMENT_PTR);
|
||
EbdaPhysicalAdd = *((PUSHORT)EbdaSegmentPtr);
|
||
EbdaPhysicalAdd = EbdaPhysicalAdd << 4;
|
||
|
||
if (EbdaPhysicalAdd != 0)
|
||
FloatPtr = SearchFloatPtr(EbdaPhysicalAdd, 1024);
|
||
|
||
HalpUnmapVirtualAddress(zeroVirtual, 1);
|
||
|
||
if (FloatPtr == NULL) {
|
||
|
||
// Did not find it in EBDA.
|
||
// Look for it in the last KB of system memory.
|
||
|
||
zeroVirtual = HalpMapPhysicalMemory64( zeroPhysical, 1);
|
||
BaseMemPtr = (ULONG)(zeroVirtual + BASE_MEM_PTR);
|
||
BaseMemKb = *((PUSHORT)BaseMemPtr);
|
||
|
||
FloatPtr = SearchFloatPtr(BaseMemKb*1024, 1024);
|
||
|
||
HalpUnmapVirtualAddress(zeroVirtual, 1);
|
||
|
||
if (FloatPtr == NULL) {
|
||
|
||
// Finally, look for the floating Pointer Structure at physical
|
||
// address F0000H to FFFFFH
|
||
|
||
ByteLength = 0xfffff - 0xf0000;
|
||
|
||
FloatPtr = SearchFloatPtr(0xf0000, ByteLength);
|
||
}
|
||
}
|
||
|
||
// At this point, we have a pointer to the MPS floating structure.
|
||
|
||
return(FloatPtr);
|
||
}
|
||
|
||
|
||
struct PcMpTable *
|
||
MPS10_GetPcMpTablePtr(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the Address of the MPS configuration table built by BIOS.
|
||
This routine looks for the floating pointer structure defined
|
||
in the MPS spec. This structure points to the MPS configuration
|
||
table built by an MP BIOS. The floating pointer structure can be
|
||
located anywhere in the extended BIOS data area(physical address range
|
||
639K to 640K), and must be aligned on a 16 byte boundary.
|
||
|
||
Arguments:
|
||
None
|
||
|
||
Return Value:
|
||
struct PcMpTable * - Virtual address pointer to the PcMpTable, if
|
||
it exists, NULL otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR TempPtr;
|
||
ULONG LinearPtr;
|
||
UCHAR CheckSum;
|
||
struct PcMpTableLocator *PcMpPtrPtr;
|
||
PULONG TraversePtr;
|
||
PVOID BasePtr;
|
||
USHORT ParagraphLength;
|
||
int i;
|
||
PHYSICAL_ADDRESS physicalAddress;
|
||
|
||
// Map the physical address of the BIOS extended data area to a virtual
|
||
// address we can use.
|
||
|
||
physicalAddress = HalpPtrToPhysicalAddress( (PVOID)PCMP_TABLE_PTR_BASE );
|
||
BasePtr = (PUCHAR) HalpMapPhysicalMemory64(physicalAddress, 1);
|
||
TempPtr = BasePtr;
|
||
TraversePtr = (PULONG)((PUCHAR) TempPtr + PCMP_TABLE_PTR_OFFSET);
|
||
|
||
// Look at 16 byte boundaries for the floating pointer structure
|
||
// The structure is identified by its signature, and verified by its
|
||
// checksum.
|
||
for (i=0; i < (1024/16); ++i)
|
||
{
|
||
if (*(TraversePtr) == MP_PTR_SIGNATURE)
|
||
{
|
||
// Got a valid signature.
|
||
PcMpPtrPtr = (struct PcMpTableLocator *)TraversePtr;
|
||
|
||
// Length in 16 byte paragraphs of the floating structure.
|
||
// Normally, this should be set to 1 by the BIOS.
|
||
ParagraphLength = PcMpPtrPtr->MpTableLength;
|
||
|
||
// Check if the floating pointer structure is valid.
|
||
CheckSum = ComputeCheckSum((PUCHAR)PcMpPtrPtr,
|
||
(USHORT) (ParagraphLength*16));
|
||
if (CheckSum != 0 ) {
|
||
FAILMSG (rgzMPPTRCheck);
|
||
// Invalid structure. Continue searching.
|
||
TraversePtr += 4;
|
||
continue;
|
||
}
|
||
|
||
// We have a valid floating pointer structure.
|
||
// The value stored in the structure is a physical address of the
|
||
// MPS table built by BIOS. Get the corresponding virtual
|
||
// address.
|
||
|
||
physicalAddress = HalpPtrToPhysicalAddress( PcMpPtrPtr->TablePtr );
|
||
TempPtr = HalpMapPhysicalMemory64(physicalAddress,2);
|
||
|
||
//
|
||
// Done with base pointer.
|
||
//
|
||
|
||
HalpUnmapVirtualAddress(BasePtr, 1);
|
||
|
||
if (TempPtr == NULL) {
|
||
DEBUG_MSG ("HAL: Cannot map BIOS created MPS table\n");
|
||
return (NULL);
|
||
}
|
||
|
||
// Return the virtual address pointer to the MPS table.
|
||
return((struct PcMpTable *) TempPtr);
|
||
|
||
}
|
||
TraversePtr += 4;
|
||
}
|
||
|
||
return(NULL);
|
||
}
|
||
|
||
|
||
UCHAR
|
||
ComputeCheckSum (
|
||
IN PUCHAR SourcePtr,
|
||
IN USHORT NumOfBytes
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
This routine computes a checksum for NumOfBytes bytes, starting
|
||
from SourcePtr. It is used to validate the tables built by BIOS.
|
||
|
||
Arguments:
|
||
SourcePtr : Starting virtual address to compute checksum.
|
||
NumOfBytes: Number of bytes to compute the checksum of.
|
||
|
||
Return Value:
|
||
The checksum value.
|
||
|
||
*/
|
||
{
|
||
UCHAR Result = 0;
|
||
USHORT Count;
|
||
|
||
for(Count=0; Count < NumOfBytes; ++Count)
|
||
Result += *SourcePtr++;
|
||
|
||
return(Result);
|
||
}
|
||
|
||
|
||
struct PcMpTable *
|
||
MPS10_GetPcMpTable (
|
||
VOID
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Detects an MPS 1.0 system only.
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
Pointer to an MPS table.
|
||
--*/
|
||
{
|
||
struct SystemConfigTable *SystemConfigPtr;
|
||
|
||
UCHAR DefaultConfig, CheckSum;
|
||
struct PcMpTable *MpTablePtr;
|
||
UCHAR MpFeatureInfoByte1 = 0, MpFeatureInfoByte2 = 0;
|
||
PHYSICAL_ADDRESS physicalAddress;
|
||
|
||
// Get the virtual address of the system configuration table.
|
||
physicalAddress = HalpPtrToPhysicalAddress( (PVOID)BIOS_BASE );
|
||
SystemConfigPtr = (struct SystemConfigTable *)
|
||
HalpMapPhysicalMemory64( physicalAddress, 16);
|
||
|
||
if (SystemConfigPtr == NULL) {
|
||
DEBUG_MSG ("GetPcMpTable: Cannot map system configuration table\n");
|
||
return(NULL);
|
||
}
|
||
|
||
// HalpDisplayBIOSSysCfg(SystemConfigPtr);
|
||
|
||
// The system configuration table built by BIOS has 2 MP feature
|
||
// information bytes.
|
||
|
||
MpFeatureInfoByte1 = SystemConfigPtr->MpFeatureInfoByte1;
|
||
MpFeatureInfoByte2 = SystemConfigPtr->MpFeatureInfoByte2;
|
||
|
||
// The second MP feature information byte tells us whether the system
|
||
// has an IMCR(Interrupt Mode Control Register). We use this information
|
||
// in the HAL, so we store this information in the OS specific private
|
||
// area.
|
||
|
||
if ((MpFeatureInfoByte2 & IMCR_MASK) == 0) {
|
||
HalpMpInfoTable.IMCRPresent = 0;
|
||
} else {
|
||
HalpMpInfoTable.IMCRPresent = 1;
|
||
}
|
||
|
||
#ifndef SETUP
|
||
|
||
// The second MP feature information byte tells us whether Time
|
||
// Stamp Counter should be used as a high-resolution timer on
|
||
// multiprocessor systems.
|
||
|
||
if ((MpFeatureInfoByte2 & MULT_CLOCKS_MASK) != 0) {
|
||
HalpUse8254 = 1;
|
||
}
|
||
#endif
|
||
|
||
// MP feature byte 1 indicates if the system is MPS compliant
|
||
if (! (MpFeatureInfoByte1 & PCMP_IMPLEMENTED)) {
|
||
// The MP feature information byte indicates that this
|
||
// system is not MPS compliant.
|
||
FAILMSG (rgzNoMpsTable);
|
||
return(NULL);
|
||
}
|
||
|
||
// The system is MPS compliant. MP feature byte 2 indicates if the
|
||
// system is a default configuration or not.
|
||
DefaultConfig = (MpFeatureInfoByte1 & PCMP_CONFIG_MASK) >> 1;
|
||
|
||
if (DefaultConfig) {
|
||
return GetDefaultConfig(DefaultConfig);
|
||
}
|
||
|
||
// DefaultConfig == 0. This means that the BIOS has built a MP
|
||
// config table for us. The BIOS will also build a floating pointer
|
||
// structure that points to the MP config table. This floating pointer
|
||
// structure resides in the BIOS extended data area.
|
||
MpTablePtr = MPS10_GetPcMpTablePtr();
|
||
|
||
if (MpTablePtr == NULL) {
|
||
FAILMSG (rgzNoMPTable); // Could not find BIOS created MPS table
|
||
return(NULL);
|
||
}
|
||
|
||
// We have a pointer to the MP config table. Check if the table is valid.
|
||
|
||
if ((MpTablePtr->Signature != PCMP_SIGNATURE) ||
|
||
(MpTablePtr->TableLength < sizeof(struct PcMpTable)) ) {
|
||
FAILMSG(rgzMPSBadSig);
|
||
return(NULL);
|
||
}
|
||
|
||
CheckSum = ComputeCheckSum((PUCHAR)MpTablePtr, MpTablePtr->TableLength);
|
||
if (CheckSum != 0) {
|
||
FAILMSG(rgzMPSBadCheck);
|
||
return(NULL);
|
||
}
|
||
|
||
return MpTablePtr;
|
||
}
|
||
|
||
struct PcMpTable *
|
||
GetPcMpTable(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This routine gets the MP table for a MPS compliant system.
|
||
For a MPS compliant system, either the BIOS builds an MP table, or
|
||
it indicates that the system is one of the default configurations
|
||
defined in the MPS spec. The MP feature information bytes in the BIOS
|
||
system configuration table indicate whether the system is one of the
|
||
default systems, or has a BIOS created MP table. For a default system
|
||
configuration, this routine uses a statically built default table.
|
||
This routine copies the MPS table into private system memory, and
|
||
returns a pointer to this table.
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
Pointer to the private copy of the MP table that has been copied in
|
||
system memory.
|
||
|
||
*/
|
||
{
|
||
|
||
struct FloatPtrStruct *FloatingPtr;
|
||
UCHAR CheckSum;
|
||
struct PcMpTable *MpTablePtr;
|
||
UCHAR MpFeatureInfoByte1 = 0, MpFeatureInfoByte2 = 0;
|
||
PUCHAR TempPtr;
|
||
PHYSICAL_ADDRESS physicalAddress;
|
||
ULONG tableLength;
|
||
|
||
DEBUG_MSG("GetMpTable\n");
|
||
|
||
FloatingPtr = PcMpGetFloatingPtr();
|
||
|
||
if (FloatingPtr == NULL) {
|
||
FAILMSG (rgzNoMPTable);
|
||
return(NULL);
|
||
}
|
||
|
||
// The floating structure has 2 MP feature information bytes.
|
||
|
||
MpFeatureInfoByte1 = FloatingPtr->MpFeatureInfoByte1;
|
||
MpFeatureInfoByte2 = FloatingPtr->MpFeatureInfoByte2;
|
||
|
||
// The second MP feature information byte tells us whether the system
|
||
// has an IMCR(Interrupt Mode Control Register). We use this information
|
||
// in the HAL, so we store this information in the OS specific private
|
||
// area.
|
||
|
||
if ((MpFeatureInfoByte2 & IMCR_MASK) == 0)
|
||
HalpMpInfoTable.IMCRPresent = 0;
|
||
else
|
||
HalpMpInfoTable.IMCRPresent = 1;
|
||
|
||
if (MpFeatureInfoByte1 != 0) {
|
||
// The system configuration is one of the default
|
||
// configurations defined in the MPS spec. Find out which
|
||
// default configuration it is and get a pointer to the
|
||
// corresponding default table.
|
||
|
||
return GetDefaultConfig(MpFeatureInfoByte1);
|
||
}
|
||
|
||
|
||
// MpFeatureInfoByte1 == 0. This means that the BIOS has built a MP
|
||
// config table for us. The address of the OEM created table is in
|
||
// the MPS floating structure.
|
||
|
||
physicalAddress = HalpPtrToPhysicalAddress( FloatingPtr->TablePtr );
|
||
TempPtr = HalpMapPhysicalMemory64(physicalAddress,2);
|
||
|
||
HalpUnmapVirtualAddress(FloatingPtr, 1);
|
||
|
||
if (TempPtr == NULL) {
|
||
DEBUG_MSG ("HAL: Cannot map OEM MPS table [1]\n");
|
||
return (NULL);
|
||
}
|
||
|
||
MpTablePtr = (struct PcMpTable *)TempPtr;
|
||
|
||
// We have a pointer to the MP config table. Check if the table is valid.
|
||
|
||
if ((MpTablePtr->Signature != PCMP_SIGNATURE) ||
|
||
(MpTablePtr->TableLength < sizeof(struct PcMpTable)) ) {
|
||
FAILMSG (rgzMPSBadSig);
|
||
return(NULL);
|
||
}
|
||
|
||
//
|
||
// Now re-map it, making sure that we have mapped enough pages.
|
||
//
|
||
|
||
tableLength = MpTablePtr->TableLength + MpTablePtr->ExtTableLength;
|
||
|
||
HalpUnmapVirtualAddress(TempPtr, 2);
|
||
|
||
MpTablePtr = (struct PcMpTable *)HalpMapPhysicalMemory64(
|
||
physicalAddress,
|
||
(ULONG)(((physicalAddress.QuadPart + tableLength) / PAGE_SIZE) -
|
||
(physicalAddress.QuadPart / PAGE_SIZE) + 1)
|
||
);
|
||
|
||
if (MpTablePtr == NULL) {
|
||
DEBUG_MSG ("HAL: Cannot map OEM MPS table [2]\n");
|
||
return (NULL);
|
||
}
|
||
|
||
CheckSum = ComputeCheckSum((PUCHAR)MpTablePtr, MpTablePtr->TableLength);
|
||
if (CheckSum != 0) {
|
||
FAILMSG (rgzMPSBadCheck);
|
||
return(NULL);
|
||
}
|
||
|
||
return MpTablePtr;
|
||
}
|
||
|
||
|
||
struct PcMpTable *
|
||
GetDefaultConfig (
|
||
IN ULONG Config
|
||
)
|
||
{
|
||
Config -= 1;
|
||
|
||
if (Config >= NUM_DEFAULT_CONFIGS) {
|
||
FAILMSG (rgzBadDefault);
|
||
return NULL;
|
||
}
|
||
|
||
#ifdef DEBUGGING
|
||
HalDisplayString ("HALMPS: Using default table\n");
|
||
#endif
|
||
|
||
#ifdef SETUP
|
||
return((struct PcMpTable *) DEFAULT_MPS_INDICATOR);
|
||
#else
|
||
return PcMpDefaultTablePtrs[Config];
|
||
#endif // SETUP
|
||
}
|