IOFWWriteCommand.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/IOSyncer.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOCommand.h>
OSDefineMetaClassAndStructors(IOFWWriteCommand, IOFWAsyncCommand)
OSMetaClassDefineReservedUnused(IOFWWriteCommand, 0);
OSMetaClassDefineReservedUnused(IOFWWriteCommand, 1);
#pragma mark -
bool IOFWWriteCommand::initWithController(IOFireWireController *control)
{
bool success = true;
fWrite = true;
success = IOFWAsyncCommand::initWithController(control);
if( success )
{
success = createMemberVariables();
}
return success;
}
bool IOFWWriteCommand::initAll( IOFireWireNub * device,
FWAddress devAddress,
IOMemoryDescriptor * hostMem,
FWDeviceCallback completion,
void * refcon,
bool failOnReset )
{
bool success = true;
fWrite = true;
success = IOFWAsyncCommand::initAll( device, devAddress, hostMem,
completion, refcon, failOnReset);
if( success )
{
success = createMemberVariables();
}
return success;
}
bool IOFWWriteCommand::initAll( IOFireWireController * control,
UInt32 generation,
FWAddress devAddress,
IOMemoryDescriptor * hostMem,
FWDeviceCallback completion,
void * refcon )
{
bool success = true;
fWrite = true;
success = IOFWAsyncCommand::initAll(control, generation, devAddress,
hostMem, completion, refcon);
if( success )
{
success = createMemberVariables();
}
return success;
}
bool IOFWWriteCommand::createMemberVariables( void )
{
bool success = true;
if( fMembers == NULL )
{
success = IOFWAsyncCommand::createMemberVariables();
}
if( fMembers )
{
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 IOFWWriteCommand::destroyMemberVariables( void )
{
if( fMembers->fSubclassMembers != NULL )
{
IOFree( fMembers->fSubclassMembers, sizeof(MemberVariables) );
fMembers->fSubclassMembers = NULL;
}
}
void IOFWWriteCommand::free()
{
destroyMemberVariables();
IOFWAsyncCommand::free();
}
IOReturn IOFWWriteCommand::reinit( FWAddress devAddress,
IOMemoryDescriptor * hostMem,
FWDeviceCallback completion,
void * refcon,
bool failOnReset )
{
return IOFWAsyncCommand::reinit( devAddress,
hostMem,
completion,
refcon,
failOnReset );
}
IOReturn IOFWWriteCommand::reinit( UInt32 generation,
FWAddress devAddress,
IOMemoryDescriptor * hostMem,
FWDeviceCallback completion,
void * refcon )
{
return IOFWAsyncCommand::reinit( generation,
devAddress,
hostMem,
completion,
refcon );
}
IOReturn IOFWWriteCommand::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 &&
((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify )
{
flags |= kIOFWWriteFlagsDeferredNotify;
}
if( fMembers &&
fMembers->fSubclassMembers &&
((MemberVariables*)fMembers->fSubclassMembers)->fFastRetryOnBusy )
{
flags |= kIOFWWriteFastRetryOnBusy;
}
result = fControl->asyncWrite( fGeneration,
fNodeID,
fAddressHi,
fAddressLo,
fSpeed,
fTrans->fTCode,
fMemDesc,
fBytesTransferred,
fPackSize,
this,
(IOFWWriteFlags)flags );
}
else
{
result = kIOFireWireOutOfTLabels;
}
IOReturn status = fStatus;
if( result != kIOReturnSuccess )
{
retain();
complete( result );
status = fStatus;
release();
}
return status;
}
void IOFWWriteCommand::gotPacket( int rcode, const void* data, int size )
{
setResponseCode( rcode );
if( rcode != kFWResponseComplete )
{
complete( kIOFireWireResponseBase+rcode );
return;
}
else
{
fBytesTransferred += fPackSize;
fSize -= fPackSize;
}
if( fSize > 0 )
{
fAddressLo += fPackSize;
updateTimer();
fCurRetries = fMaxRetries;
fControl->freeTrans( fTrans ); execute();
}
else
{
complete( kIOReturnSuccess );
}
}