windows-nt/Source/XPSP1/NT/base/hals/processor/viac3/viac3.c

516 lines
9.8 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
viac3.c
Abstract:
This module implements code that works on Cyrix processors with LongHaul power management support.
Author:
Tom Brown (t-tbrown) 07-Jun-2001
Environment:
Kernel mode
Notes:
DeviceInst = "ACPI\CentaurHauls_-_x86_Family_6_Model_7"
DeviceInst = "ACPI\CentaurHauls_-_x86_Family_6_Model_8"
ServiceName = "viac3"
Revision History:
--*/
#include "..\lib\processor.h"
#include "legacy.h"
#include "viac3.h"
//
// Must define for debug output
//
#if DBG
PUCHAR DebugName = "viac3.sys";
#endif
PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS];
UCHAR DevExtIndex;
extern GLOBALS Globals;
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
#pragma alloc_text (PAGE, InitializeAcpi2PStates)
#pragma alloc_text (PAGE, InitializeAcpi2Cstates)
#pragma alloc_text (PAGE, MergePerformanceStates)
#endif
NTSTATUS
InitializeDriver(
IN PUNICODE_STRING ServiceKeyRegPath
)
/*++
Routine Description:
Initializes the LongHaul flags be getting information from the CPU and reading
the HackFlagsOn and HackFlagsOff keys.
Arguments:
ServiceKeyRegPath - This proc drivers key in the registry
Return Value:
NTSTATUS - STATUS_SUCCESS or an error
--*/
{
ULONG flags;
LongHaulFlags = 0x0;
// This driver is not MP safe, and most likely never will
if ( Globals.SingleProcessorProfile == FALSE ) {
return STATUS_DRIVER_UNABLE_TO_LOAD; // Lib ignores this return value
}
// Just loaded, there are no queued work items
NextTransitionThrottle = INVALID_THROTTLE;
IdentifyCPUVersion();
// Add and remove flags according to registry
// HackFlagsOn will be set, then
// HackFlagsOff will be cleared
GetRegistryDwordValue((PWCHAR) VIAC3_PARAMETERS_KEY,
L"HackFlags",
&flags);
if( flags & DISABLE_ALL_HACK_FLAG ) {
DebugPrint((WARN, "All legacy functionality disabled by DISABLE_ALL_HACK_FLAG.\n"));
LongHaulFlags = 0x0;
} else if( flags & NO_SOFTVID_HACK_FLAG ) {
DebugPrint((WARN, "softVID disabled by NO_SOFTVID_HACK_FLAG.\n"));
LongHaulFlags &= ~SUPPORTS_SOFTVID_FLAG;
} else if( flags & NO_VOLTAGE_STEPPING_HACK_FLAG ) {
DebugPrint((WARN, "Will not transition voltage in steps. Can cause crashes. Set by NO_VOLTAGE_STEPPING_HACK_FLAG.\n"));
LongHaulFlags &= ~NEEDS_VOLTAGE_STEPPING_FLAG;
}
InitializeCPU();
#ifdef DBG
DebugShowCurrent();
#endif
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];
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];
//
// Since this driver does not support Functional Fixed Hardware, we
// use generic method.
//
return SetThrottleLevelGeneric(Throttle, DeviceExtension);
}
NTSTATUS
GetProcessorBrandString (
PUCHAR BrandString,
PULONG Size
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
//
// With the generic driver we only try to find the Processor Brand String
// via the CPUID
//
return GetCPUIDProcessorBrandString(BrandString, Size);
}
NTSTATUS
InitializeAcpi2PStates(
IN PFDO_DATA DevExt
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS status;
status = InitializeAcpi2PStatesGeneric(DevExt);
//
// Check that we only access FFH
//
if (NT_SUCCESS(status)) {
if ((DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceFixedFunction) ||
(DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceFixedFunction)) {
DebugPrint((ERROR, "This driver ONLY supports FFH addresses for Acpi 2.0\n"));
status = STATUS_NOT_FOUND;
goto InitializeAcpi2PStatesExit;
}
//
// Walk through _PSS states to calculate latency values
//
ValidatePssLatencyValues(DevExt);
//
// Need to merge this new data with our perfstates
//
MergePerformanceStates(DevExt);
}
InitializeAcpi2PStatesExit:
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.
--*/
{
DebugEnter();
return MergePerformanceStatesGeneric(DeviceExtension);
}
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:
DeviceExtension - The device extension for this object
NewState - Index into _PSS object
Return Value:
None
--*/
{
NTSTATUS status = STATUS_SUCCESS;
DebugEnter();
DebugAssert(DeviceExtension->PssPackage)
DebugAssert(NewState >= DeviceExtension->PpcResult);
DebugAssert(NewState < DeviceExtension->PssPackage->NumPStates);
DebugAssert(DeviceExtension->PssPackage->State[NewState].CoreFrequency);
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;
}
// Queue the transition so it always run at PASSIVE irql
status = QueueTransition( DeviceExtension, NewState);
if( NT_SUCCESS(status) ) {
DeviceExtension->CurrentPssState = NewState;
}
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 current state, transition to lowest non-throttled perf state
//
return SaveCurrentStateGoToLowVolts(DeviceExtension);
}