mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
717 lines
14 KiB
717 lines
14 KiB
/*++
|
|
|
|
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
|