/*++ 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); } } }