Portable2004_PlatformMonitor.cpp [plain text]
#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 actionFullPower ( );
static bool actionPower1 ( );
static IOPlatformMonitorAction platformActionGrid[kMaxPowerStates][kMaxThermalStates][kNumClamshellStates] =
{
{
{
actionFullPower, actionFullPower },
{
actionPower1, actionPower1 },
{
actionPower1, actionPower1 },
{
actionPower1, actionPower1 },
},
{
{
actionPower1, actionPower1 },
{
actionPower1, actionPower1 },
{
actionPower1, actionPower1 },
{
actionPower1, actionPower1 },
}
};
static ConSensorInfo conSensorArray[kMaxConSensors];
static ConSensorInfo subSensorArray[kMaxSensorIndex];
static NewThresholdInfo thermalThresholdInfoArray[kMaxMachineTypes][kMaxSensorIndex][kNumClamshellStates][kMaxThermalStates] =
{
{ { { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(54) }, { TEMP_SENSOR_FMT(52), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(59) }, { TEMP_SENSOR_FMT(57), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(79) }, { TEMP_SENSOR_FMT(75), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(79) }, { TEMP_SENSOR_FMT(75), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(103) }, { TEMP_SENSOR_FMT(99), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(101), TEMP_SENSOR_FMT(107) }, { TEMP_SENSOR_FMT(103), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(103) }, { TEMP_SENSOR_FMT(99), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(101), TEMP_SENSOR_FMT(107) }, { TEMP_SENSOR_FMT(103), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, { TEMP_SENSOR_FMT(40), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, { TEMP_SENSOR_FMT(40), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
},
{ { { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(63) }, { TEMP_SENSOR_FMT(62), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(63) }, { TEMP_SENSOR_FMT(62), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(82), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(82), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(92) }, { TEMP_SENSOR_FMT(91), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(92) }, { TEMP_SENSOR_FMT(91), TEMP_SENSOR_FMT(105) }, { TEMP_SENSOR_FMT(100), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(105), TEMP_SENSOR_FMT(115) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(73) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(83) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
},
{ { { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(76) }, { TEMP_SENSOR_FMT(74), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(76) }, { TEMP_SENSOR_FMT(74), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(75) }, { TEMP_SENSOR_FMT(73), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(75) }, { TEMP_SENSOR_FMT(73), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(82) }, { TEMP_SENSOR_FMT(80), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(82) }, { TEMP_SENSOR_FMT(80), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, { TEMP_SENSOR_FMT(37), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(42) }, { TEMP_SENSOR_FMT(37), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
},
{ { { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(68) }, { TEMP_SENSOR_FMT(66), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(50) }, { TEMP_SENSOR_FMT(45), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(50) }, { TEMP_SENSOR_FMT(45), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(108), TEMP_SENSOR_FMT(115) }, { TEMP_SENSOR_FMT(113), TEMP_SENSOR_FMT(117) }, },
},
{ { { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
{ { TEMP_SENSOR_FMT(0), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(68), TEMP_SENSOR_FMT(110) }, { TEMP_SENSOR_FMT(78), TEMP_SENSOR_FMT(93) }, { TEMP_SENSOR_FMT(88), TEMP_SENSOR_FMT(117) }, },
},
}
};
#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)
static bool actionFullPower ( )
{
IOService *serv;
debug_msg("IOPMon::actionFullPower - starting\n");
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);
}
}
if ((conSensorArray[kGPUController].state != kGPUPowerState0) &&
(serv = conSensorArray[kGPUController].conSensor)) {
conSensorArray[kGPUController].state = kGPUPowerState0;
serv->setAggressiveness (kIOFBLowPowerAggressiveness, 0);
provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonFull);
}
return true;
}
static bool actionPower1 ( )
{
IOService *serv;
debug_msg("IOPMon::actionPower1 - starting\n");
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);
}
}
if ((conSensorArray[kGPUController].state != kGPUPowerState0) &&
(serv = conSensorArray[kGPUController].conSensor)) {
conSensorArray[kGPUController].state = kGPUPowerState0;
serv->setAggressiveness (kIOFBLowPowerAggressiveness, 0);
provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonFull);
}
return true;
}
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());
goingToSleep = false;
if (macRISC2PE->processorSpeedChangeFlags & kBusSlewBasedSpeedChange)
{
macRISC2PE->processorSpeedChangeFlags &= ~kProcessorBasedSpeedChange;
gUseBusSlewing = true;
}
else
gUseBusSlewing = false;
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;
commandGateCaller = &iopmonCommandGateCaller;
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) {
newNum = newCPUSpeed / (gPEClockFrequencyInfo.cpu_clock_rate_hz /
gPEClockFrequencyInfo.bus_to_cpu_rate_num);
gPEClockFrequencyInfo.bus_to_cpu_rate_num = newNum; gPEClockFrequencyInfo.cpu_clock_rate_hz = newCPUSpeed; }
}
break;
}
}
}
}
conSensorArray[kPowerSensor].conSensorType = kIOPMonPowerSensor; conSensorArray[kPowerSensor].conSensor = this; conSensorArray[kPowerSensor].numStates = kMaxPowerStates;
conSensorArray[kPowerSensor].sensorValid = true;
conSensorArray[kPowerSensor].registered = true;
conSensorArray[kThermalSensor].conSensorType = kIOPMonThermalSensor; conSensorArray[kThermalSensor].conSensor = this;
conSensorArray[kThermalSensor].numStates = kMaxThermalStates;
conSensorArray[kThermalSensor].sensorValid = true;
conSensorArray[kThermalSensor].registered = true;
conSensorArray[kClamshellSensor].conSensorType = kIOPMonClamshellSensor; conSensorArray[kClamshellSensor].numStates = kNumClamshellStates;
conSensorArray[kClamshellSensor].sensorValid = true;
conSensorArray[kClamshellSensor].registered = false;
conSensorArray[kCPUController].conSensorType = kIOPMonCPUController; conSensorArray[kCPUController].registered = false;
conSensorArray[kGPUController].conSensorType = kIOPMonGPUController; conSensorArray[kGPUController].state = kGPUPowerState0;
conSensorArray[kGPUController].registered = true;
conSensorArray[kSlewController].conSensorType = kIOPMonSlewController; conSensorArray[kSlewController].registered = false;
for (i = 0; i < kMaxSensorIndex; i++) {
subSensorArray[i].conSensorType = kIOPMonThermalSensor;
subSensorArray[i].conSensorParent = kThermalSensor; subSensorArray[i].numStates = kMaxThermalStates;
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;
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;
updateIOPMonStateInfo(kIOPMonPowerSensor, currentPowerState);
updateIOPMonStateInfo(kIOPMonThermalSensor, currentThermalState);
updateIOPMonStateInfo(kIOPMonClamshellSensor, currentClamshellState);
provider->setProperty (gIOPMonCPUActionKey, (OSObject *)gIOPMonReduced);
provider->setProperty (gIOPMonGPUActionKey, (OSObject *)gIOPMonFull);
publishResource ("IOPlatformMonitor", this);
if (super::start (nub)) {
conSensorArray[kGPUController].conSensor = pmRootDomain;
gIOPMon = this;
return true;
} else
return false;
}
IOReturn Portable2004_PlatformMonitor::powerStateWillChangeTo (IOPMPowerFlags theFlags, unsigned long, IOService*)
{
if ( ! (theFlags & IOPMPowerOn) ) {
debug_msg ("Portable2004_PlatformMonitor::powerStateWillChangeTo - sleep\n");
savePlatformState();
if ( macRISC2PE->processorSpeedChangeFlags & kBusSlewBasedSpeedChange )
{
if (conSensorArray[kSlewController].registered) {
conSensorArray[kSlewController].state = kCPUPowerState0;
gIOPMon->setBusSlew ((UInt32) 0);
goingToSleep = true;
debug_msg ("Portable2004_PlatformMonitor::bus slew fast - sleep\n");
}
}
else
{
actionFullPower();
goingToSleep = true;
}
}
return IOPMAckImplied;
}
IOReturn Portable2004_PlatformMonitor::powerStateDidChangeTo (IOPMPowerFlags theFlags, unsigned long, IOService*)
{
if (theFlags & IOPMPowerOn) {
goingToSleep = false;
debug_msg ("Portable2004_PlatformMonitor::powerStateDidChangeTo - wake\n");
restorePlatformState();
}
return IOPMAckImplied;
}
IOReturn Portable2004_PlatformMonitor::setAggressiveness(unsigned long selector, unsigned long newLevel)
{
IOPMonEventData event;
IOReturn result;
if (goingToSleep)
return kIOReturnError;
result = super::setAggressiveness(selector, newLevel);
if (selector == kPMSetProcessorSpeed) {
if ((newLevel != currentPowerState) && (newLevel < 2)){ event.event = kIOPMonMessageStateChanged;
event.conSensor = this;
event.eventDict = (newLevel == 0) ? dictPowerHigh : dictPowerLow;
handleEvent (&event);
}
}
return result;
}
void Portable2004_PlatformMonitor::setBusSlew (UInt32 newLevel)
{
OSDictionary *dict;
const OSObject *target_value[1];
const OSSymbol *key[1];
key[0] = OSSymbol::withCString("target-value");
if (conSensorArray[kSlewController].registered == true) {
if (newLevel == 0) { target_value[0] = OSNumber::withNumber((unsigned long long) 0, 32);
dict = OSDictionary::withObjects(target_value, key, (unsigned int) 1, (unsigned int) 0);
} else {
target_value[0] = OSNumber::withNumber((unsigned long long) 1, 32);
dict = OSDictionary::withObjects(target_value, key, 1, 0);
}
conSensorArray[kSlewController].conSensor->setProperties(dict);
}
key[0]->release();
target_value[0]->release();
dict->release();
return;
}
bool Portable2004_PlatformMonitor::initPowerState ()
{
currentPowerState = kPowerState1; return true;
}
void Portable2004_PlatformMonitor::savePowerState ()
{
return; }
bool Portable2004_PlatformMonitor::restorePowerState ()
{
return (currentPowerState == kPowerState1);
}
bool Portable2004_PlatformMonitor::initThermalState ()
{
currentThermalState = kThermalState0;
return true;
}
void Portable2004_PlatformMonitor::saveThermalState ()
{
return; }
bool Portable2004_PlatformMonitor::restoreThermalState ()
{
OSNumber *threshLow, *threshHigh;
UInt32 i;
currentThermalState = kThermalState0;
for (i = 0; i < kMaxSensorIndex; i++) {
if (subSensorArray[i].registered) { subSensorArray[i].state = kMaxThermalStates;
threshLow = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonLowThresholdKey);
threshLow->setValue((long long)0);
threshHigh = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonHighThresholdKey);
threshHigh->setValue((long long)0);
subSensorArray[i].conSensor->setProperties (subSensorArray[i].threshDict);
}
}
return false;
}
bool Portable2004_PlatformMonitor::initClamshellState ()
{
currentClamshellState = kClamshellStateOpen;
return true;
}
void Portable2004_PlatformMonitor::saveClamshellState ()
{
return; }
bool Portable2004_PlatformMonitor::restoreClamshellState ()
{
return false;
}
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)) {
if (num = OSDynamicCast (OSNumber, dict->getObject (gIOPMonCurrentValueKey))) {
value = num->unsigned32BitValue();
value &= ~kIOPMForceLowSpeed;
if (!(((machineType == kPB54MachineType) || (machineType == kPB55MachineType)) &&
(((((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;
}
#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);
else if ((value & kIOPMClosedClamshell) != 0)
IOLog ("kIOPMClosedClamshell - 0x%lx & (0x%lx)\n", value, kIOPMClosedClamshell);
#endif
num->setValue((long long)value);
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;
handleEvent (&event);
return kIOReturnSuccess;
}
}
}
return kIOReturnBadArgument;
}
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;
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;
}
bool Portable2004_PlatformMonitor::initPlatformState ()
{
if (initPowerState() &&
initThermalState() &&
initClamshellState())
return true;
else
return false;
}
void Portable2004_PlatformMonitor::savePlatformState ()
{
savePowerState();
saveThermalState();
saveClamshellState();
return;
}
void Portable2004_PlatformMonitor::restorePlatformState ()
{
bool doAdjust;
lastPowerState = kMaxPowerStates;
lastThermalState = kMaxThermalStates;
lastClamshellState = kNumClamshellStates;
doAdjust = restorePowerState();
doAdjust |= restoreThermalState();
doAdjust |= restoreClamshellState();
if (doAdjust) {
lastAction = 0; adjustPlatformState ();
}
return;
}
bool Portable2004_PlatformMonitor::adjustPlatformState ()
{
IOPlatformMonitorAction actionToTake;
bool result = true;
bool reevaluateThermalLevels = false;
actionToTake = platformActionGrid[currentPowerState][currentThermalState][currentClamshellState];
if (lastPowerState != currentPowerState) {
lastPowerState = currentPowerState;
updateIOPMonStateInfo(kIOPMonPowerSensor, currentPowerState);
}
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)(); lastAction = actionToTake; }
if ( reevaluateThermalLevels )
{
UInt32 i;
OSNumber *threshLow, *threshHigh;
for (i = 0; i < kMaxSensorIndex; i++) {
if (subSensorArray[i].registered) { subSensorArray[i].state = kMaxThermalStates;
threshLow = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonLowThresholdKey);
threshLow->setValue((long long)0);
threshHigh = (OSNumber *)subSensorArray[i].threshDict->getObject (gIOPMonHighThresholdKey);
threshHigh->setValue((long long)0);
subSensorArray[i].conSensor->setProperties (subSensorArray[i].threshDict);
}
}
}
return result;
}
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;
if (subsi < kMaxSensorIndex) csInfo = &subSensorArray[subsi];
else
csInfo = &conSensorArray[csi];
csInfo->conSensor = conSensor;
csInfo->dict = dict;
dict->retain ();
initialState = initialValue = 0;
switch (csInfo->conSensorType) {
case kIOPMonThermalSensor:
if (!csInfo->sensorValid)
return kIOReturnUnsupported;
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));
conSensor->setProperties (csInfo->threshDict);
csInfo->registered = true;
break;
case kIOPMonPowerSensor:
initialState = kPowerState1; break;
case kIOPMonClamshellSensor:
if (!retrieveCurrentValue (dict, &initialValue))
return kIOReturnBadArgument;
csInfo->registered = true;
break;
case kIOPMonCPUController:
initialState = kCPUPowerState1; csInfo->registered = true;
break;
case kIOPMonGPUController:
initialState = kGPUPowerState0; break;
case kIOPMonSlewController:
obj = csInfo->dict->getObject ("current-value");
initialValue = (OSDynamicCast (OSNumber, obj))->unsigned32BitValue();
initialState = initialValue;
csInfo->registered = true;
break;
default:
break;
}
csInfo->value = initialValue;
csInfo->state = initialState;
return kIOReturnSuccess;
}
bool Portable2004_PlatformMonitor::unregisterSensor (UInt32 sensorID)
{
if (sensorID >= kMaxSensors)
return false;
conSensorArray[sensorID].conSensor = NULL;
return true;
}
bool Portable2004_PlatformMonitor::lookupConSensorInfo (OSDictionary *dict, IOService *conSensor,
UInt32 *type, UInt32 *index, UInt32 *subIndex)
{
OSSymbol *typeString;
UInt32 tempType;
OSObject *obj, *obj2;
*index = kMaxConSensors; *subIndex = kMaxSensorIndex; *type = tempType = kIOPMonUnknownSensor; obj = dict->getObject (gIOPMonTypeKey);
obj2 = dict->getObject (gIOPMonConTypeKey);
if ((obj && (typeString = OSDynamicCast (OSSymbol, obj))) || (obj2 && (typeString = OSDynamicCast (OSSymbol, obj2)))) {
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;
*type = (tempType == kIOPMonUnknownSensor) ? subSensorArray[*subIndex].conSensorType : tempType;
return true;
}
for (*index = 0; *index < kMaxConSensors; (*index)++) {
if (conSensorArray[*index].conSensorType == tempType) {
*type = tempType;
break;
}
}
return (*index < kMaxConSensors);
}
UInt32 Portable2004_PlatformMonitor::lookupThermalStateFromValue (UInt32 sensorIndex, ThermalValue value)
{
UInt32 i;
UInt32 curSensorState;
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 (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;
IOLog ("Portable2004_PlatformMonitor::lookupStateFromValue - sensor %ld over limit\n", sensorIndex);
return kMaxThermalStates;
}
return kThermalState0;
}
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 = nextPowerState;
result = adjustPlatformState ();
}
return result;
}
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)
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);
subSensorArray[subsi].conSensor->setProperties (subSensorArray[subsi].threshDict);
}
if (currentThermalState != myThermalState) {
UInt32 i, maxState;
maxState = 0;
for (i = 0; i < kMaxSensorIndex; i++)
if (subSensorArray[i].registered)
maxState = (maxState > subSensorArray[i].state) ? maxState : subSensorArray[i].state;
if (currentThermalState != maxState)
{
if (maxState < kMaxThermalStates) {
kprintf("*** Portable2004_PlatformMonitor::handleThermalEvent, maxState = %d, currentThermalState = %d ***\n", maxState, currentThermalState);
currentThermalState = maxState;
result = adjustPlatformState ();
}
}
}
}
return result;
}
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;
}
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;
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: result = me->handlePowerEvent (&commandSet->eventData);
break;
case kIOPMonThermalSensor: result = me->handleThermalEvent (&commandSet->eventData);
break;
case kIOPMonClamshellSensor: 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;
}