/*++

Copyright (c) 2000  Microsoft Corporation

Module Name:

    bios.c

Abstract:

    This module implements code to make BIOS calls

Author:

    Jake Oshins (3/18/00) - create file

Environment:

    Kernel mode

Notes:

Revision History:

--*/
#include <ntddk.h>
#include "p3.h"
#include "ntacpi.h"

extern P3_GLOBALS P3_Globals;
extern PROCESSOR_STATE_INFO Coppermine100[];
extern PROCESSOR_STATE_INFO Coppermine133[];
extern PROCESSOR_STATE_INFO Tualatin100[];
extern PROCESSOR_STATE_INFO Tualatin133[];


ULONG StateFlags;
PPROCESSOR_STATE_INFO ProcessorStateInfo;
LEGACY_GEYSERVILLE_INT15 LegacyInterface;
const CHAR SignatureString[] = "Copyright (c) 1999 Intel Corporation";

NTSTATUS
AcpiFindRsdt (
  OUT PACPI_BIOS_MULTI_NODE *AcpiMulti
  );

__inline
ULONG
GetBusRatio (
  VOID
  );

__inline
BOOLEAN
Is133MhzBus (
  VOID
  );
  
NTSTATUS
GetMaxProcFrequencySMM (
  PULONG    MaxSpeed
  );
  

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, InitializeLegacyInterface)
#pragma alloc_text (PAGE, FindLegacyGeyservilleInterface)
#pragma alloc_text (PAGE, GetMaxProcFrequencySMM)
#pragma alloc_text (PAGE, GetCurrentStateSmm)
#pragma alloc_text (PAGE, SetCurrentSetupSmm)
#pragma alloc_text (PAGE, GetCurrentProcFrequency)
#pragma alloc_text (PAGE, GetBusRatio)
#pragma alloc_text (PAGE, GetLegacyMaxProcFrequency)
#pragma alloc_text (PAGE, CollectProcessorInfomation)
#endif


NTSTATUS
InitializeLegacyInterface (
  PLEGACY_GEYSERVILLE_INTERFACE_INFO Info,
  PFDO_DATA DeviceExtension
  )
/*++

  Description:
    

  Arguments:
    
    
  Return Value:

    NTSTATUS


--*/ 
{
    NTSTATUS status;
    ULONG    currentState;
    ULONG    smiCmdData = 0;
    ULONG    smiCmdPort = 0;
       
    DebugEnter();
    PAGED_CODE();

    //
    // Must be a Geyserville processor
    //
    
    status = CollectProcessorInfomation();

    if (!NT_SUCCESS(status)) {
      goto InitializeLegacyInterfaceExit;
    }

    DumpStateFlags(StateFlags);
    DebugPrint((MAXTRACE, "Bus Ratio == %u\n", GetBusRatio()));
    DebugPrint((MAXTRACE, "Ist Field == %u\n", P3_Globals.IstField));
    

    //
    // Check for Legacy Geyserville Interface override values.
    //
    
    GetRegistryDwordValue(P3_PARAMETERS_KEY, 
                          L"SmiCmdPort", 
                          &smiCmdPort);    

    GetRegistryDwordValue(P3_PARAMETERS_KEY, 
                          L"SmiCmdData", 
                          &smiCmdData);


    //
    // NOTE: if we have the SmiCmdData value but not the SmiCmdPort value, we
    //       could grab the SmiCmdPort value from HalpFixedAcpiDescTable->smi_cmd_io_port
    //

    
    //
    // If we already have both the SmiCmdPort and the SmiCmdData,
    // then we already have the data we need, otherwise copy INT 15 E820 
    // data to LegacyInterface structure...
    //

    if (!(smiCmdPort && smiCmdData)) {
      status = FindLegacyGeyservilleInterface();

      if (!NT_SUCCESS(status)) {
        goto InitializeLegacyInterfaceExit;
      }
    }
    
        
    if (smiCmdPort) {
      //
      // 4chan: server2003 change (UCHAR to USHORT)
      //
      LegacyInterface.CommandPortAddress = (USHORT) smiCmdPort;
      DebugPrint((INFO, "  Overriding SmiCommandPortAddress with registry value 0x%x\n", 
                 smiCmdPort));
    }

    if (smiCmdData) {
      LegacyInterface.CommandDataValue = (UCHAR) smiCmdData;
      DebugPrint((INFO, "  Overriding SmiCommandDataVale with registry value 0x%x\n", 
                 smiCmdData));
    }

    
    //
    // Set the Default Behavior for AC and DC
    //
    
    P3_Globals.MaxLevelAc = 0;
    P3_Globals.MaxLevelDc = 1;
    

    //
    // Check for INT 15 or Registy Flag overrides
    //

    if (LegacyInterface.Signature == 'GS') {

      //
      // If the values returned from the INT 15 Interface look
      // reasonable, use them, other wise we'll use the defaults.
      //
      
      if (LegacyInterface.MaxLevelAc < MAX_GEYSERVILLE_STATES) {
        P3_Globals.MaxLevelAc = LegacyInterface.MaxLevelAc;
      }

      if (LegacyInterface.MaxLevelDc < MAX_GEYSERVILLE_STATES) { 
        P3_Globals.MaxLevelDc = LegacyInterface.MaxLevelDc;
      }

      //
      // sanity check, some machines report this info incorrectly.
      //

      if (P3_Globals.MaxLevelAc > P3_Globals.MaxLevelDc) {
        P3_Globals.MaxLevelAc = P3_Globals.MaxLevelDc;
      }
      
    }

    
    if (P3_Globals.HackFlags & ENABLE_HIGH_SPEED_ON_BATTERY) {
      P3_Globals.MaxLevelDc = 0;
      DeviceExtension->PpcResult = 0;
    }

    
    //
    // Init the SMI Interface
    //
    
    status = InitializeSmmInterface();

    if (!NT_SUCCESS(status)) {

      //
      // found INT 15 interface or registry override values,
      // but were unable to Initialize SMM Interface, log error
      //
      
      QueueEventLogWrite(DeviceExtension, 
                         PROCESSOR_LEGACY_INTERFACE_FAILURE, 
                         0);

      
      
      goto InitializeLegacyInterfaceExit;
    }

    //
    // Find out more about what state we're in and what
    // states we can use.
    //

    status = GetCurrentStateSmm(Info);


InitializeLegacyInterfaceExit:

    DebugExitStatus(status);
    return status;
   
}

