|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
amdk6msr.c
Abstract:
This module implements code specific to the AMDK6-2 processor
Author:
Todd Carpenter (7/20/00) - create file
Environment:
Kernel mode
Revision History:
--*/ #include <ntddk.h>
#include <ntacpi.h>
#include "amdk6.h"
extern LEGACY_GEMINI_SMI LegacyInterface; extern HalpFixedAcpiDescTable;
PUCHAR ProcessorToBusClockRatioStr[] = {
"4.5x", // 0
"5.0x", // 1
"4.0x", // 2
"5.5x", // 3
"2.0x", // 4
"3.0x", // 5
"6.0x", // 6
"3.5x", // 7
};
NTSTATUS GetCurrentCpuSpeedMSR ( OUT PULONG CpuSpeed ) /*++
Routine Description: Arguments: Return Value:
--*/ { NTSTATUS status; UCHAR vidANDbf; ULONG state; LARGE_INTEGER msrInfo;
DebugAssert(LegacyInterface.GBDT); DebugAssert(CpuSpeed);
msrInfo.QuadPart = ReadMSR(AMDK6_GEMINI_PSOR_MSR);
//
// VID [20:16 ] and BF [ 2:0 ] --> VID [4:0 ] and BF [7:5 ]
//
vidANDbf = (UCHAR)(((msrInfo.LowPart >> 16) & 0x1f) | ((msrInfo.LowPart & 0x7) << 5)); status = ConvertVidBfValueToGeminiState(vidANDbf, &state);
if (NT_SUCCESS(status)) { *CpuSpeed = LegacyInterface.GBDT->State[state].CpuFrequency; } return status;
}
NTSTATUS SetCurrentStateMSR ( ULONG State ) /*++
Description:
Arguments:
Return Value:
NTSTATUS
--*/ { #define STOP_GRANT_TIME_OUT 3 // ISSUE: need to check bus clock to gen this number
LARGE_INTEGER msrInfo; NTSTATUS status = STATUS_NOT_SUPPORTED; ULONG esiReturned, geminiState; UCHAR vidANDbf = 0; ULONG bvcValue = 0;
DebugAssert(LegacyInterface.EpmIoAddress);
//
// Convert to Gemini State
//
geminiState = CONVERT_PERF_STATE_INDEX(State);
//
// Lookup VID and BF values for geminiState
//
vidANDbf = (LegacyInterface.GBDT->State[geminiState].Vid) | ((LegacyInterface.GBDT->State[geminiState].Bf) << 5);
//
// Build BVC value to write to I/O space to initiate transition
//
bvcValue |= (STOP_GRANT_TIME_OUT << 12); // Stop Grant Time-out Counter
bvcValue |= (0x6 << 8); // BVF[11:8] == 0110
bvcValue |= vidANDbf; //
_asm {
//
// Disable bus masters
//
mov edx, [HalpFixedAcpiDescTable + 72] in al, dx // read PM2_CNT_BLK
mov cl, al // save current PM2_CNT_BLK
or al, 0x1 // set ARB_DIS bit
out dx, al // write PM2_CNT_BLK
//
// initiate processor transition
//
mov edx, LegacyInterface.EpmIoAddress mov eax, bvcValue out dx, eax
//
// Restore bus master access
//
mov edx, [HalpFixedAcpiDescTable + 72] mov al, cl out dx, al
}
//
// BUGBUG: Need to figure out error checking. Should probably go read
// see if PSOR reflects our new vid and bf values.
//
return STATUS_SUCCESS; }
NTSTATUS ReadEpmInfo ( OUT PULONG EpmInfo ) /*++
Routine Description: Arguments: Return Value:
--*/ { ULONG emp;
_asm {
mov eax, AMDK6_GEMINI_CPUID_EPM xor ebx, ebx xor ecx, ecx xor edx, edx // will be destroyed by the cpuid
cpuid mov emp, edx
}
if (ARGUMENT_PRESENT(EpmInfo)) { *EpmInfo = emp; }
return STATUS_SUCCESS; }
NTSTATUS EnableGeminiTransitionsMSR ( PULONG BaseAddress ) /*++
Routine Description: Arguments: Return Value:
--*/ { ULARGE_INTEGER msrInfo;
DebugAssert(BaseAddress); //
// EPMR contains I/O block address for perf transitions
//
msrInfo.QuadPart = ReadMSR(AMDK6_GEMINI_EPMR_MSR);
*BaseAddress = (msrInfo.LowPart & ~0xf) + 8; DebugPrint((INFO, "EnableGeminiTransitionsMSR: Base Address = 0x%x\n", *BaseAddress));
//
// Enable mobile feature base address
//
msrInfo.LowPart |= 0x1; WriteMSR(AMDK6_GEMINI_EPMR_MSR, msrInfo.QuadPart);
return STATUS_SUCCESS;
}
VOID DisplayEPM ( IN ULONG Epm ) {
DebugPrint((MAXTRACE, "Enhanced Power Management Information (0x%x):\n", Epm)); DebugPrint((MAXTRACE, " Temperature Sensor: %sSupported\n", (Epm & 0x1) ? "" : "NOT ")); DebugPrint((MAXTRACE, " Bus Divisor Control: %sSupported\n", (Epm & 0x2) ? "" : "NOT ")); DebugPrint((MAXTRACE, " Voltage Id control: %sSupported\n", (Epm & 0x4) ? "" : "NOT ")); DebugPrint((MAXTRACE, "\n")); }
VOID DisplayEPMR ( IN ULONG Epmr ) {
DebugPrint((MAXTRACE, "Enhanced Power Management Register (0x%x):\n", Epmr)); DebugPrint((MAXTRACE, " Mobile Feature Base Address = %sEnabled\n", (Epmr & 0x1) ? "" : "NOT ")); DebugPrint((MAXTRACE, " Generate Special Bus Cycle = %sEnabled\n", (Epmr & 0x2) ? "" : "NOT ")); DebugPrint((MAXTRACE, " I/O Base Address = 0x%x\n", ((Epmr >> 4) & 0xffff))); DebugPrint((MAXTRACE, "\n")); }
VOID DisplayPSOR ( IN ULONG Psor ) {
DebugPrint((MAXTRACE, "Processor State Observability (0x%x):\n", Psor)); DebugPrint((MAXTRACE, " Bus Frequency Divisor (Internal) = 0x%x (%s)\n", (Psor & 0x3), ProcessorToBusClockRatioStr[(Psor & 0x3)])); DebugPrint((MAXTRACE, " Processor Stepping Id = 0x%x\n", ((Psor >> 4) & 0xf))); DebugPrint((MAXTRACE, " L2 Cache Present = %s\n", (Psor & 0x256) ? "No" : "Yes")); DebugPrint((MAXTRACE, " Voltage Id = 0x%x\n", ((Psor >> 16) & 0x1f))); DebugPrint((MAXTRACE, " Bus Frequency Divisor (External) = 0x%x (%s)\n", ((Psor >> 21) & 0x3), ProcessorToBusClockRatioStr[((Psor >> 21) & 0x3)])); DebugPrint((MAXTRACE, "\n")); }
|