IOFWWriteQuadCommand.cpp [plain text]
#include <IOKit/firewire/IOFWCommand.h>
#include <IOKit/firewire/IOFireWireController.h>
#include <IOKit/firewire/IOFireWireNub.h>
#include <IOKit/firewire/IOLocalConfigDirectory.h>
#include <IOKit/assert.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOCommand.h>
OSDefineMetaClassAndStructors(IOFWWriteQuadCommand, IOFWAsyncCommand)
OSMetaClassDefineReservedUnused(IOFWWriteQuadCommand, 0);
OSMetaClassDefineReservedUnused(IOFWWriteQuadCommand, 1);
#pragma mark -
bool IOFWWriteQuadCommand::initWithController(IOFireWireController *control)
{
bool success = true;
fWrite = true;
success = IOFWAsyncCommand::initWithController(control);
if( success )
{
success = createMemberVariables();
}
if( success )
{
success = createMemoryDescriptor();
}
return success;
}
bool IOFWWriteQuadCommand::initAll( IOFireWireNub * device,
FWAddress devAddress,
UInt32 * quads,
int numQuads,
FWDeviceCallback completion,
void * refcon,
bool failOnReset )
{
bool result = true;
if( numQuads > kMaxWriteQuads )
{
result = false;
}
if( result )
{
fWrite = true;
result = IOFWAsyncCommand::initAll( device,
devAddress,
NULL,
completion,
refcon,
failOnReset);
}
if( result )
{
result = createMemberVariables();
}
if( result )
{
((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify = false;
setQuads( quads, numQuads );
}
if( result )
{
result = createMemoryDescriptor();
}
return result;
}
bool IOFWWriteQuadCommand::initAll( IOFireWireController * control,
UInt32 generation,
FWAddress devAddress,
UInt32 * quads,
int numQuads,
FWDeviceCallback completion,
void * refcon )
{
bool result = true;
if( numQuads > kMaxWriteQuads )
{
result = false;
}
if( result )
{
fWrite = true;
result = IOFWAsyncCommand::initAll( control,
generation,
devAddress,
NULL,
completion,
refcon );
}
if( result )
{
result = createMemberVariables();
}
if( result )
{
((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify = false;
setQuads( quads, numQuads );
}
if( result )
{
result = createMemoryDescriptor();
}
return result;
}
bool IOFWWriteQuadCommand::createMemberVariables( void )
{
bool success = true;
if( fMembers == NULL )
{
success = IOFWAsyncCommand::createMemberVariables();
}
if( fMembers && fMembers->fSubclassMembers == NULL )
{
if( success )
{
fMembers->fSubclassMembers = IOMalloc( sizeof(MemberVariables) );
if( fMembers->fSubclassMembers == NULL )
success = false;
}
if( success )
{
bzero( fMembers->fSubclassMembers, sizeof(MemberVariables) );
}
if( !success )
{
destroyMemberVariables();
}
}
return success;
}
void IOFWWriteQuadCommand::destroyMemberVariables( void )
{
if( fMembers->fSubclassMembers != NULL )
{
IOFree( fMembers->fSubclassMembers, sizeof(MemberVariables) );
fMembers->fSubclassMembers = NULL;
}
}
bool IOFWWriteQuadCommand::createMemoryDescriptor( void )
{
bool result = true;
bool prepared = false;
if( result )
{
((MemberVariables*)fMembers->fSubclassMembers)->fMemory = IOMemoryDescriptor::withAddress( fQuads, kMaxWriteQuads * sizeof(UInt32), kIODirectionOutIn );
if( ((MemberVariables*)fMembers->fSubclassMembers)->fMemory == NULL )
result = false;
}
if( result )
{
IOReturn status = ((MemberVariables*)fMembers->fSubclassMembers)->fMemory->prepare( kIODirectionOutIn );
if( status == kIOReturnSuccess )
{
prepared = true;
}
else
{
result = false;
}
}
if( !result )
{
if( ((MemberVariables*)fMembers->fSubclassMembers)->fMemory != NULL )
{
if( prepared )
{
((MemberVariables*)fMembers->fSubclassMembers)->fMemory->complete( kIODirectionOutIn );
}
((MemberVariables*)fMembers->fSubclassMembers)->fMemory->release();
((MemberVariables*)fMembers->fSubclassMembers)->fMemory = NULL;
}
}
return result;
}
void IOFWWriteQuadCommand::destroyMemoryDescriptor()
{
if( (fMembers != NULL) &&
(fMembers->fSubclassMembers != NULL) &&
((MemberVariables*)fMembers->fSubclassMembers)->fMemory != NULL )
{
((MemberVariables*)fMembers->fSubclassMembers)->fMemory->complete( kIODirectionOutIn );
((MemberVariables*)fMembers->fSubclassMembers)->fMemory->release();
((MemberVariables*)fMembers->fSubclassMembers)->fMemory = NULL;
}
}
void IOFWWriteQuadCommand::free()
{
destroyMemoryDescriptor();
destroyMemberVariables();
IOFWAsyncCommand::free();
}
IOReturn IOFWWriteQuadCommand::reinit( FWAddress devAddress,
UInt32 * quads,
int numQuads,
FWDeviceCallback completion,
void * refcon,
bool failOnReset )
{
IOReturn status = kIOReturnSuccess;
if(numQuads > kMaxWriteQuads)
{
status = kIOReturnUnsupported;
}
if( status == kIOReturnSuccess )
{
status = IOFWAsyncCommand::reinit( devAddress,
NULL,
completion,
refcon,
failOnReset );
}
if( status == kIOReturnSuccess )
{
setQuads( quads, numQuads );
}
return status;
}
IOReturn IOFWWriteQuadCommand::reinit( UInt32 generation,
FWAddress devAddress,
UInt32 * quads,
int numQuads,
FWDeviceCallback completion,
void * refcon )
{
IOReturn status = kIOReturnSuccess;
if( numQuads > kMaxWriteQuads )
{
status = kIOReturnUnsupported;
}
if( status == kIOReturnSuccess )
{
status = IOFWAsyncCommand::reinit( generation, devAddress, NULL, completion, refcon );
}
if( status == kIOReturnSuccess )
{
setQuads( quads, numQuads );
}
return status;
}
void IOFWWriteQuadCommand::setQuads( UInt32 * quads, int numQuads )
{
int i;
fSize = 4 * numQuads;
for( i = 0; i < numQuads; i++ )
{
fQuads[i] = *quads++;
}
fQPtr = fQuads;
}
IOReturn IOFWWriteQuadCommand::execute()
{
IOReturn result;
fStatus = kIOReturnBusy;
if( !fFailOnReset )
{
fDevice->getNodeIDGeneration( fGeneration, fNodeID );
fSpeed = fControl->FWSpeed( fNodeID );
if( fMembers->fMaxSpeed < fSpeed )
{
fSpeed = fMembers->fMaxSpeed;
}
}
fPackSize = fSize;
if( fPackSize > fMaxPack )
{
fPackSize = fMaxPack;
}
int maxPack = (1 << fControl->maxPackLog(fWrite, fNodeID));
if( maxPack < fPackSize )
{
fPackSize = maxPack;
}
fTrans = fControl->allocTrans( this );
if( fTrans )
{
UInt32 flags = kIOFWWriteFlagsNone;
if( fMembers && fMembers->fSubclassMembers )
{
if( ((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify )
{
flags |= kIOFWWriteFlagsDeferredNotify;
}
if( ((IOFWAsyncCommand::MemberVariables*)fMembers)->fForceBlockRequests )
{
flags |= kIOFWWriteBlockRequest;
}
}
result = fControl->asyncWrite( fGeneration,
fNodeID,
fAddressHi,
fAddressLo,
fSpeed,
fTrans->fTCode,
((MemberVariables*)fMembers->fSubclassMembers)->fMemory,
0,
fPackSize,
this,
(IOFWWriteFlags)flags );
}
else
{
result = kIOFireWireOutOfTLabels;
}
IOReturn status = fStatus;
if( result != kIOReturnSuccess )
{
retain();
complete( result );
status = fStatus;
release();
}
return status;
}
void IOFWWriteQuadCommand::gotPacket( int rcode, const void* data, int size )
{
setResponseCode( rcode );
if( rcode != kFWResponseComplete )
{
complete( kIOFireWireResponseBase+rcode );
return;
}
else
{
fQPtr += fPackSize / 4;
fSize -= fPackSize;
fBytesTransferred += fPackSize ;
}
if( fSize > 0 )
{
fAddressLo += fPackSize;
updateTimer();
fCurRetries = fMaxRetries;
fControl->freeTrans( fTrans );
execute();
}
else
{
complete( kIOReturnSuccess );
}
}