NTSTATUS
FindLegacyGeyservilleInterface (
  VOID
  )
/*++

  Routine Description:

    This routine looks in the registry to find out if Geyserville
    is supported on this system via Intel's SMI interface.  If
    so it collects information about how to use the interface.

  Arguments:
    
  Return Value:

    NTSTATUS

--*/ 
{
    PACPI_BIOS_MULTI_NODE     multiNode;
    PLEGACY_GEYSERVILLE_INT15 int15Info;
    NTSTATUS status;

    DebugEnter();
    PAGED_CODE();

    status = AcpiFindRsdt(&multiNode);

    if (!NT_SUCCESS(status)) {
      goto FindLegacyGeyservilleInterfaceExit;
    }

    //
    // Geyserville BIOS information is appended to the E820 entries.
    //
    
    int15Info = (PLEGACY_GEYSERVILLE_INT15)&(multiNode->E820Entry[multiNode->Count]);

    if (int15Info->Signature == 'GS') {

      //
      // This BIOS supports Geyserville.
      //
  
      RtlCopyMemory(&LegacyInterface, 
                    int15Info, 
                    sizeof(LEGACY_GEYSERVILLE_INT15));
      
      status = STATUS_SUCCESS;
      
    } else {
    
      status = STATUS_NOT_FOUND;

    }
    
    ExFreePool(multiNode);


FindLegacyGeyservilleInterfaceExit:

    DebugExitStatus(status);
    return status;
}

NTSTATUS
InitializeSmmInterface (
  VOID
  )
/*++

  Routine Description:

    This routine makes the first Geyserville SMI, enabling
    the other functions.

  Arguments:
    
  Return Value:

    NTSTATUS

--*/ 
{
    ULONG   regEax, regEbx, regEdx, returnCode;
    PHYSICAL_ADDRESS signatureAddr;
    
    //
    // Enable Geyserville SMM.
    //

    regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
    regEbx = GeyservilleControl;
    regEdx = LegacyInterface.CommandPortAddress;

    signatureAddr = MmGetPhysicalAddress((PVOID)SignatureString);
    ASSERT(signatureAddr.QuadPart);

    _asm {
        mov     edx, regEdx
        mov     eax, regEax
        mov     ebx, regEbx
        mov     ecx, GeyservilleControlEnableApp
        mov     esi, signatureAddr.LowPart
        xor     edi, edi
        out     dx, al
        mov     returnCode, edi
    }

    if (returnCode == GeyservilleControlSuccessful) {
    
      return STATUS_SUCCESS;

    } else {

      DebugPrint((ERROR, "InitializeSmmInterface() Failed! rc=0x%x\n", returnCode));
      return STATUS_UNSUCCESSFUL;
    }

}


