IOPlatformPlugin.cpp [plain text]
#include "IOPlatformPlugin.h"
#define super IOService
OSDefineMetaClassAndStructors(IOPlatformPlugin, IOService)
#pragma mark
#pragma mark *** IOPlatformPluginFamily Global Symbols ***
const OSSymbol * gIOPPluginForceUpdateKey;
const OSSymbol * gIOPPluginForceUpdateAllKey;
const OSSymbol * gIOPPluginForceSensorCurValKey;
const OSSymbol * gIOPPluginReleaseForcedSensorKey;
const OSSymbol * gIOPPluginForceControlTargetValKey;
const OSSymbol * gIOPPluginReleaseForcedControlKey;
const OSSymbol * gIOPPluginForceCtrlLoopMetaStateKey;
const OSSymbol * gIOPPluginReleaseForcedCtrlLoopKey;
const OSSymbol * gIOPPluginVersionKey;
const OSSymbol * gIOPPluginTypeKey;
const OSSymbol * gIOPPluginLocationKey;
const OSSymbol * gIOPPluginZoneKey;
const OSSymbol * gIOPPluginCurrentValueKey;
const OSSymbol * gIOPPluginPollingPeriodKey;
const OSSymbol * gIOPPluginRegisteredKey;
const OSSymbol * gIOPPluginSensorDataKey;
const OSSymbol * gIOPPluginControlDataKey;
const OSSymbol * gIOPPluginCtrlLoopDataKey;
const OSSymbol * gIOPPluginSensorIDKey;
const OSSymbol * gIOPPluginSensorFlagsKey;
const OSSymbol * gIOPPluginCurrentStateKey;
const OSSymbol * gIOPPluginLowThresholdKey;
const OSSymbol * gIOPPluginHighThresholdKey;
const OSSymbol * gIOPPluginTypeTempSensor;
const OSSymbol * gIOPPluginTypePowerSensor;
const OSSymbol * gIOPPluginTypeVoltageSensor;
const OSSymbol * gIOPPluginTypeCurrentSensor;
const OSSymbol * gIOPPluginTypeADCSensor;
const OSSymbol * gIOPPluginControlIDKey;
const OSSymbol * gIOPPluginControlFlagsKey;
const OSSymbol * gIOPPluginTargetValueKey;
const OSSymbol * gIOPPluginControlMinValueKey;
const OSSymbol * gIOPPluginControlMaxValueKey;
const OSSymbol * gIOPPluginTypeSlewControl;
const OSSymbol * gIOPPluginTypeFanRPMControl;
const OSSymbol * gIOPPluginTypeFanPWMControl;
const OSSymbol * gIOPPluginControlClass;
const OSSymbol * gIOPPluginSensorClass;
const OSSymbol * gIOPPluginEnvInternalOvertemp;
const OSSymbol * gIOPPluginEnvExternalOvertemp;
const OSSymbol * gIOPPluginEnvDynamicPowerStep;
const OSSymbol * gIOPPluginEnvControlFailed;
const OSSymbol * gIOPPluginCtrlLoopIDKey;
const OSSymbol * gIOPPluginCtrlLoopMetaState;
const OSSymbol * gIOPPluginThermalLocalizedDescKey;
const OSSymbol * gIOPPluginThermalValidConfigsKey;
const OSSymbol * gIOPPluginThermalMetaStatesKey;
const OSSymbol * gIOPPluginPlatformID;
const OSNumber * gIOPPluginZero;
const OSNumber * gIOPPluginOne;
IOPlatformPlugin * platformPlugin;
#pragma mark
#pragma mark *** IOService method overrides ***
bool IOPlatformPlugin::start(IOService *nub)
{
mach_timespec_t waitTimeout;
AbsoluteTime now;
const OSArray * tempArray;
IONotifier * restartNotifier;
if (!super::start (nub)) goto failOnly;
platformPlugin = this;
initSymbols();
gIOPPluginZero = OSNumber::withNumber( (unsigned long long) 0, 1);
gIOPPluginOne = OSNumber::withNumber( (unsigned long long) 1, 1);
timerCallout = thread_call_allocate( (thread_call_func_t) IOPlatformPlugin::timerEventOccured,
(thread_call_param_t) this );
if (!timerCallout)
{
IOLog("IOPlatformPlugin::start failed to allocate thread callout\n");
goto failReleaseSymbols;
}
envInfo = OSDictionary::withCapacity(3);
setProperty(kIOPPluginEnvInfoKey, envInfo);
setEnv(gIOPPluginEnvInternalOvertemp, (tempArray = OSArray::withCapacity(0)));
tempArray->release();
setEnv(gIOPPluginEnvExternalOvertemp, (tempArray = OSArray::withCapacity(0)));
tempArray->release();
setEnv(gIOPPluginEnvControlFailed, (tempArray = OSArray::withCapacity(0)));
tempArray->release();
setEnv(gIOPPluginEnvDynamicPowerStep, gIOPPluginZero);
envChanged = false;
machineConfig = probeConfig();
DLOG("IOPlatformPlugin MACHINE CONFIG %u\n", machineConfig);
initThermalProfile(nub);
clock_get_uptime(&now);
setTimeout(now);
waitTimeout.tv_sec = 30;
waitTimeout.tv_nsec = 0;
pmRootDomain = OSDynamicCast(IOPMrootDomain,
waitForService(serviceMatching("IOPMrootDomain"), &waitTimeout));
if (pmRootDomain != 0)
{
pmRootDomain->registerInterestedDriver(this);
PMinit();
nub->joinPMtree(this);
}
restartNotifier = registerPrioritySleepWakeInterest(&sysPowerDownHandler, this, 0);
registerService();
publishResource ("IOPlatformMonitor", this); publishResource ("IOPlatformPlugin", this);
return(true);
failReleaseSymbols:
gIOPPluginZero->release();
gIOPPluginZero = NULL;
gIOPPluginOne->release();
gIOPPluginOne = NULL;
failOnly:
return(false);
}
void IOPlatformPlugin::stop(IOService *nub)
{
thread_call_cancel(timerCallout);
thread_call_free(timerCallout);
}
bool IOPlatformPlugin::init( OSDictionary * dict )
{
if (!super::init(dict)) return(false);
gate = IORecursiveLockAlloc();
if (!gate) return(false);
controls = NULL;
controlInfoDicts = NULL;
sensors = NULL;
sensorInfoDicts = NULL;
ctrlLoops = NULL;
ctrlLoopInfoDicts = NULL;
envInfo = NULL;
pluginPowerState = kIOPPluginRunning;
return(true);
}
void IOPlatformPlugin::free( void )
{
if (controls) { controls->release(); controls = NULL; }
if (controlInfoDicts)
{
removeProperty(gIOPPluginControlDataKey);
controlInfoDicts->release();
controlInfoDicts = NULL;
}
if (sensors) { sensors->release(); sensors = NULL; }
if (sensorInfoDicts)
{
removeProperty(gIOPPluginSensorDataKey);
sensorInfoDicts->release();
sensorInfoDicts = NULL;
}
if (ctrlLoops) { ctrlLoops->release(); ctrlLoops = NULL; }
if (ctrlLoopInfoDicts)
{
removeProperty(gIOPPluginCtrlLoopDataKey);
ctrlLoopInfoDicts->release();
ctrlLoopInfoDicts = NULL;
}
if (envInfo) { envInfo->release(); envInfo = NULL; }
IORecursiveLockFree(gate);
super::free();
}
#pragma mark
#pragma mark *** Initialization Routines ***
void IOPlatformPlugin::initSymbols( void )
{
gIOPPluginForceUpdateKey = OSSymbol::withCString( kIOPPluginForceUpdateKey );
gIOPPluginForceUpdateAllKey = OSSymbol::withCString( kIOPPluginForceUpdateAllKey );
gIOPPluginForceSensorCurValKey = OSSymbol::withCString( kIOPPluginForceSensorCurValKey );
gIOPPluginReleaseForcedSensorKey = OSSymbol::withCString( kIOPPluginReleaseForcedSensorKey );
gIOPPluginForceControlTargetValKey = OSSymbol::withCString( kIOPPluginForceCtrlTargetValKey );
gIOPPluginReleaseForcedControlKey = OSSymbol::withCString( kIOPPluginReleaseForcedControlKey );
gIOPPluginForceCtrlLoopMetaStateKey = OSSymbol::withCString( kIOPPluginForceCtrlLoopMetaStateKey );
gIOPPluginReleaseForcedCtrlLoopKey = OSSymbol::withCString( kIOPPluginReleaseForcedCtrlLoopKey );
gIOPPluginVersionKey = OSSymbol::withCString( kIOPPluginVersionKey );
gIOPPluginTypeKey = OSSymbol::withCString( kIOPPluginTypeKey );
gIOPPluginLocationKey = OSSymbol::withCString( kIOPPluginLocationKey );
gIOPPluginZoneKey = OSSymbol::withCString( kIOPPluginZoneKey );
gIOPPluginCurrentValueKey = OSSymbol::withCString( kIOPPluginCurrentValueKey );
gIOPPluginPollingPeriodKey = OSSymbol::withCString( kIOPPluginPollingPeriodKey );
gIOPPluginRegisteredKey = OSSymbol::withCString( kIOPPluginRegisteredKey );
gIOPPluginSensorDataKey = OSSymbol::withCString( kIOPPluginSensorDataKey );
gIOPPluginControlDataKey = OSSymbol::withCString( kIOPPluginControlDataKey );
gIOPPluginCtrlLoopDataKey = OSSymbol::withCString( kIOPPluginCtrlLoopDataKey );
gIOPPluginSensorIDKey = OSSymbol::withCString( kIOPPluginSensorIDKey );
gIOPPluginSensorFlagsKey = OSSymbol::withCString( kIOPPluginSensorFlagsKey );
gIOPPluginCurrentStateKey = OSSymbol::withCString( kIOPPluginCurrentStateKey );
gIOPPluginLowThresholdKey = OSSymbol::withCString( kIOPPluginLowThresholdKey );
gIOPPluginHighThresholdKey = OSSymbol::withCString( kIOPPluginHighThresholdKey );
gIOPPluginTypeTempSensor = OSSymbol::withCString( kIOPPluginTypeTempSensor );
gIOPPluginTypePowerSensor = OSSymbol::withCString( kIOPPluginTypePowerSensor );
gIOPPluginTypeVoltageSensor = OSSymbol::withCString( kIOPPluginTypeVoltageSensor );
gIOPPluginTypeCurrentSensor = OSSymbol::withCString( kIOPPluginTypeCurrentSensor );
gIOPPluginTypeADCSensor = OSSymbol::withCString( kIOPPluginTypeADCSensor );
gIOPPluginControlIDKey = OSSymbol::withCString( kIOPPluginControlIDKey );
gIOPPluginControlFlagsKey = OSSymbol::withCString( kIOPPluginControlFlagsKey );
gIOPPluginTargetValueKey = OSSymbol::withCString( kIOPPluginTargetValueKey );
gIOPPluginControlMinValueKey = OSSymbol::withCString( kIOPPluginControlMinValueKey );
gIOPPluginControlMaxValueKey = OSSymbol::withCString( kIOPPluginControlMaxValueKey );
gIOPPluginTypeSlewControl = OSSymbol::withCString( kIOPPluginTypeSlewControl );
gIOPPluginTypeFanRPMControl = OSSymbol::withCString( kIOPPluginTypeFanRPMControl );
gIOPPluginTypeFanPWMControl = OSSymbol::withCString( kIOPPluginTypeFanPWMControl );
gIOPPluginControlClass = OSSymbol::withCString( kIOPPluginControlClass );
gIOPPluginSensorClass = OSSymbol::withCString( kIOPPluginSensorClass );
gIOPPluginEnvInternalOvertemp = OSSymbol::withCString( kIOPPluginEnvInternalOvertemp );
gIOPPluginEnvExternalOvertemp = OSSymbol::withCString( kIOPPluginEnvExternalOvertemp );
gIOPPluginEnvDynamicPowerStep = OSSymbol::withCString( kIOPPluginEnvDynamicPowerStep );
gIOPPluginEnvControlFailed = OSSymbol::withCString( kIOPPluginEnvControlFailed );
gIOPPluginCtrlLoopIDKey = OSSymbol::withCString( kIOPPluginCtrlLoopIDKey );
gIOPPluginCtrlLoopMetaState = OSSymbol::withCString( kIOPPluginCtrlLoopMetaState );
gIOPPluginThermalLocalizedDescKey = OSSymbol::withCString( kIOPPluginThermalLocalizedDescKey );
gIOPPluginThermalValidConfigsKey = OSSymbol::withCString( kIOPPluginThermalValidConfigsKey );
gIOPPluginThermalMetaStatesKey = OSSymbol::withCString( kIOPPluginThermalMetaStatesKey );
gIOPPluginPlatformID = OSSymbol::withCString( kIOPPluginPlatformIDValue );
}
bool IOPlatformPlugin::initThermalProfile(IOService *nub)
{
const OSDictionary *thermalProfile;
#ifdef PLUGIN_DEBUG
const OSDictionary *dict;
const OSString *string;
const OSArray *array;
#endif
thermalProfile = OSDynamicCast(OSDictionary, getProperty(kIOPPluginThermalProfileKey));
if (thermalProfile == NULL)
{
DLOG("IOPlatformPlugin::initThermalProfile failed to find thermal profile!!\n");
return(false);
}
#ifdef PLUGIN_DEBUG
else
{
if ((string = OSDynamicCast(OSString, thermalProfile->getObject(kIOPPluginThermalCreationDateKey))) != NULL)
{
#endif
DLOG("IOPlatformPlugin::initThermalProfile found profile created %s\n", string->getCStringNoCopy());
#ifdef PLUGIN_DEBUG
}
}
if ((array = OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalConfigsKey))) != NULL &&
(dict = OSDynamicCast(OSDictionary, array->getObject(machineConfig))) != NULL &&
(string = OSDynamicCast(OSString, dict->getObject(kIOPPluginThermalGenericDescKey))) != NULL)
{
#endif
DLOG("IOPlatformPlugin::initThermalProfile using config %s\n", string->getCStringNoCopy());
#ifdef PLUGIN_DEBUG
}
else
{
#endif
DLOG("IOPlatformPlugin::initThermalProfile profile does not contain Config %u information!\n", machineConfig);
#ifdef PLUGIN_DEBUG
}
#endif
if (!initControls( OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalControlsKey)) ))
{
DLOG("IOPlatformPlugin::initThermalProfile failure while parsing control array\n");
return(false);
}
if (!initSensors( OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalSensorsKey)) ))
{
DLOG("IOPlatformPlugin::initThermalProfile failure while parsing sensor array\n");
return(false);
}
if (!initCtrlLoops( OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalCtrlLoopsKey)) ))
{
DLOG("IOPlatformPlugin::initThermalProfile failure while parsing ctrlloop array\n");
return(false);
}
return(true);
}
bool IOPlatformPlugin::initControls( const OSArray * controlDicts )
{
const OSString * string;
const OSDictionary * dict;
const OSArray * array;
IOPlatformControl * control;
IOReturn result;
int i, count;
controls = OSArray::withCapacity(0);
controlInfoDicts = OSArray::withCapacity(0);
setProperty(gIOPPluginControlDataKey, controlInfoDicts);
if (controlDicts == NULL)
{
DLOG("IOPlatformPlugin::initControls no control array\n");
return(true);
}
count = controlDicts->getCount();
for (i = 0; i < count; i++)
{
if ((dict = OSDynamicCast(OSDictionary, controlDicts->getObject(i))) == NULL)
{
DLOG("IOPlatformPlugin::initControls error grabbing controlDicts element %d, skipping\n", i);
continue;
}
if ((array = OSDynamicCast(OSArray, dict->getObject(gIOPPluginThermalValidConfigsKey))) != NULL &&
!validOnConfig(array))
{
continue;
}
if ((string = OSDynamicCast(OSString, dict->getObject(kIOClassKey))) == NULL)
{
string = gIOPPluginControlClass;
}
else
{
}
if ((control = OSDynamicCast(IOPlatformControl,
OSMetaClass::allocClassWithName(string))) == NULL)
{
DLOG("IOPlatformPlugin::initControls failed to allocate %s\n", string->getCStringNoCopy());
continue;
}
if ((result = control->initPlatformControl(dict)) != kIOReturnSuccess)
{
DLOG("IOPlatformPlugin::initControls failed to init control object\n");
control->release();
continue;
}
control->getInfoDict()->setObject(kIOClassKey, string);
controls->setObject(control);
}
return(true);
}
bool IOPlatformPlugin::initSensors( const OSArray * sensorDicts )
{
const OSString * string;
const OSDictionary * dict;
const OSArray * array;
IOPlatformSensor * sensor;
IOReturn result;
int i, count;
sensors = OSArray::withCapacity(0);
sensorInfoDicts = OSArray::withCapacity(0);
setProperty(gIOPPluginSensorDataKey, sensorInfoDicts);
if (sensorDicts == NULL)
{
DLOG("IOPlatformPlugin::initSensors no sensor array\n");
return(true);
}
count = sensorDicts->getCount();
for (i = 0; i < count; i++)
{
if ((dict = OSDynamicCast(OSDictionary, sensorDicts->getObject(i))) == NULL)
{
DLOG("IOPlatformPlugin::initSensors error grabbing sensorDicts element %d, skipping\n", i);
continue;
}
if ((array = OSDynamicCast(OSArray, dict->getObject(gIOPPluginThermalValidConfigsKey))) != NULL &&
!validOnConfig(array))
{
continue;
}
if ((string = OSDynamicCast(OSString, dict->getObject(kIOClassKey))) == NULL)
{
string = gIOPPluginSensorClass;
}
else
{
}
if ((sensor = OSDynamicCast(IOPlatformSensor,
OSMetaClass::allocClassWithName(string))) == NULL)
{
DLOG("IOPlatformPlugin::initSensors failed to allocate %s\n", string->getCStringNoCopy());
continue;
}
if ((result = sensor->initPlatformSensor(dict)) != kIOReturnSuccess)
{
DLOG("IOPlatformPlugin::initSensors failed to init sensor object\n");
sensor->release();
continue;
}
sensor->getInfoDict()->setObject(kIOClassKey, string);
sensors->setObject( sensor );
}
return(true);
}
bool IOPlatformPlugin::initCtrlLoops( const OSArray * ctrlLoopDicts )
{
const OSString * string;
const OSDictionary * dict;
const OSArray * array;
IOPlatformCtrlLoop * ctrlLoop;
IOReturn result;
int i, count;
ctrlLoops = OSArray::withCapacity(0);
ctrlLoopInfoDicts = OSArray::withCapacity(0);
setProperty( gIOPPluginCtrlLoopDataKey, ctrlLoopInfoDicts );
if (ctrlLoopDicts == NULL)
{
DLOG("IOPlatformPlugin::initCtrlLoops no ctrlloop array\n");
return(true);
}
count = ctrlLoopDicts->getCount();
for (i = 0; i < count; i++)
{
if ((dict = OSDynamicCast(OSDictionary, ctrlLoopDicts->getObject(i))) == NULL)
{
DLOG("IOPlatformPlugin::initCtrlLoops error parsing ctrlLoopDicts element %d, skipping\n", i);
continue;
}
if ((array = OSDynamicCast(OSArray, dict->getObject(gIOPPluginThermalValidConfigsKey))) != NULL &&
!validOnConfig(array))
{
continue;
}
if ((string = OSDynamicCast(OSString, dict->getObject(kIOClassKey))) == NULL)
{
DLOG("IOPlatformPlugin::initCtrlLoops no IOPlatformCtrlLoop subclass specified, skipping...\n");
continue;
}
if ((ctrlLoop = OSDynamicCast(IOPlatformCtrlLoop,
OSMetaClass::allocClassWithName(string))) == NULL)
{
DLOG("IOPlatformPlugin::initCtrlLoops failed to allocate %s\n", string->getCStringNoCopy());
continue;
}
if ((result = ctrlLoop->initPlatformCtrlLoop(dict)) != kIOReturnSuccess)
{
DLOG("IOPlatformPlugin::initCtrlLoops failed to init CtrlLoop object\n");
ctrlLoop->release();
continue;
}
ctrlLoop->getInfoDict()->setObject(kIOClassKey, string);
ctrlLoops->setObject(ctrlLoop);
ctrlLoopInfoDicts->setObject( ctrlLoop->getInfoDict() );
}
return(true);
}
#pragma mark
#pragma mark *** Machine Config Routines ***
UInt8 IOPlatformPlugin::probeConfig(void)
{
return 0; }
UInt8 IOPlatformPlugin::getConfig( void )
{
return machineConfig;
}
bool IOPlatformPlugin::validOnConfig( const OSArray * validConfigs )
{
const OSNumber * number;
int j, nconfigs;
bool valid = false;
if (validConfigs == NULL) return(false);
nconfigs = validConfigs->getCount();
for (j = 0; j < nconfigs; j++)
{
if ((number = OSDynamicCast(OSNumber, validConfigs->getObject(j))) != NULL &&
machineConfig == number->unsigned8BitValue())
{
valid = true;
break;
}
}
return( valid );
}
#pragma mark
#pragma mark *** Sensor / Control / CtrlLoop Lookup Routines ***
IOPlatformSensor *IOPlatformPlugin::lookupSensorByID( const OSNumber * sensorID ) const
{
IOPlatformSensor *tmpSensor, *result = NULL;
if (sensorID && sensors)
{
unsigned int i, count;
count = sensors->getCount();
for (i=0; i<count; i++)
{
tmpSensor = OSDynamicCast(IOPlatformSensor, sensors->getObject(i));
if (tmpSensor && sensorID->isEqualTo( tmpSensor->getSensorID() ))
{
result = tmpSensor;
break;
}
}
}
return(result);
}
IOPlatformControl *IOPlatformPlugin::lookupControlByID( const OSNumber * controlID ) const
{
IOPlatformControl *tmpControl, *result = NULL;
if (controlID && controls)
{
unsigned int i, count;
count = controls->getCount();
for (i=0; i<count; i++)
{
tmpControl = OSDynamicCast(IOPlatformControl, controls->getObject(i));
if (controlID &&controlID->isEqualTo( tmpControl->getControlID() ))
{
result = tmpControl;
break;
}
}
}
return(result);
}
IOPlatformCtrlLoop *IOPlatformPlugin::lookupCtrlLoopByID( const OSNumber * ctrlLoopID ) const
{
IOPlatformCtrlLoop *tmpCtrlLoop, *result = NULL;
if (ctrlLoopID && controls)
{
unsigned int i, count;
count = ctrlLoops->getCount();
for (i=0; i<count; i++)
{
tmpCtrlLoop = OSDynamicCast(IOPlatformCtrlLoop, ctrlLoops->getObject(i));
if (ctrlLoopID && ctrlLoopID->isEqualTo( tmpCtrlLoop->getCtrlLoopID() ))
{
result = tmpCtrlLoop;
break;
}
}
}
return(result);
}
#pragma mark
#pragma mark *** Environment Helpers ***
bool IOPlatformPlugin::setEnv( const OSString *aKey, const OSMetaClassBase *anObject )
{
if (envInfo->setObject( aKey, anObject ))
{
envChanged = true;
return(true);
}
else
{
return(false);
}
}
bool IOPlatformPlugin::setEnv( const char *aKey, const OSMetaClassBase *anObject )
{
if (envInfo->setObject( aKey, anObject ))
{
envChanged = true;
return(true);
}
else
{
return(false);
}
}
bool IOPlatformPlugin::setEnv( const OSSymbol *aKey, const OSMetaClassBase *anObject )
{
if (envInfo->setObject( aKey, anObject ))
{
envChanged = true;
return(true);
}
else
{
return(false);
}
}
bool IOPlatformPlugin::setEnvArray( const OSSymbol * aKey, const OSObject * setter, bool setting )
{
OSArray * array;
int i, count;
if ((array = OSDynamicCast(OSArray, getEnv( aKey ))) != NULL)
{
count = array->getCount();
for (i=0; i<count; i++)
{
if (array->getObject(i) == setter) break;
}
if (i<count && !setting)
{
array->removeObject(i);
if (array->getCount() == 0)
{
envChanged = true;
}
return(true);
}
if (i>=count && setting)
{
array->setObject(setter);
envChanged = true;
return(true);
}
}
return(false);
}
bool IOPlatformPlugin::envArrayCondIsTrue( const OSSymbol *cond ) const
{
OSArray * array;
if ((array = OSDynamicCast(OSArray, getEnv( cond ))) != NULL &&
array->getCount() > 0)
{
return(true);
}
else
{
return(false);
}
}
bool IOPlatformPlugin::envArrayCondIsTrueForObject( const OSObject * obj, const OSSymbol *cond ) const
{
OSArray * array;
int i, count;
if ((array = OSDynamicCast(OSArray, getEnv( cond ))) != NULL)
{
count = array->getCount();
for (i=0; i<count; i++)
{
if (array->getObject(i) == obj)
{
return(true);
}
}
}
return(false);
}
OSObject *IOPlatformPlugin::getEnv( const char *aKey ) const
{
return envInfo->getObject( aKey );
}
OSObject *IOPlatformPlugin::getEnv( const OSString *aKey ) const
{
return envInfo->getObject( aKey );
}
OSObject *IOPlatformPlugin::getEnv( const OSSymbol *aKey ) const
{
return envInfo->getObject( aKey );
}
void IOPlatformPlugin::environmentChanged( void )
{
IOPlatformCtrlLoop *loop;
int i, count;
if (ctrlLoops)
{
count = ctrlLoops->getCount();
for (i=0; i<count; i++)
{
if ((loop = OSDynamicCast(IOPlatformCtrlLoop, ctrlLoops->getObject(i))) != NULL)
{
loop->updateMetaState();
loop->adjustControls();
}
}
}
}
#pragma mark
#pragma mark *** Miscellaneous Helpers ***
void IOPlatformPlugin::sleepSystem( void )
{
DLOG("IOPlatformPlugin::sleepSystem issuing sleep demand\n");
pmRootDomain->sleepSystem();
}
void IOPlatformPlugin::setTimeout( const AbsoluteTime now )
{
AbsoluteTime loopDeadline, soonest;
IOPlatformCtrlLoop *loop;
int i, count, cmp;
if (ctrlLoops)
{
AbsoluteTime_to_scalar(&soonest) = 0;
count = ctrlLoops->getCount();
for (i=0; i<count; i++)
{
if ((loop = OSDynamicCast(IOPlatformCtrlLoop, ctrlLoops->getObject(i))) != NULL)
{
loopDeadline = loop->getDeadline();
if (AbsoluteTime_to_scalar(&loopDeadline) != 0)
{
if (CMP_ABSOLUTETIME(&loopDeadline, &now) == -1)
{
DLOG("IOPlatformPlugin::setTimeout ctrlloop %d's deadline already passed\n", i);
thread_call_enter( timerCallout );
return;
}
else
{
cmp = CMP_ABSOLUTETIME(&loopDeadline, &soonest);
if ( AbsoluteTime_to_scalar(&soonest) == 0 || cmp == -1 )
{
AbsoluteTime_to_scalar(&soonest) = AbsoluteTime_to_scalar(&loopDeadline);
}
}
}
}
}
if (AbsoluteTime_to_scalar(&soonest) != 0)
{
thread_call_enter_delayed( timerCallout, soonest );
}
}
}
#pragma mark
#pragma mark *** Event Handling Helpers ***
IOReturn IOPlatformPlugin::handleEvent(IOPPluginEventData *event)
{
IOReturn status;
AbsoluteTime now;
thread_call_cancel(timerCallout);
clock_get_uptime(&now);
switch (event->eventType)
{
case IOPPluginEventTimer:
timerHandler(now);
status = kIOReturnSuccess;
break;
case IOPPluginEventMessage:
status = messageHandler((UInt32)event->param1, OSDynamicCast(IOService, (OSMetaClassBase *) event->param2),
OSDynamicCast(OSDictionary, (OSMetaClassBase *) event->param3));
break;
case IOPPluginEventSetAggressiveness:
status = setAggressivenessHandler((unsigned long) event->param1, (unsigned long) event->param2);
break;
case IOPPluginEventSystemWillSleep:
status = sleepHandler();
break;
case IOPPluginEventSystemDidWake:
status = wakeHandler();
break;
case IOPPluginEventSystemRestarting:
status = restartHandler();
break;
case IOPPluginEventSetProperties:
status = setPropertiesHandler( OSDynamicCast(OSObject, (OSMetaClassBase *) event->param1) );
break;
case IOPPluginEventPlatformFunction:
default:
DLOG("IOPlatformPlugin::handleEvent got unknown event type\n");
status = kIOReturnUnsupported;
break;
}
if (envChanged)
{
environmentChanged();
envChanged = false;
}
if (pluginPowerState != kIOPPluginSleeping) setTimeout(now);
return(status);
}
IOReturn IOPlatformPlugin::dispatchEvent(IOPPluginEventData *event)
{
IOReturn status;
IORecursiveLockLock(gate);
status = handleEvent(event);
IORecursiveLockUnlock(gate);
return(status);
}
#pragma mark
#pragma mark *** Unsynchronized Entry Points ***
IOReturn IOPlatformPlugin::setAggressiveness(unsigned long selector, unsigned long newLevel)
{
IOReturn result;
IOPPluginEventData saEvent;
result = super::setAggressiveness(selector, newLevel);
saEvent.eventType = IOPPluginEventSetAggressiveness;
saEvent.param1 = (void *) selector;
saEvent.param2 = (void *) newLevel;
dispatchEvent(&saEvent);
return(result);
}
IOReturn IOPlatformPlugin::message( UInt32 type, IOService * provider, void * argument)
{
IOPPluginEventData msgEvent;
msgEvent.eventType = IOPPluginEventMessage;
msgEvent.param1 = (void *) type;
msgEvent.param2 = (void *) provider;
msgEvent.param3 = (void *) argument;
return dispatchEvent(&msgEvent);
}
IOReturn IOPlatformPlugin::setProperties( OSObject * properties )
{
IOPPluginEventData spEvent;
spEvent.eventType = IOPPluginEventSetProperties;
spEvent.param1 = (void *) properties;
return dispatchEvent(&spEvent);
}
void IOPlatformPlugin::timerEventOccured( void *self )
{
IOPPluginEventData tEvent;
IOPlatformPlugin * me = OSDynamicCast(IOPlatformPlugin, (OSMetaClassBase *) self);
if (me)
{
tEvent.eventType = IOPPluginEventTimer;
me->dispatchEvent(&tEvent);
}
}
IOReturn IOPlatformPlugin::powerStateWillChangeTo( IOPMPowerFlags theFlags, unsigned long, IOService*)
{
IOPPluginEventData powerStateEvent;
IOReturn status = IOPMAckImplied;
if ( ! (theFlags & IOPMPowerOn) )
{
DLOG("IOPlatformPlugin::powerStateWillChangeTo theFlags = 0x%X\n", theFlags);
powerStateEvent.eventType = IOPPluginEventSystemWillSleep;
status = dispatchEvent(&powerStateEvent);
}
return(status);
}
IOReturn IOPlatformPlugin::powerStateDidChangeTo( IOPMPowerFlags theFlags, unsigned long, IOService*)
{
IOPPluginEventData powerStateEvent;
IOReturn status = IOPMAckImplied;
if ( theFlags & IOPMPowerOn )
{
DLOG("IOPlatformPlugin::powerStateDidChangeTo theFlags = 0x%X\n", theFlags);
powerStateEvent.eventType = IOPPluginEventSystemDidWake;
status = dispatchEvent(&powerStateEvent);
}
return(status);
}
IOReturn IOPlatformPlugin::sysPowerDownHandler(void *target, void *refCon, UInt32 messageType, IOService *service, void *messageArgument, vm_size_t argSize )
{
IOPPluginEventData powerStateEvent;
IOReturn status = IOPMAckImplied;
IOPlatformPlugin * me = OSDynamicCast(IOPlatformPlugin, (OSMetaClassBase *) target);
if (me == NULL)
return(status);
switch (messageType)
{
case kIOMessageSystemWillSleep:
break;
case kIOMessageSystemWillPowerOff: case kIOMessageSystemWillRestart: powerStateEvent.eventType = IOPPluginEventSystemRestarting;
status = me->dispatchEvent(&powerStateEvent);
break;
default:
break;
}
return(status);
}
#pragma mark
#pragma mark *** Synchronized Event Handlers ***
IOReturn IOPlatformPlugin::setAggressivenessHandler(unsigned long selector, unsigned long newLevel)
{
if (selector == kPMSetProcessorSpeed)
{
const OSNumber * speed;
DLOG("IOPlatformPlugin::setAggressivenessHandler Dynamic Power Step = %lx\n", newLevel);
speed = OSNumber::withNumber( (unsigned long long) newLevel, 32 );
setEnv(gIOPPluginEnvDynamicPowerStep, speed);
speed->release();
}
return(IOPMAckImplied);
}
IOReturn IOPlatformPlugin::messageHandler(UInt32 type, IOService *sender, OSDictionary *dict)
{
IOPlatformSensor * sensorRef;
IOPlatformStateSensor * stateSensorRef;
OSSerialize *s;
switch (type)
{
case kIOPPluginMessageRegister:
return registrationHandler( sender, dict );
case kIOPPluginMessageLowThresholdHit:
case kIOPPluginMessageHighThresholdHit:
sensorRef = lookupSensorByID( OSDynamicCast(OSNumber, dict->getObject(gIOPPluginSensorIDKey)) );
if ((stateSensorRef = OSDynamicCast(IOPlatformStateSensor, sensorRef)) != NULL)
{
return stateSensorRef->thresholdHit( type == kIOPPluginMessageLowThresholdHit, dict );
}
break;
case kIOPPluginMessageGetPlatformID:
if ( dict )
{
dict->setObject( kIOPPluginPlatformIDKey, gIOPPluginPlatformID );
}
return kIOReturnSuccess;
break;
default:
if ((s = OSSerialize::withCapacity(2048)) != NULL &&
dict->serialize(s))
{
DLOG("IOPlatformPlugin::messageHandler - unknown message type %08lx\n"
" sender: %s\n"
" dict: %s\n", type, sender->getName(), s->text());
s->release();
}
else
{
DLOG("IOPlatformPlugin::messageHandler unable to serialize\n");
}
break;
}
return(kIOReturnSuccess);
}
IOReturn IOPlatformPlugin::registrationHandler( IOService *sender, OSDictionary *dict )
{
const OSNumber *id;
IOPlatformSensor *sensor;
IOPlatformControl *control;
IOReturn status = kIOReturnError;
if (!sender || !dict)
{
DLOG("IOPlatformPlugin::registrationHandler got bad args!\n");
return(kIOReturnBadArgument);
}
if ((id = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginSensorIDKey))) != NULL)
{
sensor = lookupSensorByID( id );
if (sensor) {
if (sensor->isRegistered() == kOSBooleanTrue)
{
DLOG("IOPlatformPlugin::registrationHandler sensor with id 0x%lx already registered!!\n", id->unsigned32BitValue());
return(kIOReturnPortExists);
}
DLOG("IOPlatformPlugin::registrationHandler got known entity, sensor id 0x%08lX\n",
sensor->getSensorID()->unsigned32BitValue());
status = sensor->registerDriver( sender, dict );
if (status == kIOReturnSuccess)
sensorInfoDicts->setObject( sensor->getInfoDict() );
return(status);
}
else {
#ifdef PLUGIN_DEBUG
const OSNumber * tempID;
tempID = OSDynamicCast(OSNumber, sender->getProperty(kIOPPluginSensorIDKey));
#endif
DLOG("IOPlatformPlugin::registrationHandler got unknown entity, sensor id 0x%08lX\n",
tempID != NULL ? tempID->unsigned32BitValue() : 0xDEADBEEF);
if ((sensor = OSDynamicCast(IOPlatformSensor,
OSMetaClass::allocClassWithName(gIOPPluginSensorClass))) == NULL)
{
DLOG("IOPlatformPlugin::registrationHandler failed to allocate IOPlatformSensor\n");
return(kIOReturnNoResources);
}
if ((status = sensor->initPlatformSensor( sender, dict )) != kIOReturnSuccess)
{
DLOG("IOPlatformPlugin::registrationHandler failed to init sensor from unlisted registrant\n");
sensor->release();
return(status);
}
sensors->setObject( sensor );
status = sensor->registerDriver( sender, dict );
if (status == kIOReturnSuccess)
sensorInfoDicts->setObject( sensor->getInfoDict() );
return(status);
}
}
else if ((id = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginControlIDKey))) != NULL)
{
control = lookupControlByID( id );
if (control) {
if (control->isRegistered() == kOSBooleanTrue)
{
DLOG("IOPlatformPlugin::registrationHandler control with id 0x%lx already registered!!\n", id->unsigned32BitValue());
return(kIOReturnPortExists);
}
DLOG("IOPlatformPlugin::registrationHandler got known entity, control id 0x%08lX\n",
control->getControlID()->unsigned32BitValue());
status = control->registerDriver( sender, dict );
#ifdef PLUGIN_DEBUG
const OSString *name1, *name2;
name1 = control->getControlType();
name2 = OSDynamicCast(OSString, dict->getObject( kIOPPluginControlTypeKey ));
if (name1 && name2 && !name1->isEqualTo(name2))
{
#endif
DLOG("IOPlatformPlugin::registrationHandler thermal profile overrode control type\n");
#ifdef PLUGIN_DEBUG
}
#endif
if (status == kIOReturnSuccess)
controlInfoDicts->setObject( control->getInfoDict() );
return status;
}
else {
#ifdef PLUGIN_DEBUG
const OSNumber * tempID;
tempID = OSDynamicCast(OSNumber, sender->getProperty(kIOPPluginControlIDKey));
#endif
DLOG("IOPlatformPlugin::registrationHandler got unknown entity, control id 0x%08lX\n",
tempID != NULL ? tempID->unsigned32BitValue() : 0xDEADBEEF);
if ((control = OSDynamicCast(IOPlatformControl,
OSMetaClass::allocClassWithName(gIOPPluginControlClass))) == NULL)
{
DLOG("IOPlatformPlugin::registrationHandler failed to allocate IOPlatformControl\n");
return(kIOReturnNoResources);
}
if ((status = control->initPlatformControl( sender, dict )) != kIOReturnSuccess)
{
DLOG("IOPlatformPlugin::registrationHandler failed to init control from unlisted registrant\n");
control->release();
return(status);
}
controls->setObject( control );
status = control->registerDriver( sender, dict );
if (status == kIOReturnSuccess)
controlInfoDicts->setObject( control->getInfoDict() );
return(status);
}
}
else
{
IOLog("IOPlatformPlugin got registration from unknown entity %s\n", sender->getName());
return(kIOReturnUnsupported);
}
}
IOReturn IOPlatformPlugin::setPropertiesHandler( OSObject * properties )
{
IOReturn status = kIOReturnUnsupported;
#if IMPLEMENT_SETPROPERTIES
OSDictionary * commandDict, * forceDict;
const OSNumber * id, * num;
ControlValue controlValue;
IOPlatformSensor * sensor;
IOPlatformControl * control;
IOPlatformCtrlLoop * ctrlLoop;
if ((commandDict = OSDynamicCast(OSDictionary, properties)) == NULL)
return kIOReturnBadArgument;
if (commandDict->getObject(gIOPPluginForceUpdateKey) != NULL)
{
if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginSensorIDKey))) != NULL)
{
if ((sensor = lookupSensorByID(id)) != NULL)
{
sensor->setCurrentValue( sensor->forceAndFetchCurrentValue() );
status = kIOReturnSuccess;
}
}
else if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginControlIDKey))) != NULL)
{
if ((control = lookupControlByID( id )) != NULL)
{
control->setCurrentValue( control->forceAndFetchCurrentValue() );
status = kIOReturnSuccess;
}
}
}
else if ((commandDict->getObject(gIOPPluginForceUpdateAllKey)) != NULL)
{
int i, count;
if (sensors)
{
count = sensors->getCount();
for (i=0; i<count; i++)
{
if ((sensor = OSDynamicCast(IOPlatformSensor, sensors->getObject(i))) != NULL)
{
sensor->setCurrentValue( sensor->forceAndFetchCurrentValue() );
}
}
}
if (controls)
{
count = controls->getCount();
for (i=0; i<count; i++)
{
if ((control = OSDynamicCast(IOPlatformControl, controls->getObject(i))) != NULL)
{
control->setCurrentValue( control->forceAndFetchCurrentValue() );
}
}
}
status = kIOReturnSuccess;
}
else if ((num = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginForceControlTargetValKey))) != NULL)
{
if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginControlIDKey))) != NULL &&
(control = lookupControlByID(id)) != NULL)
{
controlValue = num->unsigned32BitValue();
if (control->sendTargetValue( controlValue, true ))
{
control->getInfoDict()->setObject(gIOPPluginForceControlTargetValKey, num);
status = kIOReturnSuccess;
}
}
}
else if ((num = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginReleaseForcedControlKey))) != NULL)
{
if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginControlIDKey))) != NULL &&
(control = lookupControlByID(id)) != NULL &&
(control->getInfoDict()->getObject(gIOPPluginForceControlTargetValKey)) != NULL)
{
if (control->sendTargetValue( control->getTargetValue(), true ))
{
control->getInfoDict()->removeObject(gIOPPluginForceControlTargetValKey);
status = kIOReturnSuccess;
}
}
}
else if ((forceDict = OSDynamicCast(OSDictionary, commandDict->getObject(gIOPPluginForceCtrlLoopMetaStateKey))) != NULL)
{
if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginCtrlLoopIDKey))) != NULL &&
(ctrlLoop = lookupCtrlLoopByID(id)) != NULL)
{
ctrlLoop->getInfoDict()->setObject(gIOPPluginForceCtrlLoopMetaStateKey, forceDict);
ctrlLoop->updateMetaState();
status = kIOReturnSuccess;
}
}
else if (OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginReleaseForcedCtrlLoopKey)) != NULL)
{
if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginCtrlLoopIDKey))) != NULL &&
(ctrlLoop = lookupCtrlLoopByID(id)) != NULL &&
(ctrlLoop->getInfoDict()->getObject(gIOPPluginForceCtrlLoopMetaStateKey)) != NULL)
{
ctrlLoop->getInfoDict()->removeObject(gIOPPluginForceCtrlLoopMetaStateKey);
ctrlLoop->updateMetaState();
status = kIOReturnSuccess;
}
}
#endif // IMPLEMENT_SETPROPERTIES
return(status);
}
void IOPlatformPlugin::timerHandler( const AbsoluteTime now )
{
AbsoluteTime loopDeadline;
IOPlatformCtrlLoop *loop;
int i, count;
if (ctrlLoops)
{
count = ctrlLoops->getCount();
for (i=0; i<count; i++)
{
if ((loop = OSDynamicCast(IOPlatformCtrlLoop, ctrlLoops->getObject(i))) != NULL)
{
loopDeadline = loop->getDeadline();
if (AbsoluteTime_to_scalar(&loopDeadline) != 0 &&
CMP_ABSOLUTETIME(&loopDeadline, &now) <= 0)
{
loop->deadlinePassed();
}
}
}
}
}
IOReturn IOPlatformPlugin::sleepHandler(void)
{
DLOG("IOPlatformPlugin::sleepHandler - entered\n");
pluginPowerState = kIOPPluginSleeping;
return(IOPMAckImplied);
}
IOReturn IOPlatformPlugin::wakeHandler(void)
{
IOPlatformCtrlLoop *loop;
int i, count;
DLOG("IOPlatformPlugin::wakeHandler - entered\n");
if (ctrlLoops)
{
count = ctrlLoops->getCount();
for (i=0; i<count; i++)
{
if ((loop = OSDynamicCast(IOPlatformCtrlLoop, ctrlLoops->getObject(i))) != NULL)
{
loop->didWake();
}
}
}
envChanged = true;
pluginPowerState = kIOPPluginRunning;
return(IOPMAckImplied);
}
IOReturn IOPlatformPlugin::restartHandler(void)
{
DLOG("IOPlatformPlugin::restartHandler - entered\n");
pluginPowerState = kIOPPluginSleeping;
return(IOPMAckImplied);
}