IOI2CController.cpp [plain text]
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/pwr_mgt/IOPMPrivate.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOLocks.h>
#include <IOKit/IOUserClient.h>
#include "IOI2CController.h"
#include "IOI2CService.h"
#include "IOI2CDefs.h"
#if (defined(I2C_DEBUG) && I2C_DEBUG)
#define DLOG(fmt, args...) IOLog(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
#define I2C_ERRLOG 1
#if (defined(I2C_ERRLOG) && I2C_ERRLOG)
#define ERRLOG(fmt, args...) do{IOLog(fmt, ## args);kprintf(fmt, ## args);}while(0)
#else
#define ERRLOG(fmt, args...)
#endif
#define I2C_DLOGPWR 1
#if (defined(I2C_DLOGPWR) && I2C_DLOGPWR)
#define DLOGPWR(fmt, args...) kprintf(fmt, ## args)
#else
#define DLOGPWR(fmt, args...)
#endif
#define I2C_DEBUG_VERBOSE 1
#if (defined(I2C_DEBUG_VERBOSE) && I2C_DEBUG_VERBOSE)
#define DLOGI2C(opt, fmt, args...) do{if(opt&kI2COption_VerboseLog)kprintf(fmt, ## args);}while(0)
#else
#define DLOGI2C(opt, fmt, args...)
#endif
#ifdef kUSE_IOLOCK
#define I2CLOCK IOLockLock(fClientLock)
#define I2CUNLOCK {IOLockUnlock(fClientLock);IOSleep(0);}
#else
#define I2CLOCK semaphore_wait(fClientSem)
#define I2CUNLOCK semaphore_signal(fClientSem)
#endif
#pragma mark
#pragma mark *** IOI2CController class ***
#pragma mark
#define super IOService
OSDefineMetaClassAndAbstractStructors( IOI2CController, IOService )
bool
IOI2CController::start(
IOService *provider)
{
IOReturn status;
OSData *data;
DLOG("+IOI2CController::start\n");
if (false == super::start(provider))
{
ERRLOG("-IOI2CController::start super::start failed\n");
return false;
}
fProvider = provider;
if (kIOReturnSuccess != (status = initI2CResources()))
{
ERRLOG("-IOI2CController::start initI2CResources returned: 0x%lx\n", (UInt32)status);
freeI2CResources();
return false;
}
if (data = OSDynamicCast(OSData, provider->getProperty("max-i2c-data-length")))
fMaxI2CDataLength = *((UInt32*)data->getBytesNoCopy());
else
fMaxI2CDataLength = 4;
if (data = OSDynamicCast(OSData, provider->getProperty("AAPL,i2c-bus")))
{
fI2CBus = *((UInt32*)data->getBytesNoCopy()); DLOG("IOI2CController::start found \"AAPL,i2c-bus\" property:0x%lx\n",fI2CBus);
}
else
fI2CBus = kIOI2CMultiBusID;
if (fDisablePowerManagement)
{
OSIterator *busIter, *devIter;
IORegistryEntry *bus, *dev;
if (busIter = fProvider->getChildIterator(gIODTPlane))
{
while (bus = OSDynamicCast(IORegistryEntry, busIter->getNextObject()))
{
if (devIter = bus->getChildIterator(gIODTPlane))
{
while (dev = OSDynamicCast(IORegistryEntry, devIter->getNextObject()))
dev->setProperty("AAPL,no-power", true);
devIter->release();
}
}
busIter->release();
}
DLOGPWR("Controller Is Usable\n-------------------------------\n");
fDeviceIsUsable = TRUE;
}
else
InitializePowerManagement();
DLOG("-IOI2CController::start\n");
return true;
}
void
IOI2CController::stop (
IOService *provider)
{
DLOG("IOI2CController::stop\n");
fDeviceIsUsable = FALSE;
if (initialized)
PMstop();
if (fIOSyncThreadCall)
{
thread_call_cancel(fIOSyncThreadCall);
thread_call_free(fIOSyncThreadCall);
fIOSyncThreadCall = 0;
}
super::stop(provider);
}
void IOI2CController::free ( void )
{
freeI2CResources();
super::free();
}
#pragma mark
#pragma mark *** I2C resource init and cleanup... ***
#pragma mark
IOReturn
IOI2CController::initI2CResources(void)
{
symLockI2CBus = OSSymbol::withCStringNoCopy(kLockI2Cbus);
symUnlockI2CBus = OSSymbol::withCStringNoCopy(kUnlockI2Cbus);
symWriteI2CBus = OSSymbol::withCStringNoCopy(kWriteI2Cbus);
symReadI2CBus = OSSymbol::withCStringNoCopy(kReadI2Cbus);
symPowerInterest = OSSymbol::withCStringNoCopy("IOI2CPowerStateInterest");
symPowerClient = OSSymbol::withCStringNoCopy("client");
symPowerAcked = OSSymbol::withCStringNoCopy("acked");
symGetMaxI2CDataLength = OSSymbol::withCStringNoCopy(kIOI2CGetMaxI2CDataLength);
if (!symLockI2CBus || !symUnlockI2CBus || !symWriteI2CBus || !symReadI2CBus ||
!symPowerInterest || !symPowerClient || !symPowerAcked || !symGetMaxI2CDataLength)
return kIOReturnNoMemory;
#ifdef kUSE_IOLOCK
if (NULL == (fClientLock = IOLockAlloc()))
return kIOReturnNoMemory;
#else
IOReturn status;
if (kIOReturnSuccess != (status = semaphore_create(current_task(), (semaphore**)&fClientSem, SYNC_POLICY_FIFO, 1)))
return status;
#endif
if (NULL == (fPowerLock = IOLockAlloc()))
return kIOReturnNoMemory;
fClientLockKey = kIOI2C_CLIENT_KEY_VALID;
return kIOReturnSuccess;
}
void
IOI2CController::freeI2CResources(void)
{
fDeviceIsUsable = FALSE;
if (initialized)
PMstop();
if (fIOSyncThreadCall)
{
thread_call_cancel(fIOSyncThreadCall);
thread_call_free(fIOSyncThreadCall);
fIOSyncThreadCall = 0;
}
if (fPowerLock) { IOLockFree(fPowerLock); fPowerLock = 0; }
#ifdef kUSE_IOLOCK
if (fClientLock) { IOLockFree(fClientLock); fClientLock = 0; }
#else
if (fClientSem) { semaphore_destroy(current_task(), fClientSem); fClientSem = 0; }
#endif
if (symLockI2CBus) { symLockI2CBus->release(); symLockI2CBus = 0; }
if (symUnlockI2CBus) { symUnlockI2CBus->release(); symUnlockI2CBus = 0; }
if (symWriteI2CBus) { symWriteI2CBus->release(); symWriteI2CBus = 0; }
if (symReadI2CBus) { symReadI2CBus->release(); symReadI2CBus = 0; }
if (symPowerInterest) { symPowerInterest->release(); symPowerInterest = 0; }
if (symPowerClient) { symPowerClient->release(); symPowerClient = 0; }
if (symPowerAcked) { symPowerAcked->release(); symPowerAcked = 0; }
if (symGetMaxI2CDataLength) { symGetMaxI2CDataLength->release(); symGetMaxI2CDataLength = 0; }
}
IOReturn
IOI2CController::publishChildren(void)
{
OSIterator *iter;
IORegistryEntry *next;
IOService *nub;
if (iter = fProvider->getChildIterator(gIODTPlane))
{
while (next = OSDynamicCast(IORegistryEntry, iter->getNextObject()))
{
if (nub = new IOI2CService) {
if (nub->init(next, gIODTPlane))
{
nub->attach(this);
nub->registerService();
}
else
nub->free();
}
}
iter->release();
}
return kIOReturnSuccess;
}
#pragma mark
#pragma mark *** Power Management ***
#pragma mark
IOReturn
IOI2CController::InitializePowerManagement(void)
{
IOReturn status;
static const IOPMPowerState ourPowerStates[kIOI2CPowerState_COUNT] =
{
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, kIOPMSleepCapability, kIOPMSleep, kIOPMSleep, 0, 0, 0, 0, 0, 0, 0, 0},
{1, kIOPMDeviceUsable, kIOPMDoze, kIOPMDoze, 0, 0, 0, 0, 0, 0, 0, 0},
{1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
};
PMinit();
fProvider->joinPMtree( this);
if (kIOReturnSuccess != (status = registerPowerDriver( this, (IOPMPowerState *) ourPowerStates, kIOI2CPowerState_COUNT )))
{
ERRLOG("%s Failed to registerPowerDriver.\n", getName());
return status;
}
changePowerStateTo(kIOI2CPowerState_ON);
if (NULL == (fIOSyncThreadCall = thread_call_allocate(&IOI2CController::sIOSyncCallback, (thread_call_param_t) this)))
return kIOReturnNoResources;
if (NULL == registerPrioritySleepWakeInterest(&sSysPowerDownHandler, this))
return kIOReturnNoResources;
return kIOReturnSuccess;
}
IOReturn
IOI2CController::setPowerState(
unsigned long newPowerState,
IOService *target)
{
DLOGPWR("\n----set power------------------\n");
DLOGPWR("IOI2CController::setPowerState called with state:%lu\n", newPowerState);
if (fCurrentPowerState == newPowerState)
return IOPMAckImplied;
switch (newPowerState)
{
case kIOI2CPowerState_ON:
case kIOI2CPowerState_DOZE:
DLOGPWR("Controller Is Usable\n-------------------------------\n");
fDeviceIsUsable = TRUE;
break;
case kIOI2CPowerState_SLEEP:
case kIOI2CPowerState_OFF:
fDeviceIsUsable = FALSE;
DLOGPWR("Controller Is Unusable\n-------------------------------\n");
break;
}
fCurrentPowerState = newPowerState;
return IOPMAckImplied;
}
IOReturn
IOI2CController::sSysPowerDownHandler(
void *target,
void *refCon,
UInt32 messageType,
IOService *service,
void *messageArgument,
vm_size_t argSize)
{
IOReturn status = kIOReturnUnsupported;
IOPowerStateChangeNotification *params;
IOI2CController *self;
DLOGPWR("\n---------------------------------------------------------------------------------------------\n");
if (self = OSDynamicCast(IOI2CController, (OSMetaClassBase *)target))
{
switch (messageType)
{
case kIOMessageSystemWillSleep: break;
case kIOMessageSystemWillPowerOff: case kIOMessageSystemWillRestart: DLOGPWR("IOI2CController::sSysPowerDownHandler System will %s\n",
(messageType == kIOMessageSystemWillPowerOff)?"Power off":"Restart");
if (params = (IOPowerStateChangeNotification *) messageArgument)
{
params->returnValue = 20 * 1000 * 1000;
thread_call_enter1(self->fIOSyncThreadCall, (thread_call_param_t)params->powerRef);
IOSleep(10);
status = kIOReturnSuccess;
}
break;
default:
DLOG("IOI2CController::sSysPowerDownHandler called with 0x%lx\n", messageType);
status = kIOReturnUnsupported;
break;
}
}
return status;
}
void
IOI2CController::sIOSyncCallback(
thread_call_param_t p0,
thread_call_param_t pmRef)
{
IOI2CController *self;
DLOGPWR("IOI2CController::sIOSyncCallback - ENTERED\n");
if (self = OSDynamicCast(IOI2CController, (OSMetaClassBase *)p0))
{
self->notifyPowerStateInterest();
self->fDeviceIsUsable = FALSE; DLOGPWR("IOI2CController::sIOSyncCallback OFFLINE\n-----------------------------\n");
}
DLOGPWR("IOI2CController::sIOSyncCallback - DONE\n");
acknowledgeSleepWakeNotification(pmRef);
}
#pragma mark
#pragma mark *** External Client Interface Methods ***
#pragma mark
IOReturn
IOI2CController::newUserClient(
task_t owningTask,
void *securityID,
UInt32 type,
OSDictionary *properties,
IOUserClient **handler)
{
DLOG("%s::newUserClient\n", getName());
if (IOUserClient::clientHasPrivilege(securityID, "root") != kIOReturnSuccess)
{
ERRLOG("%s::newUserClient: Can't create user client, not privileged\n", getName());
return kIOReturnNotPrivileged;
}
if (type != kIOI2CUserClientType)
return kIOReturnUnsupported;
return super::newUserClient(owningTask, securityID, type, properties, handler);
}
IOReturn
IOI2CController::callPlatformFunction(
const OSSymbol *functionName,
bool waitForFunction,
void *param1,
void *param2,
void *param3,
void *param4)
{
if (symReadI2CBus->isEqualTo(functionName))
return clientReadI2C((IOI2CCommand *)param1, (UInt32)param2);
else
if (symWriteI2CBus->isEqualTo(functionName))
return clientWriteI2C((IOI2CCommand *)param1, (UInt32)param2);
else
if (symLockI2CBus->isEqualTo(functionName))
return clientLockI2C((UInt32)param1, (UInt32 *)param2);
else
if (symUnlockI2CBus->isEqualTo(functionName))
return clientUnlockI2C((UInt32)param1, (UInt32)param2);
else
if (symPowerInterest->isEqualTo(functionName))
return registerPowerStateInterest((IOService *)param1, (bool)param2); else
if (symGetMaxI2CDataLength->isEqualTo(functionName))
{
if (param1 == 0)
return kIOReturnBadArgument;
*(UInt32 *)param1 = fMaxI2CDataLength;
return kIOReturnSuccess;
}
return super::callPlatformFunction (functionName, waitForFunction, param1, param2, param3, param4);
}
IOReturn
IOI2CController::registerPowerStateInterest(
IOService *client,
bool isRegistering)
{
IOReturn status = kIOReturnSuccess;
OSArray *array;
OSDictionary *dict;
IOLockLock(fPowerLock);
if (0 == (array = (OSArray *) getProperty( symPowerInterest )))
{
array = OSArray::withCapacity( 1 );
if (array)
{
setProperty( symPowerInterest, array );
array->release();
}
}
if (isRegistering == false)
{
status = kIOReturnNotFound;
if (array)
{
int i, count = array->getCount();
for (i = 0; i < count; i++)
{
if (dict = OSDynamicCast(OSDictionary, array->getObject( i )))
{
if (client == OSDynamicCast(IOService, dict->getObject(symPowerClient)))
{
dict->removeObject(symPowerClient);
dict->removeObject(symPowerAcked);
array->removeObject(i);
status = kIOReturnSuccess;
break;
}
}
}
}
}
else
if (array)
{
dict = OSDictionary::withCapacity( 1 );
if (dict)
{
dict->setObject(symPowerClient, client);
dict->setObject(symPowerAcked, kOSBooleanFalse);
array->setObject( dict );
dict->release(); }
else
status = kIOReturnNoMemory;
}
else
status = kIOReturnNoMemory;
IOLockUnlock(fPowerLock);
return status;
}
bool
IOI2CController::notifyPowerStateInterest(void)
{
OSArray *array;
OSDictionary *dict;
IOService *client;
int i, count;
bool allAcked = true;
array = OSDynamicCast(OSArray , getProperty(symPowerInterest));
if (array)
{
count = array->getCount();
for (i = 0; i < count; i++)
{
if (dict = OSDynamicCast(OSDictionary, array->getObject( i )))
{
dict->setObject(symPowerAcked, kOSBooleanFalse);
if (client = OSDynamicCast(IOService, dict->getObject(symPowerClient)))
{
if (kIOReturnSuccess != client->message(0x1012c, this, 0))
{
IOLockLock(fPowerLock);
dict->setObject(symPowerAcked, kOSBooleanTrue);
IOLockUnlock(fPowerLock);
}
}
}
}
AbsoluteTime currentTime, endTime;
clock_interval_to_deadline(15, kSecondScale, &endTime);
DLOGPWR("IOI2CController waiting for %d acks\n", count);
for (;;)
{
allAcked = true;
IOSleep(5);
for (i = 0; i < count; i++)
{
if (dict = OSDynamicCast(OSDictionary, array->getObject( i )))
{
if (kOSBooleanTrue != OSDynamicCast(OSBoolean, dict->getObject(symPowerAcked)))
{
allAcked = false;
break;
}
}
}
if (allAcked == true)
break;
clock_get_uptime(¤tTime);
if ( CMP_ABSOLUTETIME(¤tTime, &endTime) > 0 )
{
ERRLOG("IOI2CController::notifyPowerStateInterest timed out waiting for acks\n");
break;
}
}
}
return allAcked;
}
IOReturn
IOI2CController::acknowledgeNotification(
IONotificationRef notification,
IOOptionBits response )
{
OSArray *array;
OSDictionary *dict;
int i, count;
IOService *target;
IOService *client;
if (target = OSDynamicCast(IOService, (OSMetaClassBase *)notification))
{
array = OSDynamicCast(OSArray , getProperty(symPowerInterest));
if (array)
{
count = array->getCount();
for (i = 0; i < count; i++)
{
if (dict = OSDynamicCast(OSDictionary, array->getObject( i )))
{
if (client = OSDynamicCast(IOService, dict->getObject(symPowerClient)))
{
if (client == target)
{
#if I2C_DLOGPWR
const char *name;
DLOGPWR("IOI2CController::acknowledgeNotification from %s\n", (name = client->getName())?name:"???");
#endif
dict->setObject(symPowerAcked, kOSBooleanTrue);
break;
}
}
}
}
}
}
return kIOReturnSuccess;
}
#pragma mark
#pragma mark *** IOI2C Transaction Methods ***
#pragma mark
IOReturn
IOI2CController::clientReadI2C(
IOI2CCommand *cmd,
UInt32 clientKey)
{
IOReturn status = kIOReturnSuccess;
int retries;
AbsoluteTime currentTime, endTime;
if (cmd == NULL)
return kIOReturnBadArgument;
if (fI2CBus != kIOI2CMultiBusID)
cmd->bus = fI2CBus;
if (fDeviceIsUsable == FALSE)
{
ERRLOG("-IOI2CController::clientReadI2C No Power\n");
status = kIOReturnNoPower;
}
else
if (clientKey == kIOI2C_CLIENT_KEY_DEFAULT)
{
if (kIOReturnSuccess == (status = clientLockI2C(cmd->bus, &clientKey)))
{
status = clientReadI2C(cmd, clientKey);
clientUnlockI2C(cmd->bus, clientKey);
}
}
else
if (fClientLockKey != clientKey)
{
ERRLOG("-IOI2CController::clientReadI2C invalid key\n");
status = kIOReturnNotOpen;
}
else
{
if ((cmd->buffer == 0) ^ (cmd->count == 0))
{
ERRLOG("-IOI2CController::clientReadI2C bad buffer:%x length:%lx argument combination\n", (int)cmd->buffer, cmd->count);
return kIOReturnBadArgument;
}
if (cmd->timeout_uS)
clock_interval_to_deadline(cmd->timeout_uS, kMicrosecondScale, &endTime);
for (retries = (int)cmd->retries; retries >= 0; retries--)
{
fTransactionInProgress = TRUE;
DLOGI2C((cmd->options), "IOI2CController::clientReadI2C cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx\n",
clientKey, cmd->bus, cmd->address, cmd->subAddress, cmd->count, cmd->mode);
status = processReadI2CBus (cmd);
if (status)
{
ERRLOG("IOI2CController::clientReadI2C cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx status:0x%x\n",
clientKey, cmd->bus, cmd->address, cmd->subAddress, cmd->count, cmd->mode, status);
}
else
{
DLOGI2C((cmd->options), "IOI2CController::clientReadI2C cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx status:0x%x\n",
clientKey, cmd->bus, cmd->address, cmd->subAddress, cmd->count, cmd->mode, status);
}
fTransactionInProgress = FALSE;
if (status == kIOReturnSuccess)
break;
if (fDeviceIsUsable == FALSE)
{
status = kIOReturnOffline;
break;
}
if (cmd->timeout_uS)
{
clock_get_uptime(¤tTime);
if ( CMP_ABSOLUTETIME(¤tTime, &endTime) > 0 )
{
status = kIOReturnTimeout;
break;
}
}
DLOG("IOI2CController::clientReadI2C retry:%lu status:0x%08x\n", cmd->retries - retries, status);
}
if (status)
ERRLOG("-IOI2CController::clientReadI2C status = 0x%08x\n", status);
}
return status;
}
IOReturn
IOI2CController::clientWriteI2C(
IOI2CCommand *cmd,
UInt32 clientKey)
{
IOReturn status = kIOReturnSuccess;
int retries;
if (cmd == NULL)
return kIOReturnBadArgument;
if (fI2CBus != kIOI2CMultiBusID)
cmd->bus = fI2CBus;
if (fDeviceIsUsable == FALSE)
{
ERRLOG("-IOI2CController::clientWriteI2C No Power\n");
status = kIOReturnNoPower;
}
else
if (clientKey == kIOI2C_CLIENT_KEY_DEFAULT)
{
if (kIOReturnSuccess == (status = clientLockI2C(cmd->bus, &clientKey)))
{
status = clientWriteI2C(cmd, clientKey);
clientUnlockI2C(cmd->bus, clientKey);
}
}
else
if (clientKey != fClientLockKey)
{
ERRLOG("-IOI2CController::clientWriteI2C invalid key\n");
status = kIOReturnNotOpen;
}
else
{
if ((cmd->buffer == 0) ^ (cmd->count == 0))
{
ERRLOG("-IOI2CController::clientWriteI2C bad buffer:%lx length:%lx argument combination (B:%lx, A:%lx S:%lx)\n", (UInt32)cmd->buffer, cmd->count,
cmd->bus, cmd->address, cmd->subAddress);
return kIOReturnBadArgument;
}
AbsoluteTime currentTime, endTime;
if (cmd->timeout_uS)
clock_interval_to_deadline(cmd->timeout_uS, kMicrosecondScale, &endTime);
for (retries = (int)cmd->retries; retries >= 0; retries--)
{
fTransactionInProgress = TRUE;
DLOGI2C((cmd->options), "IOI2CController::clientWriteI2C cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx\n",
clientKey, cmd->bus, cmd->address, cmd->subAddress, cmd->count, cmd->mode);
status = processWriteI2CBus (cmd);
if (status)
{
ERRLOG("IOI2CController::clientWriteI2C cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx status:0x%x\n",
clientKey, cmd->bus, cmd->address, cmd->subAddress, cmd->count, cmd->mode, status);
}
else
{
DLOGI2C((cmd->options), "IOI2CController::clientWriteI2C cmd key:%lx, B:%lx, A:%lx S:%lx, L:%lx, M:%lx status:0x%x\n",
clientKey, cmd->bus, cmd->address, cmd->subAddress, cmd->count, cmd->mode, status);
}
fTransactionInProgress = FALSE;
if (status == kIOReturnSuccess)
break;
if (fDeviceIsUsable == FALSE)
{
status = kIOReturnOffline;
break;
}
if (cmd->timeout_uS)
{
clock_get_uptime(¤tTime);
if ( CMP_ABSOLUTETIME(¤tTime, &endTime) > 0 )
{
status = kIOReturnTimeout;
break;
}
}
DLOG("IOI2CController::clientWriteI2C retry:%lu status:0x%08x\n", cmd->retries - retries, status);
}
if (status)
ERRLOG("-IOI2CController::clientWriteI2C status = 0x%08x\n", status);
}
return status;
}
IOReturn
IOI2CController::clientLockI2C(
UInt32 bus,
UInt32 *clientKeyRef)
{
IOReturn status;
if (clientKeyRef == NULL)
{
ERRLOG("IOI2CController::clientLockI2C invalid key ref\n");
return kIOReturnBadArgument;
}
if (fDeviceIsUsable == FALSE)
{
ERRLOG("IOI2CController::clientLockI2C fDeviceIsUsable==0\n");
return kIOReturnNoPower;
}
I2CLOCK;
if (fDeviceIsUsable == FALSE)
{
ERRLOG("IOI2CController::clientLockI2C cancel fDeviceIsUsable==0\n");
I2CUNLOCK;
return kIOReturnNoPower;
}
if (fI2CBus != kIOI2CMultiBusID)
bus = fI2CBus;
status = processLockI2CBus(bus);
if (kIOReturnSuccess != status) {
ERRLOG("IOI2CController::clientLockI2C LockBus failed:0x%lx\n", (UInt32)status);
I2CUNLOCK;
return status;
}
if (++fClientLockKey >= kIOI2C_CLIENT_KEY_RESERVED)
fClientLockKey = kIOI2C_CLIENT_KEY_VALID | kIOI2C_CLIENT_KEY_LOCKED;
*clientKeyRef = fClientLockKey;
return status;
}
IOReturn
IOI2CController::clientUnlockI2C(
UInt32 bus,
UInt32 clientKey)
{
IOReturn status;
if (fClientLockKey != clientKey)
{
ERRLOG("IOI2CController::clientUnlockI2C invalid key\n");
return kIOReturnExclusiveAccess;
}
if (0 == (fClientLockKey & kIOI2C_CLIENT_KEY_LOCKED))
{
ERRLOG("IOI2CController::clientUnlockI2C not locked\n");
return kIOReturnNotOpen;
}
if (fI2CBus != kIOI2CMultiBusID)
bus = fI2CBus;
status = processUnlockI2CBus(bus);
++fClientLockKey;
I2CUNLOCK;
return status;
}
OSMetaClassDefineReservedUnused ( IOI2CController, 0 );
OSMetaClassDefineReservedUnused ( IOI2CController, 1 );
OSMetaClassDefineReservedUnused ( IOI2CController, 2 );
OSMetaClassDefineReservedUnused ( IOI2CController, 3 );
OSMetaClassDefineReservedUnused ( IOI2CController, 4 );
OSMetaClassDefineReservedUnused ( IOI2CController, 5 );
OSMetaClassDefineReservedUnused ( IOI2CController, 6 );
OSMetaClassDefineReservedUnused ( IOI2CController, 7 );
OSMetaClassDefineReservedUnused ( IOI2CController, 8 );
OSMetaClassDefineReservedUnused ( IOI2CController, 9 );
OSMetaClassDefineReservedUnused ( IOI2CController, 10 );
OSMetaClassDefineReservedUnused ( IOI2CController, 11 );
OSMetaClassDefineReservedUnused ( IOI2CController, 12 );
OSMetaClassDefineReservedUnused ( IOI2CController, 13 );
OSMetaClassDefineReservedUnused ( IOI2CController, 14 );
OSMetaClassDefineReservedUnused ( IOI2CController, 15 );