|
|
/*++
Copyright (c) 2000 Microsoft Corporation Module Name: legacy.c Abstract: Author: Todd Carpenter (1/30/01) - create file Environment: Kernel mode
Revision History:
--*/ #include "..\lib\processor.h"
#include "amdk7.h"
#include "legacy.h"
#include "fidvid.h"
PST_SIGNATURE SystemSignature; PPST_BLOCK_HEADER PstBlockHeader;
extern ULONG AmdK7HackFlags;
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
#pragma alloc_text (PAGE, GetLegacyMaxProcFrequency)
#endif
//
// Legacy functions that must have a stub.
//
NTSTATUS InitializeNonAcpiPerformanceStates( IN PFDO_DATA DevExt ) /*++
Routine Description:
The generic processor driver doesn't have non-ACPI performance states.
Arguments:
FdoData - pointer to the device extension
Return Value:
NT status code
--*/ { NTSTATUS status; PPST_ENTRY pstMatch;
DebugEnter();
//
// Check hack flags to see if we should use the Legacy interface.
//
if (!(AmdK7HackFlags & ENABLE_LEGACY_INTERFACE)) { status = STATUS_NOT_SUPPORTED; goto InitializeNonAcpiPerformanceStatesExit; }
//
// Find the Perf States
//
status = FindPSTBlock(&PstBlockHeader); if (!NT_SUCCESS(status)) { DebugPrint((ERROR, "ERROR!! PST Block Header NOT found\n")); goto InitializeNonAcpiPerformanceStatesExit; }
DumpPSTBlock(PstBlockHeader);
//
// Generate Signature to help find correct PST
//
status = CreateSystemSignature(&SystemSignature); DebugPrint((TRACE, "Dumping System Signature...\n")); DumpPSTSignature(&SystemSignature);
if (!NT_SUCCESS(status)) { goto InitializeNonAcpiPerformanceStatesExit; }
//
// Walk through one or more PST entries to find the best match
//
status = FindMatchingPSTEntry(PstBlockHeader, &SystemSignature, &pstMatch);
if (!NT_SUCCESS(status)) { DebugPrint((ERROR, "ERROR!! Couldn't find PST entry to match system signature\n")); goto InitializeNonAcpiPerformanceStatesExit; }
DebugPrint((TRACE, "Dumping Matching Signature...\n")); DumpPSTEntry(pstMatch);
DevExt->LegacyInterface = TRUE;
//
// Set up _PCT
//
DevExt->PctPackage.Control.AddressSpaceID = AcpiGenericSpaceFixedFunction; DevExt->PctPackage.Status.AddressSpaceID = AcpiGenericSpaceFixedFunction;
//
// Convert matching PST entry into _PSS package
//
status = ConvertPstToPss(DevExt, pstMatch, &DevExt->PssPackage);
InitializeNonAcpiPerformanceStatesExit:
if (!NT_SUCCESS(status)) { //
// undo what we have done
//
if (PstBlockHeader) { ExFreePool(PstBlockHeader); PstBlockHeader = NULL; }
if (DevExt->PssPackage) { ExFreePool(DevExt->PssPackage); DevExt->PssPackage = NULL; }
DevExt->LegacyInterface = FALSE; }
DebugExitStatus(status); return status; }
NTSTATUS AcpiLegacyPerfStateTransition( IN PFDO_DATA DevExt, IN ULONG State ) /*++
Routine Description:
The generic processor driver doesn't have non-ACPI performance states.
Arguments:
State - Target State
Return Value:
NT Status
--*/ { return Acpi2PerfStateTransition(DevExt, State + DevExt->PpcResult); }
NTSTATUS GetLegacyMaxProcFrequency( OUT PULONG CpuSpeed ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { FID_VID_STATUS fidVidStatus;
DebugAssert(CpuSpeed);
fidVidStatus.AsQWord = ReadMSR(AMDK7_FID_VID_STATUS_MSR); *CpuSpeed = FSB100FidToCpuFreq[fidVidStatus.MFid]; return STATUS_SUCCESS; }
NTSTATUS FindPSTBlock ( OUT PPPST_BLOCK_HEADER PstBlock ) /*++
Description:
This routine looks in the BIOS memory area for the PST Block Header. The signature will be located on a 16-byte bountry in the area from C0000h to FFFF0h. Arguments:
Return Value:
NTSTATUS
--*/ { NTSTATUS status = STATUS_UNSUCCESSFUL; ULONG size = 0; PVOID baseAddress; ULONG_PTR address; ULONG_PTR limit; PHYSICAL_ADDRESS PhysAddress; DebugEnter(); DebugAssert(PstBlock); PAGED_CODE();
PhysAddress.HighPart = 0; PhysAddress.LowPart = PST_SEARCH_RANGE_BEGIN;
//
// Map memory to search for PST Table
//
baseAddress = MmMapIoSpace(PhysAddress, PST_SEARCH_RANGE_LENGTH, 0);
if (!baseAddress) { status = STATUS_INSUFFICIENT_RESOURCES; goto FindPSTBlockExit; }
//
// Compute limit for the for loop. Do not start a scan within 16 bytes of
// physical address 0xFFFFF
//
address = (ULONG_PTR) baseAddress; limit = address + PST_SEARCH_RANGE_LENGTH - PST_SEARCH_INTERVAL; for (; address <= limit; address += PST_SEARCH_INTERVAL) {
if (*(PULONG)address == PST_BLOCK_SIGNATURE && (!memcmp(((PPST_BLOCK_HEADER)address)->Signature, PST_BLOCK_SIGNATURE_STRING, PST_BLOCK_SIGNATURE_STRING_LEN))) { DebugPrint((TRACE, "Found PST Header Block at %p\n", address)); //
// We found the PST Block Header, copy it.
//
size = GetPSTSize((PPST_BLOCK_HEADER)address); *PstBlock = ExAllocatePoolWithTag(PagedPool, size, PROCESSOR_POOL_TAG); if (!(*PstBlock)) { status = STATUS_INSUFFICIENT_RESOURCES; goto FindPSTBlockExit; } RtlCopyMemory(*PstBlock, (PVOID)address, size); status = STATUS_SUCCESS; break; } }
FindPSTBlockExit:
//
// Unmap mapped memory
//
if (baseAddress) { MmUnmapIoSpace(baseAddress, PST_SEARCH_RANGE_LENGTH); }
DebugExitStatus(status); return status; }
NTSTATUS FindMatchingPSTEntry( IN PPST_BLOCK_HEADER PstBlock, IN PPST_SIGNATURE Signature, OUT PPPST_ENTRY PstStates ) /*++
Routine Description: Arguments: Return Value:
--*/ { NTSTATUS status = STATUS_UNSUCCESSFUL; ULONG x, y; PPST_ENTRY pstEntry;
//DebugEnter();
DebugAssert(PstBlock); DebugAssert(Signature); DebugAssert(PstStates);
//
// Walk PST Block looking for matching PST Signature.
//
//
// Get First PST Entry
//
pstEntry = &PstBlock->PstState;
for (x=0; x < PstBlock->NumPST; x++) { if ((pstEntry->CpuId == Signature->CpuId) && (pstEntry->FSBSpeed == Signature->FSBSpeed) && (pstEntry->MaxFid == Signature->MaxFid) && (pstEntry->StartVid == Signature->StartVid)) {
//
// Found Match, we assume there should only be one match, but
// if there are more, we take the first one.
//
*PstStates = pstEntry; status = STATUS_SUCCESS; break;
} //
// Get Next PST State
//
pstEntry = (PPST_ENTRY)((PUCHAR)pstEntry + sizeof(PST_ENTRY) + (sizeof(PST_DATA) * (pstEntry->NumPStates - 1)));
}
return status; }
NTSTATUS CreateSystemSignature( PPST_SIGNATURE Signature ) /*++
Routine Description: Arguments: Return Value:
--*/ { NTSTATUS status; ULONG junk; FID_VID_STATUS fidVidStatus;
//DebugEnter();
DebugAssert(Signature); PAGED_CODE();
//
// Gather info needed to select the correct PST for this processor.
//
//
// Get special CPUID using extended CPUID fuction 1
//
CPUID(0x80000001, &Signature->CpuId, &junk, &junk, &junk);
//
// Get MAX Fid & Startup VID
//
fidVidStatus.AsQWord = ReadMSR(AMDK7_FID_VID_STATUS_MSR); Signature->MaxFid = (UCHAR) fidVidStatus.MFid; Signature->StartVid = (UCHAR) fidVidStatus.SVid;
//
// Get Front Side Bus speed
//
Signature->FSBSpeed = GetFSBSpeed(); DebugAssert(Signature->FSBSpeed);
return STATUS_SUCCESS; }
UCHAR GetFSBSpeed( VOID ) /*++
Routine Description: Arguments: Return Value:
--*/ { UCHAR speed;
PAGED_CODE();
//
// FSB Speed == CPU frequency / FSB multiplier
//
// toddcar - 4/30/01 - ISSUE:
// Need to finish support for 133mhz
//
speed = 100; return speed; }
NTSTATUS ConvertPstToPss ( IN PFDO_DATA DevExt, IN PPST_ENTRY PstEntry, OUT PACPI_PSS_PACKAGE *PssPackage ) /*++
Routine Description: Arguments: Return Value:
--*/ { NTSTATUS status = STATUS_SUCCESS; ULONG pssSize; ULONG x; ULONG currentState; PACPI_PSS_PACKAGE tmpPss;
DebugEnter(); DebugAssert(PstEntry); DebugAssert(PssPackage); PAGED_CODE();
//
// Allocate a chunk for PssPackage
//
pssSize = (sizeof(ACPI_PSS_DESCRIPTOR) * (PstEntry->NumPStates - 1)) + sizeof(ACPI_PSS_PACKAGE);
tmpPss = ExAllocatePoolWithTag(NonPagedPool, pssSize, PROCESSOR_POOL_TAG);
if (!tmpPss) { status = STATUS_INSUFFICIENT_RESOURCES; goto ConvertPstToPssExit; }
RtlZeroMemory(tmpPss, pssSize); tmpPss->NumPStates = PstEntry->NumPStates;
//
// Build a _PSS table
//
for (x = 0; x < PstEntry->NumPStates; x++) { PSS_CONTROL pssControl = {0}; PSS_STATUS pssStatus = {0}; ULONG pssState = (PstEntry->NumPStates - 1) - x;
pssControl.Fid = pssStatus.Fid = PstEntry->States[x].Fid; pssControl.Vid = pssStatus.Vid = PstEntry->States[x].Vid; pssControl.SGTC = PstEntry->FSBSpeed * 100; // need to finish support for 133mhz bus
tmpPss->State[pssState].Control = pssControl.AsDWord; tmpPss->State[pssState].Status = pssStatus.AsDWord; DebugAssert(pssControl.Fid < INVALID_FID_VALUE); tmpPss->State[pssState].CoreFrequency = FSB100FidToCpuFreq[pssControl.Fid];
DebugAssert(pssControl.Vid < INVALID_VID_VALUE); tmpPss->State[pssState].Power = MobileVidToCpuVoltage[pssControl.Vid];
}
//
// Walk through each state collecting more information
//
status = FindCurrentPssPerfState(tmpPss, ¤tState); if (!NT_SUCCESS(status)) { goto ConvertPstToPssExit; }
DevExt->CurrentPssState = currentState; DevExt->PssPackage = tmpPss;
//
// Set Latency Info
//
status = ValidatePssLatencyValues(DevExt);
//
// Restore saved state
//
if (DevExt->CurrentPssState != currentState) { Acpi2PerfStateTransition(DevExt, currentState); }
//
// Need to merge this new data with our perfstates
//
MergePerformanceStates(DevExt); ConvertPstToPssExit:
if (!NT_SUCCESS(status)) {
if (DevExt->PssPackage) { ExFreePool(DevExt->PssPackage); DevExt->PssPackage = NULL; }
}
DebugExitStatus(status); return status;
} ULONG GetPSTSize( IN PPST_BLOCK_HEADER PstBlock ) /*++
Routine Description: Arguments: Return Value:
--*/ { ULONG size; ULONG x; PPST_ENTRY pstEntry;
DebugAssert(PstBlock);
size = sizeof(PST_BLOCK_HEADER); // include block header, and one pst entry
size += sizeof(PST_ENTRY) * (PstBlock->NumPST - 1);
pstEntry = &PstBlock->PstState;
for (x=0; x < PstBlock->NumPST; x++) {
size += sizeof(PST_DATA) * (pstEntry->NumPStates-1); pstEntry = (PPST_ENTRY)((PUCHAR)pstEntry + sizeof(PST_ENTRY) + (sizeof(PST_DATA) * (pstEntry->NumPStates - 1)));
}
return size;
}
#if DBG
VOID DumpPSTBlock( PPST_BLOCK_HEADER PstBlock ) {
ULONG x, y; PPST_ENTRY pstEntry;
DebugAssert(PstBlock);
DebugPrint((TRACE, "\n")); DebugPrint((TRACE, "PstBlock:\n")); DebugPrint((TRACE, " Signature: %.10s\n", PstBlock->Signature)); DebugPrint((TRACE, " TableVersion: %u\n", PstBlock->TableVersion)); DebugPrint((TRACE, " Flags: 0x%x\n", PstBlock->Flags)); DebugPrint((TRACE, " SettlingTime: %u us\n", PstBlock->SettlingTime)); DebugPrint((TRACE, " Reserved1: 0x0\n", PstBlock->Reserved1)); DebugPrint((TRACE, " NumPST: %u\n", PstBlock->NumPST)); DebugPrint((TRACE, "\n"));
//
// Get First PST Entry
//
pstEntry = &PstBlock->PstState;
for (x=0; x < PstBlock->NumPST; x++) {
DumpPSTEntry(pstEntry); //
// Get Next PST State
//
pstEntry = (PPST_ENTRY)((PUCHAR)pstEntry + sizeof(PST_ENTRY) + (sizeof(PST_DATA) * (pstEntry->NumPStates - 1)));
} }
VOID DumpPSTEntry( PPST_ENTRY PstEntry ) { ULONG y;
DebugPrint((TRACE, "PST Entry:\n")); DebugPrint((TRACE, " CpuId: 0x%x\n", PstEntry->CpuId)); DebugPrint((TRACE, " FSBSpeed: %u mhz\n", PstEntry->FSBSpeed)); DebugPrint((TRACE, " MaxFid: 0x%x\n", PstEntry->MaxFid)); DebugPrint((TRACE, " StartVid: 0x%x\n", PstEntry->StartVid)); DebugPrint((TRACE, " NumPStates %u\n", PstEntry->NumPStates)); for (y=0; y < PstEntry->NumPStates; y++) { DebugPrint((TRACE, " State #%u (Fid: 0x%x, Vid: 0x%x)\n", y, PstEntry->States[y].Fid, PstEntry->States[y].Vid)); } DebugPrint((TRACE, "\n"));
}
VOID DumpPSTSignature( PPST_SIGNATURE PstSig ) {
DebugPrint((TRACE, "PST Signature:\n")); DebugPrint((TRACE, " CpuId: 0x%x\n", PstSig->CpuId)); DebugPrint((TRACE, " FSBSpeed: %u mhz\n", PstSig->FSBSpeed)); DebugPrint((TRACE, " MaxFid: 0x%x\n", PstSig->MaxFid)); DebugPrint((TRACE, " StartVid: 0x%x\n", PstSig->StartVid)); DebugPrint((TRACE, "\n"));
} #endif
|