IOPMUADBController.cpp [plain text]
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/IOSyncer.h>
#include "IOPMUADBController.h"
#define super IOADBController
OSDefineMetaClassAndStructors(IOPMUADBController, IOADBController)
IOService * IOPMUADBController::probe( IOService * provider, SInt32 * score )
{
if (super::probe(provider, score) == NULL)
return NULL;
if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'") ||
IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'"))
return this;
OSData *kl = OSDynamicCast(OSData, provider->getProperty("compatible"));
if ((kl != NULL) && kl->isEqualTo("pmu", 3))
return this;
return NULL;
}
bool IOPMUADBController::start ( IOService * nub )
{
PMUdriver = waitForService(serviceMatching("ApplePMU"));
waitingForData = NULL;
if (PMUdriver->callPlatformFunction("registerForPMUInterrupts", true, (void*) (kPMUADBint | kPMUenvironmentInt), (void*)handleADBInterrupt, (void*)this, NULL) != kIOReturnSuccess) {
#ifdef VERBOSE_LOGS_ON
IOLog("IOPMUADBController::start registerForPMUInterrupts kPMUADBint fails\n");
#endif // VERBOSE_LOGS_ON
return false;
}
requestMutexLock = NULL;
requestMutexLock = IOLockAlloc();
if (!requestMutexLock)
return false;
clamshellOpen = true;
if( !super::start(nub))
return false;
return true;
}
void IOPMUADBController::free ( )
{
if (requestMutexLock != NULL) {
IOLockFree (requestMutexLock);
requestMutexLock = NULL;
}
if (PMUdriver != NULL)
PMUdriver->callPlatformFunction("deRegisterClient", true, (void*)this, (void*)(kPMUADBint | kPMUenvironmentInt), NULL, NULL);
}
IOReturn IOPMUADBController::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer)
{
IOReturn returnValue = kIOReturnError;
IOByteCount rLength = 1;
UInt8 rBuffer;
SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, &rLength, &rBuffer};
#ifdef VERBOSE_LOGS_ON
IOLog("ApplePMUInterface::localSendMiscCommand 0x%02x %d 0x%08lx 0x%08lx 0x%08lx\n",
command, sLength, sBuffer, rLength, rBuffer);
#endif
if (PMUdriver != NULL) {
#ifdef VERBOSE_LOGS_ON
IOLog("IOPMUADBController::localSendMiscCommand calling PMUdriver->callPlatformFunction\n");
#endif
returnValue = PMUdriver->callPlatformFunction("sendMiscCommand", true, (void*)&prmBlock, NULL, NULL, NULL);
}
#ifdef VERBOSE_LOGS_ON
IOLog("IOPMUADBController::localSendMiscCommand end 0x%08lx\n", returnValue);
#endif
return returnValue;
}
void
IOPMUADBController::handleADBInterrupt(IOService *client, UInt8 interruptMask, UInt32 length, UInt8 *buffer)
{
IOPMUADBController *myThis = OSDynamicCast(IOPMUADBController, client);
if (myThis == NULL)
return;
if (interruptMask & kPMUenvironmentInt)
{
if (buffer)
{
if (*buffer & kClamshellClosedEventMask)
myThis->clamshellOpen = false;
else
myThis->clamshellOpen = true;
}
if ( !(interruptMask & kPMUautopoll))
{
return; }
}
if ((interruptMask & kPMUautopoll) && (myThis->autopollOn))
{
if (myThis->clamshellOpen)
{
autopollHandler(client, buffer[0], length - 1, buffer + 1); }
else if ( (buffer[0] == 0x2c) && (buffer[1] == 0x7f) && (buffer[2] == 0x7f))
{
autopollHandler(client, buffer[0], length - 1, buffer + 1); }
else if ( (buffer[0] == 0x2c) && (buffer[1] == 0xff) && (buffer[2] == 0xff))
{
autopollHandler(client, buffer[0], length - 1, buffer + 1); }
}
else {
if (myThis->waitingForData != NULL) {
myThis->dataLen = length - 1;
bcopy(buffer + 1, myThis->dataBuffer, myThis->dataLen);
myThis->waitingForData->signal();
}
}
}
IOReturn IOPMUADBController::cancelAllIO ( void )
{
if (waitingForData != NULL) {
dataLen = 0; waitingForData->signal();
}
return kPMUNoError;
}
IOReturn IOPMUADBController::setAutoPollPeriod ( int )
{
return kPMUNotSupported;
}
IOReturn IOPMUADBController::getAutoPollPeriod ( int * )
{
return kPMUNotSupported;
}
IOReturn IOPMUADBController::setAutoPollList ( UInt16 PollBitField )
{
if (requestMutexLock != NULL)
IOLockLock(requestMutexLock);
pollList = PollBitField;
if ( autopollOn ) {
UInt8 oBuffer[4];
oBuffer[0] = 0; oBuffer[1] = 0x86; oBuffer[2] = (UInt8)(PollBitField >> 8); oBuffer[3] = (UInt8)(PollBitField & 0xff);
localSendMiscCommand (kPMUpMgrADB, 4, oBuffer);
}
if (requestMutexLock != NULL)
IOLockUnlock(requestMutexLock);
return kPMUNoError;
}
IOReturn IOPMUADBController::getAutoPollList ( UInt16 * activeAddressMask )
{
*activeAddressMask = pollList;
return kPMUNoError;
}
IOReturn IOPMUADBController::setAutoPollEnable ( bool enable )
{
UInt8 oBuffer[4];
if (requestMutexLock != NULL)
IOLockLock(requestMutexLock);
autopollOn = enable;
if ( enable ) { oBuffer[0] = 0;
oBuffer[1] = 0x86;
oBuffer[2] = (UInt8)(pollList >> 8);
oBuffer[3] = (UInt8)(pollList & 0xff);
localSendMiscCommand (kPMUpMgrADB, 4, oBuffer);
}
else {
if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'") ||
IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'"))
IOSleep(1500);
localSendMiscCommand (kPMUpMgrADBoff, 0, NULL);
}
if (requestMutexLock != NULL)
IOLockUnlock(requestMutexLock);
return kPMUNoError;
}
IOReturn IOPMUADBController::resetBus ( void )
{
if (requestMutexLock != NULL)
IOLockLock(requestMutexLock);
UInt8 oBuffer[4];
oBuffer[0] = kPMUResetADBBus;
oBuffer[1] = 0;
oBuffer[2] = 0;
waitingForData = IOSyncer::create();
localSendMiscCommand (kPMUpMgrADB, 3, oBuffer);
waitingForData->wait(); waitingForData = 0;
if (requestMutexLock != NULL)
IOLockUnlock(requestMutexLock);
if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'") ||
IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'"))
IOSleep(1500);
return kPMUNoError;
}
IOReturn IOPMUADBController::flushDevice ( IOADBAddress address )
{
if (requestMutexLock != NULL)
IOLockLock(requestMutexLock);
UInt8 oBuffer[4];
oBuffer[0] = kPMUFlushADB | (address << kPMUADBAddressField);
oBuffer[1] = ( autopollOn ? 2 : 0 );
oBuffer[2] = 0;
waitingForData = IOSyncer::create();
localSendMiscCommand (kPMUpMgrADB, 3, oBuffer);
waitingForData->wait(); waitingForData = 0;
if (requestMutexLock != NULL)
IOLockUnlock(requestMutexLock);
return kPMUNoError;
}
IOReturn IOPMUADBController::readFromDevice ( IOADBAddress address, IOADBRegister adbRegister,
UInt8 * data, IOByteCount * length )
{
if ( (length == NULL) || (data == NULL) ) {
return kPMUParameterError;
}
if (requestMutexLock != NULL)
IOLockLock(requestMutexLock);
UInt8 oBuffer[4];
oBuffer[0] = kPMUReadADB | (address << kPMUADBAddressField) | (adbRegister);
oBuffer[1] = ( autopollOn ? 2 : 0 );
oBuffer[2] = 0;
waitingForData = IOSyncer::create();
localSendMiscCommand (kPMUpMgrADB, 3, oBuffer);
waitingForData->wait(); waitingForData = 0;
*length = (dataLen < *length ? dataLen : *length);
bcopy(dataBuffer, data, *length);
if (requestMutexLock != NULL)
IOLockUnlock(requestMutexLock);
if (dataLen == 0 ) { return ADB_RET_NOTPRESENT;
}
return ADB_RET_OK;
}
IOReturn IOPMUADBController::writeToDevice ( IOADBAddress address, IOADBRegister adbRegister,
UInt8 * data, IOByteCount * length )
{
if ( (* length == 0) || (data == NULL) || (* length > 252) )
{
return kPMUParameterError;
}
if (address == 0)
return kPMUNoError;
if (requestMutexLock != NULL)
IOLockLock(requestMutexLock);
UInt8 oBuffer[256];
oBuffer[0] = kPMUWriteADB | (address << kPMUADBAddressField) | (adbRegister);
oBuffer[1] = ( autopollOn ? 2 : 0 );
oBuffer[2] = *length;
bcopy(data, &oBuffer[3], *length);
waitingForData = IOSyncer::create();
localSendMiscCommand (kPMUpMgrADB, 3 + *length, oBuffer);
waitingForData->wait();
waitingForData = 0;
if (requestMutexLock != NULL)
IOLockUnlock(requestMutexLock);
return kPMUNoError;
}