NTSTATUS
GetMaxProcFrequencySMM (
  PULONG MaxSpeed
  )
/*++

  Routine Description:

    This routine determines the maximun speed of the processor.

  Arguments:

    MaxSpeed - returned information
    
  Return Value:

    NTSTATUS

--*/ 
{
  LEGACY_GEYSERVILLE_INTERFACE_INFO info;
  NTSTATUS status;
  ULONG cpuSpeed;
  ULONG msrResult;
  ULONG busRatio;
 

  DebugEnter();
  PAGED_CODE();
  
  status = GetCurrentStateSmm(&info);

  if (!NT_SUCCESS(status)) {
    goto GetMaxProcFrequencySMMExit;
  }

  //
  // If we are in state 0, then just get current speed
  //
  // If we are in state 1:
  //   get current state's bin value
  //   add bin delta value
  //   convert bin value to Cpu Speed
  //


  //
  // High Volts
  //
  
  if (info.CurrentState == 0) {

    GetCurrentProcFrequency(0, &cpuSpeed);

  } else {

    ULONG binValue;
    ULONG newBinValue;
    ULONG index;
    
    //
    // Low Volts
    //

    DebugAssert(info.CurrentState == 1);


    //
    // Get Current Bin Value
    //

    busRatio = GetBusRatio();
    DebugPrint((MAXTRACE, "BusRatio == %u\n", busRatio));

    //
    // An error has occurred
    //
    
    if (busRatio >= PROC_STATE_INFO_SIZE) {
      DebugPrint((ERROR, "BusRatio invalid value = 0x%x\n", busRatio));
      DebugAssert(busRatio >= PROC_STATE_INFO_SIZE);
      return STATUS_UNSUCCESSFUL;
    }
    
    
    binValue = ProcessorStateInfo[busRatio].BinValue;
    DebugPrint((MAXTRACE, "BinValue == %u\n", binValue));

    newBinValue = binValue + P3_Globals.IstField;
    DebugPrint((MAXTRACE, "IstField == %u\n", P3_Globals.IstField));
    DebugPrint((MAXTRACE, "New BinValue == %u\n", newBinValue));


    cpuSpeed = FindCpuSpeedByBinValue(newBinValue, ProcessorStateInfo);
    DebugPrint((MAXTRACE, "Current CpuSpeed == %u\n", ProcessorStateInfo[busRatio].Frequency));
    DebugPrint((MAXTRACE, "Max CpuSpeed == %u\n", cpuSpeed));

  }

  
  if (ARGUMENT_PRESENT(MaxSpeed)) {
    DebugPrint((TRACE, "GetMaxProcFrequencySMM() returning %u Mhz\n", cpuSpeed));
    *MaxSpeed = cpuSpeed;
  }


GetMaxProcFrequencySMMExit:

  DebugExitStatus(status);
  return status;
  
}

NTSTATUS
GetCurrentStateSmm (
  PLEGACY_GEYSERVILLE_INTERFACE_INFO Info
  )
/*++

  Routine Description:

    This routine determines the current processor state.

  Arguments:

    Info    - returned information
    
  Return Value:

    NTSTATUS

--*/ 
{
    ULONG     regEax, regEbx, regEdx;
    ULONG     returnCode, currentState, interfaceInfo;
   
    PAGED_CODE();
    ASSERT(Info);

    
    //
    // GetGeyservilleStatus
    //

    regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
    regEbx = GetGeyservilleStatus;
    regEdx = LegacyInterface.CommandPortAddress;

    _asm {
        mov     edx, regEdx
        mov     eax, regEax
        mov     ebx, regEbx
        xor     esi, esi
        xor     edi, edi
        out     dx, al
        mov     interfaceInfo, esi
        mov     returnCode, edi
        mov     currentState, ebx
    }
    
    //
    // Suck up the return values.
    //

    Info->CurrentState = currentState;
    Info->InterfaceMajorRev  = (UCHAR)(interfaceInfo >> 24);
    Info->InterfaceMinorRev  = (USHORT)((interfaceInfo >> 8) & 0xffff);
    Info->InterfaceReserved  = (UCHAR)(interfaceInfo & 0xff);
    Info->MaxSupportedStates = (UCHAR)(returnCode >> 24);
    Info->CurrentlyAvailableStates = (UCHAR)((returnCode >> 16) & 0xff);
    Info->CurrentBiosSettings = (UCHAR)(returnCode & 0xff);

    return STATUS_SUCCESS;
    
}

