IOFWUserIsochPort.cpp [plain text]
#include <IOKit/firewire/IOFWIsochPort.h>
#include <IOKit/firewire/IOFireWireDevice.h>
#include <IOKit/firewire/IOFireWireController.h>
#include <IOKit/firewire/IOFireWireLink.h>
#include "IOFireWireUserClient.h"
#include "IOFWUserIsochPort.h"
#include <IOKit/IOMemoryDescriptor.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 ;
}
#pragma mark -
#pragma mark --- IOFWUserIsochPortProxy ----------
OSDefineMetaClassAndStructors(IOFWUserIsochPortProxy, OSObject)
Boolean
IOFWUserIsochPortProxy::init(
IOFireWireUserClient* inUserClient)
{
fUserClient = inUserClient ;
fPortStarted = false ;
fPortAllocated = false ;
fPort = NULL ;
IOFireWireUserClientLog_("IOFWUserIsochPortProxy::init: this=%p, fPort %p, fUserClient %p\n", this, fPort, fUserClient) ;
return true ;
}
IOReturn
IOFWUserIsochPortProxy::getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported)
{
IOReturn result = kIOReturnSuccess ;
if (!fPort)
result = createPort() ;
if ( result == kIOReturnSuccess )
result = fPort->getSupported(maxSpeed, chanSupported) ;
return result ;
}
IOReturn
IOFWUserIsochPortProxy::allocatePort(IOFWSpeed speed, UInt32 chan)
{
IOReturn result = kIOReturnSuccess ;
if (!fPortAllocated)
{
if (!fPort)
result = createPort() ;
if ( result == kIOReturnSuccess )
result = fPort->allocatePort(speed, chan) ;
fPortAllocated = (kIOReturnSuccess == result) ;
}
return result ;
}
IOReturn
IOFWUserIsochPortProxy::releasePort()
{
IOReturn result = kIOReturnSuccess ;
if ( fPortStarted )
{
IOFireWireUserClientLog_( ("IOFWUserIsochPortProxy::releasePort: calling releasePort() before stop()!\n" ) ) ;
if (!fPort)
IOLog("%s %u: strange: fPort == nil when emergency releasing port.\n", __FILE__, __LINE__) ;
if ( kIOReturnSuccess != fPort->stop() )
IOLog("%s %u: fPort->stop() returned error\n", __FILE__, __LINE__) ;
}
if (fPortAllocated)
{
if (!fPort)
{
IOLog("%s %u: strange: fPort == nil when calling releasePort.\n", __FILE__, __LINE__) ;
result = kIOReturnError ;
}
if ( result == kIOReturnSuccess )
result = fPort->releasePort() ;
fPortAllocated = false ;
}
return result ;
}
IOReturn
IOFWUserIsochPortProxy::start()
{
IOReturn result = kIOReturnSuccess ;
if (fPortAllocated && !fPortStarted)
{
if (!fPort)
result = createPort() ;
if ( result == kIOReturnSuccess )
result = fPort->start() ;
else
IOLog("%s %u: IOFWUserIsochPortProxt::Start(): error %x trying to allocate isoch port\n", __FILE__, __LINE__, result ) ;
IOFireWireUserClientLog_("starting port %p\n", this) ;
fPortStarted = (kIOReturnSuccess == result) ;
}
return result ;
}
IOReturn
IOFWUserIsochPortProxy::stop()
{
IOReturn result = kIOReturnSuccess ;
if (fPortStarted)
{
IOFireWireUserClientLog_("IOFWUserIsochPortProxy::stop: stopping port %p\n", fPort) ;
if (!fPort)
{
IOLog("%s %u: IOFWUserIsochPortProxy::stop(): fPort == nil!\n", __FILE__, __LINE__) ;
result = kIOReturnError ;
}
if ( result == kIOReturnSuccess )
result = fPort->stop() ;
fPortStarted = false ;
}
return result ;
}
void
IOFWUserIsochPortProxy::free()
{
IOFireWireUserClientLog_("IOFWUserIsochPortProxy::free: this=%p, releasing fPort @ %p\n", this, fPort) ;
if (fPort)
{
fPort->release() ;
fPort = NULL ;
}
OSObject::free() ;
}
IOReturn
IOFWUserIsochPortProxy::createPort()
{
IOReturn result = kIOReturnSuccess ;
IOFWUserIsochPort* newPort = new IOFWUserIsochPort ;
if (newPort && !newPort->init())
{
newPort->release() ;
newPort = NULL ;
result = kIOReturnNoMemory ;
IOLog("%s %u: couldn't make newPort!\n", __FILE__, __LINE__) ;
}
fPort = newPort ;
return result ;
}
#pragma mark -
#pragma mark --- IOFWUserLocalIsochPortProxy ----------
OSDefineMetaClassAndStructors(IOFWUserLocalIsochPortProxy, IOFWUserIsochPortProxy)
Boolean
IOFWUserLocalIsochPortProxy::initWithUserDCLProgram( FWLocalIsochPortAllocateParams* inParams, IOFireWireUserClient* inUserClient)
{
if (!IOFWUserIsochPortProxy::init(inUserClient))
{
IOLog("%s %u:IOFWUserIsochPortProxy::init failed\n", __FILE__, __LINE__) ;
return false ;
}
fTalking = inParams->talking ;
fStartEvent = inParams->startEvent ;
fStartState = inParams->startState ;
fStartMask = inParams->startMask ;
fUserObj = inParams->userObj ;
fTaskInfo.fTask = fUserClient->getOwningTask();
IOReturn result = kIOReturnSuccess ;
IOVirtualRange* programRanges = NULL ;
IOVirtualRange* bufferRanges = NULL ;
programRanges = new IOVirtualRange[ inParams->userDCLProgramRangeCount ] ;
IOMemoryDescriptor* programRangesMem =
IOMemoryDescriptor::withAddress((IOVirtualAddress)(inParams->userDCLProgramRanges),
sizeof(IOVirtualRange) * inParams->userDCLProgramRangeCount,
kIODirectionIn, fUserClient->getOwningTask() ) ;
if (!programRangesMem)
{
IOLog("%s %u: Couldn't create programRangesMem\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
IOByteCount programStartOffset = 0 ;
if ( kIOReturnSuccess == result )
result = programRangesMem->prepare() ;
if ( kIOReturnSuccess == result )
{
programRangesMem->readBytes(0 ,
programRanges,
sizeof(IOVirtualRange) * inParams->userDCLProgramRangeCount) ;
programRangesMem->complete() ;
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)
{
IOLog("%s %u: Couldn't get fUserDCLProgramMem\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
}
if ( kIOReturnSuccess == result )
{
result = fUserDCLProgramMem->prepare() ;
fUserDCLProgramMemPrepared = ( result == kIOReturnSuccess ) ;
}
if (kIOReturnSuccess == result)
{
fDCLProgramBytes = fUserDCLProgramMem->getLength() ;
if ( NULL == ( fKernDCLProgramBuffer = new UInt8[ fDCLProgramBytes ] ) )
{
result = kIOReturnNoMemory ;
IOLog("%s %u: couldn't get fKernDCLProgramBuffer\n", __FILE__, __LINE__) ;
}
else
fKernDCLProgramStart = (DCLCommandStruct*)(fKernDCLProgramBuffer + programStartOffset) ;
}
if ( inParams->userDCLBufferRangeCount > 0 )
{
if ( kIOReturnSuccess == result )
{
if ( NULL == ( bufferRanges = new IOVirtualRange[ inParams->userDCLBufferRangeCount ] ) )
{
result = kIOReturnNoMemory ;
IOLog("%s %u: couldn't get bufferRanges\n", __FILE__, __LINE__) ;
}
}
IOMemoryDescriptor* bufferRangesMem = 0 ;
if (kIOReturnSuccess == result)
{
bufferRangesMem = IOMemoryDescriptor::withAddress((IOVirtualAddress)inParams->userDCLBufferRanges,
inParams->userDCLBufferRangeCount * sizeof(IOVirtualRange),
kIODirectionOutIn, fUserClient->getOwningTask() ) ;
if (!bufferRangesMem)
{
IOLog("%s %u: couldn't get bufferRangesMem\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
}
if ( kIOReturnSuccess == result )
result = bufferRangesMem->prepare() ;
if (kIOReturnSuccess == result)
{
bufferRangesMem->readBytes(0, bufferRanges, bufferRangesMem->getLength()) ;
bufferRangesMem->complete() ;
}
if ( bufferRangesMem )
{
bufferRangesMem->release() ;
}
if ( kIOReturnSuccess == result )
{
fUserBufferMem = IOMemoryDescriptor::withRanges( bufferRanges, inParams->userDCLBufferRangeCount,
kIODirectionOutIn, fUserClient->getOwningTask() ) ;
if ( !fUserBufferMem )
{
IOLog("%s %u: couldn't get fUserBufferMem\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
}
if ( kIOReturnSuccess == result )
{
result = fUserBufferMem->prepare( kIODirectionOutIn ) ;
fUserBufferMemPrepared = ( kIOReturnSuccess == result ) ;
if (!fUserBufferMemPrepared)
IOLog("%s %u:couldn't prepare mem\n", __FILE__, __LINE__) ;
}
}
if (kIOReturnSuccess == result)
{
fUserToKernelDCLLookupTableLength = inParams->userDCLProgramDCLCount ;
fUserToKernelDCLLookupTable = new DCLCommandStruct*[ fUserToKernelDCLLookupTableLength ] ;
if ( !fUserToKernelDCLLookupTable )
{
IOLog("%s %u: couldn't get fUserToKernelDCLLookupTable\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
}
DCLCommandStruct** userDCLTable = NULL ; if (kIOReturnSuccess == result)
{
userDCLTable = new (DCLCommandStruct*)[ fUserToKernelDCLLookupTableLength ] ;
if (!userDCLTable)
{
IOLog("%s %u: couldn't get userDCLTable\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
}
if ( kIOReturnSuccess == result )
{
fUserDCLProgramMem->readBytes(0, fKernDCLProgramBuffer, fDCLProgramBytes) ;
if ( fUserBufferMem )
{
fUserBufferMemMap = fUserBufferMem->map() ;
if ( !fUserBufferMemMap )
{
fKernDCLProgramStart = NULL ;
result = kIOReturnVMError ;
IOLog("%s %u: couldn't map!\n", __FILE__, __LINE__) ;
}
else
{
fTaskInfo.fDataBaseAddr = fUserBufferMemMap->getVirtualAddress();
fTaskInfo.fDataSize = fUserBufferMemMap->getLength();
fTaskInfo.fCallRefCon = fUserBufferMem;
}
}
if (fKernDCLProgramStart)
{
DCLCommandStruct* pCurrentKernDCL = fKernDCLProgramStart ;
UInt32 lookupTableLength = 0 ;
DCLCommandStruct* lastNextUserDCL = inParams->userDCLProgram ;
IOByteCount lastDistance = programStartOffset ;
while ( pCurrentKernDCL && (kIOReturnSuccess == result) )
{
IOByteCount distance = 0 ;
IOVirtualRange tempBufferRange ;
userDCLTable[lookupTableLength] = lastNextUserDCL ;
lastNextUserDCL = pCurrentKernDCL->pNextDCLCommand ;
fUserToKernelDCLLookupTable[lookupTableLength] = pCurrentKernDCL ;
pCurrentKernDCL->compilerData = 0 ;
if (getDCLDataBuffer(pCurrentKernDCL, & tempBufferRange.address, & tempBufferRange.length))
{
if ( tempBufferRange.address != NULL && tempBufferRange.length > 0 )
{
if (!findOffsetInRanges( tempBufferRange.address,
bufferRanges,
inParams->userDCLBufferRangeCount,
& distance))
{
IOFireWireUserClientLog_("IOFWUserLocalIsochPortProxy::initWithUserDCLProgram: couldn't find DCL data buffer in buffer ranges") ;
}
IOVirtualAddress baseAddr = fUserBufferMemMap->getVirtualAddress() ;
setDCLDataBuffer( pCurrentKernDCL, baseAddr + distance, tempBufferRange.length ) ;
}
}
switch( pCurrentKernDCL->opcode & ~kFWDCLOpFlagMask )
{
case kDCLCallProcOp:
result = convertToKernelDCL( (DCLCallProcStruct*) pCurrentKernDCL,
userDCLTable[lookupTableLength] ) ;
break ;
default:
break ;
}
++lookupTableLength ;
if ( pCurrentKernDCL->pNextDCLCommand && kIOReturnSuccess == result )
{
if ( !findOffsetInRanges( (IOVirtualAddress)( pCurrentKernDCL->pNextDCLCommand ), programRanges, inParams->userDCLProgramRangeCount, & distance ) )
{
IOFireWireUserClientLog_("IOFWUserLocalIsochPortProxy::initWithUserDCLProgram: couldn't find DCL next ptr in program ranges") ;
pCurrentKernDCL->pNextDCLCommand = NULL ;
}
else
pCurrentKernDCL->pNextDCLCommand = (DCLCommandStruct*)(fKernDCLProgramBuffer + distance) ;
}
fUserDCLProgramMem->writeBytes(lastDistance + ( (IOVirtualAddress)&pCurrentKernDCL->compilerData - (IOVirtualAddress)&pCurrentKernDCL->pNextDCLCommand ),
& lookupTableLength , sizeof(pCurrentKernDCL->compilerData)) ;
lastDistance = distance ;
pCurrentKernDCL = pCurrentKernDCL->pNextDCLCommand ;
}
if ( kIOReturnSuccess == result )
{
UInt32 hint = 0 ;
pCurrentKernDCL = fKernDCLProgramStart ;
while ( pCurrentKernDCL && (kIOReturnSuccess == result) )
{
switch( pCurrentKernDCL->opcode & ~kFWDCLOpFlagMask )
{
case kDCLJumpOp:
result = convertToKernelDCL( (DCLJumpStruct*) pCurrentKernDCL, userDCLTable, fUserToKernelDCLLookupTable, lookupTableLength, hint ) ;
break ;
case kDCLUpdateDCLListOp:
result = convertToKernelDCL( (DCLUpdateDCLListStruct*)pCurrentKernDCL, userDCLTable, fUserToKernelDCLLookupTable, lookupTableLength, hint) ;
break ;
default:
break ;
}
pCurrentKernDCL = pCurrentKernDCL->pNextDCLCommand ;
}
}
}
}
delete[] programRanges ;
delete[] bufferRanges ;
delete[] userDCLTable ;
return (kIOReturnSuccess == result) ;
}
void
IOFWUserLocalIsochPortProxy::free()
{
if (fUserBufferMem)
{
if (fUserBufferMemPrepared)
fUserBufferMem->complete() ;
if ( fUserBufferMemMap )
fUserBufferMemMap->release() ;
IOFireWireUserClientLog_("releasing fUserBufferMem, retain=%u\n", fUserBufferMem->getRetainCount()) ;
fUserBufferMem->release() ;
}
if ( fUserDCLProgramMem )
{
if ( fUserDCLProgramMemPrepared )
fUserDCLProgramMem->complete() ;
fUserDCLProgramMem->release() ;
fUserDCLProgramMem = NULL ;
}
delete[] fUserToKernelDCLLookupTable ;
if (fKernDCLProgramBuffer)
{
DCLCommandStruct* currentDCL = fKernDCLProgramStart ;
while (currentDCL)
{
switch( currentDCL->opcode )
{
case kDCLCallProcOp:
if (((DCLCallProcStruct*)currentDCL)->procData)
delete (AsyncRefHolder*)(((DCLCallProcStruct*)currentDCL)->procData) ;
break ;
case kDCLUpdateDCLListOp:
delete[] ((DCLUpdateDCLListStruct*)currentDCL)->dclCommandList ;
break ;
default:
break ;
}
currentDCL = currentDCL->pNextDCLCommand ;
}
delete[] fKernDCLProgramBuffer ;
}
IOFWUserIsochPortProxy::free() ;
}
IOReturn
IOFWUserLocalIsochPortProxy::getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported)
{
if (!fPort)
createPort() ;
IOReturn result = IOFWUserIsochPortProxy::getSupported( maxSpeed, chanSupported ) ;
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::allocatePort(IOFWSpeed speed, UInt32 chan)
{
IOReturn result = kIOReturnSuccess ;
if (!fPort)
result = createPort() ;
if ( result == kIOReturnSuccess && fUserBufferMem && !fUserBufferMemPrepared )
{
result = fUserBufferMem->prepare() ;
fUserBufferMemPrepared = ( result == kIOReturnSuccess ) ;
}
if ( result == kIOReturnSuccess && !fUserDCLProgramMemPrepared )
{
result = fUserDCLProgramMem->prepare() ;
fUserDCLProgramMemPrepared = ( result == kIOReturnSuccess ) ;
}
if (kIOReturnSuccess == result)
result = IOFWUserIsochPortProxy::allocatePort(speed, chan) ;
else
{
IOFireWireUserClientLog_("%s %u IOFWUserLocalIsochPortProxy::allocatePort: failed with error %x\n", __FILE__, __LINE__, result ) ;
fPort->release() ;
fPort = NULL ;
}
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::releasePort()
{
IOReturn result = kIOReturnSuccess ;
if (fPort)
{
result = IOFWUserIsochPortProxy::releasePort() ;
if ( fUserBufferMemPrepared )
{
fUserBufferMem->complete() ;
fUserBufferMemPrepared = false ;
}
if ( fUserDCLProgramMemPrepared )
{
fUserDCLProgramMem->complete() ;
fUserDCLProgramMemPrepared = false ;
}
fPort->release() ;
fPort = NULL ;
}
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::stop()
{
IOFireWireLink* link = fUserClient->getOwner()->getController()->getLink() ;
link->closeIsochGate() ;
#if IOFIREWIREDEBUG > 0
IOReturn result =
#endif
IOFireWireUserClient::sendAsyncResult( fStopTokenAsyncRef, kIOFireWireLastDCLToken, & fUserObj, 1 ) ;
IOFireWireUserClientLogIfErr_(result, "IOFWUserLocalIsochPortProxy::stop: sendAsyncResult returned error 0x%08lX!\n", (UInt32) result) ;
IOReturn err = IOFWUserIsochPortProxy::stop() ;
link->openIsochGate() ;
return err ;
}
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 ;
case kDCLPtrTimeStampOp:
*outDataBuffer = (IOVirtualAddress)((DCLPtrTimeStamp*)inDCL)->timeStampPtr ;
*outDataLength = sizeof( *(((DCLPtrTimeStamp*)inDCL)->timeStampPtr) ) ;
result = true ;
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 ;
case kDCLPtrTimeStampOp:
((DCLPtrTimeStamp*)inDCL)->timeStampPtr = (UInt32*)inDataBuffer ;
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=%08lX",
(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,
UInt32& inOutHint )
{
IOReturn result = kIOReturnSuccess ;
if ( !userToKernLookup( (DCLCommandStruct*) inDCLCommand->pJumpDCLLabel,
inUserDCLTable,
inUserToKernelDCLLookupTable,
inTableLength,
inOutHint,
& (DCLCommandStruct*)inDCLCommand->pJumpDCLLabel))
result = kIOReturnError ;
IOFireWireUserClientLogIfErr_( result, "couldn't convert jump DCL (inDCLCommand=0x%08lX, inDCLCommand->pJumpDCLLabel=0x%08lX)\n", (UInt32)inDCLCommand, (UInt32)inDCLCommand->pJumpDCLLabel) ;
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::convertToKernelDCL(
DCLUpdateDCLListStruct* inDCLCommand,
DCLCommandStruct* inUserDCLTable[],
DCLCommandStruct* inUserToKernelDCLLookupTable[],
UInt32 inTableLength,
UInt32& inOutHint )
{
IOReturn result = kIOReturnSuccess ;
IOByteCount listSize = inDCLCommand->numDCLCommands * sizeof(DCLCommandStruct*) ;
IOMemoryDescriptor* dclListMem = IOMemoryDescriptor::withAddress(
(IOVirtualAddress) inDCLCommand->dclCommandList,
listSize,
kIODirectionIn,
fUserClient->getOwningTask() ) ;
if (!dclListMem)
{
IOLog("%s %u: couldn't get dclListMem\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
if ( kIOReturnSuccess == result )
{
inDCLCommand->dclCommandList = new (DCLCommandStruct*)[inDCLCommand->numDCLCommands] ;
if (!inDCLCommand->dclCommandList)
{
IOFireWireUserClientLog_("%s %u: couldn't allocate inDCLCommand->dclCommandList\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
}
if ( kIOReturnSuccess == result )
{
if ( dclListMem->readBytes(0, inDCLCommand->dclCommandList, listSize) < listSize )
{
IOFireWireUserClientLog_("%s %u: dclListMem->readBytes failed\n", __FILE__, __LINE__) ;
result = kIOReturnVMError ;
}
}
if ( kIOReturnSuccess == result )
{
for(UInt32 index = 0; index < inDCLCommand->numDCLCommands; ++index)
{
if ( !userToKernLookup( inDCLCommand->dclCommandList[index],
inUserDCLTable,
inUserToKernelDCLLookupTable,
inTableLength,
inOutHint,
& (inDCLCommand->dclCommandList)[index]))
{
IOFireWireUserClientLog_("%s %u: couldn't find dcl referenced in dcl list in program\n", __FILE__, __LINE__) ;
result = kIOReturnError ;
}
}
}
if (dclListMem)
{
dclListMem->release() ;
}
return result ;
}
IOReturn
IOFWUserLocalIsochPortProxy::convertToKernelDCL(
DCLCallProcStruct* inDCLCommand,
DCLCommandStruct* inUserDCL )
{
IOReturn result = kIOReturnSuccess ;
AsyncRefHolder* holder = new AsyncRefHolder ;
if (!holder)
{
IOLog("%s %u: couldn't get holder\n", __FILE__, __LINE__) ;
result = kIOReturnNoMemory ;
}
else
{
(holder->asyncRef)[0] = 0 ;
holder->userRefCon = inUserDCL ;
holder->obj = this ;
inDCLCommand->procData = (UInt32) holder ;
inDCLCommand->proc = & (IOFWUserLocalIsochPortProxy::dclCallProcHandler) ;
}
IOFireWireUserClientLogIfErr_(result, "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,
UInt32& inOutHint,
DCLCommandStruct** outDCLCommand)
{
inOutHint = (inOutHint - 1) % inTableLength ;
UInt32 tableIndex = inOutHint ;
do
{
if ( inUserDCLList[tableIndex] != inDCLCommand )
{
tableIndex = (tableIndex + 1) % inTableLength ;
}
else
{
*outDCLCommand = inKernDCLList[tableIndex] ;
inOutHint = tableIndex ;
if ( inDCLCommand == NULL )
{
IOFireWireUserClientLog_("IOFWUserLocalIsochPortProxy::userToKernLookup: ") ;
}
return true ;
}
} while ( tableIndex != inOutHint ) ;
IOFireWireUserClientLog_("IOFWUserLocalIsochPortProxy::userToKernLookup: couldn't find 0x%08lX\n", (UInt32)inDCLCommand) ;
return false ;
}
void
IOFWUserLocalIsochPortProxy::dclCallProcHandler(
DCLCommandStruct* pDCLCommand)
{
AsyncRefHolder* holder = (AsyncRefHolder*) (((DCLCallProcStruct*)pDCLCommand)->procData) ;
IOFWUserLocalIsochPortProxy* me = (IOFWUserLocalIsochPortProxy*) holder->obj ;
#if IOFIREWIREUSERCLIENTDEBUG > 0
if (!me->fUserClient->getStatistics())
panic("%s %u", __FILE__, __LINE__) ;
me->fUserClient->getStatistics()->isochCallbacks->addValue( 1 ) ;
#endif
if ((holder->asyncRef)[0])
{
#if IOFIREWIREUSERCLIENTDEBUG > 0
IOReturn result =
#endif
IOFireWireUserClient::sendAsyncResult( holder->asyncRef,
kIOReturnSuccess,
& me->fUserObj, 1) ;
IOFireWireUserClientLogIfErr_(result, "IOFWUserLocalIsochPortProxy::dclCallProcHandler: sendAsyncResult returned error 0x%08lX!\n", (UInt32) result) ;
}
}
IOReturn
IOFWUserLocalIsochPortProxy::setAsyncRef_DCLCallProc(
OSAsyncReference asyncRef,
DCLCallCommandProcPtr inProc )
{
DCLCommandStruct* pCurrentDCL = fKernDCLProgramStart ;
AsyncRefHolder* holder ;
IOFireWireUserClient::setAsyncReference( asyncRef, (mach_port_t) asyncRef[0], (void*)inProc, (void*)0xFFFFFFFF ) ;
bcopy( asyncRef, fStopTokenAsyncRef, sizeof( OSAsyncReference ) ) ;
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 )
{
IOFireWireUserClientLog_("IOFWUserLocalIsochPort::modifyJumpDCL: DCL index (inJumpDCLCompilerData=%lu, inLabelDCLCompilerData=%lu) past end of lookup table (length=%lu)\n",
inJumpDCLCompilerData,
inLabelDCLCompilerData,
fUserToKernelDCLLookupTableLength) ;
return kIOReturnBadArgument ;
}
DCLJumpStruct* pJumpDCL = (DCLJumpStruct*)(fUserToKernelDCLLookupTable[inJumpDCLCompilerData]) ;
pJumpDCL->pJumpDCLLabel = (DCLLabelStruct*)(fUserToKernelDCLLookupTable[inLabelDCLCompilerData]) ;
if ((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) ;
return kIOReturnSuccess ;
}
IOReturn
IOFWUserLocalIsochPortProxy::modifyJumpDCLSize( UInt32 dclCompilerData, IOByteCount newSize )
{
--dclCompilerData ;
if ( dclCompilerData > fUserToKernelDCLLookupTableLength )
{
IOFireWireUserClientLog_("IOFWUserLocalIsochPort::modifyJumpDCLSize: DCL index (dclCompilerData=%lu) past end of lookup table (length=%lu)\n",
dclCompilerData, fUserToKernelDCLLookupTableLength ) ;
return kIOReturnBadArgument ;
}
DCLTransferPacket* dcl = (DCLTransferPacket*)( fUserToKernelDCLLookupTable[ dclCompilerData ] ) ;
if (fPort)
return ((IOFWLocalIsochPort*)fPort)->notify(kFWDCLModifyNotification, &(DCLCommand*)dcl, 1) ;
return kIOReturnSuccess ;
}
IOReturn
IOFWUserLocalIsochPortProxy::createPort()
{
IOReturn result = kIOReturnSuccess ;
if ( fUserBufferMem && !fUserBufferMemPrepared )
{
result = fUserBufferMem->prepare(kIODirectionOutIn) ;
fUserBufferMemPrepared = (kIOReturnSuccess == result) ;
}
if ( result == kIOReturnSuccess )
{
fPort = fUserClient->getOwner()->getController()->createLocalIsochPort(
fTalking,
fKernDCLProgramStart,
&fTaskInfo,
fStartEvent,
fStartState,
fStartMask) ;
if (!fPort)
{
IOLog("%s %u: no fPort", __FILE__, __LINE__) ;
return kIOReturnNoMemory ;
}
}
return kIOReturnSuccess ;
}