IOFWUserIsochPort.cpp [plain text]
#include <IOKit/firewire/IOFWIsochPort.h>
#include <IOKit/firewire/IOFireWireUserClient.h>
#include <IOKit/firewire/IOFWUserIsochPort.h>
#include <IOKit/firewire/IOFireWireDevice.h>
#include <IOKit/firewire/IOFireWireController.h>
OSDefineMetaClassAndStructors(IOFWUserIsochPort, IOFWIsochPort)
bool
IOFWUserIsochPort::init()
{
return IOFWIsochPort::init() ;
}
IOReturn
IOFWUserIsochPort::getSupported(
IOFWSpeed& maxSpeed,
UInt64& chanSupported)
{
IOFireWireUserClientLog_(("+ IOFWUserIsochPort::getSupported\n")) ;
return kIOReturnUnsupported ;
}
IOReturn
IOFWUserIsochPort::allocatePort(IOFWSpeed speed, UInt32 chan)
{
IOFireWireUserClientLog_(("+ IOFWUserIsochPort::allocatePort\n")) ;
return kIOReturnSuccess ;
}
IOReturn
IOFWUserIsochPort::releasePort()
{
IOFireWireUserClientLog_(("+ IOFWUserIsochPort::releasePort\n")) ;
return kIOReturnSuccess ;
}
IOReturn
IOFWUserIsochPort::start()
{
IOFireWireUserClientLog_(("+ IOFWUserIsochPort::start\n")) ;
return kIOReturnSuccess ;
}
IOReturn
IOFWUserIsochPort::stop()
{
IOFireWireUserClientLog_(("+ IOFWUserIsochPort::stop\n")) ;
return kIOReturnSuccess ;
}
OSDefineMetaClassAndStructors(IOFWUserIsochPortProxy, OSObject)
Boolean
IOFWUserIsochPortProxy::init(
IOFireWireUserClient* inUserClient)
{
fUserClient = inUserClient ;
fUserClient->retain() ;
fPortStarted = false ;
fPortAllocated = false ;
IOFWUserIsochPort* newPort = new IOFWUserIsochPort ;
if (newPort && !newPort->init())
{
newPort->release() ;
newPort = NULL ;
}
fPort = newPort ;
return (fPort != NULL) ;
}
IOReturn
IOFWUserIsochPortProxy::getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported)
{
return fPort->getSupported(maxSpeed, chanSupported) ;
}
IOReturn
IOFWUserIsochPortProxy::allocatePort(IOFWSpeed speed, UInt32 chan)
{
IOReturn result = kIOReturnSuccess ;
if (!fPortAllocated)
{
result = fPort->allocatePort(speed, chan) ;
fPortAllocated = (kIOReturnSuccess == result) ;
}
return result ;
}
IOReturn
IOFWUserIsochPortProxy::releasePort()
{
IOReturn result = kIOReturnSuccess ;
IOFireWireUserClientLogIfFalse_(fPortStarted, ("IOFWUserIsochPortProxy::releasePort: calling releasePort() before stop()!\n")) ;
if (fPortAllocated)
{
result = fPort->releasePort() ;
fPortAllocated = false ;
}
return result ;
}
IOReturn
IOFWUserIsochPortProxy::start()
{
IOReturn result = kIOReturnSuccess ;
if (fPortAllocated && !fPortStarted)
{
fPortStarted = (kIOReturnSuccess == result) ;
result = fPort->start() ;
}
return result ;
}
IOReturn
IOFWUserIsochPortProxy::stop()
{
IOReturn result = kIOReturnSuccess ;
if (fPortStarted)
{
result = fPort->stop() ;
fPortStarted = false ;
}
return result ;
}
void
IOFWUserIsochPortProxy::free()
{
if (fPort)
{
fPort->release() ;
fPort = NULL ;
}
if (fUserClient)
{
fUserClient->release() ;
fUserClient = NULL ;
}
OSObject::free() ;
}
OSDefineMetaClassAndStructors(IOFWUserLocalIsochPortProxy, IOFWUserIsochPortProxy)
Boolean
IOFWUserLocalIsochPortProxy::initWithUserDCLProgram(
FWLocalIsochPortAllocateParams* inParams,
IOFireWireUserClient* inUserClient)
{
if (!IOFWUserIsochPortProxy::init(inUserClient))
return false ;
fUserDCLProgramMem = NULL ;
fDCLProgramBytes = 0 ;
fKernDCLProgramBuffer = NULL ;
fUserBufferMem = NULL ;
fUserBufferMemPrepared = false ;
fTalking = inParams->talking ;
fStartEvent = inParams->startEvent ;
fStartState = inParams->startState ;
fStartMask = inParams->startMask ;
IOReturn result = kIOReturnSuccess ;
IOByteCount tempLength = 0 ;
IOVirtualRange* programRanges = NULL ;
IOVirtualRange* bufferRanges = NULL ;
programRanges = (IOVirtualRange*) IOMalloc(inParams->userDCLProgramRangeCount * sizeof(IOVirtualRange)) ;
IOMemoryDescriptor* programRangesMem =
IOMemoryDescriptor::withAddress((IOVirtualAddress)(inParams->userDCLProgramRanges),
sizeof(IOVirtualRange) * inParams->userDCLProgramRangeCount,
kIODirectionIn, fUserClient->getOwningTask() ) ;
if (!programRangesMem)
result = kIOReturnNoMemory ;
IOByteCount programStartOffset = 0 ;
if ( kIOReturnSuccess == result )
{
programRangesMem->readBytes(0 ,
programRanges,
sizeof(IOVirtualRange) * inParams->userDCLProgramRangeCount) ;
programRangesMem->release() ;
if (!findOffsetInRanges( (IOVirtualAddress)(inParams->userDCLProgram),
programRanges,
inParams->userDCLProgramRangeCount,
& programStartOffset))
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::initWithUserDCLProgram: failed to find program starting point in ranges provided")) ;
fUserDCLProgramMem = IOMemoryDescriptor::withRanges(programRanges, inParams->userDCLProgramRangeCount,
kIODirectionOutIn, fUserClient->getOwningTask()) ;
if (!fUserDCLProgramMem)
result = kIOReturnNoMemory ;
if (kIOReturnSuccess == result)
result = fUserDCLProgramMem->prepare(kIODirectionOutIn) ;
fUserDCLProgramMemPrepared = (kIOReturnSuccess == result) ;
}
if (kIOReturnSuccess == result)
{
fDCLProgramBytes = fUserDCLProgramMem->getLength() ;
if (NULL == (fKernDCLProgramBuffer = (UInt8*) IOMalloc(fDCLProgramBytes)))
result = kIOReturnNoMemory ;
fKernDCLProgramStart = (DCLCommandStruct*)(fKernDCLProgramBuffer + programStartOffset) ;
}
if ( kIOReturnSuccess == result )
{
if (NULL == (bufferRanges = (IOVirtualRange*) IOMalloc( sizeof(IOVirtualRange) * inParams->userDCLBufferRangeCount)))
result = kIOReturnNoMemory ;
}
IOMemoryDescriptor* bufferRangesMem = 0 ;
if (kIOReturnSuccess == result)
{
bufferRangesMem = IOMemoryDescriptor::withAddress((IOVirtualAddress)inParams->userDCLBufferRanges,
inParams->userDCLBufferRangeCount * sizeof(IOVirtualRange),
kIODirectionIn, fUserClient->getOwningTask() ) ;
if (!bufferRangesMem)
result = kIOReturnNoMemory ;
}
if (kIOReturnSuccess == result)
{
bufferRangesMem->readBytes(0, bufferRanges, bufferRangesMem->getLength()) ;
bufferRangesMem->release() ;
}
if (kIOReturnSuccess == result)
{
fUserBufferMem = IOMemoryDescriptor::withRanges(bufferRanges, inParams->userDCLBufferRangeCount,
kIODirectionOutIn, fUserClient->getOwningTask()) ;
if (!fUserBufferMem)
result = kIOReturnNoMemory ;
}
if (kIOReturnSuccess == result)
{
result = fUserBufferMem->prepare(kIODirectionOutIn) ;
fUserBufferMemPrepared = (kIOReturnSuccess == result) ;
}
if (kIOReturnSuccess == result)
{
fUserToKernelDCLLookupTableLength = inParams->userDCLProgramDCLCount ;
fUserToKernelDCLLookupTable = (DCLCommandStruct**) IOMalloc( sizeof(DCLCommandStruct*) * fUserToKernelDCLLookupTableLength) ;
if (!fUserToKernelDCLLookupTable)
result = kIOReturnNoMemory ;
}
DCLCommandStruct** userDCLTable ; if (kIOReturnSuccess == result)
{
userDCLTable = (DCLCommandStruct**) IOMalloc( sizeof(DCLCommandStruct*) * fUserToKernelDCLLookupTableLength) ;
if (!userDCLTable)
result = kIOReturnNoMemory ;
}
if ( kIOReturnSuccess == result )
{
DCLCommandStruct* pCurrentKernDCL = fKernDCLProgramStart ;
IOByteCount distance = 0 ;
UInt32 rangeIndex = 0 ;
UInt32 dclIndex = 0 ;
IOVirtualRange tempBufferRange ;
fUserDCLProgramMem->readBytes(0, fKernDCLProgramBuffer, fDCLProgramBytes) ;
if (pCurrentKernDCL)
{
DCLCommandStruct* lastNextUserDCL = inParams->userDCLProgram ;
IOByteCount lastDistance = programStartOffset ;
while (pCurrentKernDCL && (kIOReturnSuccess == result) )
{
distance = 0 ;
rangeIndex = 0 ;
userDCLTable[dclIndex] = lastNextUserDCL ;
lastNextUserDCL = pCurrentKernDCL->pNextDCLCommand ;
fUserToKernelDCLLookupTable[dclIndex] = pCurrentKernDCL ;
pCurrentKernDCL->compilerData = 0 ;
if (getDCLDataBuffer(pCurrentKernDCL, & tempBufferRange.address, & tempBufferRange.length))
{
if (!findOffsetInRanges( tempBufferRange.address,
bufferRanges,
inParams->userDCLBufferRangeCount,
& distance))
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::initWithUserDCLProgram: couldn't find DCL data buffer in buffer ranges")) ;
setDCLDataBuffer(pCurrentKernDCL, (IOVirtualAddress)fUserBufferMem->getVirtualSegment(distance, & tempLength), tempBufferRange.length) ;
}
switch( pCurrentKernDCL->opcode & ~kFWDCLOpFlagMask )
{
case kDCLJumpOp:
dclIndex++ ;
result = convertToKernelDCL( (DCLJumpStruct*) pCurrentKernDCL,
userDCLTable,
fUserToKernelDCLLookupTable,
dclIndex) ;
break ;
case kDCLUpdateDCLListOp:
dclIndex++ ;
result = convertToKernelDCL( (DCLUpdateDCLListStruct*)pCurrentKernDCL,
userDCLTable,
fUserToKernelDCLLookupTable,
dclIndex) ;
break ;
case kDCLPtrTimeStampOp:
dclIndex++ ;
result = convertToKernelDCL( (DCLPtrTimeStampStruct*) pCurrentKernDCL,
bufferRanges,
inParams->userDCLBufferRangeCount,
fUserBufferMem) ;
break ;
case kDCLCallProcOp:
result = convertToKernelDCL( (DCLCallProcStruct*) pCurrentKernDCL,
userDCLTable[dclIndex]) ;
dclIndex++ ;
break ;
default:
dclIndex++ ;
break ;
}
if (pCurrentKernDCL->pNextDCLCommand)
{
if (!findOffsetInRanges( (IOVirtualAddress)(pCurrentKernDCL->pNextDCLCommand),
programRanges,
inParams->userDCLProgramRangeCount,
& distance))
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::initWithUserDCLProgram: couldn't find DCL next ptr in program ranges")) ;
else
pCurrentKernDCL->pNextDCLCommand = (DCLCommandStruct*)(fKernDCLProgramBuffer + distance) ;
}
else
pCurrentKernDCL->pNextDCLCommand = NULL ;
fUserDCLProgramMem->writeBytes(lastDistance + ( (IOVirtualAddress)&pCurrentKernDCL->compilerData - (IOVirtualAddress)&pCurrentKernDCL->pNextDCLCommand ),
&dclIndex, sizeof(pCurrentKernDCL->compilerData)) ;
lastDistance = distance ;
pCurrentKernDCL = pCurrentKernDCL->pNextDCLCommand ;
}
if (result != kIOReturnSuccess)
IOFireWireUserClientLog_(("result converting DCL #%lud = %08lX\n", dclIndex-1, (UInt32) result)) ;
}
if (userDCLTable)
{
IOFree(userDCLTable, sizeof(DCLCommandStruct*) * fUserToKernelDCLLookupTableLength) ;
userDCLTable = NULL ;
}
}
if (programRanges)
{
IOFree(programRanges, inParams->userDCLProgramRangeCount * sizeof(IOVirtualRange)) ;
programRanges = NULL ;
}
if (bufferRanges)
{
IOFree( bufferRanges, sizeof(IOVirtualRange) * inParams->userDCLBufferRangeCount) ;
bufferRanges = NULL ;
}
if (kIOReturnSuccess == result)
result = createPort() ;
return (kIOReturnSuccess == result) ;
}
void
IOFWUserLocalIsochPortProxy::free()
{
if (fUserBufferMem)
{
if (fUserBufferMemPrepared)
fUserBufferMem->complete() ;
fUserBufferMem->release() ;
fUserBufferMem = NULL ;
}
if (fUserDCLProgramMem)
{
if (fUserDCLProgramMemPrepared)
fUserDCLProgramMem->complete() ;
fUserDCLProgramMem->release() ;
fUserDCLProgramMem = NULL ;
}
if (fUserToKernelDCLLookupTable)
{
IOFree(fUserToKernelDCLLookupTable, sizeof(DCLCommandStruct*) * fUserToKernelDCLLookupTableLength) ;
fUserToKernelDCLLookupTable = NULL ;
}
if (fKernDCLProgramBuffer)
{
IOFree( fKernDCLProgramBuffer, fDCLProgramBytes) ;
fKernDCLProgramBuffer = NULL ;
}
IOFWUserIsochPortProxy::free() ;
}
IOReturn
IOFWUserLocalIsochPortProxy::getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported)
{
if (!fPort)
createPort() ;
return IOFWUserIsochPortProxy::getSupported( maxSpeed, chanSupported ) ;
}
IOReturn
IOFWUserLocalIsochPortProxy::allocatePort(IOFWSpeed speed, UInt32 chan)
{
IOReturn result = kIOReturnSuccess ;
if (!fPort)
result = createPort() ;
if (kIOReturnSuccess == result)
result = IOFWUserIsochPortProxy::allocatePort(speed, chan) ;
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::releasePort()
{
IOReturn result = kIOReturnSuccess ;
if (fPort)
{
result = IOFWUserIsochPortProxy::releasePort() ;
fPort->release() ;
fPort = NULL ;
}
return result ;
}
Boolean
IOFWUserLocalIsochPortProxy::getDCLDataBuffer(
const DCLCommandStruct* inDCL,
IOVirtualAddress* outDataBuffer,
IOByteCount* outDataLength)
{
Boolean result = false ;
switch(inDCL->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketWithHeaderStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
*outDataBuffer = (IOVirtualAddress)((DCLTransferPacketStruct*)inDCL)->buffer ;
*outDataLength = ((DCLTransferPacketStruct*)inDCL)->size ;
result = true ;
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
break ;
default:
break ;
}
return result ;
}
void
IOFWUserLocalIsochPortProxy::setDCLDataBuffer(
DCLCommandStruct* inDCL,
IOVirtualAddress inDataBuffer,
IOByteCount inDataLength)
{
switch(inDCL->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketWithHeaderStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
((DCLTransferPacketStruct*)inDCL)->buffer = (void*) inDataBuffer ;
((DCLTransferPacketStruct*)inDCL)->size = inDataLength ;
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
break ;
default:
break ;
}
}
IOByteCount
IOFWUserLocalIsochPortProxy::getDCLSize(
DCLCommandStruct* inDCL)
{
IOByteCount result = 0 ;
switch(inDCL->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketWithHeaderStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
result = sizeof(DCLTransferPacketStruct) ;
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
result = sizeof(DCLTransferBufferStruct) ;
break ;
case kDCLCallProcOp:
result = sizeof(DCLCallProcStruct) ;
break ;
case kDCLLabelOp:
result = sizeof(DCLLabelStruct) ;
break ;
case kDCLJumpOp:
result = sizeof(DCLJumpStruct) ;
break ;
case kDCLSetTagSyncBitsOp:
result = sizeof(DCLSetTagSyncBitsStruct) ;
break ;
case kDCLUpdateDCLListOp:
result = sizeof(DCLUpdateDCLListStruct) ;
break ;
case kDCLPtrTimeStampOp:
result = sizeof(DCLPtrTimeStampStruct) ;
}
return result ;
}
void
IOFWUserLocalIsochPortProxy::printDCLProgram(
const DCLCommandStruct* inDCL,
UInt32 inDCLCount)
{
const DCLCommandStruct* currentDCL = inDCL ;
UInt32 index = 0 ;
IOLog("IOFWUserLocalIsochPortProxy::printDCLProgram: inDCL=0x%08lX, inDCLCount=%08lX\n", (UInt32)inDCL, (UInt32)inDCLCount) ;
while ( (index < inDCLCount) && currentDCL )
{
IOLog("\n#0x%04lX @0x%08lX next=0x%08lX, cmplrData=0x%08lX, op=%u ",
index,
(UInt32)currentDCL,
(UInt32)currentDCL->pNextDCLCommand,
(UInt32)currentDCL->compilerData,
(int) currentDCL->opcode) ;
switch(currentDCL->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketWithHeaderStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
IOLog("(DCLTransferPacketStruct) buffer=%08lX, size=%u",
(UInt32)((DCLTransferPacketStruct*)currentDCL)->buffer,
(int)((DCLTransferPacketStruct*)currentDCL)->size) ;
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
IOLog("(DCLTransferBufferStruct) buffer=%08lX, size=%lu, packetSize=%08X, bufferOffset=%08X",
(UInt32)((DCLTransferBufferStruct*)currentDCL)->buffer,
((DCLTransferBufferStruct*)currentDCL)->size,
((DCLTransferBufferStruct*)currentDCL)->packetSize,
(UInt32)((DCLTransferBufferStruct*)currentDCL)->bufferOffset) ;
break ;
case kDCLCallProcOp:
IOLog("(DCLCallProcStruct) proc=%08lX, procData=%08lX (OSAsyncRef: ref @ 0x%08lX, userRefCon=%08lX)",
(UInt32)((DCLCallProcStruct*)currentDCL)->proc,
(UInt32)((DCLCallProcStruct*)currentDCL)->procData,
(UInt32)((AsyncRefHolder*)((DCLCallProcStruct*)currentDCL)->procData)->asyncRef,
(UInt32)((AsyncRefHolder*)((DCLCallProcStruct*)currentDCL)->procData)->userRefCon) ;
break ;
case kDCLLabelOp:
IOLog("(DCLLabelStruct)") ;
break ;
case kDCLJumpOp:
IOLog("(DCLJumpStruct) pJumpDCLLabel=%08lX",
(UInt32)((DCLJumpStruct*)currentDCL)->pJumpDCLLabel) ;
break ;
case kDCLSetTagSyncBitsOp:
IOLog("(DCLSetTagSyncBitsStruct) tagBits=%04lX, syncBits=%04lX",
(UInt32)((DCLSetTagSyncBitsStruct*)currentDCL)->tagBits,
(UInt32)((DCLSetTagSyncBitsStruct*)currentDCL)->syncBits) ;
break ;
case kDCLUpdateDCLListOp:
IOLog("(DCLUpdateDCLListStruct) dclCommandList=%08lX, numDCLCommands=%lud\n",
(UInt32)((DCLUpdateDCLListStruct*)currentDCL)->dclCommandList,
((DCLUpdateDCLListStruct*)currentDCL)->numDCLCommands) ;
for(UInt32 listIndex=0; listIndex < ((DCLUpdateDCLListStruct*)currentDCL)->numDCLCommands; listIndex++)
{
IOLog("%08lX ", (UInt32)(((DCLUpdateDCLListStruct*)currentDCL)->dclCommandList)[listIndex]) ;
IOSleep(8) ;
}
IOLog("\n") ;
break ;
case kDCLPtrTimeStampOp:
IOLog("(DCLPtrTimeStampStruct) timeStampPtr=0x%08lX",
(UInt32)((DCLPtrTimeStampStruct*)currentDCL)->timeStampPtr) ;
}
currentDCL = currentDCL->pNextDCLCommand ;
index++ ;
IOSleep(40) ;
}
IOLog("\n") ;
if (index != inDCLCount)
IOLog("unexpected end of program\n") ;
if (currentDCL != NULL)
IOLog("program too long for count\n") ;
}
IOReturn
IOFWUserLocalIsochPortProxy::convertToKernelDCL(
DCLJumpStruct* inDCLCommand,
DCLCommandStruct* inUserDCLTable[],
DCLCommandStruct* inUserToKernelDCLLookupTable[],
UInt32 inTableLength )
{
IOReturn result = kIOReturnSuccess ;
if ( !userToKernLookup( (DCLCommandStruct*) inDCLCommand->pJumpDCLLabel,
inUserDCLTable,
inUserToKernelDCLLookupTable,
inTableLength,
& (DCLCommandStruct*)inDCLCommand->pJumpDCLLabel))
result = kIOReturnError ;
if (kIOReturnSuccess != result)
IOFireWireUserClientLog_(("couldn't convert jump DCL (inDCLCommand=0x%08lX, inDCLCommand->pJumpDCLLabel=0x%08lX)\n", (UInt32)inDCLCommand, (UInt32)inDCLCommand->pJumpDCLLabel)) ;
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::convertToKernelDCL(
DCLPtrTimeStampStruct* inDCLCommand,
IOVirtualRange* inBufferRanges,
UInt32 inBufferRangeCount,
IOMemoryDescriptor* inKernelBufferMem)
{
IOByteCount offset ;
IOByteCount tempLength ;
IOReturn result = kIOReturnSuccess ;
if (!findOffsetInRanges((IOVirtualAddress)(inDCLCommand->timeStampPtr), inBufferRanges, inBufferRangeCount, & offset))
result = kIOReturnError ;
inDCLCommand->timeStampPtr = (UInt32*) inKernelBufferMem->getVirtualSegment(offset, & tempLength) ;
if (!inDCLCommand->timeStampPtr)
result = kIOReturnVMError ;
if (kIOReturnSuccess != result)
IOFireWireUserClientLog_(("couldn't convert ptr time stamp DCL\n")) ;
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::convertToKernelDCL(
DCLUpdateDCLListStruct* inDCLCommand,
DCLCommandStruct* inUserDCLTable[],
DCLCommandStruct* inUserToKernelDCLLookupTable[],
UInt32 inTableLength )
{
IOReturn result = kIOReturnSuccess ;
IOByteCount listSize = inDCLCommand->numDCLCommands * sizeof(DCLCommandStruct*) ;
IOMemoryDescriptor* dclListMem = IOMemoryDescriptor::withAddress(
(IOVirtualAddress) inDCLCommand->dclCommandList,
listSize,
kIODirectionIn,
fUserClient->getOwningTask() ) ;
if (!dclListMem)
result = kIOReturnNoMemory ;
if ( kIOReturnSuccess == result )
{
inDCLCommand->dclCommandList = (DCLCommandStruct**) IOMalloc( sizeof(DCLCommandStruct*) * inDCLCommand->numDCLCommands) ;
if (!inDCLCommand->dclCommandList)
result = kIOReturnNoMemory ;
}
if ( kIOReturnSuccess == result )
{
if ( dclListMem->readBytes(0, inDCLCommand->dclCommandList, listSize) < listSize )
result = kIOReturnVMError ;
}
if ( kIOReturnSuccess == result )
{
for(UInt32 index = 0; index < inDCLCommand->numDCLCommands; index++)
{
if ( !userToKernLookup( inDCLCommand->dclCommandList[index],
inUserDCLTable,
inUserToKernelDCLLookupTable,
inTableLength,
& (inDCLCommand->dclCommandList)[index]))
result = kIOReturnError ;
}
}
if (dclListMem)
dclListMem->release() ;
if (kIOReturnSuccess != result)
IOFireWireUserClientLog_(("couldn't convert update dcl list\n")) ;
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::convertToKernelDCL(
DCLCallProcStruct* inDCLCommand,
DCLCommandStruct* inUserDCL )
{
IOReturn result = kIOReturnSuccess ;
AsyncRefHolder* holder = (AsyncRefHolder*) IOMalloc( sizeof(AsyncRefHolder) ) ;
if (!holder)
result = kIOReturnNoMemory ;
else
{
(holder->asyncRef)[0] = 0 ;
holder->userRefCon = inUserDCL ;
inDCLCommand->procData = (UInt32) holder ;
inDCLCommand->proc = & (IOFWUserLocalIsochPortProxy::dclCallProcHandler) ;
}
if (kIOReturnSuccess != result)
IOFireWireUserClientLog_(("couldn't convert call proc DCL\n")) ;
return result ;
}
Boolean
IOFWUserLocalIsochPortProxy::findOffsetInRanges(
IOVirtualAddress inAddress,
IOVirtualRange inRanges[],
UInt32 inRangeCount,
IOByteCount* outOffset)
{
UInt32 index = 0 ;
IOByteCount distanceInRange ;
Boolean found = false ;
*outOffset = 0 ;
while (!found && (index < inRangeCount))
{
distanceInRange = inAddress - inRanges[index].address ;
if (found = ((distanceInRange >= 0) && (distanceInRange < inRanges[index].length)))
*outOffset += distanceInRange ;
else
*outOffset += inRanges[index].length ;
index++ ;
}
return found ;
}
Boolean
IOFWUserLocalIsochPortProxy::userToKernLookup(
DCLCommandStruct* inDCLCommand,
DCLCommandStruct* inUserDCLList[],
DCLCommandStruct* inKernDCLList[],
UInt32 inTableLength,
DCLCommandStruct** outDCLCommand)
{
UInt32 tableIndex = 0 ;
Boolean found = false ;
while ( !found && (tableIndex < inTableLength) )
{
if ( found = (inUserDCLList[tableIndex] == inDCLCommand) )
*outDCLCommand = inKernDCLList[tableIndex] ;
tableIndex++ ;
}
if (found && (inDCLCommand == NULL))
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::userToKernLookup: ")) ;
if (!found)
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::userToKernLookup: couldn't find 0x%08lX\n", (UInt32)inDCLCommand)) ;
return found ;
}
void
IOFWUserLocalIsochPortProxy::dclCallProcHandler(
DCLCommandStruct* pDCLCommand)
{
AsyncRefHolder* holder = (AsyncRefHolder*) (((DCLCallProcStruct*)pDCLCommand)->procData) ;
if ((holder->asyncRef)[0])
{
IOReturn result = IOFireWireUserClient::sendAsyncResult( holder->asyncRef,
kIOReturnSuccess,
NULL, 0) ;
if (kIOReturnSuccess != result)
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::dclCallProcHandler: sendAsyncResult returned error 0x%08lX!\n", (UInt32) result)) ;
}
}
IOReturn
IOFWUserLocalIsochPortProxy::setAsyncRef_DCLCallProc(
OSAsyncReference asyncRef,
DCLCallCommandProcPtr inProc)
{
DCLCommandStruct* pCurrentDCL = fKernDCLProgramStart ;
AsyncRefHolder* holder ;
while (pCurrentDCL) {
if ((pCurrentDCL->opcode & ~kFWDCLOpFlagMask) == kDCLCallProcOp)
{
holder = (AsyncRefHolder*)((DCLCallProcStruct*)pCurrentDCL)->procData ;
IOFireWireUserClient::setAsyncReference( asyncRef, (mach_port_t) asyncRef[0],
(void*) inProc,
holder->userRefCon );
bcopy( asyncRef,
& holder->asyncRef,
sizeof(OSAsyncReference)) ;
}
pCurrentDCL = pCurrentDCL->pNextDCLCommand ;
}
return kIOReturnSuccess ;
}
IOReturn
IOFWUserLocalIsochPortProxy::modifyJumpDCL(
UInt32 inJumpDCLCompilerData,
UInt32 inLabelDCLCompilerData)
{
inJumpDCLCompilerData-- ;
inLabelDCLCompilerData-- ;
if ( inJumpDCLCompilerData > fUserToKernelDCLLookupTableLength || inLabelDCLCompilerData > fUserToKernelDCLLookupTableLength )
return kIOReturnBadArgument ;
DCLJumpStruct* pJumpDCL = (DCLJumpStruct*)(fUserToKernelDCLLookupTable[inJumpDCLCompilerData]) ;
pJumpDCL->pJumpDCLLabel = (DCLLabelStruct*)(fUserToKernelDCLLookupTable[inLabelDCLCompilerData]) ;
if ((pJumpDCL->opcode & ~kFWDCLOpFlagMask) != kDCLJumpOp ||
(pJumpDCL->pJumpDCLLabel->opcode & ~kFWDCLOpFlagMask) != kDCLLabelOp)
{
IOFireWireUserClientLog_(("IOFWUserLocalIsochPortProxy::modifyJumpDCL: modifying non-jump or pointing jump to non-label\n")) ;
return kIOReturnBadArgument ;
}
if (!pJumpDCL->compilerData)
return kIOReturnSuccess ;
if (fPort)
return ((IOFWLocalIsochPort*)fPort)->notify(kFWDCLModifyNotification, & (DCLCommandStruct*)pJumpDCL, 1) ;
else
return kIOReturnSuccess ;
}
IOReturn
IOFWUserLocalIsochPortProxy::createPort()
{
fPort = fUserClient->getOwner()->getController()->createLocalIsochPort(
fTalking,
fKernDCLProgramStart,
0,
fStartEvent,
fStartState,
fStartMask) ;
if (!fPort)
return kIOReturnNoMemory ;
return kIOReturnSuccess ;
}