|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
crusoe.c
Abstract:
This module implements code specific to the Crusoe processor
Author:
Todd Carpenter (10/31/00) - create file
Environment:
Kernel mode
Notes:
DeviceInst = "ACPI\GenuineTMx86_-_x86_Family_5_Model_4" ServiceName = "crusoe" Revision History:
--*/ #include "crusoe.h"
#include "..\lib\processor.h"
#if DBG
PUCHAR DebugName = "Crusoe.sys"; #endif
PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS]; UCHAR DevExtIndex;
extern GLOBALS Globals; extern LONGRUN_STATES LongRunStates;
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, InitializeDriver)
#pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
#pragma alloc_text (PAGE, InitializeAcpi2PStates)
#pragma alloc_text (PAGE, InitializeAcpi2Cstates)
#pragma alloc_text (PAGE, MergePerformanceStates)
#pragma alloc_text (PAGE, GetLegacyMaxProcFrequency)
#pragma alloc_text (PAGE, AdjustLegacyProcessorPerformanceStates)
#pragma alloc_text (PAGE, GetProcessorBrandString)
#endif
NTSTATUS InitializeDriver( PUNICODE_STRING ServiceKeyRegPath ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { PAGED_CODE(); return STATUS_SUCCESS; }
NTSTATUS InitializeNonAcpiPerformanceStates( IN PFDO_DATA DeviceExtension ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { NTSTATUS status; DebugEnter(); PAGED_CODE();
//
// We automatically fail to use the Legacy Interface
//
if (Globals.HackFlags & DISABLE_LEGACY_INTERFACE_FLAG) { DebugPrint((ERROR, " Legacy Interface Disabled\n")); return STATUS_NOT_FOUND; }
//
// Find and gather legacy interface info
//
status = InitializeLegacyInterface(DeviceExtension); if (!NT_SUCCESS(status)) { DebugExitStatus(status); return status; } //
// Found Legacy Interface, and is available to use.
//
DeviceExtension->LegacyInterface = TRUE;
//
// Merge Perf states with other states we may have.
//
status = MergePerformanceStates(DeviceExtension); DumpProcessorPerfStates(DeviceExtension->PerfStates); if (!NT_SUCCESS(status)) { if (DeviceExtension->PerfStates) { ExFreePool(DeviceExtension->PerfStates); }
if (DeviceExtension->PssPackage) { ExFreePool(DeviceExtension->PssPackage); } DeviceExtension->PerfStates = NULL; DeviceExtension->LegacyInterface = FALSE; }
DebugExitStatus(status); return status; }
NTSTATUS AcpiLegacyPerfStateTransition( IN PFDO_DATA DevExt, IN ULONG State ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { return Acpi2PerfStateTransition(DevExt, State); }
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];
//
// Since this driver does not support Functional Fixed Hardware, we
// use generic method.
//
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 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((ERROR, "This driver ONLY supports FFH addresses for Acpi 2.0\n")); status = STATUS_NOT_FOUND; }
//
// 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(); PAGED_CODE();
//
// 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(); PAGED_CODE();
//
// Use the generic method to merge our perf states with stop clock states
//
return MergePerformanceStatesGeneric(DeviceExtension);
}
NTSTATUS Acpi2PerfStateTransition( IN PFDO_DATA DevExt, 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
--*/ { ULONG lowerBound; ULONG uppperBound; NTSTATUS status = STATUS_SUCCESS; STATE_INFO stateInfo; CRUSOE_PSS_VALUE pssControl; CRUSOE_PSS_VALUE pssStatus; ULARGE_INTEGER longRunRange;
DebugEnter(); //
// The only type of Acpi 2.0 implementation this driver supports is FFH
//
DebugAssert(DevExt); DebugAssert(DevExt->PctPackage.Control.AddressSpaceID == AcpiGenericSpaceFixedFunction); DebugAssert(DevExt->PctPackage.Status.AddressSpaceID == AcpiGenericSpaceFixedFunction);
pssControl.AsDWord = DevExt->PssPackage->State[NewState].Control; pssStatus.AsDWord = DevExt->PssPackage->State[NewState].Status; //
// Sanity Check illeagal conditions
//
if (pssControl.Min > MAX_LONGRUN_VALUE) { DebugPrint((ERROR, "ERROR: illegal LongRun value: Min=0x%x\n", pssControl.Min)); pssControl.Min = MAX_LONGRUN_VALUE; }
if (pssControl.Max > MAX_LONGRUN_VALUE) { DebugPrint((ERROR, "ERROR: illegal LongRun value: Max=0x%x\n", pssControl.Max)); pssControl.Max = MAX_LONGRUN_VALUE; }
if (pssControl.Min > pssControl.Max) { DebugPrint((ERROR, "ERROR: illegal LongRun Range: Min: 0x%x, Max: 0x%x\n", pssControl.Min, pssControl.Max));
pssControl.Min = pssControl.Max; }
//
// Transition to new performance state
//
DebugPrint((ERROR, "Setting Long Run Range: l=0x%x, u=0x%x\n", pssControl.Min, pssControl.Max)); SetCurrentPerformanceRange(pssControl.Min, pssControl.Max);
//
// Check to see if the transition was successful
// NOTE: we have to check the LongRun Range rather than a specific state as
// there is no way to know which state within a given range the cpu
// will be in.
//
longRunRange.QuadPart = GetCurrentPerformanceRange();
if ((longRunRange.HighPart == pssStatus.Max) && (longRunRange.LowPart == pssStatus.Min)) {
DevExt->CurrentPssState = NewState;
} else {
DebugPrint((ERROR, "ERROR! Expected: l=0x%x, h=0x%x Recieved: l=0x%x, h=0x%x\n", pssStatus.Min, pssStatus.Max, longRunRange.LowPart, longRunRange.HighPart));
status = STATUS_UNSUCCESSFUL; }
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); }
NTSTATUS GetLegacyMaxProcFrequency( OUT PULONG CpuSpeed ) /*++
Description:
Arguments: Return Value:
NTSTATUS
--*/ { PAGED_CODE(); return GetMaxCpuSpeed(CpuSpeed); }
NTSTATUS AdjustLegacyProcessorPerformanceStates( IN OUT PPROCESSOR_PERFORMANCE_STATES PerfStates ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { PAGED_CODE(); return STATUS_SUCCESS; }
NTSTATUS GetProcessorBrandString ( PUCHAR BrandString, PULONG Size ) /*++
Routine Description: Arguments: Return Value:
--*/ { PAGED_CODE(); //
// This processor family supports CPUID Brand String
//
return GetCPUIDProcessorBrandString(BrandString, Size); }
|