IOFWCompareAndSwapCommand.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(IOFWCompareAndSwapCommand, IOFWAsyncCommand)
OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 0);
OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 1);
OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 2);
OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 3);
#pragma mark -
bool IOFWCompareAndSwapCommand::initWithController(IOFireWireController *control)
{
bool result = true;
result = IOFWAsyncCommand::initWithController(control);
if( result )
{
result = createMemberVariables();
}
if( result )
{
result = createMemoryDescriptor();
}
return result;
}
bool IOFWCompareAndSwapCommand::initAll( IOFireWireNub * device,
FWAddress devAddress,
const UInt32 * cmpVal,
const UInt32 * newVal,
int size,
FWDeviceCallback completion,
void * refcon,
bool failOnReset )
{
bool result = true;
result = IOFWAsyncCommand::initAll( device,
devAddress,
NULL,
completion,
refcon,
failOnReset );
if( result )
{
result = createMemberVariables();
}
if( result )
{
setInputVals( cmpVal, newVal, size );
}
if( result )
{
result = createMemoryDescriptor();
}
return result;
}
bool IOFWCompareAndSwapCommand::initAll( IOFireWireController * control,
UInt32 generation,
FWAddress devAddress,
const UInt32 * cmpVal,
const UInt32 * newVal,
int size,
FWDeviceCallback completion,
void * refcon )
{
bool result = true;
result = IOFWAsyncCommand::initAll( control,
generation,
devAddress,
NULL,
completion,
refcon );
if( result )
{
result = createMemberVariables();
}
if( result )
{
setInputVals( cmpVal, newVal, size );
}
if( result )
{
result = createMemoryDescriptor();
}
return result;
}
bool IOFWCompareAndSwapCommand::createMemberVariables( void )
{
bool success = true;
if( fMembers == NULL )
{
if( success )
{
fMembers = (MemberVariables*)IOMalloc( sizeof(MemberVariables) );
if( fMembers == NULL )
success = false;
}
if( success )
{
bzero( fMembers, sizeof(MemberVariables) );
}
if( !success )
{
destroyMemberVariables();
}
}
return success;
}
void IOFWCompareAndSwapCommand::destroyMemberVariables( void )
{
if( fMembers != NULL )
{
IOFree( fMembers, sizeof(MemberVariables) );
fMembers = NULL;
}
}
bool IOFWCompareAndSwapCommand::createMemoryDescriptor()
{
bool result = true;
bool prepared = false;
if( result )
{
fMembers->fMemory = IOMemoryDescriptor::withAddress( fInputVals, 4 * sizeof(UInt32), kIODirectionOutIn );
if( fMembers->fMemory == NULL )
result = false;
}
if( result )
{
IOReturn status = fMembers->fMemory->prepare( kIODirectionOutIn );
if( status == kIOReturnSuccess )
{
prepared = true;
}
else
{
result = false;
}
}
if( !result )
{
if( fMembers->fMemory != NULL )
{
if( prepared )
{
fMembers->fMemory->complete( kIODirectionOutIn );
}
fMembers->fMemory->release();
fMembers->fMemory = NULL;
}
}
return result;
}
void IOFWCompareAndSwapCommand::destroyMemoryDescriptor()
{
if( fMembers->fMemory != NULL )
{
fMembers->fMemory->complete( kIODirectionOutIn );
fMembers->fMemory->release();
fMembers->fMemory = NULL;
}
}
void IOFWCompareAndSwapCommand::free()
{
destroyMemoryDescriptor();
destroyMemberVariables();
IOFWAsyncCommand::free();
}
IOReturn IOFWCompareAndSwapCommand::reinit( FWAddress devAddress,
const UInt32 * cmpVal,
const UInt32 * newVal,
int size,
FWDeviceCallback completion,
void * refcon,
bool failOnReset )
{
IOReturn status = kIOReturnSuccess;
status = IOFWAsyncCommand::reinit( devAddress, NULL, completion, refcon, failOnReset );
if( status == kIOReturnSuccess )
{
setInputVals( cmpVal, newVal, size );
}
return status;
}
IOReturn IOFWCompareAndSwapCommand::reinit( UInt32 generation,
FWAddress devAddress,
const UInt32 * cmpVal,
const UInt32 * newVal,
int size,
FWDeviceCallback completion,
void * refcon )
{
IOReturn status = kIOReturnSuccess;
status = IOFWAsyncCommand::reinit( generation, devAddress, NULL, completion, refcon );
if( status == kIOReturnSuccess )
{
setInputVals( cmpVal, newVal, size );
}
return status;
}
void IOFWCompareAndSwapCommand::setInputVals( const UInt32 * cmpVal, const UInt32 * newVal, int size )
{
int i;
for( i = 0; i < size; i++ )
{
fInputVals[i] = cmpVal[i];
fInputVals[size+i] = newVal[i];
}
fSize = 8 * size;
}
IOReturn IOFWCompareAndSwapCommand::execute()
{
IOReturn result;
fStatus = kIOReturnBusy;
if( !fFailOnReset )
{
fDevice->getNodeIDGeneration(fGeneration, fNodeID);
fSpeed = fControl->FWSpeed( fNodeID );
if( IOFWAsyncCommand::fMembers->fMaxSpeed < fSpeed )
{
fSpeed = IOFWAsyncCommand::fMembers->fMaxSpeed;
}
}
fTrans = fControl->allocTrans(this);
if( fTrans )
{
result = fControl->asyncLock( fGeneration,
fNodeID,
fAddressHi,
fAddressLo,
fSpeed,
fTrans->fTCode,
kFWExtendedTCodeCompareSwap,
fMembers->fMemory,
0,
fSize,
this );
}
else
{
IOLog("IOFWCompareAndSwapCommand::execute: Out of tLabels?\n");
result = kIOFireWireOutOfTLabels;
}
IOReturn status = fStatus;
if( result != kIOReturnSuccess )
{
retain();
complete(result);
status = fStatus;
release();
}
else
{
fBytesTransferred = fSize ;
}
return status;
}
bool IOFWCompareAndSwapCommand::locked( UInt32 * oldVal )
{
int i;
bool result = true;
for( i = 0; i < fSize / 8; i++ )
{
result = result && (fInputVals[i] == fOldVal[i]);
oldVal[i] = fOldVal[i];
}
return result;
}
void IOFWCompareAndSwapCommand::gotPacket( int rcode, const void* data, int size )
{
int i;
if( rcode != kFWResponseComplete )
{
complete( kIOFireWireResponseBase + rcode );
return;
}
for( i = 0; i < size / 4; i++ )
{
fOldVal[i] = ((UInt32 *)data)[i];
}
complete( kIOReturnSuccess );
}