171 lines
3.6 KiB
C
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);
|
|
}
|
|
}
|
|
}
|