NTSTATUS
SetCurrentStateSmm (
  ULONG  NewState
  )
/*++

  Routine Description:

    This routine sets the current processor state.

  Arguments:

    NewState    - target state
    
  Return Value:

    STATUS_SUCCESS      - new state currently in use
    STATUS_NOT_FOUND    - new state unreachable
    STATUS_RETRY        - new state reachable, but this transition didn't work
    STATUS_UNSUCCESSFUL - hard error                      

--*/ 
{
    ULONG    regEax, regEbx, regEdx;
    ULONG    returnCode, currentState;
    static ULONG errorCount;

    if (NewState > 1) {
      DebugAssert((NewState == 0) || (NewState == 1));
      return STATUS_INVALID_PARAMETER;
    }
    
    
    //
    // SetGeyservilleState
    //

    regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
    regEbx = SetGeyservilleState;
    regEdx = LegacyInterface.CommandPortAddress;

    _asm {
        mov     edx, regEdx
        mov     eax, regEax
        mov     ebx, regEbx
        mov     ecx, NewState
        xor     edi, edi
        out     dx, al
        mov     returnCode, edi
        mov     currentState, ebx
    }

    switch (returnCode) {

      case GeyservilleSetSuccessful:
        if (currentState != NewState) {
          DebugPrint((ERROR, "SetCurrentStateSmm(%u): BIOS ERROR: SMI returned"
                      " success with invalid current SpeedStep state = %u\n", 
                      NewState, 
                      currentState));
                      
          DebugAssert(currentState != NewState);
          return STATUS_INVALID_DEVICE_STATE;                  
        }
        return STATUS_SUCCESS;
        
      case GeyservilleStateUnavailable:
        return STATUS_NOT_FOUND;

      case GeyservilleUnsuccessfulTransition:
        return STATUS_RETRY;

      case GeyservilleAbortCritical:
        return STATUS_CANCELLED;
       
      case GeyservilleSetUnknownError:
        //DebugPrint((ERROR, "SetCurrentStateSmm() rc=GeyservilleSetUnknownError\n"));
        return STATUS_UNSUCCESSFUL;

      case GeyservilleTransitionUnavailable:
        return STATUS_PERF_TRANSITIONS_UNAVAILABLE;
        
      default:
        //DebugPrint((ERROR, "SetCurrentStateSmm() Unknown return code 0x%x\n", returnCode));
        return STATUS_UNSUCCESSFUL;
        
    }

}

NTSTATUS
SetCurrentSetupSmm (
  IN ULONG NewState
  )
/*++

  Description:
    

  Arguments:
    
    
  Return Value:

    NTSTATUS


--*/ 
{
    ULONG    regEax, regEbx, regEdx;
    ULONG    returnCode;

    PAGED_CODE();
    TRAP();

    //
    // SetGeyservilleSetup
    //

    regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
    regEbx = SetGeyservilleSetup;
    regEdx = LegacyInterface.CommandPortAddress;

    _asm {
        mov     edx, regEdx
        mov     eax, regEax
        mov     ebx, regEbx
        mov     ecx, NewState
        xor     edi, edi
        out     dx, al
        mov     returnCode, edi
    }

    
    if (returnCode == 0) {
        return STATUS_SUCCESS;
    } else {
        return STATUS_UNSUCCESSFUL;
    }
}


NTSTATUS
GetCurrentProcFrequency (
  IN  ULONG  State,
  OUT PULONG CpuSpeed
  )
