857 lines
17 KiB
C
857 lines
17 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
amdk7.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements code specific to the AMDK7 processor
|
|||
|
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Todd Carpenter (1/30/01) - create file
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
DeviceInst = "ACPI\AuthenticAMD_-_x86_Family_6_Model_6"
|
|||
|
ServiceName = "amdk7"
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
#include "..\lib\processor.h"
|
|||
|
#include "amdk7.h"
|
|||
|
|
|||
|
#if DBG
|
|||
|
PUCHAR DebugName = "AmdK7.sys";
|
|||
|
#endif
|
|||
|
|
|||
|
PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS];
|
|||
|
UCHAR DevExtIndex;
|
|||
|
ULONG AmdK7HackFlags;
|
|||
|
|
|||
|
extern GLOBALS Globals;
|
|||
|
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text (PAGE, InitializeDriver)
|
|||
|
#pragma alloc_text (PAGE, GetProcessorBrandString)
|
|||
|
#pragma alloc_text (PAGE, InitializeAcpi2PStates)
|
|||
|
#pragma alloc_text (PAGE, InitializeAcpi2Cstates)
|
|||
|
#pragma alloc_text (PAGE, MergePerformanceStates)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
InitializeDriver(
|
|||
|
PUNICODE_STRING ServiceKeyRegPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Get AmdK7 Hack Flags
|
|||
|
//
|
|||
|
|
|||
|
GetRegistryDwordValue((PWCHAR) AMDK7_PARAMETERS_KEY,
|
|||
|
L"HackFlags",
|
|||
|
&AmdK7HackFlags);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FASTCALL
|
|||
|
SetPerfLevel(
|
|||
|
IN UCHAR Throttle
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PFDO_DATA DeviceExtension;
|
|||
|
ULONG apicId;
|
|||
|
ULONG index = 0;
|
|||
|
|
|||
|
DebugEnter();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get APIC Id and retrieve Device Extension index
|
|||
|
//
|
|||
|
|
|||
|
if (!Globals.SingleProcessorProfile) {
|
|||
|
apicId = GetApicId();
|
|||
|
index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the DeviceExtension.
|
|||
|
//
|
|||
|
|
|||
|
DeviceExtension = DeviceExtensions[index];
|
|||
|
|
|||
|
//
|
|||
|
// This driver only supports FFH addresses, but SetPerfLevelGeneric
|
|||
|
// only finds the correct state, it will then call Acpi2PerfStateTransition
|
|||
|
//
|
|||
|
|
|||
|
return SetPerfLevelGeneric(Throttle, DeviceExtension);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FASTCALL
|
|||
|
SetThrottleLevel(
|
|||
|
IN UCHAR Throttle
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PFDO_DATA DeviceExtension;
|
|||
|
ULONG apicId;
|
|||
|
ULONG index = 0;
|
|||
|
|
|||
|
DebugEnter();
|
|||
|
|
|||
|
//
|
|||
|
// Get APIC Id and retrieve Device Extension index
|
|||
|
//
|
|||
|
|
|||
|
if (!Globals.SingleProcessorProfile) {
|
|||
|
apicId = GetApicId();
|
|||
|
index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get the DeviceExtension.
|
|||
|
//
|
|||
|
|
|||
|
DeviceExtension = DeviceExtensions[index];
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// This driver supports Acpi 1.0b style of throttling, use
|
|||
|
// generic function
|
|||
|
//
|
|||
|
|
|||
|
return SetThrottleLevelGeneric(Throttle, DeviceExtension);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
GetProcessorBrandString (
|
|||
|
PUCHAR BrandString,
|
|||
|
PULONG Size
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// This processor supports the CpuId based brand string
|
|||
|
//
|
|||
|
|
|||
|
return GetCPUIDProcessorBrandString(BrandString, Size);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
InitializeAcpi2PStates(
|
|||
|
IN PFDO_DATA DevExt
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
status = InitializeAcpi2PStatesGeneric(DevExt);
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
if ((DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceFixedFunction) ||
|
|||
|
(DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceFixedFunction)) {
|
|||
|
|
|||
|
DebugPrint((WARN, "ONLY Acpi 2.0 FFH addresses are supported\n"));
|
|||
|
DebugPrint((WARN, "NOT using Acpi 2.0 Performance States\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Undo what InitializeAcpi2PStatesGeneric() did
|
|||
|
//
|
|||
|
|
|||
|
if (DevExt->PssPackage) {
|
|||
|
ExFreePool(DevExt->PssPackage);
|
|||
|
DevExt->PssPackage = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_NOT_SUPPORTED;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Walk through _PSS states to calculate latency values
|
|||
|
//
|
|||
|
|
|||
|
ValidatePssLatencyValues(DevExt);
|
|||
|
|
|||
|
//
|
|||
|
// Need to merge this new data with our perfstates
|
|||
|
//
|
|||
|
|
|||
|
MergePerformanceStates(DevExt);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
InitializeAcpi2Cstates(
|
|||
|
PFDO_DATA DevExt
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function looks to see if there is an ACPI 2.0 _CST object in the
|
|||
|
namespace, and, if there is, it replaces the functions found by
|
|||
|
InitializeAcpi1Cstates.
|
|||
|
|
|||
|
Further note: This function leaves the filling in of throttling functions
|
|||
|
to the InitializePerformanceStates functions.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceExtension
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A NTSTATUS code to indicate the result of the initialization.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG apicId;
|
|||
|
ULONG index = 0;
|
|||
|
|
|||
|
DebugEnter();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Record the address of this processor's DeviceExtension, as the
|
|||
|
// throttling API doesn't give it to us.
|
|||
|
//
|
|||
|
|
|||
|
if (!Globals.SingleProcessorProfile) {
|
|||
|
|
|||
|
//
|
|||
|
// save the index into the DeviceExtension[] for later retrieval based
|
|||
|
// on APIC Id.
|
|||
|
//
|
|||
|
|
|||
|
apicId = Globals.ProcInfo.ProcIdToApicId[DevExt->ProcObjInfo.PhysicalID];
|
|||
|
Globals.ProcInfo.ApicIdToDevExtIndex[apicId] = DevExtIndex;
|
|||
|
|
|||
|
index = DevExtIndex++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// save Device Extension pointer
|
|||
|
//
|
|||
|
|
|||
|
DeviceExtensions[index] = DevExt;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// This processor driver only supports I/O Space based Cstates.
|
|||
|
// InitializeAcpi2IoSpaceCstates() will fail if it finds Cstates with
|
|||
|
// non AcpiGenericSpaceIO type addresses.
|
|||
|
//
|
|||
|
|
|||
|
return InitializeAcpi2IoSpaceCstates(DevExt);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MergePerformanceStates(
|
|||
|
IN PFDO_DATA DeviceExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine looks at the performance states stored in the device extension.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceExtension
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A NTSTATUS code to indicate the result of the initialization.
|
|||
|
|
|||
|
NOTE:
|
|||
|
|
|||
|
- The caller must hold PerfStateLock.
|
|||
|
|
|||
|
- This is called during START_DEVICE, and after recieving a Notify(0x80)
|
|||
|
on the processor.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
NTSTATUS findStatus;
|
|||
|
ULONG pssState = 0xdeadbeef;
|
|||
|
|
|||
|
DebugEnter();
|
|||
|
|
|||
|
//
|
|||
|
// This function just merges available _PSS and stop clock throttle states
|
|||
|
//
|
|||
|
|
|||
|
status = MergePerformanceStatesGeneric(DeviceExtension);
|
|||
|
|
|||
|
//
|
|||
|
// With amdk7.sys, the order of transition execution differs if going from a
|
|||
|
// higher state to a lower state when compared to going from a lower state to
|
|||
|
// a higher state... Therefore, it is important that we set the current state
|
|||
|
// before registering new performance states with the kernel.
|
|||
|
//
|
|||
|
// NOTE: MergePerformanceStatesGeneric() will invalidate CurrentPerfState,
|
|||
|
// so it must be set here.
|
|||
|
//
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
findStatus = FindCurrentPssPerfState(DeviceExtension->PssPackage, &pssState);
|
|||
|
|
|||
|
if (NT_SUCCESS(findStatus)) {
|
|||
|
DebugAssert(pssState < DeviceExtension->PssPackage->NumPStates);
|
|||
|
DeviceExtension->CurrentPerfState = pssState;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
Acpi2PerfStateTransition(
|
|||
|
IN PFDO_DATA DeviceExtension,
|
|||
|
IN ULONG NewState
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine changes the performance state of the processor
|
|||
|
based on ACPI 2.0 performance state objects.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
State - Index into _PSS object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
ULONG transitionStatus;
|
|||
|
ULONG pssControl;
|
|||
|
ULONG64 fidControl;
|
|||
|
ULONG64 vidControl;
|
|||
|
ULONG64 fidVidStatus;
|
|||
|
|
|||
|
DebugEnter();
|
|||
|
DebugAssert(DeviceExtension->PssPackage)
|
|||
|
DebugAssert(NewState >= DeviceExtension->PpcResult);
|
|||
|
DebugAssert(NewState < DeviceExtension->PssPackage->NumPStates);
|
|||
|
DebugAssert(DeviceExtension->PssPackage->State[NewState].Control);
|
|||
|
|
|||
|
|
|||
|
if (DeviceExtension->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceFixedFunction) {
|
|||
|
DebugAssert(!"Acpi2PerfStateTransition ONLY understands FFH addresses");
|
|||
|
status = STATUS_UNSUCCESSFUL;
|
|||
|
goto Acpi2PerfStateTransitionExit;
|
|||
|
}
|
|||
|
|
|||
|
if (NewState == DeviceExtension->CurrentPssState) {
|
|||
|
DebugPrint((WARN, "Acpi2PerfStateTransition() CurrentState == TargetState, exiting...\n"));
|
|||
|
goto Acpi2PerfStateTransitionExit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Transitioning the Mobile Athlon Processor requires two steps:
|
|||
|
//
|
|||
|
// If transitioning from a higher state to a lower state, then:
|
|||
|
// 1) core frequency transition
|
|||
|
// 2) core voltage transition
|
|||
|
//
|
|||
|
// If transitioning from a lower state to a higher state, then:
|
|||
|
// 1) core voltage transition
|
|||
|
// 2) core frequency transition
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Get Frequency and Voltage value to write to MSR
|
|||
|
//
|
|||
|
|
|||
|
pssControl = DeviceExtension->PssPackage->State[NewState].Control;
|
|||
|
fidControl = ConvertPssControlToFidVidControl(pssControl, TRUE);
|
|||
|
vidControl = ConvertPssControlToFidVidControl(pssControl, FALSE);
|
|||
|
|
|||
|
if (NewState > DeviceExtension->CurrentPssState) {
|
|||
|
|
|||
|
//
|
|||
|
// High -> Low
|
|||
|
//
|
|||
|
|
|||
|
DebugPrint((TRACE, "Perf Transition: state %u -> state %u\n", DeviceExtension->CurrentPssState, NewState));
|
|||
|
DebugPrint((TRACE, "FidControl = 0x%I64x, VidControl = 0x%I64x\n", fidControl, vidControl));
|
|||
|
AmdK7FidVidTransition(fidControl);
|
|||
|
AmdK7FidVidTransition(vidControl);
|
|||
|
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Low -> High
|
|||
|
//
|
|||
|
|
|||
|
DebugPrint((TRACE, "Perf Transition: state %u -> state %u\n", DeviceExtension->CurrentPssState, NewState));
|
|||
|
DebugPrint((TRACE, "VidControl = 0x%I64x, FidControl = 0x%I64x\n", vidControl, fidControl));
|
|||
|
AmdK7FidVidTransition(vidControl);
|
|||
|
AmdK7FidVidTransition(fidControl);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// check status
|
|||
|
//
|
|||
|
|
|||
|
fidVidStatus = ReadMSR(AMDK7_FID_VID_STATUS_MSR);
|
|||
|
transitionStatus = ConvertFidVidStatusToPssStatus(fidVidStatus);
|
|||
|
|
|||
|
if (transitionStatus == DeviceExtension->PssPackage->State[NewState].Status) {
|
|||
|
|
|||
|
DeviceExtension->CurrentPssState = NewState;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DebugPrint((ERROR, "ERROR! Expected 0x%x status value, recieved 0x%x\n",
|
|||
|
DeviceExtension->PssPackage->State[NewState].Status,
|
|||
|
transitionStatus));
|
|||
|
|
|||
|
DebugPrint((ERROR, "_PSS[%u]->Status:\n", NewState));
|
|||
|
DumpPssStatus(DeviceExtension->PssPackage->State[NewState].Status);
|
|||
|
|
|||
|
DebugPrint((ERROR, "FidVidStatus MSR:\n", fidVidStatus));
|
|||
|
DumpFidVidStatus(fidVidStatus);
|
|||
|
|
|||
|
status = STATUS_UNSUCCESSFUL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Acpi2PerfStateTransitionExit:
|
|||
|
|
|||
|
DebugExitStatus(status);
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ProcessResumeFromSleepState(
|
|||
|
SYSTEM_POWER_STATE PreviousState,
|
|||
|
PFDO_DATA DeviceExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DebugEnter();
|
|||
|
|
|||
|
//
|
|||
|
// if we are resuming from Hibernate, and this is an Acpi 2.0 system,
|
|||
|
// we must re-claim perf state and cstate control from the bios.
|
|||
|
//
|
|||
|
|
|||
|
if (PreviousState == PowerSystemHibernate) {
|
|||
|
|
|||
|
if (DeviceExtension->PssPackage) {
|
|||
|
AssumeProcessorPerformanceControl();
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceExtension->CstPresent) {
|
|||
|
AssumeCStateControl();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// restore previous state
|
|||
|
//
|
|||
|
|
|||
|
return RestoreToSavedPerformanceState(DeviceExtension);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ProcessSuspendToSleepState(
|
|||
|
SYSTEM_POWER_STATE TargetState,
|
|||
|
PFDO_DATA DeviceExtension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DebugEnter();
|
|||
|
|
|||
|
//
|
|||
|
// save previous state, transition to lowest non-throttled perf state
|
|||
|
//
|
|||
|
|
|||
|
return SaveCurrentStateGoToLowVolts(DeviceExtension);
|
|||
|
}
|
|||
|
|
|||
|
ULONG64
|
|||
|
ConvertPssControlToFidVidControl(
|
|||
|
ULONG PssControlValue,
|
|||
|
BOOLEAN Fid
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
NOTES:
|
|||
|
|
|||
|
_PSS Control field:
|
|||
|
|
|||
|
Bit Name
|
|||
|
---- ----
|
|||
|
4:0 FID
|
|||
|
9:5 VID
|
|||
|
29:10 SGTC
|
|||
|
31:30 Reserved
|
|||
|
|
|||
|
|
|||
|
FidVidCtl:
|
|||
|
|
|||
|
Bit Name Function
|
|||
|
---- ---- --------
|
|||
|
4:0 FID[4:0] New 5-bit FID to transition to
|
|||
|
7:5 reserved
|
|||
|
12:8 VID[4:0] New 5-bit VID to transition to
|
|||
|
15:13 reserved
|
|||
|
16 FIDC FID Control bit
|
|||
|
17 VIDC VID Control bit
|
|||
|
19:18 reserved
|
|||
|
20 FidChgRatio Fid Change Ratio (always set to 1)
|
|||
|
31:21 reserved
|
|||
|
51:32 SGTC[19:0] Stop-Grant Timeout Count (write only)
|
|||
|
63:52 reserved
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
FID_VID_CONTROL fidVidControl = {0};
|
|||
|
PSS_CONTROL pssControl;
|
|||
|
|
|||
|
//DebugEnter();
|
|||
|
DebugAssert(PssControlValue);
|
|||
|
|
|||
|
pssControl.AsDWord = PssControlValue;
|
|||
|
fidVidControl.Fid = pssControl.Fid;
|
|||
|
fidVidControl.Vid = pssControl.Vid;
|
|||
|
fidVidControl.FidChngRatio = 1;
|
|||
|
|
|||
|
//
|
|||
|
// The timeout needed for the Frequency Transion (FID) is exactly half that
|
|||
|
// needed by the Voltage Transion (VID). We do this because of the latency
|
|||
|
// savings
|
|||
|
//
|
|||
|
|
|||
|
if (Fid) {
|
|||
|
|
|||
|
fidVidControl.SGTC = pssControl.SGTC / 2;
|
|||
|
fidVidControl.FidControl = 1;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
fidVidControl.SGTC = pssControl.SGTC;
|
|||
|
fidVidControl.VidControl = 1;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return fidVidControl.AsQWord;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
ConvertFidVidStatusToPssStatus(
|
|||
|
ULONG64 FidVidStatusValue
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
NOTES:
|
|||
|
|
|||
|
FidVidStatus:
|
|||
|
|
|||
|
Bit Name Function
|
|||
|
---- ---- --------
|
|||
|
4:0 CFID[4:0] Current 5-bit FID
|
|||
|
7:5 reserved
|
|||
|
12:8 SFID[4:0] Startup 5-bit FID
|
|||
|
15:13 reserved
|
|||
|
20:16 MFID[4:0] Maximum 5-bit FID
|
|||
|
31:21 reserved
|
|||
|
36:32 CVID[4:0] Current 5-bit VID
|
|||
|
39:37 reserved
|
|||
|
44:40 SVID[4:0] Startup 5-bit VID
|
|||
|
47:45 reserved
|
|||
|
52:48 MVID[4:0] Maximum 5-bit VID
|
|||
|
63:53 reserved
|
|||
|
|
|||
|
_PSS Status Field:
|
|||
|
|
|||
|
Bit Name
|
|||
|
---- ----
|
|||
|
4:0 FID current frequency
|
|||
|
9:5 VID current voltage
|
|||
|
31:10 reserved
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PSS_STATUS pssStatus;
|
|||
|
FID_VID_STATUS fidVidStatus;
|
|||
|
|
|||
|
//DebugEnter();
|
|||
|
DebugAssert(FidVidStatusValue);
|
|||
|
|
|||
|
fidVidStatus.AsQWord = FidVidStatusValue;
|
|||
|
pssStatus.Fid = fidVidStatus.CFid;
|
|||
|
pssStatus.Vid = fidVidStatus.CVid;
|
|||
|
pssStatus.Reserved = 0;
|
|||
|
|
|||
|
return pssStatus.AsDWord;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FindCurrentPssPerfState(
|
|||
|
PACPI_PSS_PACKAGE PssPackage,
|
|||
|
PULONG PssState
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|||
|
ULONG x;
|
|||
|
ULONG transitionStatus;
|
|||
|
ULONG64 fidVidStatus;
|
|||
|
|
|||
|
DebugEnter();
|
|||
|
DebugAssert(PssPackage);
|
|||
|
DebugAssert(PssState);
|
|||
|
|
|||
|
fidVidStatus = ReadMSR(AMDK7_FID_VID_STATUS_MSR);
|
|||
|
transitionStatus = ConvertFidVidStatusToPssStatus(fidVidStatus);
|
|||
|
|
|||
|
for (x=0; x < PssPackage->NumPStates; x++) {
|
|||
|
|
|||
|
if (transitionStatus == PssPackage->State[x].Status) {
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
*PssState = x;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DebugExitStatus(status);
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
VOID
|
|||
|
DumpFidVidStatus(
|
|||
|
IN ULONG64 FidVidStatus
|
|||
|
)
|
|||
|
{
|
|||
|
FID_VID_STATUS status;
|
|||
|
|
|||
|
status.AsQWord = FidVidStatus;
|
|||
|
|
|||
|
DebugPrint((MAXTRACE, " CFid: 0x%x\n", status.CFid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved1));
|
|||
|
DebugPrint((MAXTRACE, " SFid: 0x%x\n", status.SFid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved2));
|
|||
|
DebugPrint((MAXTRACE, " MFid: 0x%x\n", status.MFid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved3));
|
|||
|
DebugPrint((MAXTRACE, " CVid: 0x%x\n", status.CVid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved4));
|
|||
|
DebugPrint((MAXTRACE, " SVid: 0x%x\n", status.SVid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved5));
|
|||
|
DebugPrint((MAXTRACE, " MVid: 0x%x\n", status.MVid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved6));
|
|||
|
DebugPrint((MAXTRACE, "\n"));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
DumpFidVidControl(
|
|||
|
IN ULONG64 FidVidControl
|
|||
|
)
|
|||
|
{
|
|||
|
FID_VID_CONTROL control;
|
|||
|
|
|||
|
control.AsQWord = FidVidControl;
|
|||
|
|
|||
|
DebugPrint((MAXTRACE, " Fid: 0x%x\n", control.Fid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", control.Reserved1));
|
|||
|
DebugPrint((MAXTRACE, " Vid: 0x%x\n", control.Vid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", control.Reserved2));
|
|||
|
DebugPrint((MAXTRACE, " FidControl: 0x%x\n", control.FidControl));
|
|||
|
DebugPrint((MAXTRACE, " VidControl: 0x%x\n", control.VidControl));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", control.Reserved3));
|
|||
|
DebugPrint((MAXTRACE, " FidChngRatio: 0x%x\n", control.FidChngRatio));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", control.Reserved4));
|
|||
|
DebugPrint((MAXTRACE, " SGTC: 0x%x\n", control.SGTC));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", control.Reserved5));
|
|||
|
DebugPrint((MAXTRACE, "\n"));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
DumpPssStatus(
|
|||
|
IN ULONG PssStatus
|
|||
|
)
|
|||
|
{
|
|||
|
PSS_STATUS status;
|
|||
|
|
|||
|
status.AsDWord = PssStatus;
|
|||
|
|
|||
|
DebugPrint((MAXTRACE, " Fid: 0x%x\n", status.Fid));
|
|||
|
DebugPrint((MAXTRACE, " Vid: 0x%x\n", status.Vid));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", status.Reserved));
|
|||
|
DebugPrint((MAXTRACE, "\n"));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
DumpPssControl(
|
|||
|
IN ULONG PssControl
|
|||
|
)
|
|||
|
{
|
|||
|
PSS_CONTROL control;
|
|||
|
|
|||
|
control.AsDWord = PssControl;
|
|||
|
|
|||
|
DebugPrint((MAXTRACE, " Fid: 0x%x\n", control.Fid));
|
|||
|
DebugPrint((MAXTRACE, " Vid: 0x%x\n", control.Vid));
|
|||
|
DebugPrint((MAXTRACE, " SGTC: 0x%x\n", control.SGTC));
|
|||
|
DebugPrint((MAXTRACE, " Reserved: 0x%x\n", control.Reserved));
|
|||
|
DebugPrint((MAXTRACE, "\n"));
|
|||
|
|
|||
|
}
|
|||
|
#endif
|