/* * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * * DRI: Dave Radcliffe * */ // $Log: IOPlatformPlugin.cpp,v $ // Revision 1.13 2003/08/01 00:42:30 wgulland // Merging in branch PR-3338565 // // Revision 1.12.2.1 2003/07/31 17:53:08 eem // 3338565 - q37 intake fan speed is 97% of exhaust fan speed, but still gets // clipped at the same min/max. This prevents the intake fan speed from falling // below 300 RPM and being turned off by the FCU. Version bumped to 1.0.1b1. // // Revision 1.12 2003/07/24 21:47:16 eem // [3338565] Q37 Final Fan data // // Revision 1.11 2003/07/18 00:22:22 eem // [3329244] PCI fan conrol algorithm should use integral of power consumed // [3254911] Q37 Platform Plugin must disable debugging accessors before GM // // Revision 1.10 2003/07/17 06:57:36 eem // 3329222 and other sleep stability issues fixed. // // Revision 1.9 2003/07/16 02:02:09 eem // 3288772, 3321372, 3328661 // // Revision 1.8 2003/07/08 04:32:49 eem // 3288891, 3279902, 3291553, 3154014 // // Revision 1.7 2003/06/25 02:16:24 eem // Merged 101.0.21 to TOT, fixed PM72 lproj, included new fan settings, bumped // version to 101.0.22. // // Revision 1.6.4.1 2003/06/20 01:39:58 eem // Although commented out in this submision, there is support here to nap // the processors if the fans are at min, with the intent of keeping the // heat sinks up to temperature. // // Revision 1.6 2003/06/07 01:30:56 eem // Merge of EEM-PM72-ActiveFans-2 branch, with a few extra tweaks. This // checkin has working PID control for PowerMac7,2 platforms, as well as // a first shot at localized strings. // // Revision 1.5.2.10 2003/06/06 08:17:56 eem // Holy Motherfucking shit. PID is really working. // // Revision 1.5.2.9 2003/06/04 10:21:10 eem // Supports forced PID meta states. // // Revision 1.5.2.8 2003/06/04 00:00:51 eem // More PID stuff, working towards support for forced meta states. // // Revision 1.5.2.7 2003/06/01 14:52:51 eem // Most of the PID algorithm is implemented. // // Revision 1.5.2.6 2003/05/31 09:02:06 eem // Fix deadline check. // // Revision 1.5.2.5 2003/05/31 08:11:34 eem // Initial pass at integrating deadline-based timer callbacks for PID loops. // // Revision 1.5.2.4 2003/05/29 03:51:34 eem // Clean up environment dictionary access. // // Revision 1.5.2.3 2003/05/26 10:07:14 eem // Fixed most of the bugs after the last cleanup/reorg. // // Revision 1.5.2.2 2003/05/23 05:44:40 eem // Cleanup, ctrlloops not get notification for sensor and control registration. // // Revision 1.5.2.1 2003/05/22 01:31:04 eem // Checkin of today's work (fails compilations right now). // // Revision 1.5 2003/05/21 21:58:49 eem // Merge from EEM-PM72-ActiveFans-1 branch with initial crack at active fan // control on Q37. // // Revision 1.4.2.3 2003/05/17 11:08:22 eem // All active fan data present, table event-driven. PCI power sensors are // not working yet so PCI fan is just set to 67% PWM and forgotten about. // // Revision 1.4.2.2 2003/05/16 07:08:45 eem // Table-lookup active fan control working with this checkin. // // Revision 1.4.2.1 2003/05/14 22:07:48 eem // Implemented state-driven sensor, cleaned up "const" usage and header // inclusions. // // Revision 1.4 2003/05/13 02:13:51 eem // PowerMac7_2 Dynamic Power Step support. // // Revision 1.3.2.1 2003/05/12 11:21:10 eem // Support for slewing. // // Revision 1.3 2003/05/10 06:50:33 eem // All sensor functionality included for PowerMac7_2_PlatformPlugin. Version // is 1.0.1d12. // // Revision 1.2.2.4 2003/05/10 06:32:34 eem // Sensor changes, should be ready to merge to trunk as 1.0.1d12. // // Revision 1.2.2.3 2003/05/05 21:29:37 eem // Checkin 1.1.0d11 for PD distro and submission. Debugging turned off. // // Revision 1.2.2.2 2003/05/03 01:11:38 eem // *** empty log message *** // // Revision 1.2.2.1 2003/05/01 09:28:40 eem // Initial check-in in progress toward first Q37 checkpoint. // // Revision 1.2 2003/02/18 00:02:05 eem // 3146943: timebase enable for MP, bump version to 1.0.1d3. // // Revision 1.1.1.1 2003/02/04 00:36:43 raddog // initial import into CVS // #include "IOPlatformPlugin.h" #define super IOService OSDefineMetaClassAndStructors(IOPlatformPlugin, IOService) /* * Symbols are declared here, allocated in initSymbols(), and extern'd * in IOPlatformPluginTypes.h for easy access by all helper classes. */ 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; /* * start */ bool IOPlatformPlugin::start(IOService *nub) { mach_timespec_t waitTimeout; AbsoluteTime now; const OSArray * tempArray; //DLOG("IOPlatformPlugin::start - entered\n"); if (!super::start (nub)) goto failOnly; // store a pointer to ME!! platformPlugin = this; // set up symbols initSymbols(); // globals used for one, zero, true, false gIOPPluginZero = OSNumber::withNumber( (unsigned long long) 0, 1); gIOPPluginOne = OSNumber::withNumber( (unsigned long long) 1, 1); /* // Creates the Workloop and attaches all the event handlers to it: // --------------------------------------------------------------- workLoop = getWorkLoop(); if (workLoop == NULL) { IOLog("IOPlatformPlugin::start failed to get a workloop\n"); goto failReleaseSymbols; } // Creates the command gate for the events that need to be in the queue commandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)commandGateCaller); // and adds it to the workloop: if ((commandGate == NULL) || (workLoop->addEventSource(commandGate) != kIOReturnSuccess)) { IOLog("IOPlatformPlugin::start failed to initialize command gate\n"); goto failReleaseCmdGate; } */ // allocate the thread call used for timer callbacks 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; } // allocate the environmental info dict envInfo = OSDictionary::withCapacity(3); // expose the environment dict to the registry setProperty(kIOPPluginEnvInfoKey, envInfo); // populate the environment info dict 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); // assume fast boot // clear the envChanged flag envChanged = false; // determine what the machine configuration is and cache the result machineConfig = probeConfig(); DLOG("IOPlatformPlugin MACHINE CONFIG %u\n", machineConfig); // parse in all the info for this machine initThermalProfile(nub); // set the timer starting. Do this before we register with PM, I/O Kit, and // IOResources cause we need to guarantee that no one has already grabbed // the command gate (and caused setTimeout() to be invoked on another thread). clock_get_uptime(&now); setTimeout(now); // Before we go to sleep we wish to disable the napping mode so that the PMU // will not shutdown the system while going to sleep: waitTimeout.tv_sec = 30; waitTimeout.tv_nsec = 0; pmRootDomain = OSDynamicCast(IOPMrootDomain, waitForService(serviceMatching("IOPMrootDomain"), &waitTimeout)); if (pmRootDomain != 0) { //DLOG("IOPlatformPlugin::start to acknowledge power changes\n"); pmRootDomain->registerInterestedDriver(this); // Join the Power Management Tree to receive setAggressiveness calls. PMinit(); nub->joinPMtree(this); } // HELLO!! registerService(); // Let the world know we're open for business publishResource ("IOPlatformMonitor", this); // For backward compatibility publishResource ("IOPlatformPlugin", this); return(true); /* failReleaseCmdGate: if (commandGate) { commandGate->release(); commandGate = NULL; } */ failReleaseSymbols: // I am not releasing all the symbols created in initSymbols() because, well, // this should never fail, so I don't think it's worth the code bloat. gIOPPluginZero->release(); gIOPPluginZero = NULL; gIOPPluginOne->release(); gIOPPluginOne = NULL; failOnly: return(false); } void IOPlatformPlugin::stop(IOService *nub) { /* if (workLoop) { if (commandGate) { workLoop->removeEventSource(commandGate); commandGate->release(); commandGate = NULL; } // workLoop->release(); workLoop = NULL; } */ 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(); } 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 //DLOG("IOPlatformPlugin::initThermalProfile - entered\n"); // get the top of the thermal profile dictionary 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 } } // Determine what config we've got 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 // parse the control array if (!initControls( OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalControlsKey)) )) { DLOG("IOPlatformPlugin::initThermalProfile failure while parsing control array\n"); return(false); } // parse the sensor array if (!initSensors( OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalSensorsKey)) )) { DLOG("IOPlatformPlugin::initThermalProfile failure while parsing sensor array\n"); return(false); } // parse the ctrlloop array if (!initCtrlLoops( OSDynamicCast(OSArray, thermalProfile->getObject(kIOPPluginThermalCtrlLoopsKey)) )) { DLOG("IOPlatformPlugin::initThermalProfile failure while parsing ctrlloop array\n"); return(false); } // done //DLOG("IOPlatformPlugin::initThermalProfile - done\n"); return(true); } bool IOPlatformPlugin::initControls( const OSArray * controlDicts ) { const OSString * string; const OSDictionary * dict; const OSArray * array; IOPlatformControl * control; IOReturn result; int i, count; if (controlDicts == NULL) { DLOG("IOPlatformPlugin::initControls no control array\n"); // this is not a fatal error return(true); } // Allocate the control lists and add the control info array to the registry controls = OSArray::withCapacity(0); controlInfoDicts = OSArray::withCapacity(0); setProperty(gIOPPluginControlDataKey, controlInfoDicts); count = controlDicts->getCount(); for (i = 0; i < count; i++) { // grab the controlDicts element if ((dict = OSDynamicCast(OSDictionary, controlDicts->getObject(i))) == NULL) { DLOG("IOPlatformPlugin::initControls error grabbing controlDicts element %d, skipping\n", i); continue; } // Verify that this control is valid on this machine's config if ((array = OSDynamicCast(OSArray, dict->getObject(gIOPPluginThermalValidConfigsKey))) != NULL && !validOnConfig(array)) { // found a ValidConfigs array, and the current config is not listed, so skip this control continue; } // Determine the class to use for this control object - defaults to IOPlatformControl if ((string = OSDynamicCast(OSString, dict->getObject(kIOClassKey))) == NULL) { //DLOG("IOPlatformPlugin::initControls using IOPlatformControl default class\n"); string = gIOPPluginControlClass; } else { //DLOG("IOPlatformPlugin: control class %s\n", string->getCStringNoCopy()); } // create the control object if ((control = OSDynamicCast(IOPlatformControl, OSMetaClass::allocClassWithName(string))) == NULL) { DLOG("IOPlatformPlugin::initControls failed to allocate %s\n", string->getCStringNoCopy()); continue; } // initialize the control object if ((result = control->initPlatformControl(dict)) != kIOReturnSuccess) { DLOG("IOPlatformPlugin::initControls failed to init control object\n"); control->release(); continue; } // Add the object class to it's dictionary control->getInfoDict()->setObject(kIOClassKey, string); // Add this control to the control list 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; if (sensorDicts == NULL) { DLOG("IOPlatformPlugin::initSensors no sensor array\n"); // this is not a fatal error return(true); } // Allocate the sensor info array and put it in the registry sensors = OSArray::withCapacity(0); sensorInfoDicts = OSArray::withCapacity(0); setProperty(gIOPPluginSensorDataKey, sensorInfoDicts); count = sensorDicts->getCount(); for (i = 0; i < count; i++) { // grab the array element if ((dict = OSDynamicCast(OSDictionary, sensorDicts->getObject(i))) == NULL) { DLOG("IOPlatformPlugin::initSensors error grabbing sensorDicts element %d, skipping\n", i); continue; } // Verify that this sensor is valid on this machine's config if ((array = OSDynamicCast(OSArray, dict->getObject(gIOPPluginThermalValidConfigsKey))) != NULL && !validOnConfig(array)) { // found a ValidConfigs array, and the current config is not listed, so skip this sensor continue; } // Determine the class to use for this sensor object - defaults to IOPlatformSensor if ((string = OSDynamicCast(OSString, dict->getObject(kIOClassKey))) == NULL) { //DLOG("IOPlatformPlugin::initSensors using IOPlatformSensor default class\n"); string = gIOPPluginSensorClass; } else { //DLOG("IOPlatformPlugin::initSensors sensor class %s\n", string->getCStringNoCopy()); } // create the sensor object if ((sensor = OSDynamicCast(IOPlatformSensor, OSMetaClass::allocClassWithName(string))) == NULL) { DLOG("IOPlatformPlugin::initSensors failed to allocate %s\n", string->getCStringNoCopy()); continue; } // initialize the sensor object if ((result = sensor->initPlatformSensor(dict)) != kIOReturnSuccess) { DLOG("IOPlatformPlugin::initSensors failed to init sensor object\n"); sensor->release(); continue; } // Add the object class to it's dictionary sensor->getInfoDict()->setObject(kIOClassKey, string); // Add this sensor to the sensor array 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; if (ctrlLoopDicts == NULL) { DLOG("IOPlatformPlugin::initCtrlLoops no ctrlloop array\n"); // this is not a fatal error return(true); } // allocate the ctrlloop lists and add the ctrlloop info array to the registry ctrlLoops = OSArray::withCapacity(0); ctrlLoopInfoDicts = OSArray::withCapacity(0); setProperty( gIOPPluginCtrlLoopDataKey, ctrlLoopInfoDicts ); count = ctrlLoopDicts->getCount(); for (i = 0; i < count; i++) { // grab the array element if ((dict = OSDynamicCast(OSDictionary, ctrlLoopDicts->getObject(i))) == NULL) { DLOG("IOPlatformPlugin::initCtrlLoops error parsing ctrlLoopDicts element %d, skipping\n", i); continue; } // Verify that this ctrlloop is valid on this machine's config if ((array = OSDynamicCast(OSArray, dict->getObject(gIOPPluginThermalValidConfigsKey))) != NULL && !validOnConfig(array)) { // found a ValidConfigs array, and the current config is not listed, so skip this ctrlloop continue; } // Determine the class to use for this CtrlLoop object - IOPlatformCtrlLoop must be subclassed!! if ((string = OSDynamicCast(OSString, dict->getObject(kIOClassKey))) == NULL) { DLOG("IOPlatformPlugin::initCtrlLoops no IOPlatformCtrlLoop subclass specified, skipping...\n"); continue; } // create the CtrlLoop object if ((ctrlLoop = OSDynamicCast(IOPlatformCtrlLoop, OSMetaClass::allocClassWithName(string))) == NULL) { DLOG("IOPlatformPlugin::initCtrlLoops failed to allocate %s\n", string->getCStringNoCopy()); continue; } // initialize the CtrlLoop object if ((result = ctrlLoop->initPlatformCtrlLoop(dict)) != kIOReturnSuccess) { DLOG("IOPlatformPlugin::initCtrlLoops failed to init CtrlLoop object\n"); ctrlLoop->release(); continue; } // Add the object class to it's dictionary ctrlLoop->getInfoDict()->setObject(kIOClassKey, string); // Add this ctrlloop to the ctrlloop array ctrlLoops->setObject(ctrlLoop); // control loops don't register, so just add this to the registry now ctrlLoopInfoDicts->setObject( ctrlLoop->getInfoDict() ); } return(true); } bool IOPlatformPlugin::validOnConfig( const OSArray * validConfigs ) { const OSNumber * number; int j, nconfigs; bool valid = false; // Verify that this control is valid on this machine's config 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 ); } IOPlatformSensor *IOPlatformPlugin::lookupSensorByID( const OSNumber * sensorID ) const { IOPlatformSensor *tmpSensor, *result = NULL; if (sensorID && sensors) { unsigned int i, count; count = sensors->getCount(); for (i=0; igetObject(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; igetObject(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; igetObject(i)); if (ctrlLoopID && ctrlLoopID->isEqualTo( tmpCtrlLoop->getCtrlLoopID() )) { result = tmpCtrlLoop; break; } } } return(result); } 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); } } /* * Some environment conditions are set per-ctrlloop, so we can track which ctrl loops are causing * a condition to exists. If the array is empty, none of the loops are exhibiting the condition. */ bool IOPlatformPlugin::setEnvArray( const OSSymbol * aKey, const OSObject * setter, bool setting ) { OSArray * array; int i, count; if ((array = OSDynamicCast(OSArray, getEnv( aKey ))) != NULL) { // see if the ctrl loop is already listed in the array count = array->getCount(); for (i=0; igetObject(i) == setter) break; } // we found the ctrl loop and we want to remove it if (iremoveObject(i); if (array->getCount() == 0) { envChanged = true; } return(true); } // we didn't find the ctrl loop and we want to add it if (i>=count && setting) { array->setObject(setter); envChanged = true; return(true); } } // something went wrong: the key doesn't exist in the env dict, or the ctrl loop // is already listed in the array and can't be added again, or the ctrl loop is // not already listed and cannot be removed return(false); } // return true if any ctrl loop has the indicated condition set to true bool IOPlatformPlugin::envArrayCondIsTrue( const OSSymbol *cond ) const { OSArray * array; if ((array = OSDynamicCast(OSArray, getEnv( cond ))) != NULL && array->getCount() > 0) { return(true); } else { return(false); } } // return true if the indicated ctrl loop has the indicated condition set to true 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; igetObject(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; // let the control loops update their meta state and, if necessary, adjust their controls if (ctrlLoops) { count = ctrlLoops->getCount(); for (i=0; igetObject(i))) != NULL) { //DLOG("IOPlatformPlugin::enviromentChanged notifying ctrlLoop %d\n", i); loop->updateMetaState(); loop->adjustControls(); } } } } UInt8 IOPlatformPlugin::probeConfig(void) { return 0; // generic class doesn't know anything about a machine's configs... } UInt8 IOPlatformPlugin::getConfig( void ) { return machineConfig; } void IOPlatformPlugin::setTimeout( const AbsoluteTime now ) { AbsoluteTime loopDeadline, soonest; IOPlatformCtrlLoop *loop; int i, count, cmp; //DLOG("IOPlatformPlugin::setTimeout - entered\n"); // find the soonest non-zero deadline if (ctrlLoops) { AbsoluteTime_to_scalar(&soonest) = 0; count = ctrlLoops->getCount(); for (i=0; igetObject(i))) != NULL) { loopDeadline = loop->getDeadline(); if (AbsoluteTime_to_scalar(&loopDeadline) != 0) { if (CMP_ABSOLUTETIME(&loopDeadline, &now) == -1) { // There is a non-zero deadline that already passed. This probably means that // something went wrong and this control loop didn't get it's timer callback. // If we get here, just schedule a thread callout for the soonest possible // dispatch. 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 ); } } } void IOPlatformPlugin::timerHandler( const AbsoluteTime now ) { AbsoluteTime loopDeadline; IOPlatformCtrlLoop *loop; int i, count; //DLOG("IOPlatformPlugin::timerHandler - entered\n"); // check deadlines and call updateControls() on any control loop whose deadline has // passed ( and is non-zero ). if (ctrlLoops) { count = ctrlLoops->getCount(); for (i=0; igetObject(i))) != NULL) { loopDeadline = loop->getDeadline(); if (AbsoluteTime_to_scalar(&loopDeadline) != 0 && CMP_ABSOLUTETIME(&loopDeadline, &now) <= 0) { //DLOG("IOPlatformPlugin::timerHandler ctrlLoop %d deadline passed\n", i); loop->deadlinePassed(); } } } } } IOReturn IOPlatformPlugin::setPropertiesHandler( OSObject * properties ) { IOReturn status = kIOReturnUnsupported; #ifdef PLUGIN_DEBUG OSDictionary * commandDict, * forceDict; const OSNumber * id, * value; IOPlatformSensor * sensor; IOPlatformControl * control; IOPlatformCtrlLoop * ctrlLoop; //OSSerialize *s; //DLOG("IOPlatformPlugin::setPropertiesHandler - entered\n"); if ((commandDict = OSDynamicCast(OSDictionary, properties)) == NULL) return kIOReturnBadArgument; // look for a force-update request if (commandDict->getObject(gIOPPluginForceUpdateKey) != NULL) { //DLOG("IOPlatformPlugin::setProperties force-update\n"); // force-update is accompanied by either a sensor-id or a ctrl-id if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginSensorIDKey))) != NULL) { if ((sensor = lookupSensorByID(id)) != NULL && (value = sensor->fetchCurrentValue()) != NULL) { //DLOG("IOPlatformPlugin::setProperties force-update sensor-id %u\n", id->unsigned16BitValue()); // update current-value sensor->setCurrentValue( value ); value->release(); status = kIOReturnSuccess; } } else if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginControlIDKey))) != NULL) { if ((control = lookupControlByID( id )) != NULL && (value = control->fetchCurrentValue()) != NULL) { //DLOG("IOPlatformPlugin::setProperties force-update control-id %u\n", id->unsigned16BitValue()); // update current-value control->setCurrentValue( value ); value->release(); status = kIOReturnSuccess; } } } // look for force-update-all request else if ((commandDict->getObject(gIOPPluginForceUpdateAllKey)) != NULL) { //DLOG("IOPlatformPlugin::setProperties force-update-all\n"); int i, count; if (sensors) { count = sensors->getCount(); for (i=0; igetObject(i))) != NULL && (value = sensor->fetchCurrentValue()) != NULL) { sensor->setCurrentValue( value ); value->release(); } } } if (controls) { count = controls->getCount(); for (i=0; igetObject(i))) != NULL && (value = control->fetchCurrentValue()) != NULL) { DLOG("IOPlatformPlugin::setProperties control %d value 0x%08lX\n", i, value->unsigned32BitValue()); control->setCurrentValue( value ); value->release(); } } } // everything is updated status = kIOReturnSuccess; } /* else if ((commandDict->getObject(gIOPPluginForceSensorCurValKey)) != NULL) { } */ // force a control value else if ((value = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginForceControlTargetValKey))) != NULL) { if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginControlIDKey))) != NULL && (control = lookupControlByID(id)) != NULL) { if (control->sendTargetValue( value, true )) { control->getInfoDict()->setObject(gIOPPluginForceControlTargetValKey, value); DLOG("IOPlatformPlugin Control ID 0x%08lX Forced to 0x%08lX\n", id->unsigned32BitValue(), value->unsigned32BitValue()); } } } // release a forced control value else if ((value = 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 )) { DLOG("IOPlatformPlugin ControlID 0x%08lX Release Forced Value\n", id->unsigned32BitValue()); control->getInfoDict()->removeObject(gIOPPluginForceControlTargetValKey); } } } // force a control loop meta state 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(); } /* if ((s = OSSerialize::withCapacity(2048)) != NULL && commandDict->serialize(s)) { DLOG("IOPlatformPlugin::setPropertiesHandler force-ctrlloop-meta-state %s\n", s->text()); } if (s) s->release(); */ } // release a forced control loop meta state else if ((value = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginReleaseForcedCtrlLoopKey))) != NULL) { OSSerialize *s; if ((s = OSSerialize::withCapacity(2048)) != NULL && commandDict->serialize(s)) { DLOG("IOPlatformPlugin::setPropertiesHandler release-forced-ctrlloop %s\n", s->text()); } if (s) s->release(); if ((id = OSDynamicCast(OSNumber, commandDict->getObject(gIOPPluginCtrlLoopIDKey))) != NULL && (ctrlLoop = lookupCtrlLoopByID(id)) != NULL && (ctrlLoop->getInfoDict()->getObject(gIOPPluginForceCtrlLoopMetaStateKey)) != NULL) { DLOG("IOPlatformPlugin CtrlLoopID 0x%08lX Release Forced Ctrl Loop\n", id->unsigned32BitValue()); ctrlLoop->getInfoDict()->removeObject(gIOPPluginForceCtrlLoopMetaStateKey); ctrlLoop->updateMetaState(); } } // DLOG("IOPlatformPlugin::setPropertiesHandler - done\n"); #endif // PLUGIN_DEBUG return(status); } IOReturn IOPlatformPlugin::registrationHandler( IOService *sender, OSDictionary *dict ) { const OSNumber *id; IOPlatformSensor *sensor; IOPlatformControl *control; IOReturn status = kIOReturnError; //DLOG("IOPlatformPlugin::registrationHandler - entered\n"); // sanity check args if (!sender || !dict) { DLOG("IOPlatformPlugin::registrationHandler got bad args!\n"); return(kIOReturnBadArgument); } // Look for a sensor-id if ((id = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginSensorIDKey))) != NULL) { // Look for the sensor in the thermal profile info sensor = lookupSensorByID( id ); if (sensor) // sensor is already listed { // duplicate registration? 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 // the registration is from an unlisted sensor { #ifdef PLUGIN_DEBUG const OSNumber * tempID; tempID = OSDynamicCast(OSNumber, sender->getProperty("sensor-id")); #endif DLOG("IOPlatformPlugin::registrationHandler got unknown entity, sensor id 0x%08lX\n", tempID != NULL ? tempID->unsigned32BitValue() : 0xDEADBEEF); // create the sensor object if ((sensor = OSDynamicCast(IOPlatformSensor, OSMetaClass::allocClassWithName(gIOPPluginSensorClass))) == NULL) { DLOG("IOPlatformPlugin::registrationHandler failed to allocate IOPlatformSensor\n"); return(kIOReturnNoResources); } // initialize the sensor object if ((status = sensor->initPlatformSensor(sender)) != kIOReturnSuccess) { DLOG("IOPlatformPlugin::registrationHandler failed to init sensor from unlisted registrant\n"); sensor->release(); return(status); } // add this new sensor to the list sensors->setObject( sensor ); status = sensor->registerDriver( sender, dict ); if (status == kIOReturnSuccess) sensorInfoDicts->setObject( sensor->getInfoDict() ); return(status); } } // Look for a control-id else if ((id = OSDynamicCast(OSNumber, dict->getObject(gIOPPluginControlIDKey))) != NULL) { // Look for the control in the thermal profile info control = lookupControlByID( id ); if (control) // control is already listed { // duplicate or conflict? 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; // flag a warning if the thermal profile and reported types don't match 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 { DLOG("IOPlatformPlugin::registrationHandler unrecognized control ID %08lX\n", id->unsigned32BitValue()); return status; } } else { IOLog("IOPlatformPlugin got registration from unknown entity %s\n", sender->getName()); return(kIOReturnUnsupported); } } IOReturn IOPlatformPlugin::sleepHandler(void) { /* // Sleep sequence: kprintf("IOPlatformPlugin::powerStateWillChangeTo (currently unsupported!!) to acknowledge power changes (DOWN) we set napping false\n"); IOLog("IOPlatformPlugin::powerStateWillChangeTo (currently unsupported!!) to acknowledge power changes (DOWN) we set napping false\n"); // xxx- this is placeholder code. We need to make this happen for each cpu // rememberNap = ml_enable_nap(getCPUNumber(), false); // Disable napping (the function returns the previous state) */ DLOG("IOPlatformPlugin::sleepHandler - entered\n"); pluginPowerState = kIOPPluginSleeping; return(IOPMAckImplied); } IOReturn IOPlatformPlugin::wakeHandler(void) { /* // Wake sequence: kprintf("IOPlatformPlugin::powerStateWillChangeTo (currently unsupported!!) to acknowledge power changes (UP) we set napping %s\n", rememberNap ? "true" : "false"); IOLog("IOPlatformPlugin::powerStateWillChangeTo (currently unsupported!!) to acknowledge power changes (UP) we set napping %s\n", rememberNap ? "true" : "false"); // xxx- this is placeholder code. We need to make this happen for each cpu // ml_enable_nap(getCPUNumber(), rememberNap); // Re-set the nap as it was before. */ IOPlatformCtrlLoop *loop; int i, count; DLOG("IOPlatformPlugin::wakeHandler - entered\n"); // tell all the control loop we just woke up if (ctrlLoops) { count = ctrlLoops->getCount(); for (i=0; igetObject(i))) != NULL) { loop->didWake(); } } } // force an update cycle for all ctrlloops by setting the environment changed flag envChanged = true; pluginPowerState = kIOPPluginRunning; 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) { //DLOG("IOPlatformPlugin::messageHander got threshold message\n"); 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::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::handleEvent(IOPPluginEventData *event) { IOReturn status; AbsoluteTime now; // Cancel any outstanding timer events. The deadlines will be checked and the timer reset after this // event is serviced. 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 IOPPluginEventSetProperties: status = setPropertiesHandler( OSDynamicCast(OSObject, (OSMetaClassBase *) event->param1) ); break; case IOPPluginEventPlatformFunction: default: DLOG("IOPlatformPlugin::handleEvent got unknown event type\n"); status = kIOReturnUnsupported; break; } // if there were any changes to the environment, notify control loops if (envChanged) { environmentChanged(); // clear the environment changed flag envChanged = false; } // check deadlines and set the timer if necessary if (pluginPowerState != kIOPPluginSleeping) setTimeout(now); return(status); } /* static */ /* IOReturn IOPlatformPlugin::commandGateCaller(OSObject *object, void *arg0, void *arg1, void *arg2, void *arg3) { IOPlatformPlugin *me; IOPPluginEventData *event; if ((me = OSDynamicCast(IOPlatformPlugin, object)) == NULL || (event = (IOPPluginEventData *) arg0) == NULL) { DLOG("IOPlatformPlugin::commandGateCaller invalid args\n"); return(kIOReturnBadArgument); } return me->handleEvent(event); } */ IOReturn IOPlatformPlugin::dispatchEvent(IOPPluginEventData *event) { IOReturn status; // close the gate IORecursiveLockLock(gate); // handle the event status = handleEvent(event); // open the gate IORecursiveLockUnlock(gate); return(status); } 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::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); } /* static */ void IOPlatformPlugin::timerEventOccured( void *self ) { IOPPluginEventData tEvent; IOPlatformPlugin * me = OSDynamicCast(IOPlatformPlugin, (OSMetaClassBase *) self); if (me) { tEvent.eventType = IOPPluginEventTimer; me->dispatchEvent(&tEvent); } } void IOPlatformPlugin::sleepSystem( void ) { DLOG("IOPlatformPlugin::sleepSystem issuing sleep demand\n"); pmRootDomain->sleepSystem(); }