/* * Copyright (c) 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) 2003 Apple Computer, Inc. All rights reserved. * */ /* IMPORTANT NOTE: Clamshell State is better thought of as Environmental State. If the computer should be */ /* forced slow for environmental reasons, like clamshell closed, low battery, etc (not thermals), then the bool */ /* you're looking for is kClamshellStateClosed. If the machine does not need to be forced slow, it is */ /* kClamshellStateOpen. */ #include "Portable2004_PlatformMonitor.h" static const OSSymbol *gIOPMonPowerStateKey; static const OSSymbol *gIOPMonThermalStateKey; static const OSSymbol *gIOPMonClamshellStateKey; static const OSSymbol *gIOPMonCPUActionKey; static const OSSymbol *gIOPMonGPUActionKey; static const OSSymbol *gIOPMonState0; static const OSSymbol *gIOPMonState1; static const OSSymbol *gIOPMonState2; static const OSSymbol *gIOPMonState3; static const OSSymbol *gIOPMonFull; static const OSSymbol *gIOPMonReduced; static const OSSymbol *gIOPMonSlow; static Portable2004_PlatformMonitor *gIOPMon; static IOService *provider; static bool gUseBusSlewing; static bool gUsePowerPlay; static UInt32 gCurrentGPUState; // Possible platform actions static bool actionFullPower ( ); static bool actionPower1 ( ); //static bool actionPower1GPU1 ( ); Currently not used //static bool actionPower1GPU2 ( ); Currently not used /* * The platformActionGrid, which is platform-dependent, is an n-dimension array, where n corresponds * to kMaxSensors. The depth of each array dimension corresponds to the maxStates value for each sensor. * Each element in the array indicates the action to take (one of the above possible platform actions) * based on the current overall state of the system. * * Note that "sensor" can be intrepreted fairly loosely. For example, user selection of "Highest" vs. * "Reduced" processor performance in the Energy Saver preferences is viewed as "sensory input" and * is handled in the table accordingly. */ static IOPlatformMonitorAction platformActionGrid[kMaxPowerStates][kMaxThermalStates][kNumClamshellStates] = { { /* bug 3163342: ramping down the GPU doesn't lower thermals or save power, so we're switching from actionPower1GPUx to actionPower1 */ { actionFullPower, // kPowerState0 / kThermalState0 / kClamShellStateOpen actionFullPower // kPowerState0 / kThermalState0 / kClamShellStateClosed }, { actionPower1, // kPowerState0 / kThermalState1 / kClamShellStateOpen actionPower1 // kPowerState0 / kThermalState1 / kClamShellStateClosed }, { actionPower1, // kPowerState0 / kThermalState2 / kClamShellStateOpen actionPower1 // kPowerState0 / kThermalState2 / kClamShellStateClosed }, { actionPower1, // kPowerState0 / kThermalState3 / kClamShellStateOpen actionPower1 // kPowerState0 / kThermalState3 / kClamShellStateClosed }, }, { { actionPower1, // kPowerState1 / kThermalState0 / kClamShellStateOpen actionPower1 // kPowerState1 / kThermalState0 / kClamShellStateClosed }, { actionPower1, // kPowerState1 / kThermalState1 / kClamShellStateOpen actionPower1 // kPowerState1 / kThermalState1 / kClamShellStateClosed }, { actionPower1, // kPowerState1 / kThermalState2 / kClamShellStateOpen actionPower1 // kPowerState1 / kThermalState2 / kClamShellStateClosed }, { actionPower1, // kPowerState1 / kThermalState3 / kClamShellStateOpen actionPower1 // kPowerState1 / kThermalState3 / kClamShellStateClosed }, } }; /* * conSensorArray, like platformActionArray is platform-dependent. One element for each primary * controller/sensor and each must register itself with us before we can use it. * * conSensorArray is initialized in the start routine. */ static ConSensorInfo conSensorArray[kMaxConSensors]; /* * The subSensorArray contains information about secondary sensors and maps those sensors into the primary * sensor. There are kMaxSensorIndex subSensors and each must map to a primary sensor. On this platform, * all individual sensors are thermal so all map to kThermalSensor, although that may not always be the case. * If more than one thermal zone is to be managed then a primary thermal sensor would be created for each * zone and the subSensorArray can be used to map each sensor into a particular zone. * * subSensorArray is initialized in the start routine. */ static ConSensorInfo subSensorArray[kMaxSensorIndex]; /* * The thermalThresholdInfoArray is another 4-dimensional array detailing threshold and state information * for each sensor. For this platform, an additional factor is clamshell state, so that is one of the * dimensions here. */ static SmallerThresholdInfo thermalThresholdInfoArray[kMaxMachineTypes][kMaxSensorIndex][kNumClamshellStates][kMaxThermalStates] = { { // PowerBook6,4 values ( Q54A ) { // Sensor 0 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(54) }, // kThermalState0 { TEMP_SENSOR_FMT(52), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(59) }, // kThermalState0 { TEMP_SENSOR_FMT(57), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 1 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(79) }, // kThermalState0 { TEMP_SENSOR_FMT(75), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(79) }, // kThermalState0 { TEMP_SENSOR_FMT(75), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 2 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(103) }, // kThermalState0 { TEMP_SENSOR_FMT(99), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(101), TEMP_SENSOR_FMT(107) }, // kThermalState2 { TEMP_SENSOR_FMT(103), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(103) }, // kThermalState0 { TEMP_SENSOR_FMT(99), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(101), TEMP_SENSOR_FMT(107) }, // kThermalState2 { TEMP_SENSOR_FMT(103), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 3 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, // kThermalState0 { TEMP_SENSOR_FMT(40), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, // kThermalState0 { TEMP_SENSOR_FMT(40), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 4 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, }, { // PowerBook6,5 values ( Q72 / Q73 ) { // Sensor 0 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(63) }, // kThermalState0 { TEMP_SENSOR_FMT(62), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, // kThermalState2 { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(63) }, // kThermalState0 { TEMP_SENSOR_FMT(62), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, // kThermalState2 { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, // kThermalState3 }, }, { // Sensor 1 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(83) }, // kThermalState0 { TEMP_SENSOR_FMT(82), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, // kThermalState2 { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(83) }, // kThermalState0 { TEMP_SENSOR_FMT(82), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, // kThermalState2 { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, // kThermalState3 }, }, { // Sensor 2 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(92) }, // kThermalState0 { TEMP_SENSOR_FMT(91), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, // kThermalState2 { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(92) }, // kThermalState0 { TEMP_SENSOR_FMT(91), TEMP_SENSOR_FMT(105) }, // kThermalState1 { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, // kThermalState2 { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, // kThermalState3 }, }, { // Sensor 3 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 4 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, }, { // PowerBook5,4 values (Q16a) { // Sensor 0 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(76) }, // kThermalState0 { TEMP_SENSOR_FMT(74), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(76) }, // kThermalState0 { TEMP_SENSOR_FMT(74), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 1 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(75) }, // kThermalState0 { TEMP_SENSOR_FMT(73), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(75) }, // kThermalState0 { TEMP_SENSOR_FMT(73), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 2 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(82) }, // kThermalState0 { TEMP_SENSOR_FMT(80), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(82) }, // kThermalState0 { TEMP_SENSOR_FMT(80), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 3 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, // kThermalState0 { TEMP_SENSOR_FMT(37), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, // kThermalState0 { TEMP_SENSOR_FMT(37), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 4 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, }, { // PowerBook5,5 values (Q41a) { // Sensor 0 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 1 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 2 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 3 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(50) }, // kThermalState0 { TEMP_SENSOR_FMT(45), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(50) }, // kThermalState0 { TEMP_SENSOR_FMT(45), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 4 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, }, { // PowerBook5,6 values (Q16b) { // Sensor 0 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(76) }, // kThermalState0 { TEMP_SENSOR_FMT(74), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(76) }, // kThermalState0 { TEMP_SENSOR_FMT(74), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 1 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(75) }, // kThermalState0 { TEMP_SENSOR_FMT(73), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(75) }, // kThermalState0 { TEMP_SENSOR_FMT(73), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 2 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(82) }, // kThermalState0 { TEMP_SENSOR_FMT(80), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(82) }, // kThermalState0 { TEMP_SENSOR_FMT(80), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 3 (Battery sensor) { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, // kThermalState0 { TEMP_SENSOR_FMT(37), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, // kThermalState0 { TEMP_SENSOR_FMT(37), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 4 (Trackpad flex sensor) { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(48) }, // kThermalState0 { TEMP_SENSOR_FMT(46), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(48) }, // kThermalState0 { TEMP_SENSOR_FMT(46), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, }, { // PowerBook5,7 values (Q41b) { // Sensor 0 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 1 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 2 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, // kThermalState0 { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 3 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(50) }, // kThermalState0 { TEMP_SENSOR_FMT(45), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(50) }, // kThermalState0 { TEMP_SENSOR_FMT(45), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, // kThermalState2 { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, { // Sensor 4 { // Clamshell open // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, { // Clamshell closed // thresholdLow, thresholdHigh, // currentState { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, // kThermalState0 { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, // kThermalState1 { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, // kThermalState2 { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, // kThermalState3 }, }, } }; #ifndef sub_iokit_graphics # define sub_iokit_graphics err_sub(5) #endif #ifndef kIOFBLowPowerAggressiveness # define kIOFBLowPowerAggressiveness iokit_family_err(sub_iokit_graphics,1) #endif #define super IOPlatformMonitor OSDefineMetaClassAndStructors(Portable2004_PlatformMonitor, IOPlatformMonitor) // ********************************************************************************** // actionFullPower // // ********************************************************************************** static bool actionFullPower ( ) { IOService *serv; debug_msg("IOPMon::actionFullPower - starting\n"); // CPU at full power if not already there if (gUseBusSlewing) { serv = conSensorArray[kSlewController].conSensor; if ((conSensorArray[kSlewController].state != kCPUPowerState0) && (serv = conSensorArray[kSlewController].conSensor)) { debug_msg ("IOPMon::actionFullPower - slewing fast\n"); if (conSensorArray[kSlewController].registered) { conSensorArray[kSlewController].state = kCPUPowerState0; gIOPMon->setBusSlew ((UInt32) 0); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonFull); } } } else { if ((conSensorArray[kCPUController].state != kCPUPowerState0) && (serv = conSensorArray[kCPUController].conSensor)) { conSensorArray[kCPUController].state = kCPUPowerState0; debug_msg ("IOPMon::actionFullPower - sending CPU aggressiveness 2\n"); serv->setAggressiveness (kPMSetProcessorSpeed, 2); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonFull); } } // GPU at full power if not already there if ((conSensorArray[kGPUController].state != kGPUPowerState0) && (serv = conSensorArray[kGPUController].conSensor)) { conSensorArray[kGPUController].state = kGPUPowerState0; gCurrentGPUState = kGPUPowerState0; //debug_msg ("IOPMon::actionFullPower - sending GPU aggressiveness 0\n"); serv->setAggressiveness (kIOFBLowPowerAggressiveness, 0); provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonFull); } return true; } // ********************************************************************************** // actionPower1 // // ********************************************************************************** static bool actionPower1 ( ) { IOService *serv; debug_msg("IOPMon::actionPower1 - starting\n"); // Step down CPU if not already slow if (gUseBusSlewing) { if ((conSensorArray[kSlewController].state != kCPUPowerState1) && (serv = conSensorArray[kSlewController].conSensor)) { debug_msg ("IOPMon::actionPower1 - slewing slow\n"); if (conSensorArray[kSlewController].registered) { conSensorArray[kSlewController].state = kCPUPowerState1; gIOPMon->setBusSlew ((UInt32) 1); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonReduced); } } } else { if ((conSensorArray[kCPUController].state != kCPUPowerState1) && (serv = conSensorArray[kCPUController].conSensor)) { conSensorArray[kCPUController].state = kCPUPowerState1; debug_msg ("IOPMon::actionPower1 - sending CPU aggressiveness 3\n"); serv->setAggressiveness (kPMSetProcessorSpeed, 3); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonReduced); } } // GPU is still at full power if ((conSensorArray[kGPUController].state != kGPUPowerState1) && (serv = conSensorArray[kGPUController].conSensor)) { if (gUsePowerPlay) { conSensorArray[kGPUController].state = kGPUPowerState1; gCurrentGPUState = kGPUPowerState1; serv->setAggressiveness (kIOFBLowPowerAggressiveness, 3); provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonReduced); } else { conSensorArray[kGPUController].state = kGPUPowerState0; //debug_msg ("IOPMon::actionPower1 - sending GPU aggressiveness 0\n"); serv->setAggressiveness (kIOFBLowPowerAggressiveness, 0); provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonFull); } } return true; } // Commenting out routines that are not actively being used. // ********************************************************************************** // actionPower1GPU1 // // ********************************************************************************** /* static bool actionPower1GPU1 ( ) { IOService *serv; // Step down CPU if not already slow if ((conSensorArray[kSlewController].state != kCPUPowerState1) && (serv = conSensorArray[kSlewController].conSensor)) { conSensorArray[kSlewController].state = kCPUPowerState1; debug_msg ("IOPMon::actionPower1GPU1 - CPU sending aggressiveness 1\n"); gIOPMon->setBusSlew ((UInt32) 1); //serv->setAggressiveness (kPMSetProcessorSpeed, 1); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonReduced); } // GPU to reduced power if ((conSensorArray[kGPUController].state != kGPUPowerState1) && (serv = conSensorArray[kGPUController].conSensor)) { conSensorArray[kGPUController].state = kGPUPowerState1; debug_msg ("IOPMon::actionPower1GPU1 - sending GPU aggressiveness 1\n"); serv->setAggressiveness (kIOFBLowPowerAggressiveness, 1); provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonReduced); } return true; } */ // ********************************************************************************** // actionPower1GPU2 // // ********************************************************************************** /* static bool actionPower1GPU2 ( ) { IOService *serv; // Step down CPU if not already slow if ((conSensorArray[kSlewController].state != kCPUPowerState1) && (serv = conSensorArray[kSlewController].conSensor)) { conSensorArray[kSlewController].state = kCPUPowerState1; debug_msg ("IOPMon::actionPower1GPU2 - CPU sending aggressiveness 1\n"); gIOPMon->setBusSlew ((UInt32) 1); //serv->setAggressiveness (kPMSetProcessorSpeed, 1); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonReduced); } // GPU to lowest power if ((conSensorArray[kGPUController].state != kGPUPowerState2) && (serv = conSensorArray[kGPUController].conSensor)) { conSensorArray[kGPUController].state = kGPUPowerState2; debug_msg ("IOPMon::actionPower1GPU2 - sending GPU aggressiveness 2\n"); serv->setAggressiveness (kIOFBLowPowerAggressiveness, 2); provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonSlow); } return true; } */ // ********************************************************************************** // start // // ********************************************************************************** bool Portable2004_PlatformMonitor::start ( IOService * nub ) { UInt32 i; const char *platform_name; IORegistryEntry *cpuEntry, *powerPCEntry; OSIterator *childIterator; OSData *cpuSpeedData; UInt32 newCPUSpeed, newNum; if (!initSymbols()) return false; if (!initPlatformState ()) return false; provider = nub; debug_msg("Portable2004_PlatformMonitor::start - starting\n"); macRISC2PE = OSDynamicCast(MacRISC2PE, getPlatform()); // Set up flag that tells us when the Platform monitor is about to go to sleep to false // ...this flag is used to tell when to ignore all setaggressiveness calls... goingToSleep = false; if (macRISC2PE->processorSpeedChangeFlags & kBusSlewBasedSpeedChange) { // platform expert assumes that dynamic power stepping means that it's a processor-based //speed change, but here it's not, so fix flags macRISC2PE->processorSpeedChangeFlags &= ~kProcessorBasedSpeedChange; gUseBusSlewing = true; } else gUseBusSlewing = false; // check if we need to enable the GPU "PowerPlay" feature... if (macRISC2PE->processorSpeedChangeFlags & kSupportsPowerPlay) { debug_msg("Portable2004_PlatformMonitor::start - this machine supports PowerPlay\n"); // Even though the BootROM indicates this machine supports PowerPlay we are disabling it for // all machines that Portable2004 support, which is Q16A and Q41A. This is due to performance issues // seen when playing games in "Automatic" mode gUsePowerPlay = false; } else { debug_msg("Portable2004_PlatformMonitor::start - this machine does NOT support PowerPlay\n"); gUsePowerPlay = false; } // For now, these machines lack PMU based Speed changing as well. // macRISC2PE->processorSpeedChangeFlags |= kPMUBasedSpeedChange; platform_name = macRISC2PE->getParentEntry(gIOServicePlane)->getName(); if (!strcmp(platform_name, "PowerBook6,4")) machineType = kPB64MachineType; else if (!strcmp(platform_name, "PowerBook6,5")) machineType = kPB65MachineType; else if (!strcmp(platform_name, "PowerBook5,4")) machineType = kPB54MachineType; else if (!strcmp(platform_name, "PowerBook5,5")) machineType = kPB55MachineType; else if (!strcmp(platform_name, "PowerBook5,6")) machineType = kPB56MachineType; else if (!strcmp(platform_name, "PowerBook5,7")) machineType = kPB57MachineType; commandGateCaller = &iopmonCommandGateCaller; // Inform superclass about our caller // use the "max-clock-frequency" to determine what the CPU speed should be if its greater // than what OF reported to us in the "clock-frequency" property cpuEntry = fromPath("/cpus", gIODTPlane); if (cpuEntry != 0) { if ((childIterator = cpuEntry->getChildIterator (gIODTPlane)) != NULL) { while ((powerPCEntry = (IORegistryEntry *)(childIterator->getNextObject ())) != NULL) { if (!strncmp ("PowerPC", powerPCEntry->getName(gIODTPlane), strlen ("PowerPC"))) { cpuSpeedData = OSDynamicCast( OSData, powerPCEntry->getProperty( "max-clock-frequency" )); if (cpuSpeedData) { newCPUSpeed = *(UInt32 *) cpuSpeedData->getBytesNoCopy(); if (newCPUSpeed != gPEClockFrequencyInfo.cpu_clock_rate_hz) { // IOLog("Portable2004_PlatformMonitor::start - use max-clock-frequency to set new CPU speed\n"); newNum = newCPUSpeed / (gPEClockFrequencyInfo.cpu_clock_rate_hz / gPEClockFrequencyInfo.bus_to_cpu_rate_num); gPEClockFrequencyInfo.bus_to_cpu_rate_num = newNum; // Set new numerator gPEClockFrequencyInfo.cpu_clock_rate_hz = newCPUSpeed; // Set new speed } } break; } } } } // Initialize our controller/sensor types (platform-dependent) // Primary sensors conSensorArray[kPowerSensor].conSensorType = kIOPMonPowerSensor; // platform power monitor conSensorArray[kPowerSensor].conSensor = this; // platform power monitor conSensorArray[kPowerSensor].numStates = kMaxPowerStates; conSensorArray[kPowerSensor].sensorValid = true; conSensorArray[kPowerSensor].registered = true; // built-in conSensorArray[kThermalSensor].conSensorType = kIOPMonThermalSensor; // primary thermal sensor conSensorArray[kThermalSensor].conSensor = this; conSensorArray[kThermalSensor].numStates = kMaxThermalStates; conSensorArray[kThermalSensor].sensorValid = true; conSensorArray[kThermalSensor].registered = true; // built-in aggregate sensor conSensorArray[kClamshellSensor].conSensorType = kIOPMonClamshellSensor; // pmu clamshell sensor conSensorArray[kClamshellSensor].numStates = kNumClamshellStates; conSensorArray[kClamshellSensor].sensorValid = true; conSensorArray[kClamshellSensor].registered = false; // Controllers conSensorArray[kCPUController].conSensorType = kIOPMonCPUController; // cpu controller conSensorArray[kCPUController].registered = false; conSensorArray[kGPUController].conSensorType = kIOPMonGPUController; // gpu controller conSensorArray[kGPUController].state = kGPUPowerState0; gCurrentGPUState = kGPUPowerState0; // initialize our global to indicate GPU boots fast as well conSensorArray[kGPUController].registered = true; // built-in conSensorArray[kSlewController].conSensorType = kIOPMonSlewController; // slew controller conSensorArray[kSlewController].registered = false; // Subsensors (all are thermal sensors) for (i = 0; i < kMaxSensorIndex; i++) { subSensorArray[i].conSensorType = kIOPMonThermalSensor; subSensorArray[i].conSensorParent = kThermalSensor; // Index into primary array of our parent subSensorArray[i].numStates = kMaxThermalStates; // If a sensor is not to be used, set sensorValid false; subSensorArray[i].sensorValid = true; subSensorArray[i].registered = false; } if (!(dictPowerLow = OSDictionary::withCapacity (3))) return false; if (!(dictPowerHigh = OSDictionary::withCapacity (3))) return false; if (!(dictClamshellOpen = OSDictionary::withCapacity (2))) return false; if (!(dictClamshellClosed = OSDictionary::withCapacity (2))) return false; // On platforms with more than one CPU these dictionaries must accurately reflect which cpu is involved dictPowerLow->setObject (gIOPMonCPUIDKey, OSNumber::withNumber ((unsigned long long)0, 32)); dictPowerLow->setObject (gIOPMonCurrentValueKey, OSNumber::withNumber ((unsigned long long)kPowerState1, 32)); dictPowerLow->setObject (gIOPMonTypeKey, gIOPMonTypePowerSens); dictPowerHigh->setObject (gIOPMonCPUIDKey, OSNumber::withNumber ((unsigned long long)0, 32)); dictPowerHigh->setObject (gIOPMonCurrentValueKey, OSNumber::withNumber ((unsigned long long)kPowerState0, 32)); dictPowerHigh->setObject (gIOPMonTypeKey, gIOPMonTypePowerSens); dictClamshellOpen->setObject (gIOPMonCurrentValueKey, OSNumber::withNumber ((unsigned long long)kClamshellStateOpen, 32)); dictClamshellOpen->setObject (gIOPMonTypeKey, gIOPMonTypeClamshellSens); dictClamshellClosed->setObject (gIOPMonCurrentValueKey, OSNumber::withNumber ((unsigned long long)kClamshellStateClosed, 32)); dictClamshellClosed->setObject (gIOPMonTypeKey, gIOPMonTypeClamshellSens); if (!gIOPMonPowerStateKey) gIOPMonPowerStateKey = OSSymbol::withCString (kIOPMonPowerStateKey); if (!gIOPMonThermalStateKey) gIOPMonThermalStateKey = OSSymbol::withCString (kIOPMonThermalStateKey); if (!gIOPMonClamshellStateKey) gIOPMonClamshellStateKey = OSSymbol::withCString (kIOPMonClamshellStateKey); if (!gIOPMonCPUActionKey) gIOPMonCPUActionKey = OSSymbol::withCString (kIOPMonCPUActionKey); if (!gIOPMonGPUActionKey) gIOPMonGPUActionKey = OSSymbol::withCString (kIOPMonGPUActionKey); if (!gIOPMonState0) gIOPMonState0 = OSSymbol::withCString (kIOPMonState0); if (!gIOPMonState1) gIOPMonState1 = OSSymbol::withCString (kIOPMonState1); if (!gIOPMonState2) gIOPMonState2 = OSSymbol::withCString (kIOPMonState2); if (!gIOPMonState3) gIOPMonState3 = OSSymbol::withCString (kIOPMonState3); if (!gIOPMonFull) gIOPMonFull = OSSymbol::withCString (kIOPMonFull); if (!gIOPMonReduced) gIOPMonReduced = OSSymbol::withCString (kIOPMonReduced); if (!gIOPMonSlow) gIOPMonSlow = OSSymbol::withCString (kIOPMonSlow); lastPowerState = kMaxPowerStates; lastThermalState = kMaxThermalStates; lastClamshellState = kNumClamshellStates; // Put initial state and action info into the IORegistry updateIOPMonStateInfo(kIOPMonPowerSensor, currentPowerState); updateIOPMonStateInfo(kIOPMonThermalSensor, currentThermalState); updateIOPMonStateInfo(kIOPMonClamshellSensor, currentClamshellState); provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonReduced); provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonFull); // Let the world know we're open for business publishResource ("IOPlatformMonitor", this); if (super::start (nub)) { // pmRootDomain (found by our parent) is the recipient of GPU controller messages conSensorArray[kGPUController].conSensor = pmRootDomain; gIOPMon = this; return true; } else return false; } // ********************************************************************************** // powerStateWillChangeTo // // ********************************************************************************** IOReturn Portable2004_PlatformMonitor::powerStateWillChangeTo (IOPMPowerFlags theFlags, unsigned long, IOService*) { if ( ! (theFlags & IOPMPowerOn) ) { // Sleep sequence: goingToSleep = true; debug_msg ("Portable2004_PlatformMonitor::powerStateWillChangeTo - sleep\n"); savePlatformState(); actionFullPower(); } return IOPMAckImplied; } // ********************************************************************************** // powerStateDidChangeTo // // ********************************************************************************** IOReturn Portable2004_PlatformMonitor::powerStateDidChangeTo (IOPMPowerFlags theFlags, unsigned long, IOService*) { if (theFlags & IOPMPowerOn) { // Wake sequence: debug_msg ("Portable2004_PlatformMonitor::powerStateDidChangeTo - wake\n"); // we don't want to remember any prior actions and start "fresh" after a wake from sleep restorePlatformState(); goingToSleep = false; } return IOPMAckImplied; } // ********************************************************************************** // setAggressiveness // // setAggressiveness is called by the Power Manager to change our power state // It is most commonly called when the user changes the Energy Saver preferences // to change the power state but it can be called for other reasons. // // One of these reasons is a forced-reduced-speed condition but we now detect and // act on this condition immediately (through a clamshell event) so by the time the // PM calls us here we have already altered the condition and there is nothing to do. // // ********************************************************************************** IOReturn Portable2004_PlatformMonitor::setAggressiveness(unsigned long selector, unsigned long newLevel) { IOPMonEventData event; IOReturn result; if (goingToSleep) return kIOReturnError; result = super::setAggressiveness(selector, newLevel); newLevel &= 0x7FFFFFFF; // mask off high bit... upcoming kernel change will use the high bit to indicate whether setAggressiveness call // was user induced (Energy Saver) or not. Currently not using this info so mask it off. if (selector == kPMSetProcessorSpeed) { // IOLog ("Portable2004_PlatformMonitor::setAggressiveness - newLevel %ld, currentPowerState %ld\n", newLevel, currentPowerState); if (((newLevel != currentPowerState) || (gCurrentGPUState != currentPowerState)) && (newLevel < 2)){ // This only works if we have two power states // create and transmit internal event event.event = kIOPMonMessageStateChanged; event.conSensor = this; event.eventDict = (newLevel == 0) ? dictPowerHigh : dictPowerLow; // send it handleEvent (&event); } } return result; } // ********************************************************************************** // setBusSlew // // ********************************************************************************** void Portable2004_PlatformMonitor::setBusSlew (UInt32 newLevel) { OSDictionary *dict; const OSObject *target_value[1]; const OSSymbol *key[1]; key[0] = OSSymbol::withCString("target-value"); // we should have a slewcontroller, but let's check to make sure. if (conSensorArray[kSlewController].registered == true) { if (newLevel == 0) { // set bus speed high target_value[0] = OSNumber::withNumber((unsigned long long) 0, 32); dict = OSDictionary::withObjects(target_value, key, (unsigned int) 1, (unsigned int) 0); //IOLog ("Portable2004_PlatformMonitor::setBusSlew - slew high, newlevel = %d\n", newLevel); } else { target_value[0] = OSNumber::withNumber((unsigned long long) 1, 32); dict = OSDictionary::withObjects(target_value, key, 1, 0); //IOLog ("Portable2004_PlatformMonitor::setBusSlew - slew low, newlevel = %d\n", newLevel); } conSensorArray[kSlewController].conSensor->setProperties(dict); } key[0]->release(); target_value[0]->release(); dict->release(); return; } // ********************************************************************************** // initPowerState // // ********************************************************************************** bool Portable2004_PlatformMonitor::initPowerState () { currentPowerState = kPowerState1; // We will have booted slow return true; } // ********************************************************************************** // savePowerState // // ********************************************************************************** void Portable2004_PlatformMonitor::savePowerState () { return; // Currently nothing to do } // ********************************************************************************** // restorePowerState // // ********************************************************************************** bool Portable2004_PlatformMonitor::restorePowerState () { // This platform is always fast coming out of sleep, so if our current power // state is slow (kPowerState1) return true to force an update. return (currentPowerState == kPowerState1); } // ********************************************************************************** // initThermalState // // ********************************************************************************** bool Portable2004_PlatformMonitor::initThermalState () { currentThermalState = kThermalState0; return true; } // ********************************************************************************** // saveThermalState // // ********************************************************************************** void Portable2004_PlatformMonitor::saveThermalState () { return; // Nothing to do } // ********************************************************************************** // restoreThermalState // // ********************************************************************************** bool Portable2004_PlatformMonitor::restoreThermalState () { OSNumber *threshLow, *threshHigh; UInt32 i; // reset current thermal state to the initial state since we're starting fresh... currentThermalState = kThermalState0; // need to get updated info from sensors for (i = 0; i < kMaxSensorIndex; i++) { if (subSensorArray[i].registered) { // Is sensor registered? subSensorArray[i].state = kThermalState0; //Set indeterminate state // Set to "normal"/non-overtemp thresholds - this will cause sensor to update info if overtemp is reached threshLow = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonLowThresholdKey); threshLow->setValue((long long)thermalThresholdInfoArray[machineType][i][kClamshellStateOpen][kThermalState0].thresholdLow); threshHigh = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonHighThresholdKey); threshHigh->setValue((long long)thermalThresholdInfoArray[machineType][i][kClamshellStateOpen][kThermalState0].thresholdHigh); // Send thresholds to sensor subSensorArray[i].conSensor->setProperties (subSensorArray[i].threshDict); } } /* * This routine returns false because we don't want to force an adjust of the platform * state just yet. That will happen automatically when the sensors respond to the low * thresholds */ return false; } // ********************************************************************************** // initClamshellState // // ********************************************************************************** bool Portable2004_PlatformMonitor::initClamshellState () { currentClamshellState = kClamshellStateOpen; return true; } // ********************************************************************************** // saveClamshellState // // ********************************************************************************** void Portable2004_PlatformMonitor::saveClamshellState () { return; // Nothing to do } // ********************************************************************************** // restoreClamshellState // // ********************************************************************************** bool Portable2004_PlatformMonitor::restoreClamshellState () { // Currently nothing to do. // We'll get the right state next time monitor power is called return false; } // ********************************************************************************** // monitorPower // // ********************************************************************************** IOReturn Portable2004_PlatformMonitor::monitorPower (OSDictionary *dict, IOService *provider) { UInt32 type, index, subIndex, value; OSNumber *num; IOPMonEventData event; bool clamshellChanged; if (lookupConSensorInfo (dict, provider, &type, &index, &subIndex)) { // See if any low power conditions exist. if (num = OSDynamicCast (OSNumber, dict->getObject (gIOPMonCurrentValueKey))) { value = num->unsigned32BitValue(); value &= ~kIOPMForceLowSpeed; // Clear low speed bit // For Q16A and Q41A with a >= 65W adapter plugged in OR airline adapter, // don't enforce force-reduced-speed conditions. if (!(((machineType == kPB54MachineType) || (machineType == kPB55MachineType) || (machineType == kPB56MachineType) || (machineType == kPB57MachineType)) && (((((value & 0xFF000000) >> 24) > 0) && (((value & 0xFF000000) >> 24) >= 0x41)) || ((((value & 0xFF000000) >> 24) == 0) && ((value & (kIOPMACInstalled | kIOPMACnoChargeCapability)) == (kIOPMACInstalled | kIOPMACnoChargeCapability)))))) { if ((value & (kIOPMACInstalled | kIOPMACnoChargeCapability)) == (kIOPMACInstalled | kIOPMACnoChargeCapability)) value |= kIOPMForceLowSpeed; else if ((value & (kIOPMRawLowBattery | kIOPMBatteryDepleted)) != 0) value |= kIOPMForceLowSpeed; else if ((value & kIOPMBatteryInstalled) == 0) value |= kIOPMForceLowSpeed; // Clamshell is a little different than P58, which only used it to control L3 cache // 3143038: we don't want to force low speed on closed clamshell on P99 anymore. //else if ((value & kIOPMClosedClamshell) != 0) //value |= kIOPMForceLowSpeed; } #if 0 if ((value & (kIOPMACInstalled | kIOPMACnoChargeCapability)) == (kIOPMACInstalled | kIOPMACnoChargeCapability)) IOLog ("(kIOPMACInstalled | kIOPMACnoChargeCapability) - 0x%lx & (0x%lx)\n", value, (kIOPMACInstalled | kIOPMACnoChargeCapability)); else if ((value & (kIOPMRawLowBattery | kIOPMBatteryDepleted)) != 0) IOLog ("(kIOPMRawLowBattery | kIOPMBatteryDepleted) - 0x%lx & (0x%lx)\n", value, (kIOPMRawLowBattery | kIOPMBatteryDepleted)); else if ((value & kIOPMBatteryInstalled) == 0) IOLog ("kIOPMBatteryInstalled - 0x%lx & (0x%lx)\n", value, kIOPMBatteryInstalled); // Clamshell is a little different than P58, which only used it to control L3 cache else if ((value & kIOPMClosedClamshell) != 0) IOLog ("kIOPMClosedClamshell - 0x%lx & (0x%lx)\n", value, kIOPMClosedClamshell); #endif num->setValue((long long)value); // Send updated value back if ((value & kIOPMClosedClamshell) != 0) clamshellChanged = (currentClamshellState == kClamshellStateOpen); else clamshellChanged = (currentClamshellState != kClamshellStateOpen); if (clamshellChanged) { event.event = kIOPMonMessageStateChanged; event.conSensor = this; event.eventDict = (currentClamshellState == kClamshellStateOpen) ? dictClamshellClosed : dictClamshellOpen; // send it handleEvent (&event); return kIOReturnSuccess; } /* if ((value & (kIOPMACInstalled | kIOPMACnoChargeCapability)) == (kIOPMACInstalled | kIOPMACnoChargeCapability)) kprintf ("(kIOPMACInstalled | kIOPMACnoChargeCapability) - 0x%lx & (0x%lx)\n", value, (kIOPMACInstalled | kIOPMACnoChargeCapability)); else if ((value & (kIOPMRawLowBattery | kIOPMBatteryDepleted)) != 0) kprintf ("(kIOPMRawLowBattery | kIOPMBatteryDepleted) - 0x%lx & (0x%lx)\n", value, (kIOPMRawLowBattery | kIOPMBatteryDepleted)); else if ((value & kIOPMBatteryInstalled) == 0) kprintf ("kIOPMBatteryInstalled - 0x%lx & (0x%lx)\n", value, kIOPMBatteryInstalled); // Clamshell is a little different than P58, which only used it to control L3 cache else if ((value & kIOPMClosedClamshell) != 0) kprintf ("kIOPMClosedClamshell - 0x%lx & (0x%lx)\n", value, kIOPMClosedClamshell); */ /* * Strictly speaking, most of the above situations aren't closed clamshell conditions but * for the purposes of the state machine it's OK to treat them that way. That may not be true * on all platforms. */ /* if (((value & kIOPMForceLowSpeed) && (currentClamshellState == kClamshellStateOpen)) || ((!(value & kIOPMForceLowSpeed)) && (currentClamshellState == kClamshellStateClosed))) { //IOLog ("monitorPower: sending clamshell %s event based on flags 0x%lx\n", // (currentClamshellState == kClamshellStateOpen) ? "closed" : "open", value); // create and transmit internal event event.event = kIOPMonMessageStateChanged; event.conSensor = this; event.eventDict = (currentClamshellState == kClamshellStateOpen) ? dictClamshellClosed : dictClamshellOpen; // send it handleEvent (&event); return kIOReturnSuccess; } */ } } return kIOReturnBadArgument; } // ********************************************************************************** // updateIOPMonStateInfo // // ********************************************************************************** void Portable2004_PlatformMonitor::updateIOPMonStateInfo (UInt32 type, UInt32 state) { const OSSymbol *stateKey, *stateValue; stateKey = stateValue = NULL; if (type == kIOPMonPowerSensor) stateKey = gIOPMonPowerStateKey; else if (type == kIOPMonThermalSensor) stateKey = gIOPMonThermalStateKey; else if (type == kIOPMonClamshellSensor) stateKey = gIOPMonClamshellStateKey; // Thermal has the most states so we use that to look up state values if (state == kThermalState0) stateValue = gIOPMonState0; else if (state == kThermalState1) stateValue = gIOPMonState1; else if (state == kThermalState2) stateValue = gIOPMonState2; else if (state == kThermalState3) stateValue = gIOPMonState3; if (stateKey && stateValue) provider->setProperty (stateKey, (OSObject *)stateValue); return; } // ********************************************************************************** // initPlatformState // // ********************************************************************************** bool Portable2004_PlatformMonitor::initPlatformState () { if (initPowerState() && initThermalState() && initClamshellState()) return true; else return false; } // ********************************************************************************** // savePlatformState // // -- protected by CommandGate - call via IOPlatformMonitor::savePlatformState // // ********************************************************************************** void Portable2004_PlatformMonitor::savePlatformState () { savePowerState(); saveThermalState(); saveClamshellState(); return; } // ********************************************************************************** // restorePlatformState // // -- protected by CommandGate - call via IOPlatformMonitor::restorePlatformState // // ********************************************************************************** void Portable2004_PlatformMonitor::restorePlatformState () { bool doAdjust; // Last states are indeterminate lastPowerState = kMaxPowerStates; lastThermalState = kMaxThermalStates; lastClamshellState = kNumClamshellStates; // If restoration of any of the states requires action (i.e., if they returned // true), force an update doAdjust = restorePowerState(); doAdjust |= restoreThermalState(); doAdjust |= restoreClamshellState(); if (doAdjust) { lastAction = 0; // Force update adjustPlatformState (); } return; } // ********************************************************************************** // adjustPlatformState // // This gets called whenever there is a possible state change. A state change doesn't // imply that you always have to take an action - in fact, most of the time you don't - // so only if the action we should take is different from the last action we took do // we do something. // // ********************************************************************************** bool Portable2004_PlatformMonitor::adjustPlatformState () { IOPlatformMonitorAction actionToTake; bool result = true; bool reevaluateThermalLevels = false; //IOLog ("Portable2004_PlatformMonitor::adjustPlatformState - entered, cps %ld, cts %ld, ccs %ld\n", // currentPowerState, currentThermalState, currentClamshellState); // Look up action to take for current state actionToTake = platformActionGrid[currentPowerState][currentThermalState][currentClamshellState]; // Current state becomes the last state, update info if (lastPowerState != currentPowerState) { lastPowerState = currentPowerState; updateIOPMonStateInfo(kIOPMonPowerSensor, currentPowerState); } else if (currentPowerState != gCurrentGPUState) lastAction = 0; if (lastThermalState != currentThermalState) { lastAction = 0; lastThermalState = currentThermalState; updateIOPMonStateInfo(kIOPMonThermalSensor, currentThermalState); } if (lastClamshellState != currentClamshellState) { lastClamshellState = currentClamshellState; updateIOPMonStateInfo(kIOPMonClamshellSensor, currentClamshellState); reevaluateThermalLevels = true; } if (actionToTake != lastAction) { result = (*actionToTake)(); // Do it lastAction = actionToTake; // Remember what it was we did } // Since the platform state changed, we really should re-evaluate all our threshold settings... if ( reevaluateThermalLevels ) { UInt32 i; OSNumber *threshLow, *threshHigh; for (i = 0; i < kMaxSensorIndex; i++) { if (subSensorArray[i].registered) { // Is sensor registered? subSensorArray[i].state = kMaxThermalStates; //Set indeterminate state // Set low thresholds - this will cause sensor to update info threshLow = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonLowThresholdKey); threshLow->setValue((long long)0); threshHigh = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonHighThresholdKey); threshHigh->setValue((long long)0); // Send thresholds to sensor subSensorArray[i].conSensor->setProperties (subSensorArray[i].threshDict); } } } return result; } // ********************************************************************************** // registerConSensor // // ********************************************************************************** IOReturn Portable2004_PlatformMonitor::registerConSensor (OSDictionary *dict, IOService *conSensor) { UInt32 csi, subsi, type, initialState, initialValue; ConSensorInfo *csInfo; OSObject *obj; if (!lookupConSensorInfo (dict, conSensor, &type, &csi, &subsi)) return kIOReturnBadArgument; //IOLog ("Portable2004_PlatformMonitor::registerConSensor - type %ld, csi %ld, subsi %ld\n", type, csi, subsi); if (subsi < kMaxSensorIndex) // Is subsensor index valid? If so use subSensorArray csInfo = &subSensorArray[subsi]; else csInfo = &conSensorArray[csi]; csInfo->conSensor = conSensor; csInfo->dict = dict; dict->retain (); initialState = initialValue = 0; // type dependent initialization switch (csInfo->conSensorType) { case kIOPMonThermalSensor: /* * Thermal sensors get aggregated through the subSensorArray. The main thermal sensor * entry in conSensorArray only tracks the overall state */ if (!csInfo->sensorValid) return kIOReturnUnsupported; // Don't need this sensor - tell it to go away //if (!retrieveCurrentValue (dict, &initialThermalValue)) // return kIOReturnBadArgument; // Figure out our initial state // Just initialize the initial state/initial value to 0 for now and let the normal HandleThermalEvent get called if it needs to later... //initialState = lookupThermalStateFromValue (subsi, initialThermalValue); if (!(csInfo->threshDict = OSDictionary::withCapacity(3))) return kIOReturnNoMemory; csInfo->threshDict->setObject (gIOPMonIDKey, OSNumber::withNumber (subsi, 32)); csInfo->threshDict->setObject (gIOPMonLowThresholdKey, OSNumber::withNumber (thermalThresholdInfoArray[machineType][subsi][currentClamshellState][initialState].thresholdLow, 32)); csInfo->threshDict->setObject (gIOPMonHighThresholdKey, OSNumber::withNumber (thermalThresholdInfoArray[machineType][subsi][currentClamshellState][initialState].thresholdHigh, 32)); // Send thresholds to sensor conSensor->setProperties (csInfo->threshDict); csInfo->registered = true; break; case kIOPMonPowerSensor: initialState = kPowerState1; // Booted slow break; case kIOPMonClamshellSensor: if (!retrieveCurrentValue (dict, &initialValue)) return kIOReturnBadArgument; csInfo->registered = true; break; case kIOPMonCPUController: initialState = kCPUPowerState1; // Booted slow - meaning DFS should be set to "slow" csInfo->registered = true; // set the PMU multiplier to be fast //csInfo->conSensor->setAggressiveness (kPMSetProcessorSpeed, 2); break; case kIOPMonGPUController: if (gUsePowerPlay) initialState = kGPUPowerState1; // GPU starts out slow if we support PowerPlay else initialState = kGPUPowerState0; // otherwise, GPU starts out fast break; case kIOPMonSlewController: obj = csInfo->dict->getObject ("current-value"); initialValue = (OSDynamicCast (OSNumber, obj))->unsigned32BitValue(); initialState = initialValue; //initialState = kCPUPowerState0; // Booted fast - PM should call and change if neccessary csInfo->registered = true; break; default: break; } csInfo->value = initialValue; csInfo->state = initialState; return kIOReturnSuccess; } // ********************************************************************************** // unregisterSensor // // ********************************************************************************** bool Portable2004_PlatformMonitor::unregisterSensor (UInt32 sensorID) { if (sensorID >= kMaxSensors) return false; conSensorArray[sensorID].conSensor = NULL; return true; } // ********************************************************************************** // lookupConSensorInfo // // ********************************************************************************** bool Portable2004_PlatformMonitor::lookupConSensorInfo (OSDictionary *dict, IOService *conSensor, UInt32 *type, UInt32 *index, UInt32 *subIndex) { OSSymbol *typeString; UInt32 tempType; OSObject *obj, *obj2; *index = kMaxConSensors; // assume not found *subIndex = kMaxSensorIndex; // assume not found // See if we have a type *type = tempType = kIOPMonUnknownSensor; // assume not obj = dict->getObject (gIOPMonTypeKey); obj2 = dict->getObject (gIOPMonConTypeKey); if ((obj && (typeString = OSDynamicCast (OSSymbol, obj))) || (obj2 && (typeString = OSDynamicCast (OSSymbol, obj2)))) { //if (typeString = OSDynamicCast (OSSymbol, dict->getObject (gIOPMonTypeKey))) { if (typeString->isEqualTo (gIOPMonTypePowerSens)) tempType = kIOPMonPowerSensor; else if (typeString->isEqualTo (gIOPMonTypeThermalSens)) tempType = kIOPMonThermalSensor; else if (typeString->isEqualTo (gIOPMonTypeClamshellSens)) tempType = kIOPMonClamshellSensor; else if (typeString->isEqualTo (gIOPMonTypeCPUCon)) tempType = kIOPMonCPUController; else if (typeString->isEqualTo (gIOPMonTypeGPUCon)) tempType = kIOPMonGPUController; else if (typeString->isEqualTo (gIOPMonTypeSlewCon)) tempType = kIOPMonSlewController; else if (typeString->isEqualTo (gIOPMonTypeFanCon)) tempType = kIOPMonFanController; } if (retrieveSensorIndex (dict, subIndex)) { if (*subIndex >= kMaxSensorIndex) return false; // We're dealing with a subSensor, so set the type and validate it in the subSensor array by index *type = (tempType == kIOPMonUnknownSensor) ? subSensorArray[*subIndex].conSensorType : tempType; return true; } /* * Treat anything else as a primary sensor. * For this platform there is only one of each primary controller/sensor so if we find the type * we have the index. */ for (*index = 0; *index < kMaxConSensors; (*index)++) { if (conSensorArray[*index].conSensorType == tempType) { *type = tempType; break; } } return (*index < kMaxConSensors); } // ********************************************************************************** // lookupThermalStateFromValue // // ********************************************************************************** UInt32 Portable2004_PlatformMonitor::lookupThermalStateFromValue (UInt32 sensorIndex, ThermalValue value) { UInt32 i; UInt32 curSensorState; // First, lets see if we are at our current know sensor state... curSensorState = subSensorArray[sensorIndex].state; if (curSensorState != kMaxThermalStates) { if (value > thermalThresholdInfoArray[machineType][sensorIndex][currentClamshellState][curSensorState].thresholdLow && value < thermalThresholdInfoArray[machineType][sensorIndex][currentClamshellState][curSensorState].thresholdHigh) return curSensorState; } // If not, lets see what state we are at... if (value > thermalThresholdInfoArray[machineType][sensorIndex][currentClamshellState][0].thresholdLow) { for (i = 0 ; i < subSensorArray[sensorIndex].numStates; i++) if (value > thermalThresholdInfoArray[machineType][sensorIndex][currentClamshellState][i].thresholdLow && value < thermalThresholdInfoArray[machineType][sensorIndex][currentClamshellState][i].thresholdHigh) return i; // This is bad as sensor's already over the limit - need to figure right response IOLog ("Portable2004_PlatformMonitor::lookupStateFromValue - sensor %ld over limit\n", sensorIndex); return kMaxThermalStates; } // Safely below the lowest threshold return kThermalState0; } // ********************************************************************************** // handlePowerEvent // // -- protected by CommandGate - call through handleEvent // // ********************************************************************************** bool Portable2004_PlatformMonitor::handlePowerEvent (IOPMonEventData *eventData) { UInt32 nextPowerState; bool result; debug_msg("Portable2004_PlatformMonitor::handlePowerEvent - started\n"); if (!(retrieveCurrentValue (eventData->eventDict, &nextPowerState))) return false; result = true; if ((currentPowerState != nextPowerState) || (currentPowerState != gCurrentGPUState)) { currentPowerState = nextPowerState; result = adjustPlatformState (); } return result; } // ********************************************************************************** // handleThermalEvent // // -- protected by CommandGate - call through handleEvent // // ********************************************************************************** bool Portable2004_PlatformMonitor::handleThermalEvent (IOPMonEventData *eventData) { UInt32 type, csi, subsi, myThermalState; ThermalValue value; OSNumber *threshLow, *threshHigh; bool result; debug_msg("Portable2004_PlatformMonitor::handleThermalEvent - started\n"); result = true; if (!(retrieveCurrentValue (eventData->eventDict, &value))) return false; switch (eventData->event) { case kIOPMonMessageLowThresholdHit: case kIOPMonMessageHighThresholdHit: if (lookupConSensorInfo (eventData->eventDict, eventData->conSensor, &type, &csi, &subsi) && subSensorArray[subsi].registered) { myThermalState = lookupThermalStateFromValue (subsi, value); if (myThermalState >= kMaxSensorIndex) result = false; } else result = false; break; default: IOLog ("Portable2004_PlatformMonitor::handleThermalEvent - event %ld not handled\n", eventData->event); result = false; break; } if (result) { if (myThermalState != subSensorArray[subsi].state) { subSensorArray[subsi].state = myThermalState; if (!subSensorArray[subsi].registered) // Not registered return false; threshLow = (OSNumber *)subSensorArray[subsi].threshDict->getObject (gIOPMonLowThresholdKey); threshLow->setValue((long long)thermalThresholdInfoArray[machineType][subsi][currentClamshellState][myThermalState].thresholdLow); threshHigh = (OSNumber *)subSensorArray[subsi].threshDict->getObject (gIOPMonHighThresholdKey); threshHigh->setValue((long long)thermalThresholdInfoArray[machineType][subsi][currentClamshellState][myThermalState].thresholdHigh); // Send thresholds to sensor subSensorArray[subsi].conSensor->setProperties (subSensorArray[subsi].threshDict); } if (currentThermalState != myThermalState) { UInt32 i, maxState; // Find the current max state among all the sensors maxState = 0; for (i = 0; i < kMaxSensorIndex; i++) if (subSensorArray[i].registered) maxState = (maxState > subSensorArray[i].state) ? maxState : subSensorArray[i].state; // If new max state is different than current, update platform state if (currentThermalState != maxState) { if (maxState < kMaxThermalStates) // Don't want to set a thermal state too high { kprintf("*** Portable2004_PlatformMonitor::handleThermalEvent, maxState = %d, currentThermalState = %d ***\n", maxState, currentThermalState); currentThermalState = maxState; result = adjustPlatformState (); } } } } return result; } // ********************************************************************************** // handleClamshellEvent // // -- protected by CommandGate - call through handleEvent // // ********************************************************************************** bool Portable2004_PlatformMonitor::handleClamshellEvent (IOPMonEventData *eventData) { UInt32 nextClamshellState; bool result; debug_msg("Portable2004_PlatformMonitor::handleClamshellEvent - started\n"); if (!(retrieveCurrentValue (eventData->eventDict, &nextClamshellState))) return false; result = true; if (currentClamshellState != nextClamshellState) { currentClamshellState = nextClamshellState; result = adjustPlatformState (); } return result; } // ********************************************************************************** // iopmonCommandGateCaller - invoked by commandGate->runCommand // // This is single threaded!! // // ********************************************************************************** //static IOReturn Portable2004_PlatformMonitor::iopmonCommandGateCaller(OSObject *object, void *arg0, void *arg1, void *arg2, void *arg3) { Portable2004_PlatformMonitor *me; IOPMonCommandThreadSet *commandSet; UInt32 type, conSensorID, subSensorID; bool result; // Pull our event data and, since we're a static function, a reference to our object // out of the parameters if (((commandSet = (IOPMonCommandThreadSet *)arg0) == NULL) || ((me = OSDynamicCast(Portable2004_PlatformMonitor, commandSet->me)) == NULL)) return kIOReturnError; result = true; switch (commandSet->command) { case kIOPMonCommandHandleEvent: if (!(commandSet->eventData.eventDict)) { IOLog ("Portable2004_PlatformMonitor::iopmonCommandGateCaller - bad dictionary\n"); return kIOReturnBadArgument; } if (!(commandSet->eventData.conSensor)) { IOLog ("Portable2004_PlatformMonitor::iopmonCommandGateCaller - bad conSensor\n"); return kIOReturnBadArgument; } if (!me->lookupConSensorInfo (commandSet->eventData.eventDict, commandSet->eventData.conSensor, &type, &conSensorID, &subSensorID)) { IOLog ("Portable2004_PlatformMonitor::iopmonCommandGateCaller - bad sensor info lookup\n"); return kIOReturnBadArgument; } switch (type) { case kIOPMonPowerSensor: // platform power monitor result = me->handlePowerEvent (&commandSet->eventData); break; case kIOPMonThermalSensor: // zone 1 thermal sensor result = me->handleThermalEvent (&commandSet->eventData); break; case kIOPMonClamshellSensor: // pmu clamshell sensor result = me->handleClamshellEvent (&commandSet->eventData); break; default: IOLog ("Portable2004_PlatformMonitor::iopmonCommandGateCaller - bad sensorType(%ld), sensorID(%ld), subsi(%ld)\n", type, conSensorID, subSensorID); result = false; break; } break; case kIOPMonCommandSaveState: me->savePlatformState (); break; case kIOPMonCommandRestoreState: me->restorePlatformState (); break; default: IOLog ("Portable2004_PlatformMonitor::iopmonCommandGateCaller - bad command %ld\n", commandSet->command); result = false; break; } return result ? kIOReturnSuccess : kIOReturnError; }