IOI2CMaxim6690.cpp [plain text]
#include "IOI2CMaxim6690.h"
#define super IOI2CDevice
OSDefineMetaClassAndStructors(IOI2CMaxim6690, IOI2CDevice)
bool IOI2CMaxim6690::init( OSDictionary *dict )
{
if (!super::init(dict)) return(false);
fGetSensorValueSym = NULL;
return(true);
}
void IOI2CMaxim6690::free( void )
{
super::free();
}
bool IOI2CMaxim6690::start( IOService *nub )
{
IOService *childNub;
OSArray * nubArray;
DLOG("IOI2CMaxim6690::start - entered\n");
if (!fGetSensorValueSym)
fGetSensorValueSym = OSSymbol::withCString("getSensorValue");
if (!super::start(nub)) return(false);
while (isI2COffline())
IOSleep(10);
UInt8 deviceID;
if (kIOReturnSuccess != readI2C(kReadDeviceID, &deviceID, 1))
{
IOLog("IOI2CMaxim6690@%lx::start device not responding!\n", getI2CAddress());
freeI2CResources();
return false;
}
nubArray = parseSensorParamsAndCreateNubs( nub );
if (nubArray == NULL || nubArray->getCount() == 0)
{
IOLog("IOI2CMaxim6690@%lx::start no thermal sensors found\n", getI2CAddress());
if (nubArray) nubArray->release();
freeI2CResources();
return(false);
}
registerService();
for (unsigned int index = 0; index < nubArray->getCount(); index++)
{
childNub = OSDynamicCast(IOService, nubArray->getObject(index));
if (childNub) childNub->registerService();
}
nubArray->release();
return(true);
}
void IOI2CMaxim6690::stop( IOService *nub )
{
DLOG("IOI2CMaxim6690::stop - entered\n");
performFunctionsWithFlags(kIOPFFlagOnTerm);
if (fGetSensorValueSym) { fGetSensorValueSym->release(); fGetSensorValueSym = NULL; }
if (fPlatformFuncArray) { fPlatformFuncArray->release(); fPlatformFuncArray = NULL; }
super::stop( nub );
}
IOReturn IOI2CMaxim6690::callPlatformFunction(const OSSymbol *functionName,
bool waitForFunction, void *param1, void *param2,
void *param3, void *param4)
{
UInt32 id = (UInt32)param1;
SInt32 *temp_buf = (SInt32 *)param2;
DLOG("IOI2CMaxim6690::callPlatformFunction(%x) %s %s %08lx %08lx %08lx %08lx\n",
getI2CAddress(), functionName->getCStringNoCopy(), waitForFunction ? "TRUE" : "FALSE",
(UInt32) param1, (UInt32) param2, (UInt32) param3, (UInt32) param4);
if (functionName->isEqualTo(fGetSensorValueSym) == true)
{
if (isI2COffline() == true)
return(kIOReturnOffline);
if (temp_buf == NULL)
return(kIOReturnBadArgument);
if (id == fHWSensorIDMap[0])
{
return(getInternalTemp(temp_buf));
}
else if (id == fHWSensorIDMap[1])
{
return(getExternalTemp(temp_buf));
}
}
return(super::callPlatformFunction(functionName, waitForFunction,
param1, param2, param3, param4));
}
OSArray *IOI2CMaxim6690::parseSensorParamsAndCreateNubs(IOService *nub)
{
IOService *childNub;
OSData *tmp_osdata;
OSArray *nubArray = NULL;
unsigned i, n_sensors = 0;
UInt32 version, *id = NULL, *zone = NULL, *polling_period = NULL;
const char *type = NULL, *location = NULL;
char work[32];
tmp_osdata = OSDynamicCast(OSData,
nub->getProperty(kDTSensorParamsVersionKey));
if (tmp_osdata == NULL)
{
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs no param version\n");
return(NULL);
}
version = *((UInt32 *)tmp_osdata->getBytesNoCopy());
tmp_osdata = OSDynamicCast(OSData,
nub->getProperty(kDTSensorIDKey));
if (tmp_osdata == NULL)
{
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs no ids\n");
return(NULL);
}
n_sensors = tmp_osdata->getLength() / sizeof(UInt32);
if (n_sensors > 2)
{
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs too many sensors %u\n", n_sensors);
return(NULL);
}
id = (UInt32 *)tmp_osdata->getBytesNoCopy();
tmp_osdata = OSDynamicCast(OSData,
nub->getProperty(kDTSensorZoneKey));
if (tmp_osdata == NULL)
{
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs no zones\n");
return(NULL);
}
zone = (UInt32 *)tmp_osdata->getBytesNoCopy();
tmp_osdata = OSDynamicCast(OSData,
nub->getProperty(kDTSensorTypeKey));
if (tmp_osdata == NULL)
{
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs no types\n");
return(NULL);
}
type = (const char *)tmp_osdata->getBytesNoCopy();
tmp_osdata = OSDynamicCast(OSData,
nub->getProperty(kDTSensorLocationKey));
if (tmp_osdata == NULL)
{
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs no locations\n");
return(NULL);
}
location = (const char *)tmp_osdata->getBytesNoCopy();
tmp_osdata = OSDynamicCast(OSData,
nub->getProperty(kDTSensorPollingPeriodKey));
if (tmp_osdata != NULL)
{
polling_period = (UInt32 *)tmp_osdata->getBytesNoCopy();
DLOG("IOI2CMaxim6690::parseSensorParamsAndCreateNubs polling period %lu\n", polling_period);
}
strcpy(work, kHWSensorNubName);
tmp_osdata = OSData::withBytes(work, strlen(work) + 1);
if (tmp_osdata == NULL) return(0);
for (i=0; i<n_sensors; i++)
{
childNub = OSDynamicCast(IOService,
OSMetaClass::allocClassWithName("IOService"));
if (!childNub || !childNub->init())
continue;
childNub->attach(this);
fHWSensorIDMap[i] = id[i];
childNub->setName(kHWSensorNubName);
childNub->setProperty("name", tmp_osdata);
childNub->setProperty("compatible", tmp_osdata);
childNub->setProperty("device_type", tmp_osdata);
childNub->setProperty(kHWSensorParamsVersionKey, &version, sizeof(UInt32));
childNub->setProperty(kHWSensorIDKey, &id[i], sizeof(UInt32));
childNub->setProperty(kHWSensorZoneKey, &zone[i], sizeof(UInt32));
childNub->setProperty(kHWSensorTypeKey, type);
type += strlen(type) + 1;
childNub->setProperty(kHWSensorLocationKey, location);
location += strlen(location) + 1;
if (polling_period && polling_period[i] != kHWSensorPollingPeriodNULL)
childNub->setProperty(kHWSensorPollingPeriodKey, &polling_period[i],
sizeof(UInt32));
if (nubArray == NULL)
{
nubArray = OSArray::withObjects((const OSObject **) &childNub, 1);
}
else
{
nubArray->setObject( childNub );
}
}
tmp_osdata->release();
return(nubArray);
}
#pragma mark -
#pragma mark *** Read Temperature Channels ***
#pragma mark -
IOReturn IOI2CMaxim6690::getInternalTemp( SInt32 * temp )
{
IOReturn status;
UInt8 integer;
UInt8 fraction;
if (kIOReturnSuccess != (status = readI2C( kReadInternalTemp, &integer, 1 )))
{
IOLog("IOI2CMaxim6690::getInternalTemp read temp failed:0x%x\n", status);
}
else if (kIOReturnSuccess != (status = readI2C( kReadInternalExtTemp, &fraction, 1 )))
{
IOLog("IOI2CMaxim6690::getInternalTemp read ext temp failed:0x%x\n", status);
}
if (kIOReturnSuccess != status) *temp = -1;
else *temp = ( ( ( ( SInt8 ) integer ) << 16 ) | ( ( fraction & 0xE0 ) << 8) );
return status;
}
IOReturn IOI2CMaxim6690::getExternalTemp( SInt32 * temp )
{
IOReturn status;
UInt8 integer;
UInt8 fraction;
if (kIOReturnSuccess != (status = readI2C( kReadExternalTemp, &integer, 1 )))
{
IOLog("IOI2CMaxim6690::getExternalTemp read temp failed:0x%x\n", status);
}
else if (kIOReturnSuccess != (status = readI2C( kReadExternalExtTemp, &fraction, 1 )))
{
IOLog("IOI2CMaxim6690::getExternalTemp read ext temp failed:0x%x\n", status);
}
if (kIOReturnSuccess != status) *temp = -1;
else *temp = ( ( ( ( SInt8 ) integer ) << 16 ) | ( ( fraction & 0xE0 ) << 8) );
return status;
}