IOPlatformFunction.cpp [plain text]
#include "IOPlatformFunction.h"
#define kCommandDescTerminator 0
static SInt32 gCommandCommandListDesc[] = { kCommandCommandListLength, kCommandDescTerminator };
static SInt32 gCommandWriteGPIODesc[] = { kCommandWriteGPIOLength, kCommandDescTerminator };
static SInt32 gCommandReadGPIODesc[] = { kCommandReadGPIOLength, kCommandDescTerminator };
static SInt32 gCommandWriteReg32Desc[] = { kCommandWriteReg32Length, kCommandDescTerminator };
static SInt32 gCommandReadReg32Desc[] = { kCommandReadReg32Length, kCommandDescTerminator };
static SInt32 gCommandWriteReg16Desc[] = { kCommandWriteReg16Length, kCommandDescTerminator };
static SInt32 gCommandReadReg16Desc[] = { kCommandReadReg16Length, kCommandDescTerminator };
static SInt32 gCommandWriteReg8Desc[] = { kCommandWriteReg8Length, kCommandDescTerminator };
static SInt32 gCommandReadReg8Desc[] = { kCommandReadReg8Length, kCommandDescTerminator };
static SInt32 gCommandDelayDesc[] = { kCommandDelayLength, kCommandDescTerminator };
static SInt32 gCommandWaitReg32Desc[] = { kCommandWaitReg32Length, kCommandDescTerminator };
static SInt32 gCommandWaitReg16Desc[] = { kCommandWaitReg16Length, kCommandDescTerminator };
static SInt32 gCommandWaitReg8Desc[] = { kCommandWaitReg8Length, kCommandDescTerminator };
static SInt32 gCommandReadI2CDesc[] = { kCommandReadI2CLength, kCommandDescTerminator };
static SInt32 gCommandWriteI2CDesc[] = { -kCommandWriteI2CLength, 4, -1, kCommandDescTerminator };
static SInt32 gCommandRMWI2CDesc[] = { -kCommandRMWI2CLength, 4, 4, 4, -1, -2, kCommandDescTerminator };
static SInt32 gCommandGeneralI2CDesc[] = { kCommandGeneralI2CLength, kCommandDescTerminator };
static SInt32 gCommandShiftBytesRightDesc[] = { kCommandShiftBytesRightLength, kCommandDescTerminator };
static SInt32 gCommandShiftBytesLeftDesc[] = { kCommandShiftBytesLeftLength, kCommandDescTerminator };
static SInt32 gCommandReadConfigDesc[] = { kCommandReadConfigLength, kCommandDescTerminator };
static SInt32 gCommandWriteConfigDesc[] = { -kCommandWriteConfigLength, 4, 4, -2, kCommandDescTerminator };
static SInt32 gCommandRMWConfigDesc[] = { -kCommandRMWConfigLength, 4, 4, 4, 4, -2, -3, kCommandDescTerminator };
static SInt32 gCommandReadI2CSubAddrDesc[] = { kCommandReadI2CSubAddrLength, kCommandDescTerminator };
static SInt32 gCommandWriteI2CSubAddrDesc[] = { -kCommandWriteI2CSubAddrLength, 4, 4, -2, kCommandDescTerminator };
static SInt32 gCommandI2CModeDesc[] = { kCommandI2CModeLength, kCommandDescTerminator };
static SInt32 gCommandRMWI2CSubAddrDesc[] = { -kCommandRMWI2CSubAddrLength, 4, 4, 4, 4, -2, -3, kCommandDescTerminator };
static SInt32 gCommandReadReg32MaskShRtXORDesc[] = { kCommandReadReg32MaskShRtXORLength, kCommandDescTerminator };
static SInt32 gCommandReadReg16MaskShRtXORDesc[] = { kCommandReadReg16MaskShRtXORLength, kCommandDescTerminator };
static SInt32 gCommandReadReg8MaskShRtXORDesc[] = { kCommandReadReg8MaskShRtXORLength, kCommandDescTerminator };
static SInt32 gCommandWriteReg32ShLtMaskDesc[] = { kCommandWriteReg32ShLtMaskLength, kCommandDescTerminator };
static SInt32 gCommandWriteReg16ShLtMaskDesc[] = { kCommandWriteReg16ShLtMaskLength, kCommandDescTerminator };
static SInt32 gCommandWriteReg8ShLtMaskDesc[] = { kCommandWriteReg8ShLtMaskLength, kCommandDescTerminator };
static SInt32 gCommandMaskandCompareDesc[] = { -kCommandMaskandCompareLength, 4, -1, -1, kCommandDescTerminator };
static SInt32 *gCommandArray[] = {
gCommandCommandListDesc, gCommandWriteGPIODesc, gCommandReadGPIODesc, gCommandWriteReg32Desc, gCommandReadReg32Desc, gCommandWriteReg16Desc, gCommandReadReg16Desc, gCommandWriteReg8Desc, gCommandReadReg8Desc, gCommandDelayDesc, gCommandWaitReg32Desc, gCommandWaitReg16Desc, gCommandWaitReg8Desc, gCommandReadI2CDesc, gCommandWriteI2CDesc, gCommandRMWI2CDesc, gCommandGeneralI2CDesc, gCommandShiftBytesRightDesc, gCommandShiftBytesLeftDesc, gCommandReadConfigDesc, gCommandWriteConfigDesc, gCommandRMWConfigDesc, gCommandReadI2CSubAddrDesc, gCommandWriteI2CSubAddrDesc, gCommandI2CModeDesc, gCommandRMWI2CSubAddrDesc, gCommandReadReg32MaskShRtXORDesc, gCommandReadReg16MaskShRtXORDesc, gCommandReadReg8MaskShRtXORDesc, gCommandWriteReg32ShLtMaskDesc, gCommandWriteReg16ShLtMaskDesc, gCommandWriteReg8ShLtMaskDesc, gCommandMaskandCompareDesc };
#ifndef PFPARSE
#define super OSObject
OSDefineMetaClassAndStructors(IOPlatformFunction, OSObject);
bool IOPlatformFunction::initWithPlatformDoFunction(OSSymbol *functionName, OSData *functionData,
OSData **moreFunctionData)
{
char tmpFunctionName[128], *tmpNamePtr, *funcNamePtr;
UInt32 *moreData;
UInt32 totalLen, result;
if (!super::init() || !functionName || !functionData)
return false;
platformFunctionData = functionData;
platformFunctionPtr = (UInt32 *)functionData->getBytesNoCopy();
platformFunctionDataLen = functionData->getLength();
iterator = IOPlatformFunctionIterator::withIOPlatformFunction (this);
if (!iterator)
return false;
moreData = iterator->scanCommand (platformFunctionPtr, platformFunctionDataLen, &totalLen,
&flags, &pHandle, &result);
if (result != kIOPFNoError)
return false;
if (moreData) {
totalLen += (sizeof(UInt32) * 2); *moreFunctionData = OSData::withBytes (moreData, (platformFunctionDataLen - totalLen));
platformFunctionDataLen = totalLen; } else {
*moreFunctionData = NULL;
}
platformFunctionData->retain();
if (flags & (kIOPFFlagOnDemand | kIOPFFlagIntGen)) {
*tmpFunctionName = '\0';
tmpNamePtr = tmpFunctionName;
funcNamePtr = (char *)functionName->getCStringNoCopy();
while (*funcNamePtr != '-') *(tmpNamePtr++) = *(funcNamePtr++);
funcNamePtr += 3; while (*funcNamePtr) *(tmpNamePtr++) = *(funcNamePtr++);
sprintf (tmpNamePtr, "-%08lx", pHandle); platformFunctionSymbol = OSSymbol::withCString(tmpFunctionName);
DLOG ("IOPF::initWithPlatformDoFunction(%lx) - creating platformFunctionSymbol '%s'\n", mypfobject, tmpFunctionName);
} else
platformFunctionSymbol = NULL;
return true;
}
IOPlatformFunction *IOPlatformFunction::withPlatformDoFunction(OSSymbol *functionName, OSData *functionData,
OSData **moreFunctionData)
{
IOPlatformFunction *me = new IOPlatformFunction;
if (me && !me->initWithPlatformDoFunction(functionName, functionData, moreFunctionData)) {
me->free();
return NULL;
}
return me;
}
void IOPlatformFunction::free()
{
if (iterator) {
iterator->release();
iterator = NULL;
}
if (platformFunctionSymbol) {
platformFunctionSymbol->release();
platformFunctionSymbol = NULL;
}
if (platformFunctionData) {
platformFunctionData->release();
platformFunctionData = NULL;
}
super::free();
}
bool IOPlatformFunction::validatePlatformFunction(UInt32 flagsMask, UInt32 pHandleValue)
{
if (pHandleValue && (pHandle != pHandleValue))
return false;
return ((flags & flagsMask) != 0);
}
bool IOPlatformFunction::platformFunctionMatch(const OSSymbol *funcSym, UInt32 flagsMask, UInt32 pHandleValue)
{
if (!(platformFunctionSymbol && funcSym))
return false;
return (platformFunctionSymbol->isEqualTo(funcSym) && validatePlatformFunction (flagsMask, pHandleValue));
}
const OSSymbol *IOPlatformFunction::getPlatformFunctionName() const
{
return platformFunctionSymbol;
}
UInt32 IOPlatformFunction::getCommandFlags() const
{
return flags;
}
UInt32 IOPlatformFunction::getCommandPHandle() const
{
return pHandle;
}
IOPlatformFunctionIterator *IOPlatformFunction::getCommandIterator()
{
if (iterator) {
iterator->retain();
iterator->reset();
}
return iterator;
}
void IOPlatformFunction::publishPlatformFunction(IOService *handler)
{
if (platformFunctionSymbol)
handler->publishResource(platformFunctionSymbol, handler);
return;
}
OSMetaClassDefineReservedUnused(IOPlatformFunction, 0);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 1);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 2);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 3);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 4);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 5);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 6);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 7);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 8);
OSMetaClassDefineReservedUnused(IOPlatformFunction, 9);
#undef super
#define super OSIterator
OSDefineMetaClassAndStructors(IOPlatformFunctionIterator, OSIterator);
IOPlatformFunctionIterator *IOPlatformFunctionIterator::withIOPlatformFunction(const IOPlatformFunction *inFunc)
{
IOPlatformFunctionIterator *me = new IOPlatformFunctionIterator;
if (me && !me->initWithIOPlatformFunction(inFunc)) {
me->free();
return 0;
}
return me;
}
bool IOPlatformFunctionIterator::initWithIOPlatformFunction(const IOPlatformFunction *inFunc)
{
if (!inFunc)
return false;
platformFunction = inFunc;
commandPtr = NULL;
totalCommandCount = 0;
currentCommandCount = 0;
isCommandList = false;
valid = true;
return true;
}
void IOPlatformFunctionIterator::free()
{
valid = false;
super::free();
return;
}
void IOPlatformFunctionIterator::reset()
{
commandPtr = platformFunction->platformFunctionPtr;
dataLengthRemaining = platformFunction->platformFunctionDataLen;
commandDone = false;
totalCommandCount = currentCommandCount = 0;
return;
}
bool IOPlatformFunctionIterator::isValid()
{
return valid;
}
OSObject *IOPlatformFunctionIterator::getNextObject()
{
return NULL;
}
#endif // !PFPARSE
bool
#ifndef PFPARSE
IOPlatformFunctionIterator::
#endif
getNextCommand(UInt32 *cmd, UInt32 *cmdLen,
UInt32 *param1, UInt32 *param2, UInt32 *param3, UInt32 *param4,
UInt32 *param5, UInt32 *param6, UInt32 *param7, UInt32 *param8,
UInt32 *param9, UInt32 *param10, UInt32 *result)
{
if (commandDone) {
*result = kIOPFNoError;
return false;
}
#ifdef PFPARSE
if (commandPtr == platformFunctionPtr) {
#else
if (commandPtr == platformFunction->platformFunctionPtr) {
#endif
commandPtr += 2; dataLengthRemaining -= 2 * sizeof(UInt32);
if (isCommandList) {
commandPtr = scanSubCommand (commandPtr, dataLengthRemaining, true, cmd, cmdLen, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, result);
dataLengthRemaining -= *cmdLen;
}
}
commandPtr = scanSubCommand (commandPtr, dataLengthRemaining, false, cmd, cmdLen, param1, param2, param3, param4, param5,
param6, param7, param8, param9, param10, result);
if (*result != kIOPFNoError)
return false;
dataLengthRemaining -= *cmdLen;
if (commandPtr == NULL) {
commandDone = true;
DLOG ("IOPFI::getNextCommand - cmd %ld, dataLenRemaining %ld, cmdLen %ld, commandPtr NULL\n",
*cmd, dataLengthRemaining, *cmdLen);
} else {
commandDone = false;
DLOG ("IOPFI::getNextCommand - cmd %ld, dataLenRemaining %ld, cmdLen %ld, *commandPtr 0x%x\n",
*cmd, dataLengthRemaining, *cmdLen, *commandPtr);
}
return true;
}
UInt32 *
#ifndef PFPARSE
IOPlatformFunctionIterator::
#endif
scanSubCommand (UInt32 *cmdPtr, UInt32 lenRemaining,
bool quickScan, UInt32 *cmd, UInt32 *cmdLen,
UInt32 *param1, UInt32 *param2, UInt32 *param3, UInt32 *param4,
UInt32 *param5, UInt32 *param6, UInt32 *param7, UInt32 *param8,
UInt32 *param9, UInt32 *param10, UInt32 *result)
{
SInt32 fixedLen, *cmdDescPtr, paramDesc, descIndex;
UInt32 *cmdBase, cmdLongLen, paramsUsed, tmpLen, *paramPtr;
*result = kIOPFNoError;
cmdBase = cmdPtr;
*cmd = *(cmdPtr++); if (*cmd > kCommandMaxCommand) {
*result = kIOPFUnknownCmd;
return cmdPtr;
}
cmdLongLen = 1; if (*cmd == kCommandCommandList) {
isCommandList = true;
totalCommandCount = *(cmdPtr++);
DLOG ("IOPFI::scanSubCommand(0x%lx) - got commandList, totalCmdCount %ld\n", mypfobject, totalCommandCount);
cmdLongLen += kCommandCommandListLength;
*cmdLen = cmdLongLen * sizeof(UInt32);
if (*cmdLen > lenRemaining)
*result = kIOPFBadCmdLength; else
paramsUsed = 0;
} else {
cmdDescPtr = gCommandArray[*cmd]; fixedLen = cmdDescPtr[0];
if (fixedLen >= 0) cmdLongLen += fixedLen;
else
cmdLongLen += (-fixedLen);
tmpLen = cmdLongLen;
if (((tmpLen - 1) > kIOPFMaxParams) || ((tmpLen * sizeof(UInt32)) > lenRemaining))
*result = kIOPFBadCmdLength; else {
*cmdLen = cmdLongLen * sizeof(UInt32); tmpLen--;
if (quickScan) {
cmdPtr += tmpLen;
} else {
DLOG ("IOPFI::scanSubCommand(%lx) - copying %ld parameters, 1st param 0x%lx\n", mypfobject, tmpLen, *cmdPtr);
paramsUsed = tmpLen;
while (1) {
*param1 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param2 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param3 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param4 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param5 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param6 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param7 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param8 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param9 = *(cmdPtr++);
if (!(--tmpLen)) break;
*param10 = *(cmdPtr++);
if (!(--tmpLen)) break;
DLOG ("IOPFI::scanSubCommand - passed param10, OOPS!\n");
break;
}
}
}
if (fixedLen < 0) { *cmdLen = cmdLongLen * sizeof (UInt32); descIndex = cmdLongLen; while ((paramDesc = cmdDescPtr[descIndex]) != kCommandDescTerminator) {
if (paramDesc < 0)
paramDesc = -paramDesc;
*cmdLen += cmdBase[paramDesc]; if (!quickScan) {
switch (descIndex) {
case 1:
paramPtr = param1;
break;
case 2:
paramPtr = param2;
break;
case 3:
paramPtr = param3;
break;
case 4:
paramPtr = param4;
break;
case 5:
paramPtr = param5;
break;
case 6:
paramPtr = param6;
break;
case 7:
paramPtr = param7;
break;
case 8:
paramPtr = param8;
break;
case 9:
paramPtr = param9;
break;
case 10:
paramPtr = param10;
break;
default:
break;
}
*paramPtr = (UInt32)cmdPtr;
paramsUsed++;
}
cmdPtr = (UInt32 *)((UInt8 *)cmdPtr + cmdBase[paramDesc]);
descIndex++;
}
}
if (isCommandList)
currentCommandCount++;
if (!quickScan) {
switch (paramsUsed) {
case 0:
if (param1) *param1 = 0;
case 1:
if (param2) *param2 = 0;
case 2:
if (param3) *param3 = 0;
case 3:
if (param4) *param4 = 0;
case 4:
if (param5) *param5 = 0;
case 5:
if (param6) *param6 = 0;
case 6:
if (param7) *param7 = 0;
case 7:
if (param8) *param8 = 0;
case 8:
if (param9) *param9 = 0;
case 9:
if (param10) *param10 = 0;
default:
break;
}
}
}
if ((*result != kIOPFNoError) || (*cmdLen == lenRemaining))
cmdPtr = NULL;
if (cmdPtr)
DLOG ("IOPFI::scanSubCommand - done, *result %ld, *cmdLen %ld, lenRemaining %ld, *cmdPtr\n",
*result, *cmdLen, lenRemaining, cmdPtr);
else
DLOG ("IOPFI::scanSubCommand - done, *result %ld, *cmdLen %ld, lenRemaining %ld, cmdPtr NULL\n",
*result, *cmdLen, lenRemaining);
return cmdPtr;
}
UInt32 *
#ifndef PFPARSE
IOPlatformFunctionIterator::
#endif
scanCommand (UInt32 *cmdPtr, UInt32 dataLen, UInt32 *cmdTotalLen,
UInt32 *flags, UInt32 *pHandle, UInt32 *result)
{
UInt32 cmdLen, cmd;
if (dataLen < 3) {
*result = kIOPFBadCmdLength;
return NULL;
}
*pHandle = *(cmdPtr++);
*flags = *(cmdPtr++);
dataLen -= 2 * sizeof(UInt32);
DLOG ("IOPFI::scanCommand: pHandle 0x%lx, flags 0x%lx, len left %ld\n", *pHandle, *flags, dataLen);
*cmdTotalLen = 0;
if ((*cmdPtr < 0) || (*cmdPtr > kCommandMaxCommand)) {
*result = kIOPFBadCmdLength;
return NULL;
}
do {
cmdPtr = scanSubCommand (cmdPtr, dataLen, true, &cmd, &cmdLen, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, result);
*cmdTotalLen += cmdLen;
if ((*result != kIOPFNoError) || !cmdPtr)
break;
dataLen -= cmdLen;
if (dataLen < 0) {
*result = kIOPFBadCmdLength;
return NULL;
}
if (!isCommandList || (currentCommandCount == totalCommandCount))
break;
} while (dataLen);
if (cmdPtr)
DLOG ("IOPFI::scanCommand: done, *cmdPtr 0x%lx\n", *cmdPtr);
else
DLOG ("IOPFI::scanCommand: done, cmdPtr NULL\n");
return cmdPtr;
}
#ifndef PFPARSE
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 0);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 1);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 2);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 3);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 4);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 5);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 6);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 7);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 8);
OSMetaClassDefineReservedUnused(IOPlatformFunctionIterator, 9);
#endif