/*++

  Description:
  
  Arguments:
      
  Return Value:

--*/
{
  ULONG cpuSpeed = 0;
   
  DebugAssert(CpuSpeed);
  UNREFERENCED_PARAMETER(State);
  PAGED_CODE();


  //
  // If this is a known Cpu, then we should be able
  // to use the tables for a fast look up.
  //
  
  if (P3_Globals.KnownCPUID) {

    ULONG index = GetBusRatio();

    if (index < PROC_STATE_INFO_SIZE) {
      cpuSpeed = ProcessorStateInfo[index].Frequency;
    }
    
  } 




  if (!cpuSpeed) {

    //
    // Something went wrong, and we weren't able to use the tables,
    // calculate by hand.
    //

    CalculateCpuFrequency(CpuSpeed);

  }


  *CpuSpeed = cpuSpeed;
  return STATUS_SUCCESS;
}


__inline
ULONG
GetBusRatio (
  VOID
  )
/*++

  Description:
    

  Arguments:
    
    
  Return Value:

   
--*/
{
  LARGE_INTEGER msrResult;
  ULONG busRatio;

  PAGED_CODE();
  
  //
  // Get Bus Ratio Value
  //
  
  msrResult.QuadPart = ReadMSR(MSR_2A);
  
  busRatio = msrResult.LowPart >> MSR_2A_BUS_RATIO_OFFSET;
  busRatio &= (BIT0+BIT1+BIT2+BIT3);

  //
  // This flag should be set on all 0x686 and newer cpu's
  //
  
  if (StateFlags & EXTENDED_BUS_RATIO) {
    if (msrResult.LowPart & MSR_2A_BUS_RATIO_MSB_BIT) {
      busRatio |= BIT4;
    }
  }

  return busRatio;
}


NTSTATUS
GetLegacyMaxProcFrequency(
  OUT PULONG CpuSpeed
  )
/*++

  Description:
    

  Arguments:
    
    
  Return Value:

    NTSTATUS


--*/ 
{
  static ULONG maxCpuSpeed;
  NTSTATUS status = STATUS_SUCCESS;

  DebugAssert(CpuSpeed);
  PAGED_CODE();

  //
  // if we have already calculated the max speed, use it
  //
  
  if (!maxCpuSpeed) {
    status = GetMaxProcFrequencySMM(&maxCpuSpeed); 
  }

  *CpuSpeed = maxCpuSpeed;
  return STATUS_SUCCESS;
}


NTSTATUS
CollectProcessorInfomation (
  VOID
  )
