PowerMac7_2_SlotFanCtrlLoop.cpp [plain text]
#include "IOPlatformPluginDefs.h"
#include "IOPlatformPluginSymbols.h"
#include "IOPlatformPlugin.h"
#include "PowerMac7_2_SlotFanCtrlLoop.h"
#define super IOPlatformPIDCtrlLoop
OSDefineMetaClassAndStructors(PowerMac7_2_SlotFanCtrlLoop, IOPlatformPIDCtrlLoop)
extern const OSSymbol * gPM72EnvSystemUncalibrated;
bool PowerMac7_2_SlotFanCtrlLoop::init( void )
{
if (!super::init()) return(false);
activeAGPControl = false;
agpSensor = NULL;
agpControl = NULL;
return(true);
}
bool PowerMac7_2_SlotFanCtrlLoop::updateMetaState( void )
{
const OSArray * metaStateArray;
const OSDictionary * metaStateDict;
const OSNumber * newMetaState;
if ((metaStateArray = OSDynamicCast(OSArray, infoDict->getObject(gIOPPluginThermalMetaStatesKey))) == NULL)
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState no meta state array\n");
return(false);
}
if ((platformPlugin->envArrayCondIsTrue(gIOPPluginEnvExternalOvertemp)) ||
(platformPlugin->getEnv(gPM72EnvSystemUncalibrated)) != NULL)
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState Entering Overtemp Mode\n");
int failsafeIndex = activeAGPControl ? 3 : 1;
const OSNumber* failsafeIndexNum = activeAGPControl ? gIOPPluginThree : gIOPPluginOne;
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState Entering Overtemp Mode (%d)\n", failsafeIndex );
if ((metaStateDict = OSDynamicCast(OSDictionary, metaStateArray->getObject( failsafeIndex ))) != NULL &&
(cacheMetaState( metaStateDict ) == true))
{
setMetaState( failsafeIndexNum );
return(true);
}
else
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState Overtemp Mode Failed!\n");
}
}
if ((metaStateDict = OSDynamicCast(OSDictionary, infoDict->getObject(gIOPPluginForceCtrlLoopMetaStateKey))) != NULL)
{
if (cacheMetaState( metaStateDict ) == true)
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState using forced meta state\n");
newMetaState = OSNumber::withNumber( 0xFFFFFFFF, 32 );
setMetaState( newMetaState );
newMetaState->release();
return(true);
}
else
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState forced meta state is invalid, removing...\n");
infoDict->removeObject(gIOPPluginForceCtrlLoopMetaStateKey);
}
}
int normalIndex = activeAGPControl ? 2 : 0;
const OSNumber* normalIndexNum = activeAGPControl ? gIOPPluginTwo : gIOPPluginZero;
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState Trying for Normal Meta State (%d)\n", normalIndex );
if ((metaStateDict = OSDynamicCast(OSDictionary, metaStateArray->getObject( normalIndex ))) != NULL &&
(cacheMetaState( metaStateDict ) == true))
{
setMetaState( normalIndexNum );
return(true);
}
else
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::updateMetaState no valid meta states!\n");
return(false);
}
}
SensorValue PowerMac7_2_SlotFanCtrlLoop::getAggregateSensorValue( void )
{
SensorValue powerValue, agpValue;
powerValue = inputSensor->forceAndFetchCurrentValue();
inputSensor->setCurrentValue( powerValue );
if ( agpSensor )
{
agpValue = agpSensor->forceAndFetchCurrentValue();
agpSensor->setCurrentValue( agpValue );
}
return( activeAGPControl ? agpValue : powerValue );
}
ControlValue PowerMac7_2_SlotFanCtrlLoop::calculateNewTarget( void ) const
{
SInt32 dRaw, rRaw;
SInt64 accum, dProd, rProd, pProd;
SInt32 result;
UInt32 newTarget;
samplePoint * latest;
if (overrideActive)
{
CTRLLOOP_DLOG("*** PID *** Override Active\n");
newTarget = outputOverride->unsigned32BitValue();
}
else
{
if (ctrlloopState == kIOPCtrlLoopFirstAdjustment)
{
result = 0;
}
else
{
dRaw = calculateDerivativeTerm().sensValue;
accum = dProd = (SInt64)G_d * (SInt64)dRaw;
rRaw = calculateIntegralTerm().sensValue;
rProd = (SInt64)G_r * (SInt64)rRaw;
accum += rProd;
latest = sampleAtIndex(0);
pProd = (SInt64)G_p * (SInt64)latest->error.sensValue;
accum += pProd;
accum >>= 36;
if ( activeAGPControl )
{
result = (SInt32)accum + (SInt32)agpControl->getTargetValue();
}
else
{
result = (SInt32)accum;
}
}
newTarget = (UInt32)(result > 0) ? result : 0;
if (newTarget < outputMin)
newTarget = outputMin;
else if (newTarget > outputMax)
newTarget = outputMax;
#if 0
#ifdef CTRLLOOP_DEBUG
if (timerCallbackActive)
{
const OSString * tempDesc;
#endif
CTRLLOOP_DLOG("%s"
" G_p=%08lX"
" G_d=%08lX"
" G_r=%08lX"
" T_cur=%08lX"
" accum=%016llX"
" result=%ld"
" T_err=%08lX"
" pProd=%016llX"
" dRaw=%08lX"
" dProd=%016llX"
" rRaw=%08lX"
" rProd=%016llX\n",
(tempDesc = OSDynamicCast( OSString, infoDict->getObject(kIOPPluginThermalGenericDescKey))) != NULL ?
tempDesc->getCStringNoCopy() : "Unknown CtrlLoop",
G_p,
G_d,
G_r,
latest->sample.sensValue,
accum,
result,
(latest->error.sensValue),
(pProd),
(dRaw),
(dProd),
(rRaw),
(rProd) );
#ifdef CTRLLOOP_DEBUG
}
#endif
#endif
}
return(newTarget);
}
void PowerMac7_2_SlotFanCtrlLoop::sendNewTarget( ControlValue newTarget )
{
if ( activeAGPControl )
{
if (ctrlloopState == kIOPCtrlLoopFirstAdjustment ||
ctrlloopState == kIOPCtrlLoopDidWake ||
newTarget != agpControl->getTargetValue() )
{
if (agpControl->sendTargetValue( newTarget ))
{
agpControl->setTargetValue(newTarget);
ctrlloopState = kIOPCtrlLoopAllRegistered;
}
else
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::sendNewTarget failed to send AGP target value\n");
}
}
if ( outputControl && outputControl->isRegistered() == kOSBooleanTrue )
{
ControlValue pciFanTarget;
pciFanTarget = ( ( pciFanMax - pciFanMin) * ( newTarget - outputMin ) ) / ( outputMax - outputMin ) + pciFanMin;
CTRLLOOP_DLOG( "NV40 FAN TARGET: %lu PCI FAN TARGET: %lu\n", newTarget, pciFanTarget );
if (ctrlloopState == kIOPCtrlLoopFirstAdjustment ||
ctrlloopState == kIOPCtrlLoopDidWake ||
pciFanTarget != outputControl->getTargetValue() )
{
if (outputControl->sendTargetValue( pciFanTarget ))
{
outputControl->setTargetValue( pciFanTarget );
ctrlloopState = kIOPCtrlLoopAllRegistered;
}
else
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::sendNewTarget failed to send PCI target value\n");
}
}
}
}
else
{
if (ctrlloopState == kIOPCtrlLoopFirstAdjustment ||
ctrlloopState == kIOPCtrlLoopDidWake ||
newTarget != outputControl->getTargetValue() )
{
if (outputControl->sendTargetValue( newTarget ))
{
outputControl->setTargetValue(newTarget);
ctrlloopState = kIOPCtrlLoopAllRegistered;
}
else
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::sendNewTarget failed to send target value\n");
}
}
}
}
void PowerMac7_2_SlotFanCtrlLoop::sensorRegistered( IOPlatformSensor * aSensor )
{
const OSData * zone;
if ( aSensor != inputSensor &&
( ( zone = aSensor->getSensorZone() ) != NULL ) &&
( *(UInt32 *)zone->getBytesNoCopy() == kIOPPluginAGPThermalZone ) )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::sensorRegistered got AGP sensor 0x%08lX\n",
aSensor->getSensorID()->unsigned32BitValue() );
aSensor->setPollingPeriod( (UInt32) kIOPPluginNoPolling );
aSensor->setPollingPeriodNS( (UInt32) kIOPPluginNoPolling );
aSensor->sendPollingPeriod();
IOService* agpSensorDriver;
IOService* agpSensorNub;
OSData* target;
if ( ( ( agpSensorDriver = aSensor->getSensorDriver() ) != NULL ) &&
( ( agpSensorNub = agpSensorDriver->getProvider() ) != NULL ) &&
( ( target = OSDynamicCast( OSData, agpSensorNub->getProperty( "input-target" ) ) ) != NULL ) )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::sensorRegistered AGP Sensor 0x%08lX has input-target 0x%08lX\n",
aSensor->getSensorID()->unsigned32BitValue(), *(UInt32 *)target->getBytesNoCopy() );
OSNumber* numTarget;
OSArray* metaStateArray;
OSDictionary* metaStateDict;
metaStateArray = OSDynamicCast( OSArray, infoDict->getObject( gIOPPluginThermalMetaStatesKey ) );
if ( ( metaStateDict = OSDynamicCast( OSDictionary, metaStateArray->getObject( 2 ) ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::sensorRegistered Failed to fetch meta state 2\n" );
goto AGP_Sensor_Init_Failed;
}
numTarget = OSNumber::withNumber( *(UInt32 *)target->getBytesNoCopy(), 32 );
metaStateDict->setObject( kIOPPIDCtrlLoopInputTargetKey, numTarget );
numTarget->release();
agpSensor = aSensor;
}
}
AGP_Sensor_Init_Failed:
if ( !activeAGPControl && agpSensor && agpControl )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::sensorRegistered AGP Card Control active\n" );
activeAGPControl = true;
updateMetaState();
}
if ( activeAGPControl ||
( inputSensor && ( inputSensor->isRegistered() == kOSBooleanTrue ) &&
outputControl && ( outputControl->isRegistered() == kOSBooleanTrue ) ) )
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::sensorRegistered starting control algorithm, AGP Control = %s\n",
activeAGPControl ? "TRUE" : "FALSE" );
ctrlloopState = kIOPCtrlLoopFirstAdjustment;
deadlinePassed();
}
}
void PowerMac7_2_SlotFanCtrlLoop::controlRegistered( IOPlatformControl * aControl )
{
const OSData * zone;
if ( aControl != outputControl &&
( ( zone = aControl->getControlZone() ) != NULL ) &&
( *(UInt32 *)zone->getBytesNoCopy() == kIOPPluginAGPThermalZone ) )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered got AGP control 0x%08lX\n",
aControl->getControlID()->unsigned32BitValue() );
OSNumber* tmpNumber;
OSArray* metaStateArray;
OSDictionary* metaStateDict;
metaStateArray = OSDynamicCast( OSArray, infoDict->getObject( gIOPPluginThermalMetaStatesKey ) );
if ( ( metaStateDict = OSDynamicCast( OSDictionary, metaStateArray->getObject( 2 ) ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered Failed to fetch meta state 2\n" );
goto AGP_Control_Init_Failed;
}
if ( ( tmpNumber = OSDynamicCast( OSNumber, metaStateDict->getObject( "pci-fan-min" ) ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered Failed to fetch pci-fan-min\n" );
goto AGP_Control_Init_Failed;
}
pciFanMin = tmpNumber->unsigned32BitValue();
if ( ( tmpNumber = OSDynamicCast( OSNumber, metaStateDict->getObject( "pci-fan-max" ) ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered Failed to fetch pci-fan-max\n" );
goto AGP_Control_Init_Failed;
}
pciFanMax = tmpNumber->unsigned32BitValue();
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered PCI FAN Min: %lu Max: %lu\n",
pciFanMin, pciFanMax );
if ( ( tmpNumber = OSNumber::withNumber( aControl->getControlMinValue(), 16 ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered Failed to fetch control's min-value\n" );
goto AGP_Control_Init_Failed;
}
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered output-min: %lu\n", tmpNumber->unsigned32BitValue() );
metaStateDict->setObject( kIOPPIDCtrlLoopOutputMinKey, tmpNumber );
tmpNumber->release();
if ( ( tmpNumber = OSNumber::withNumber( aControl->getControlMaxValue(), 16 ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered Failed to fetch control's max-value\n" );
goto AGP_Control_Init_Failed;
}
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered output-max: %lu\n", tmpNumber->unsigned32BitValue() );
metaStateDict->setObject( kIOPPIDCtrlLoopOutputMaxKey, tmpNumber );
if ( ( metaStateDict = OSDynamicCast( OSDictionary, metaStateArray->getObject( 3 ) ) ) == NULL )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered Failed to fetch meta state 3\n" );
tmpNumber->release();
goto AGP_Control_Init_Failed;
}
metaStateDict->setObject( kIOPPIDCtrlLoopOutputOverrideKey, tmpNumber );
tmpNumber->release();
agpControl = aControl;
}
AGP_Control_Init_Failed:
if ( !activeAGPControl && agpSensor && agpControl )
{
CTRLLOOP_DLOG( "PowerMac7_2_SlotFanCtrlLoop::controlRegistered AGP Card Control active\n" );
activeAGPControl = true;
updateMetaState();
}
if ( activeAGPControl ||
( inputSensor && ( inputSensor->isRegistered() == kOSBooleanTrue ) &&
outputControl && ( outputControl->isRegistered() == kOSBooleanTrue ) ) )
{
CTRLLOOP_DLOG("PowerMac7_2_SlotFanCtrlLoop::controlRegistered starting control algorithm, AGP Control = %s\n",
activeAGPControl ? "TRUE" : "FALSE" );
ctrlloopState = kIOPCtrlLoopFirstAdjustment;
deadlinePassed();
}
}