#include <IOKit/IOMessage.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOTimerEventSource.h>
#include "AppleK2Fan.h"
OSDefineMetaClassAndStructors(AppleK2Fan, IOService)
void AppleK2Fan::timerEventOccurred(OSObject *obj, IOTimerEventSource *timer)
{
UInt32 tach, count;
AppleK2Fan *me = (AppleK2Fan *)obj;
me->callPlatformFunction(me->fGetTacho, false, &tach, NULL, NULL, NULL);
if(tach < me->fLastCount)
count = 65536 + tach - me->fLastCount;
else
count = tach - me->fLastCount;
me->fLastCount = tach;
if(count == 0) {
OSDictionary *dict;
IOLog("Fan failure!\n");
dict = me->dictionaryWithProperties();
if(dict) {
me->messageClient(kIOPPluginMessageError, me->fPlatformPlugin, dict);
dict->release();
}
}
timer->setTimeoutMS(me->fPollingMS);
}
IOService * AppleK2Fan::probe(IOService *provider, SInt32 *score)
{
OSData *version;
version = OSDynamicCast(OSData, provider->getProperty("hwctrl-params-version"));
if(version && (*(UInt32 *)(version->getBytesNoCopy()) == 1))
return this;
else
return NULL;
}
bool AppleK2Fan::start(IOService *provider)
{
OSData *obj;
IOService *ior_prt;
mach_timespec_t t;
OSDictionary *dict;
OSReturn res;
static const IOPMPowerState powerStates[2] = {
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
};
if(!IOService::start(provider))
return false;
t.tv_sec = 30; t.tv_nsec = 0;
ior_prt = waitForService(resourceMatching("IOPlatformPlugin"), &t);
if(!ior_prt) {
IOLog("AppleK2Fan::start ERROR: couldn't find IOPlatformPlugin\n");
return false;
}
else {
fPlatformPlugin = (IOService*)(ior_prt->getProperty("IOPlatformPlugin"));
}
obj = OSDynamicCast(OSData, provider->getProperty("hwctrl-id"));
if(obj) {
UInt32 val = *(UInt32 *)obj->getBytesNoCopy();
setProperty("control-id", val, 32);
}
obj = OSDynamicCast(OSData, provider->getProperty("hwctrl-location"));
if(obj) {
char * val = (char *)obj->getBytesNoCopy();
setProperty("location", val);
}
obj = OSDynamicCast(OSData, provider->getProperty("hwctrl-type"));
if(obj) {
char * val = (char *)obj->getBytesNoCopy();
setProperty("type", val);
}
obj = OSDynamicCast(OSData, provider->getProperty("hwctrl-zone"));
if(obj)
setProperty("zone", obj);
obj = OSDynamicCast(OSData, provider->getProperty("hwctrl-params-version"));
if(obj) {
UInt32 val = *(UInt32 *)obj->getBytesNoCopy();
setProperty("version", val, 32);
}
setProperty("current-value", 42, 32);
setProperty("target-value", 42, 32);
dict = dictionaryWithProperties();
if(dict) {
res = messageClient(kIOPPluginMessageRegister, fPlatformPlugin, dict);
dict->release();
if(res != kIOReturnSuccess) {
IOLog("AppleK2Fan::start, messageClient returned 0x%x\n", res);
return false;
}
}
char callName[128];
OSData * data;
UInt32 handle;
data = OSDynamicCast(OSData, provider->getProperty( "AAPL,phandle" ));
handle = *((UInt32 *) data->getBytesNoCopy());
sprintf(callName,"%s-%8lx", "platform-getTACHCount", handle);
fGetTacho = OSSymbol::withCString(callName);
fPollingMS = 1000; fTimer = IOTimerEventSource::timerEventSource(this, timerEventOccurred);
getWorkLoop()->addEventSource(fTimer);
fTimer->enable();
fTimer->setTimeoutMS(fPollingMS);
PMinit();
provider->joinPMtree(this);
registerPowerDriver(this, (IOPMPowerState *)powerStates, 2);
return true;
}
IOReturn AppleK2Fan::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice)
{
if (powerStateOrdinal == 1) {
fTimer->setTimeoutMS(fPollingMS);
}
else if (powerStateOrdinal == 0) {
fTimer->cancelTimeout();
}
return(IOPMAckImplied);
}