/*++

  Description:
    

  Arguments:
    
    
  Return Value:

    NTSTATUS


--*/ 
{
  LARGE_INTEGER msr17;
  LARGE_INTEGER msr2a;
  LARGE_INTEGER msr20;
  LARGE_INTEGER msr119;
  NTSTATUS status = STATUS_SUCCESS;
  ULONG cpuIdentifier;
  ULONG istField;
  ULONG platformId;
  ULONG junk;
  ULONG tmp;

  PAGED_CODE();
  

  //
  // Get CpuId
  //
  
  CPUID(1, &cpuIdentifier, &junk, &junk, &junk);

  //
  // Get MSR 0x17 results
  //

  msr17.QuadPart = ReadMSR(MSR_17);

  
  //
  // Check mobile bit, MSR 0x17[50] .. EDX[18]
  //
  
  if (!(msr17.HighPart & MSR_17_HIGH_MOBILE_PROCESSOR)) {

    DebugPrint((WARN, "This is NOT a Mobile Intel Processor\n"));
    status = STATUS_UNSUCCESSFUL;
    goto CollectProcessorInfomationExit;
    
  }


  //
  // Collect Bus Speed Information (MSR2A[19:18])
  // 0x1 == 133mhz Bus
  //
  
  msr2a.QuadPart = ReadMSR(MSR_2A);
  msr2a.LowPart >>= MSR_2A_BUS_SPEED_OFFSET;

  if ((msr2a.LowPart & (BIT0+BIT1)) == 0x1) {
    StateFlags |= BUS_133MHZ;
  }

    
  //
  // Collect Bin value Delta MSR17[57:56] .. EDX[25:24]
  //
  
  istField = (msr17.HighPart >> MSR_17_IST_FIELD_OFFSET) & (BIT0 + BIT1);


  //
  // Modify istField for specific processor steppings
  //

  //
  // If Tualatin Processor, we have to check the Stride bit MSR17[15].
  // If the Stride bit is set, add 5 to IST value, otherwise add 2
  //

  if ((cpuIdentifier & FAMILYMODEL_MASK) == FAMILYMODEL_TUALATIN) {

    StateFlags |= TUALATINE_PROCESSOR;
    StateFlags |= EXTENDED_BUS_RATIO;

    if (cpuIdentifier <= HIGHEST_KNOWN_TUALATIN_CPUID) {
      P3_Globals.KnownCPUID = TRUE;
    }


    //
    // Select the correct table
    //
    
    ProcessorStateInfo = (StateFlags & BUS_133MHZ) ? Tualatin133 : Tualatin100;

    

    //
    // Read MSR20h[15] "Stride fuse"
    //
    
    msr20.QuadPart = ReadMSR(MSR_20);
    istField += (msr20.LowPart & MSR_20_STRIDE_BIT) ? 5 : 2;
    
        
  } else if ((cpuIdentifier & FAMILYMODEL_MASK) == FAMILYMODEL_COPPERMINE) {


    StateFlags |= COPPERMINE_PROCESSOR;

    if (cpuIdentifier <= HIGHEST_KNOWN_COPPERMINE_CPUID) {
      P3_Globals.KnownCPUID = TRUE;
    }


    //
    // Select the correct table
    //

    ProcessorStateInfo = (StateFlags & BUS_133MHZ) ? Coppermine133 : Coppermine100;
    
    if (cpuIdentifier == 0x686) {
    
      //
      // C Stepping ...
      // For 0x686 we need to perform some magic based on the PlatformId bits,
      // possibly set bit 2 in istField
      //

      StateFlags |= EXTENDED_BUS_RATIO;
      platformId = (msr17.HighPart >> MSR_17_PLATFORM_ID_OFFSET) & (BIT0 + BIT1);
    
      if (platformId & BIT1) { 
  
        //
        // Componet Type
        //
  
        if (platformId & BIT0) {
          istField |= BIT2;
        }
        
      } else { 
      
        //
        // Module Type
        //
  
        if (!(platformId & BIT0)) {
          istField |= BIT2;
        }
    
      }
    
    } else if (cpuIdentifier > 0x686) {
    
      //
      // D Stepping ...
      // We need to set bit 2 in istField if MSR 0x119[0] is set 
      //

      StateFlags |= EXTENDED_BUS_RATIO;
      
      msr119.QuadPart = ReadMSR(MSR_119);
    
      if (msr119.LowPart & BIT0) {
        istField |= BIT2;
      }
      
    }

  } else {

    DebugAssert(!"Unknown Processor Family\n");
    StateFlags = 0;

  }
  

  //
  // Check to see if this processor is SpeedStep capable
  //
  
  if (!(istField & (BIT0 + BIT1 + BIT2 + BIT3 + BIT4))) {

    DebugPrint((WARN, "This processor is NOT SpeedStep capable.\n"));
    status = STATUS_UNSUCCESSFUL;
    goto CollectProcessorInfomationExit;

  }
  

  //
  // Save the IST
  //
  
  P3_Globals.IstField = istField;

    
CollectProcessorInfomationExit:

  DebugExitStatus(status);
  return status;
  
}


ULONG
FindCpuSpeedByBinValue (
  ULONG BinValue,
  PPROCESSOR_STATE_INFO Table
  )
{

  ULONG x;
  
  DebugAssert(Table);
    
  //
  // Walk tables looking for entry with matching bin value
  //

  for (x = 0; x < PROC_STATE_INFO_SIZE; x++) {

    if (Table[x].BinValue == BinValue) {
      return Table[x].Frequency;
    }
    
  }

  return 0;

}


VOID
DumpStateFlags (
  ULONG StateFlags
  )
{

  DebugPrint((MAXTRACE, "\n"));
  DebugPrint((MAXTRACE, "State Flags:\n"));
  DebugPrint((MAXTRACE, "  Coppermine Processor:  %s\n", (StateFlags & COPPERMINE_PROCESSOR) ? "Yes" : "No"));
  DebugPrint((MAXTRACE, "  Tualatine Processor:   %s\n", (StateFlags & TUALATINE_PROCESSOR) ? "Yes" : "No"));
  DebugPrint((MAXTRACE, "  133mhz Bus:            %s\n", (StateFlags & BUS_133MHZ) ? "Yes" : "No"));
  DebugPrint((MAXTRACE, "  Extended Bus Ratio     %s\n", (StateFlags & EXTENDED_BUS_RATIO) ? "Yes" : "No"));
  DebugPrint((MAXTRACE, "\n"));
  
}
