IOFWUserCommand.cpp [plain text]
#import "IOFWUserCommand.h"
#import "IOFireWireDevice.h"
#import "IOFireWireFamilyCommon.h"
#import "IOFireWireLib.h"
OSDefineMetaClassAndAbstractStructors(IOFWUserCommand, OSObject)
OSDefineMetaClassAndStructors(IOFWUserReadCommand, IOFWUserCommand)
OSDefineMetaClassAndStructors(IOFWUserWriteCommand, IOFWUserCommand)
OSDefineMetaClassAndStructors(IOFWUserCompareSwapCommand, IOFWUserCommand)
void
IOFWUserCommand::free()
{
if ( fCommand )
{
IOReturn cmdStatus = fCommand->getStatus() ;
if ( cmdStatus == kIOReturnBusy || cmdStatus == kIOFireWirePending )
{
IOFireWireUserClientLog_("cancelling cmd %p\n", fCommand) ;
fCommand->cancel( kIOReturnAborted ) ;
}
fCommand->release() ;
}
if (fMem)
{
fMem->complete() ;
fMem->release() ;
}
}
void
IOFWUserCommand::setAsyncReference(
OSAsyncReference inAsyncRef)
{
bcopy(inAsyncRef, fAsyncRef, sizeof(OSAsyncReference)) ;
}
IOFWUserCommand*
IOFWUserCommand::withSubmitParams(
const CommandSubmitParams* inParams,
const IOFireWireUserClient* inUserClient)
{
IOFWUserCommand* result = NULL ;
switch ( inParams->type )
{
case kFireWireCommandType_Read:
case kFireWireCommandType_ReadQuadlet:
result = new IOFWUserReadCommand ;
break ;
case kFireWireCommandType_Write:
case kFireWireCommandType_WriteQuadlet:
result = new IOFWUserWriteCommand ;
break ;
case kFireWireCommandType_CompareSwap:
result = new IOFWUserCompareSwapCommand ;
break ;
default:
IOFireWireUserClientLog_(("IOFWUserCommand::withSubmitParams: bad command type!\n")) ;
break ;
}
if (result && !result->initWithSubmitParams( inParams, inUserClient ))
{
result->release() ;
result = NULL ;
}
return result ;
}
bool
IOFWUserCommand::initWithSubmitParams(
const CommandSubmitParams* inParams,
const IOFireWireUserClient* inUserClient)
{
fUserClient = inUserClient ;
return true ;
}
void
IOFWUserCommand::asyncReadWriteCommandCompletion(
void * refcon,
IOReturn status,
IOFireWireNub * device,
IOFWCommand * fwCmd)
{
IOFWUserCommand* cmd = (IOFWUserCommand*) refcon ;
if ( refcon && cmd->fAsyncRef[0] )
{
IOByteCount bytesTransferred = cmd->fCommand->getBytesTransferred() ;
#if IOFIREWIREDEBUG > 0
IOReturn result =
#endif
IOFireWireUserClient::sendAsyncResult( cmd->fAsyncRef, status, (void**) & bytesTransferred, 1 ) ;
IOFireWireUserClientLogIfErr_( result, "IOFWUserCommand::asyncReadWriteCommandCompletion: sendAsyncResult returned error 0x%08lX\n", (UInt32) result ) ;
}
}
void
IOFWUserCommand::asyncReadQuadletCommandCompletion(
void * refcon,
IOReturn status,
IOFireWireNub * device,
IOFWCommand * fwCmd)
{
IOFWUserCommand* cmd = (IOFWUserCommand*)refcon ;
if (refcon && cmd->fAsyncRef[0] )
{
#if IOFIREWIREDEBUG > 0
IOReturn result =
#endif
IOFireWireUserClient::sendAsyncResult( cmd->fAsyncRef, status, (void**)cmd->fQuads, ( cmd->fCommand->getBytesTransferred() >> 2) + 2 ) ;
IOFireWireUserClientLogIfErr_( result, "IOFireWireUserClient::asyncReadQuadletCommandCompletion: sendAsyncResult returned error 0x%08x\n", result) ;
}
}
#pragma mark -
bool
IOFWUserReadCommand::initWithSubmitParams(
const CommandSubmitParams* inParams,
const IOFireWireUserClient* inUserClient)
{
bool result = true ;
result = (NULL != IOFWUserCommand::initWithSubmitParams(inParams, inUserClient)) ;
if (result)
{
fMem = IOMemoryDescriptor::withAddress( (vm_address_t) inParams->newBuffer, inParams->newBufferSize, kIODirectionOut, fUserClient->getOwningTask() ) ;
result = (NULL != fMem) ;
}
if (result)
{
IOReturn error = fMem->prepare() ;
result = ( kIOReturnSuccess == error ) ;
}
if (!result)
{
if (fMem)
fMem->release() ;
}
return result ;
}
IOReturn
IOFWUserReadCommand::submit(
CommandSubmitParams* inParams,
CommandSubmitResult* outResult)
{
IOReturn error = kIOReturnSuccess ;
Boolean syncFlag = ( inParams->flags & kFWCommandInterfaceSyncExecute ) != 0 ;
Boolean copyFlag = ( inParams->flags & kFireWireCommandUseCopy ) != 0;
Boolean absFlag = ( inParams->flags & kFireWireCommandAbsolute ) != 0 ;
if ( inParams->staleFlags & kFireWireCommandStale_Buffer ) {
if ( fMem ) {
fMem->complete() ;
fMem->release() ;
}
if ( copyFlag ) {
if (fQuads && (fNumQuads != inParams->newBufferSize) || syncFlag) {
IOFree(fQuads, fNumQuads << 2) ;
fQuads = NULL ;
}
if (!syncFlag)
{
fNumQuads = inParams->newBufferSize ;
fQuads = (UInt32*)IOMalloc(inParams->newBufferSize << 2) ;
}
fMem = NULL ;
}
else
{
if (fQuads)
{
IOFree(fQuads, fNumQuads << 2) ;
fQuads = NULL ;
fNumQuads = 0 ;
}
if (NULL == (fMem = IOMemoryDescriptor::withAddress( (vm_address_t) inParams->newBuffer,
inParams->newBufferSize,
kIODirectionOut,
fUserClient->getOwningTask())) )
{
error = kIOReturnNoMemory ;
}
else
{
error = fMem->prepare() ;
if ( error )
{
fMem->release() ;
fMem = NULL ;
}
}
}
}
if ( not error )
{
if (fCopyFlag != copyFlag)
if (fCommand)
{
fCommand->release() ; fCommand = NULL ;
}
if (fCommand)
{
if ( copyFlag )
if (syncFlag)
{
if ( absFlag )
{
error = ((IOFWReadQuadCommand*)fCommand)->reinit( inParams->newGeneration, inParams->newTarget, (UInt32*) inParams+1, inParams->newBufferSize, NULL, this ) ;
}
else
error = ((IOFWReadQuadCommand*)fCommand)->reinit( inParams->newTarget, (UInt32*) inParams+1, inParams->newBufferSize, NULL, this, inParams->newFailOnReset) ;
}
else
{
error = ((IOFWReadQuadCommand*)fCommand)->reinit( inParams->newTarget,
fQuads,
fNumQuads,
& IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset) ;
}
else
error = ((IOFWReadCommand*)fCommand)->reinit( inParams->newTarget,
fMem,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset ) ;
fCommand->setGeneration(inParams->newGeneration) ;
IOFireWireUserClientLogIfErr_(error, "IOFWUserReadCommand::submit: fCommand->reinit error=%08x\n", error) ;
}
else {
if ( copyFlag )
{
if (syncFlag)
{
if ( absFlag )
{
fCommand = fUserClient->createReadQuadCommand( inParams->newGeneration, inParams->newTarget, (UInt32*) inParams+1, inParams->newBufferSize, NULL, this ) ;
}
else
fCommand = fUserClient->getOwner()->createReadQuadCommand( inParams->newTarget, (UInt32*) inParams+1, inParams->newBufferSize, NULL, this, inParams->newFailOnReset ) ;
}
else
{
if ( absFlag )
{
fCommand = fUserClient->createReadQuadCommand( inParams->newGeneration, inParams->newTarget, fQuads, fNumQuads, & IOFWUserCommand::asyncReadQuadletCommandCompletion, this ) ;
}
else
{
fCommand = fUserClient->getOwner()->createReadQuadCommand( inParams->newTarget,
fQuads,
fNumQuads,
& IOFWUserCommand::asyncReadQuadletCommandCompletion,
this,
inParams->newFailOnReset) ;
if ( fCommand )
fCommand->setGeneration( inParams->newGeneration ) ;
}
}
}
else
{
if ( absFlag )
{
fCommand = fUserClient->createReadCommand( inParams->newGeneration, inParams->newTarget, fMem, syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, this ) ;
}
else
{
fCommand = fUserClient->getOwner()->createReadCommand( inParams->newTarget,
fMem,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset ) ;
if ( fCommand )
fCommand->setGeneration( inParams->newGeneration ) ;
}
}
if (!fCommand)
error = kIOReturnNoMemory ;
}
}
if ( not error )
{
if (inParams->staleFlags & kFireWireCommandStale_MaxPacket)
{
fCommand->setMaxPacket(inParams->newMaxPacket) ;
}
error = fCommand->submit() ;
IOFireWireUserClientLogIfErr_(error, "IOFWUserReadCommand::submit: fCommand->submit error=%08x\n", error) ;
}
if (syncFlag)
{
outResult->result = fCommand->getStatus() ;
outResult->bytesTransferred = fCommand->getBytesTransferred() ;
}
return error ;
}
#pragma mark -
bool
IOFWUserWriteCommand::initWithSubmitParams(
const CommandSubmitParams* inParams,
const IOFireWireUserClient* inUserClient)
{
bool result = true ;
result = (NULL != IOFWUserCommand::initWithSubmitParams(inParams, inUserClient)) ;
if (result)
{
fMem = IOMemoryDescriptor::withAddress( (vm_address_t) inParams->newBuffer, inParams->newBufferSize, kIODirectionIn, fUserClient->getOwningTask() ) ;
result = (NULL != fMem) ;
}
if (result)
{
IOReturn error = fMem->prepare() ;
result = (error == kIOReturnSuccess) ;
}
if (!result)
{
if (fMem)
fMem->release() ;
}
return result ;
}
IOReturn
IOFWUserWriteCommand::submit(
CommandSubmitParams* inParams,
CommandSubmitResult* outResult)
{
IOReturn result = kIOReturnSuccess ;
Boolean syncFlag = ( inParams->flags & kFWCommandInterfaceSyncExecute ) != 0 ;
Boolean copyFlag = ( inParams->flags & kFireWireCommandUseCopy ) != 0 ;
Boolean absFlag = ( inParams->flags & kFireWireCommandAbsolute ) != 0 ;
if ( inParams->staleFlags & kFireWireCommandStale_Buffer ) {
if ( fMem ) {
fMem->complete() ;
fMem->release() ;
}
if ( copyFlag ) fMem = NULL ;
else
{
if (NULL == (fMem = IOMemoryDescriptor::withAddress( (vm_address_t) inParams->newBuffer,
inParams->newBufferSize,
kIODirectionOut,
fUserClient->getOwningTask())) )
{
result = kIOReturnNoMemory ;
}
else
{
result = fMem->prepare() ;
if ( kIOReturnSuccess != result )
{
fMem->release() ;
fMem = NULL ;
}
}
}
}
if ( kIOReturnSuccess == result)
{
if (fCopyFlag != copyFlag)
if (fCommand)
{
fCommand->release() ; fCommand = NULL ;
}
if (fCommand)
{
if ( copyFlag )
{
result = ((IOFWWriteQuadCommand*)fCommand)->reinit( inParams->newTarget,
(UInt32*) inParams+1,
inParams->newBufferSize,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset) ;
}
else
{
result = ((IOFWWriteCommand*)fCommand)->reinit( inParams->newTarget,
fMem,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset ) ;
}
IOFireWireUserClientLogIfErr_( result, "IOFWUserWriteCommand::submit: fCommand->reinit result=%08x\n", result) ;
}
else
{
if ( copyFlag )
{
if ( absFlag )
fCommand = fUserClient->createWriteQuadCommand( inParams->newGeneration, inParams->newTarget, (UInt32*) inParams+1, inParams->newBufferSize, syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, this ) ;
else
{
fCommand = fUserClient->getOwner()->createWriteQuadCommand( inParams->newTarget,
(UInt32*) inParams+1,
inParams->newBufferSize,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset ) ;
if ( fCommand )
fCommand->setGeneration( inParams->newGeneration ) ;
}
}
else
{
if ( absFlag )
fCommand = fUserClient->createWriteCommand( inParams->newGeneration,
inParams->newTarget,
fMem,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this ) ;
else
{
fCommand = fUserClient->getOwner()->createWriteCommand( inParams->newTarget,
fMem,
syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion,
this,
inParams->newFailOnReset ) ;
if ( fCommand )
fCommand->setGeneration( inParams->newGeneration ) ;
}
}
if (!fCommand)
result = kIOReturnNoMemory ;
}
}
if ( kIOReturnSuccess == result)
{
if (inParams->staleFlags & kFireWireCommandStale_MaxPacket)
fCommand->setMaxPacket(inParams->newMaxPacket) ; result = fCommand->submit() ;
IOFireWireUserClientLogIfErr_( result, "IOFWUserReadCommand::submit: fCommand->submit result=%08x\n", result) ;
}
if (syncFlag)
{
outResult->result = fCommand->getStatus() ;
outResult->bytesTransferred = fCommand->getBytesTransferred() ;
}
return result ;
}
#pragma mark -
bool
IOFWUserCompareSwapCommand::initWithSubmitParams(
const CommandSubmitParams* inParams,
const IOFireWireUserClient* inUserClient)
{
bool result = true ;
result = (NULL != IOFWUserCommand::initWithSubmitParams(inParams, inUserClient)) ;
return result ;
}
IOReturn
IOFWUserCompareSwapCommand::submit(
CommandSubmitParams* inParams,
CommandSubmitResult* outResult)
{
CompareSwapSubmitResult* result = (CompareSwapSubmitResult*)outResult ;
IOReturn error = kIOReturnSuccess ;
if ( inParams->staleFlags & kFireWireCommandStale_Buffer )
fSize = inParams->newBufferSize ;
Boolean syncFlag = ( inParams->flags & kFWCommandInterfaceSyncExecute ) != 0 ;
Boolean absFlag = ( inParams->flags & kFireWireCommandAbsolute ) != 0 ;
if ( inParams->staleFlags & kFireWireCommandStale )
{
if ( fCommand )
{
fCommand->release() ;
fCommand = NULL ;
}
if ( absFlag )
fCommand = fUserClient->createCompareAndSwapCommand( inParams->newGeneration,
inParams->newTarget,
(UInt32*)(inParams+1), (UInt32*)(inParams+1) + 2, fSize >> 2,
syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion,
this ) ;
else
{
fCommand = fUserClient->getOwner()->createCompareAndSwapCommand( inParams->newTarget,
(UInt32*)(inParams+1), (UInt32*)(inParams+1) + 2, fSize >> 2,
syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion,
this,
inParams->newFailOnReset ) ;
if ( fCommand )
fCommand->setGeneration( inParams->newGeneration ) ;
}
if ( !fCommand )
error = kIOReturnNoMemory ;
}
else {
if ( absFlag )
error =((IOFWCompareAndSwapCommand*)fCommand)->reinit( inParams->newGeneration,
inParams->newTarget, (UInt32*)(inParams+1), (UInt32*)(inParams+1) + 2, fSize >> 2, syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion, this ) ;
else
{
error = ((IOFWCompareAndSwapCommand*)fCommand)->reinit( inParams->newTarget,
(UInt32*)(inParams+1), (UInt32*)(inParams+1) + 2, fSize >> 2, syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion, this,
inParams->newFailOnReset ) ;
fCommand->setGeneration( inParams->newGeneration ) ;
}
}
if ( !error )
{
error = fCommand->submit() ;
if (syncFlag)
{
result->result = fCommand->getStatus() ;
result->bytesTransferred = fCommand->getBytesTransferred() ;
result->lockInfo.didLock = ((IOFWCompareAndSwapCommand*)fCommand)->locked( (UInt32*) & result->lockInfo.value ) ;
}
}
return error ;
}
void
IOFWUserCompareSwapCommand::asyncCompletion(
void * refcon,
IOReturn status,
IOFireWireNub * device,
IOFWCommand * fwCmd)
{
IOFWUserCompareSwapCommand* cmd = (IOFWUserCompareSwapCommand*)refcon ;
if (refcon && cmd->fAsyncRef[0] )
{
CompareSwapSubmitResult sendResult ;
sendResult.result = status ;
sendResult.bytesTransferred = cmd->fCommand->getBytesTransferred() ;
sendResult.lockInfo.didLock = (Boolean)((IOFWCompareAndSwapCommand*)cmd->fCommand)->locked( (UInt32*) & sendResult.lockInfo.value ) ;
#if IOFIREWIREDEBUG > 0
IOReturn result =
#endif
IOFireWireUserClient::sendAsyncResult( cmd->fAsyncRef, status, (void**)& sendResult, sizeof(sendResult)/sizeof(UInt32) ) ; IOFireWireUserClientLogIfErr_( result, "IOFireWireUserClient::asyncCompareSwapCommandCompletion: sendAsyncResult returned error 0x%08x\n", result) ;
}
}