windows-nt/Source/XPSP1/NT/base/hals/halacpi/ixthrotl.c
2020-09-26 16:20:57 +08:00

171 lines
3.6 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
ixthrotl.c
Abstract:
This module implements the code for throttling the processors
Author:
Jake Oshins (jakeo) 17-July-1997
Environment:
Kernel mode only.
Revision History:
--*/
#include "halp.h"
#include "acpitabl.h"
#include "xxacpi.h"
#include "pci.h"
VOID
FASTCALL
HalProcessorThrottle (
IN UCHAR Throttle
)
/*++
Routine Description:
This function limits the speed of the processor.
Arguments:
(ecx) = Throttle setting
Return Value:
none
--*/
{
PKPRCB PrcB;
PHALPMPRCB HalPrcB;
ULONG ThrottleSetting;
ULONG Addr;
ULONG Mask;
ULONG i;
ULONG PblkAddr;
#if DBG
// debug
WRITE_PORT_UCHAR ((PUCHAR) 0x80, Throttle);
#endif
PrcB = KeGetPcr()->Prcb;
HalPrcB = (PHALPMPRCB) PrcB->HalReserved;
PblkAddr = HalPrcB->PBlk.Addr;
ThrottleSetting = READ_PORT_ULONG ((PULONG) PblkAddr);
if (Throttle == HalpThrottleScale) {
//
// If this is a piix4 and we're no longer going to
// throttle, set the break events (a piix4 thing) to
// get any interrupt to wake a C2 to C3 stopped
// processor. (note that piix4 can only be set on a
// UP system). Then clear the bit to allow C2 and C3
// idle handlers to work again.
//
if (HalpPiix4 == 1) {
HalSetBusDataByOffset (
PCIConfiguration,
HalpPiix4BusNumber,
HalpPiix4SlotNumber,
&HalpPiix4DevActB,
0x58,
sizeof (ULONG)
);
HalPrcB->PBlk.AddrAndFlags &= ~PIIX4_THROTTLE_FIX;
}
//
// Throttling is off
//
ThrottleSetting &= ~PBLK_THT_EN;
WRITE_PORT_ULONG ((PULONG) PblkAddr, ThrottleSetting);
} else {
//
// Throttling is on.
//
if (HalpPiix4 == 1) {
//
// These piix4's have the thottle setting backwards, so
// invert the value
//
Throttle = (UCHAR) HalpThrottleScale - Throttle;
//
// Piix4 will hang on a high throttle setting, so make
// sure we don't do that
//
if (Throttle < 3) {
Throttle = 3;
}
}
//
// Shift the throttle and build a mask to be in the proper location
// for this platform
//
Throttle = Throttle << HalpFixedAcpiDescTable.duty_offset;
Mask = (HalpThrottleScale - 1) << HalpFixedAcpiDescTable.duty_offset;
//
// Set the rate
//
ThrottleSetting &= ~Mask;
ThrottleSetting |= Throttle | PBLK_THT_EN;
WRITE_PORT_ULONG ((PULONG) PblkAddr, ThrottleSetting);
//
// If this is a piix4 we need to disable all the break events
// (a piix4 thing) and then read the level2 processor stop
// register to get it to start throttling. Oh yes, also set
// the bit in the Paddr to stop doing C2 & C3 stops at the
// same time.
//
if (HalpPiix4 == 1) {
HalPrcB->PBlk.AddrAndFlags |= PIIX4_THROTTLE_FIX;
i = HalpPiix4DevActB & ~0x23;
HalSetBusDataByOffset (
PCIConfiguration,
HalpPiix4BusNumber,
HalpPiix4SlotNumber,
&i,
0x58,
sizeof(ULONG)
);
READ_PORT_UCHAR ((PUCHAR) PblkAddr + P_LVL2);
}
}
}