IOFireWireSBP2Login.cpp [plain text]
#include <IOKit/IOMessage.h>
#include <IOKit/sbp2/IOFireWireSBP2Login.h>
#include <IOKit/sbp2/IOFireWireSBP2LUN.h>
#include <IOKit/sbp2/IOFireWireSBP2Target.h>
#include <IOKit/firewire/IOFireWireController.h>
#include <IOKit/firewire/IOConfigDirectory.h>
#include "FWDebugging.h"
#include "IOFireWireSBP2Diagnostics.h"
OSDefineMetaClassAndStructors( IOFireWireSBP2Login, OSObject );
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 0);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 1);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 2);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 3);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 4);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 5);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 6);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 7);
OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 8);
bool IOFireWireSBP2Login::initWithLUN( IOFireWireSBP2LUN * lun )
{
IOReturn status = kIOReturnSuccess;
fLUN = lun;
fUnit = fLUN->getFireWireUnit();
fControl = fUnit->getController();
fRefCon = NULL;
fLoginGeneration = 0;
fLoginNodeID = 0;
fLoginFlags = 0;
fMaxPayloadSize = 4;
fStatusBlockAddressSpace = NULL;
fStatusNotifyCallback = NULL;
fStatusNotifyRefCon = NULL;
fUnsolicitedStatusNotifyCallback = NULL;
fUnsolicitedStatusNotifyRefCon = NULL;
fLoginORBAddressSpace = NULL;
fLoginResponseAddressSpace = NULL;
fLoginTimeoutTimerSet = false;
fLoginWriteCommand = NULL;
fLoginWriteCommandMemory = NULL;
fLoginWriteInProgress = false;
fLoginCompletionCallback = NULL;
fLoginCompletionRefCon = NULL;
fReconnectORBAddressSpace = NULL;
fReconnectStatusBlockAddressSpace = NULL;
fReconnectTime = 0;
fReconnectTimeoutTimerSet = false;
fReconnectWriteCommand = NULL;
fReconnectWriteCommandMemory = NULL;
fReconnectWriteInProgress = false;
fReconnectWriteInterrupted = false;
fLogoutORBAddressSpace = NULL;
fLogoutTimeoutTimerSet = false;
fLogoutWriteInProgress = false;
fLogoutWriteCommand = NULL;
fLogoutWriteCommandMemory = NULL;
fLogoutCompletionCallback = NULL;
fLogoutCompletionRefCon = NULL;
fFetchAgentWriteCommandInUse = false;
fFetchAgentWriteCommand = NULL;
fFetchAgentWriteCommandMemory = NULL;
fFetchAgentWriteCompletion = NULL;
fFetchAgentResetInProgress = false;
fFetchAgentResetCommand = NULL;
fFetchAgentResetRefCon = NULL;
fFetchAgentResetCompletion = NULL;
fDoorbellInProgress = false;
fDoorbellRingAgain = false;
fDoorbellCommand = NULL;
fUnsolicitedStatusEnableInProgress = false;
fUnsolicitedStatusEnableCommand = NULL;
fSetBusyTimeoutBuffer = 0x0000000f;
fSetBusyTimeoutInProgress = false;
fSetBusyTimeoutAddress = FWAddress( 0x0000FFFF, 0xF0000210 );
fSetBusyTimeoutCommand = NULL;
fPasswordBuf = NULL;
fPasswordLen = 0;
fPasswordAddressSpace = NULL;
fPasswordAddress = NULL;
fPasswordDescriptor = NULL;
fSuspended = false;
IOWorkLoop * workLoop = NULL;
if( status == kIOReturnSuccess )
{
workLoop = fLUN->getWorkLoop();
if( !workLoop )
status = kIOReturnNoResources;
}
if( status == kIOReturnSuccess )
{
fGate = IOCommandGate::commandGate( this );
if( !fGate )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
workLoop->retain();
workLoop->addEventSource( fGate );
}
if( status == kIOReturnSuccess )
{
fLoginState = kLoginStateIdle;
status = getUnitInformation();
FWKLOG( ( "IOFireWireSBP2Login : fManagementOffset = 0x%lx, fMaxORBSize = %d, fMaxCommandBlockSize = %d, success = %d\n", fManagementOffset, fMaxORBSize, fMaxCommandBlockSize ) );
}
if( status == kIOReturnSuccess )
{
status = allocateResources();
}
if( status == kIOReturnSuccess )
{
fORBSet = OSSet::withCapacity(1);
if( fORBSet == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fORBSetIterator = OSCollectionIterator::withCollection( fORBSet );
}
return (status == kIOReturnSuccess);
}
IOReturn IOFireWireSBP2Login::getUnitInformation( void )
{
IOReturn status = kIOReturnSuccess;
IOConfigDirectory * directory;
status = fUnit->getConfigDirectory( directory );
FWKLOG( ("IOFireWireSBP2Login : status = %d\n", status) );
if( status == kIOReturnSuccess )
{
FWAddress tempAddress;
directory->getKeyOffset( kManagementAgentOffsetKey, tempAddress );
fManagementOffset = (tempAddress.addressLo & 0x0fffffff) >> 2;
}
FWKLOG( ("IOFireWireSBP2Login : status = %d, fManagementOffset = %d\n", status, fManagementOffset) );
UInt32 unitCharacteristics;
if( status == kIOReturnSuccess )
status = directory->getKeyValue( kUnitCharacteristicsKey, unitCharacteristics );
if( status == kIOReturnSuccess )
{
fManagementTimeout = ((unitCharacteristics >> 8) & 0xff) * 500; UInt32 orbSize = (unitCharacteristics & 0xff) * 4;
if( orbSize < 32 )
orbSize = 32;
fMaxORBSize = orbSize;
fMaxCommandBlockSize = orbSize;
}
return status;
}
IOReturn IOFireWireSBP2Login::allocateResources( void )
{
IOReturn status = kIOReturnSuccess;
if( status == kIOReturnSuccess )
{
fLoginORBAddressSpace = IOFWPseudoAddressSpace::simpleRead( fControl, &fLoginORBAddress, sizeof(FWSBP2LoginORB), &fLoginORB );
if ( fLoginORBAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fLoginORBAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fLoginResponseAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fLoginResponseAddress,
sizeof(FWSBP2LoginResponse),
&fLoginResponse );
if ( fLoginResponseAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fLoginResponseAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fReconnectORBAddressSpace = IOFWPseudoAddressSpace::simpleRead( fControl, &fReconnectORBAddress,
sizeof(FWSBP2ReconnectORB),
&fReconnectORB );
if ( fReconnectORBAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fReconnectORBAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fStatusBlockAddressSpace = fUnit->createPseudoAddressSpace( &fStatusBlockAddress, sizeof(FWSBP2StatusBlock),
NULL, IOFireWireSBP2Login::statusBlockWriteStatic,
this );
if ( fStatusBlockAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fStatusBlockAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fReconnectStatusBlockAddressSpace =
fUnit->createPseudoAddressSpace( &fReconnectStatusBlockAddress, sizeof(FWSBP2StatusBlock),
NULL, IOFireWireSBP2Login::reconnectStatusBlockWriteStatic, this );
if ( fReconnectStatusBlockAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fReconnectStatusBlockAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fLogoutORBAddressSpace = IOFWPseudoAddressSpace::simpleRead( fControl, &fLogoutORBAddress, sizeof(FWSBP2LogoutORB),
&fLogoutORB );
if ( fLogoutORBAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fLogoutORBAddressSpace->activate();
}
fLoginORB.loginResponseAddressHi = (fLoginResponseAddress.nodeID << 16) | fLoginResponseAddress.addressHi;
fLoginORB.loginResponseAddressLo = fLoginResponseAddress.addressLo;
fLoginORB.loginResponseLength = sizeof( FWSBP2LoginResponse );
fLoginORB.lun = fLUN->getLUNumber();
FWKLOG( ("lun number = %d\n", fLoginORB.lun) );
fLoginORB.statusFIFOAddressHi = (fStatusBlockAddress.nodeID << 16) | fStatusBlockAddress.addressHi;
fLoginORB.statusFIFOAddressLo = fStatusBlockAddress.addressLo;
fReconnectORB.options = 3 | 0x8000; fReconnectORB.statusFIFOAddressHi = (fReconnectStatusBlockAddress.nodeID << 16) | fReconnectStatusBlockAddress.addressHi;
fReconnectORB.statusFIFOAddressLo = fReconnectStatusBlockAddress.addressLo;
fLogoutORB.options = 7 | 0x8000; fLogoutORB.statusFIFOAddressHi = (fStatusBlockAddress.nodeID << 16) | fStatusBlockAddress.addressHi;
fLogoutORB.statusFIFOAddressLo = fStatusBlockAddress.addressLo;
if( status == kIOReturnSuccess )
{
fLoginWriteCommandMemory = IOMemoryDescriptor::withAddress( &fLoginORBAddress, 8, kIODirectionOut);
if( fLoginWriteCommandMemory == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fLoginWriteCommand = fUnit->createWriteCommand( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)),
fLoginWriteCommandMemory,
IOFireWireSBP2Login::loginWriteCompleteStatic, this, true );
if( fLoginWriteCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fLoginTimeoutCommand = fControl->createDelayedCmd( fManagementTimeout * 1000,
IOFireWireSBP2Login::loginTimeoutStatic, this);
}
if( status == kIOReturnSuccess )
{
fReconnectWriteCommandMemory = IOMemoryDescriptor::withAddress( &fReconnectORBAddress, 8, kIODirectionOut);
if( fReconnectWriteCommandMemory == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fReconnectWriteCommand = fUnit->createWriteCommand( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)),
fReconnectWriteCommandMemory,
IOFireWireSBP2Login::reconnectWriteCompleteStatic, this, true );
if( fReconnectWriteCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fReconnectTimeoutCommand = (IOFWDelayCommand*)fControl->createDelayedCmd( ((fManagementTimeout + 1000) * 1000),
IOFireWireSBP2Login::reconnectTimeoutStatic, this);
if( !fReconnectTimeoutCommand )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fLogoutWriteCommandMemory = IOMemoryDescriptor::withAddress( &fLogoutORBAddress, 8, kIODirectionOut);
if( fLogoutWriteCommandMemory == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fLogoutWriteCommand = fUnit->createWriteCommand( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)),
fLogoutWriteCommandMemory,
IOFireWireSBP2Login::logoutWriteCompleteStatic, this, true );
if( fLogoutWriteCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fLogoutTimeoutCommand = fControl->createDelayedCmd( fManagementTimeout * 1000,
IOFireWireSBP2Login::loginTimeoutStatic, this);
}
if( status == kIOReturnSuccess )
{
fFetchAgentWriteCommandMemory = IOMemoryDescriptor::withAddress( &fLastORBAddress, 8, kIODirectionOut );
if( fFetchAgentWriteCommandMemory == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fFetchAgentWriteCommand = fUnit->createWriteCommand( FWAddress(0,0), fFetchAgentWriteCommandMemory,
IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true );
if( fFetchAgentWriteCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fFetchAgentResetCommand = fUnit->createWriteQuadCommand( FWAddress(0,0), &fFetchAgentResetBuffer, 1,
IOFireWireSBP2Login::fetchAgentResetCompleteStatic,
this, true );
if( fFetchAgentResetCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fDoorbellCommand = fUnit->createWriteQuadCommand( FWAddress(0,0), &fDoorbellBuffer, 1,
IOFireWireSBP2Login::doorbellCompleteStatic,
this, true );
if( fDoorbellCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fSetBusyTimeoutCommand = fUnit->createWriteQuadCommand( fSetBusyTimeoutAddress,
&fSetBusyTimeoutBuffer, 1,
IOFireWireSBP2Login::setBusyTimeoutCompleteStatic,
this, true );
if( fSetBusyTimeoutCommand == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
fUnsolicitedStatusEnableCommand = fUnit->createWriteQuadCommand( FWAddress(0,0), &fUnsolicitedStatusEnableBuffer, 1,
IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic,
this, true );
if( fUnsolicitedStatusEnableCommand == NULL )
status = kIOReturnNoMemory;
}
return status;
}
void IOFireWireSBP2Login::release() const
{
if( getRetainCount() >= 2 )
OSObject::release(2);
}
void IOFireWireSBP2Login::free( void )
{
IOReturn status = kIOReturnSuccess;
FWKLOG( ( "IOFireWireSBP2Login : free called\n" ) );
removeLogin();
if( fFetchAgentResetInProgress )
fFetchAgentResetCommand->cancel( kIOReturnAborted );
if( fFetchAgentResetCommand )
fFetchAgentResetCommand->release();
if( fDoorbellInProgress )
fDoorbellCommand->cancel( kIOReturnAborted );
if( fDoorbellCommand )
fDoorbellCommand->release();
if( fUnsolicitedStatusEnableInProgress )
fUnsolicitedStatusEnableCommand->cancel( kIOReturnAborted );
if( fUnsolicitedStatusEnableCommand )
fUnsolicitedStatusEnableCommand->release();
if( fSetBusyTimeoutInProgress )
fSetBusyTimeoutCommand->cancel( kIOReturnAborted );
if( fSetBusyTimeoutCommand )
fSetBusyTimeoutCommand->release();
if( fLoginWriteInProgress )
fLoginWriteCommand->cancel( kIOReturnAborted );
if( fLoginWriteCommand != NULL )
fLoginWriteCommand->release();
if( fLoginWriteCommandMemory != NULL )
fLoginWriteCommandMemory->release();
if( fLoginTimeoutTimerSet )
fLoginTimeoutCommand->cancel(kIOReturnAborted);
if( fLoginTimeoutCommand )
fLoginTimeoutCommand->release();
if( fLoginORBAddressSpace != NULL && status == kIOReturnSuccess )
{
fLoginORBAddressSpace->deactivate();
fLoginORBAddressSpace->release();
}
if( fLoginResponseAddressSpace != NULL && status == kIOReturnSuccess )
{
fLoginResponseAddressSpace->deactivate();
fLoginResponseAddressSpace->release();
}
if( fReconnectWriteInProgress )
fReconnectWriteCommand->cancel(kIOReturnAborted);
if( fReconnectWriteCommand != NULL )
fReconnectWriteCommand->release();
if( fReconnectWriteCommandMemory != NULL )
fReconnectWriteCommandMemory->release();
if( fReconnectTimeoutTimerSet )
fReconnectTimeoutCommand->cancel(kIOReturnAborted);
if( fReconnectTimeoutCommand )
fReconnectTimeoutCommand->release();
if( fReconnectORBAddressSpace != NULL && status == kIOReturnSuccess )
{
fReconnectORBAddressSpace->deactivate();
fReconnectORBAddressSpace->release();
}
if( fReconnectStatusBlockAddressSpace != NULL && status == kIOReturnSuccess )
{
fReconnectStatusBlockAddressSpace->deactivate();
fReconnectStatusBlockAddressSpace->release();
}
if( fLogoutWriteInProgress )
fLogoutWriteCommand->cancel(kIOReturnAborted);
if( fLogoutWriteCommand != NULL )
fLogoutWriteCommand->release();
if( fLogoutWriteCommandMemory != NULL )
fLogoutWriteCommandMemory->release();
if( fLogoutTimeoutTimerSet )
fLogoutTimeoutCommand->cancel(kIOReturnAborted);
if( fLogoutTimeoutCommand )
fLogoutTimeoutCommand->release();
if( fLogoutORBAddressSpace != NULL && status == kIOReturnSuccess )
{
fLogoutORBAddressSpace->deactivate();
fLogoutORBAddressSpace->release();
}
if( fFetchAgentWriteCommandInUse )
fFetchAgentWriteCommand->cancel(kIOReturnAborted);
if( fFetchAgentWriteCommand != NULL )
fFetchAgentWriteCommand->release();
if( fFetchAgentWriteCommandMemory != NULL )
fFetchAgentWriteCommandMemory->release();
if( fStatusBlockAddressSpace != NULL && status == kIOReturnSuccess )
{
fStatusBlockAddressSpace->deactivate();
fStatusBlockAddressSpace->release();
}
if( fPasswordAddressSpace != NULL )
{
fPasswordAddressSpace->deactivate();
fPasswordAddressSpace->release();
}
if( fORBSetIterator )
{
IOFireWireSBP2ORB * item = NULL;
do
{
fORBSetIterator->reset();
item = (IOFireWireSBP2ORB *)fORBSetIterator->getNextObject();
if( item )
item->release();
} while( item );
fORBSetIterator->release();
}
if( fORBSet )
fORBSet->release();
if( fGate != NULL )
{
IOWorkLoop * workLoop = NULL;
workLoop = fGate->getWorkLoop();
workLoop->removeEventSource( fGate );
workLoop->release();
fGate->release();
fGate = NULL;
}
OSObject::free();
}
IOFireWireUnit * IOFireWireSBP2Login::getFireWireUnit( void )
{
return fUnit;
}
IOFireWireSBP2LUN * IOFireWireSBP2Login::getFireWireLUN( void )
{
return fLUN;
}
UInt32 IOFireWireSBP2Login::getMaxCommandBlockSize( void )
{
return fMaxCommandBlockSize;
}
UInt32 IOFireWireSBP2Login::getLoginID( void )
{
return fLoginID;
}
void IOFireWireSBP2Login::setRefCon( void * refCon )
{
fRefCon = refCon;
}
void * IOFireWireSBP2Login::getRefCon( void )
{
return fRefCon;
}
void IOFireWireSBP2Login::setLoginFlags( UInt32 loginFlags )
{
fLoginFlags = loginFlags;
FWKLOG(( "IOFireWireSBP2Login : setLoginFlags : 0x%08lx\n", fLoginFlags ));
}
UInt32 IOFireWireSBP2Login::getLoginFlags( void )
{
return fLoginFlags;
}
void IOFireWireSBP2Login::setLoginCompletion( void * refCon, FWSBP2LoginCallback completion )
{
fLoginCompletionRefCon = refCon;
fLoginCompletionCallback = completion;
}
void IOFireWireSBP2Login::setLogoutCompletion( void * refCon, FWSBP2LogoutCallback completion )
{
fLogoutCompletionRefCon = refCon;
fLogoutCompletionCallback = completion;
}
void IOFireWireSBP2Login::setReconnectTime( UInt32 reconnectTime )
{
fReconnectTime = reconnectTime & 0x0000000f;
}
UInt32 IOFireWireSBP2Login::getReconnectTime( void )
{
return fReconnectTime;
}
void IOFireWireSBP2Login::setStatusNotifyProc( void * refCon, FWSBP2NotifyCallback callback )
{
fStatusNotifyCallback = callback;
fStatusNotifyRefCon = refCon;
}
void IOFireWireSBP2Login::getStatusNotifyProc( void ** refCon, FWSBP2NotifyCallback * callback )
{
*callback = fStatusNotifyCallback;
*refCon = fStatusNotifyRefCon;
}
void IOFireWireSBP2Login::setUnsolicitedStatusNotifyProc( void * refCon, FWSBP2NotifyCallback callback )
{
fUnsolicitedStatusNotifyCallback = callback;
fUnsolicitedStatusNotifyRefCon = refCon;
}
void IOFireWireSBP2Login::getUnsolicitedStatusNotifyProc( void ** refCon, FWSBP2NotifyCallback * callback )
{
*callback = fStatusNotifyCallback;
*refCon = fStatusNotifyRefCon;
}
void IOFireWireSBP2Login::setMaxPayloadSize( UInt32 maxPayloadSize )
{
fMaxPayloadSize = maxPayloadSize;
}
UInt32 IOFireWireSBP2Login::getMaxPayloadSize( void )
{
return fMaxPayloadSize;
}
IOReturn IOFireWireSBP2Login::setPassword( IOMemoryDescriptor * memory )
{
IOReturn status = kIOReturnSuccess;
IOByteCount len = 0;
if( fPasswordAddressSpace != NULL )
{
fPasswordAddressSpace->deactivate();
fPasswordAddressSpace->release();
fPasswordBuf = NULL;
fPasswordLen = 0;
}
if( fPasswordDescriptor != NULL )
{
fPasswordDescriptor->release();
fPasswordDescriptor = NULL;
}
if( status == kIOReturnSuccess )
{
fPasswordDescriptor = memory;
if( memory == NULL )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
fPasswordDescriptor->retain();
len = fPasswordDescriptor->getLength();
}
if( status == kIOReturnSuccess )
{
if( len <= 8 )
{
fLoginORB.password[0] = 0;
fLoginORB.password[1] = 0;
fLoginORB.passwordLength = 0;
status = memory->readBytes( 0, &(fLoginORB.password), len );
}
else
{
if( status == kIOReturnSuccess )
{
fPasswordAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fPasswordAddress, memory );
if( fPasswordAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fPasswordAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fLoginORB.passwordLength = len;
fLoginORB.password[0] = 0x0000ffff & fPasswordAddress.addressHi;
fLoginORB.password[1] = fPasswordAddress.addressLo;
}
}
}
return status;
}
IOReturn IOFireWireSBP2Login::setPassword( void * buf, UInt32 len )
{
IOReturn status = kIOReturnSuccess;
if( fPasswordAddressSpace != NULL )
{
fPasswordAddressSpace->deactivate();
fPasswordAddressSpace->release();
fPasswordBuf = NULL;
fPasswordLen = 0;
}
if( fPasswordDescriptor != NULL )
{
fPasswordDescriptor->release();
fPasswordDescriptor = NULL;
}
if( len <= 8 )
{
fPasswordBuf = buf;
fPasswordLen = len;
fLoginORB.password[0] = 0;
fLoginORB.password[1] = 0;
bcopy( buf, &(fLoginORB.password), len );
fLoginORB.passwordLength = 0;
}
else
{
if( status == kIOReturnSuccess )
{
fPasswordAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fPasswordAddress, len, buf );
if( fPasswordAddressSpace == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = fPasswordAddressSpace->activate();
}
if( status == kIOReturnSuccess )
{
fPasswordBuf = buf;
fPasswordLen = len;
fLoginORB.passwordLength = len;
fLoginORB.password[0] = 0x0000ffff & fPasswordAddress.addressHi;
fLoginORB.password[1] = fPasswordAddress.addressLo;
}
}
return status;
}
void IOFireWireSBP2Login::completeLogin( IOReturn state, const void *buf, UInt32 len, void * buf2 )
{
FWKLOG( ( "IOFireWireSBP2Login : completeLogin\n" ) );
if( fLoginCompletionCallback != NULL )
{
FWSBP2LoginCompleteParams params;
params.login = this;
params.generation = fLoginGeneration;
params.status = state;
params.loginResponse = (FWSBP2LoginResponsePtr)buf2;
params.statusBlock = (FWSBP2StatusBlock*)buf;
params.statusBlockLength = len;
(*fLoginCompletionCallback)(fLoginCompletionRefCon, ¶ms);
}
}
void IOFireWireSBP2Login::completeLogout( IOReturn state, const void *buf, UInt32 len )
{
FWKLOG( ( "IOFireWireSBP2Login : completeLogout\n" ) );
if( fLogoutCompletionCallback != NULL )
{
FWSBP2LogoutCompleteParams params;
params.login = this;
params.generation = fLoginGeneration;
params.status = state;
params.statusBlock = (FWSBP2StatusBlock*)buf;
params.statusBlockLength = len;
(*fLogoutCompletionCallback)(fLogoutCompletionRefCon, ¶ms);
}
}
IOReturn IOFireWireSBP2Login::submitLogin( void )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteLogin );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteLogin( OSObject *self, void *, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeLogin();
}
IOReturn IOFireWireSBP2Login::executeLogin( void )
{
IOReturn status = kIOReturnSuccess;
FWKLOG( ( "IOFireWireSBP2Login : executeLogin\n" ) );
if( fSuspended )
{
#if 1
completeLogin( kIOReturnError );
return kIOReturnSuccess;
#else
return kIOReturnError;
#endif
}
if( fLoginState != kLoginStateIdle )
{
return kIOReturnExclusiveAccess;
}
fLoginState = kLoginStateLoggingIn;
fLoginResponse.reserved = 0;
fLoginResponse.reconnectHold = 0;
FWKLOG(( "IOFireWireSBP2Login : fLoginFlags : 0x%08lx\n", fLoginFlags ));
fLoginORB.options = 0x0000 | 0x8000; fLoginORB.options |= (fReconnectTime << 4);
if( fLoginFlags & kFWSBP2ExclusiveLogin )
fLoginORB.options |= 0x1000;
fLoginWriteCommand->reinit( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)),
fLoginWriteCommandMemory, IOFireWireSBP2Login::loginWriteCompleteStatic,
this, true );
UInt16 unitNode; fUnit->getNodeIDGeneration(fLoginGeneration, unitNode, fLoginNodeID);
fLoginWriteInProgress = true;
status = fLoginWriteCommand->submit();
if( status != kIOReturnSuccess )
{
fLoginWriteInProgress = false;
fLoginState = kLoginStateIdle;
return status;
}
return kIOReturnSuccess;
}
void IOFireWireSBP2Login::loginWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device,
IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->loginWriteComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::loginWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ("IOFireWireSBP2Login : login write complete\n") );
fLoginWriteInProgress = false;
if( status == kIOReturnSuccess )
{
fLoginTimeoutTimerSet = true;
if( fLoginTimeoutCommand->submit() != kIOReturnSuccess )
fLoginTimeoutTimerSet = false;
}
else
{
fLoginState = kLoginStateIdle;
completeLogin( status ); }
}
void IOFireWireSBP2Login::loginTimeoutStatic( void *refcon, IOReturn status,
IOFireWireBus *bus, IOFWBusCommand *fwCmd)
{
((IOFireWireSBP2Login*)refcon)->loginTimeout( status, bus, fwCmd );
}
void IOFireWireSBP2Login::loginTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd)
{
fLoginTimeoutTimerSet = false;
if(status == kIOReturnTimeout)
{
FWKLOG( ("IOFireWireSBP2Login : login timed out\n") );
fLoginState = kLoginStateIdle;
completeLogin( kIOReturnTimeout );
}
}
void IOFireWireSBP2Login::abortLogin( void )
{
if( fLoginWriteInProgress )
fLoginWriteCommand->cancel( kIOReturnAborted );
if( fLoginTimeoutTimerSet )
fLoginTimeoutCommand->cancel( kIOReturnAborted );
fLoginState = kLoginStateIdle;
completeLogin( kIOReturnTimeout ); }
UInt32 IOFireWireSBP2Login::statusBlockWriteStatic(void *refcon, UInt16 nodeID, IOFWSpeed &speed,
FWAddress addr, UInt32 len, const void *buf, IOFWRequestRefCon lockRead)
{
return ((IOFireWireSBP2Login*)refcon)->statusBlockWrite( nodeID, speed, addr, len, buf, lockRead );
}
UInt32 IOFireWireSBP2Login::statusBlockWrite( UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len,
const void *buf, IOFWRequestRefCon lockRead )
{
FWKLOG( ( "IOFireWireSBP2Login : status block write\n" ) );
if( len < sizeof(fStatusBlock) )
bcopy( buf, &fStatusBlock, len);
else
bcopy( buf, &fStatusBlock, sizeof(fStatusBlock));
switch( fLoginState )
{
case kLoginStateLoggingIn:
if( fLoginTimeoutTimerSet )
{
fLoginTimeoutCommand->cancel(kIOReturnAborted);
}
if( ((fStatusBlock.details >> 4) & 3) == kFWSBP2RequestComplete &&
fStatusBlock.sbpStatus == kFWSBP2NoSense )
{
FWKLOG( ( "IOFireWireSBP2Login : successful login\n" ) );
fLoginID = fLoginResponse.loginID;
fReconnectORB.loginID = fLoginID;
if( fLoginResponse.length >= 16 )
fReconnectHold = (fLoginResponse.reconnectHold & 0x7fff) + 1;
else
fReconnectHold = 1;
fFetchAgentResetAddress = FWAddress( fLoginResponse.commandBlockAgentAddressHi & 0x0000ffff,
fLoginResponse.commandBlockAgentAddressLo + 0x00000004 );
fFetchAgentResetCommand->reinit( fFetchAgentResetAddress,
&fFetchAgentResetBuffer, 1,
IOFireWireSBP2Login::fetchAgentResetCompleteStatic,
this, true );
fFetchAgentAddress = FWAddress( fLoginResponse.commandBlockAgentAddressHi & 0x0000ffff,
fLoginResponse.commandBlockAgentAddressLo + 0x00000008);
fFetchAgentWriteCommand->reinit( fFetchAgentAddress, fFetchAgentWriteCommandMemory,
IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true );
fDoorbellAddress = FWAddress( fLoginResponse.commandBlockAgentAddressHi & 0x0000ffff,
fLoginResponse.commandBlockAgentAddressLo + 0x00000010 );
fDoorbellCommand->reinit( fDoorbellAddress,
&fDoorbellBuffer, 1,
IOFireWireSBP2Login::doorbellCompleteStatic,
this, true );
fUnsolicitedStatusEnableAddress = FWAddress( fLoginResponse.commandBlockAgentAddressHi & 0x0000ffff,
fLoginResponse.commandBlockAgentAddressLo + 0x00000014 );
fUnsolicitedStatusEnableCommand->reinit( fUnsolicitedStatusEnableAddress,
&fUnsolicitedStatusEnableBuffer, 1,
IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic,
this, true );
fLoginState = kLoginStateConnected;
completeLogin( kIOReturnSuccess, buf, len, &fLoginResponse );
}
else
{
FWKLOG( ( "IOFireWireSBP2Login : login failed\n" ) );
fLoginState = kLoginStateIdle;
completeLogin( kIOReturnError, buf, len, NULL );
}
break;
case kLoginStateConnected:
if( ((*((UInt8*)buf)) & 0xc0) == 0x80 )
{
if( fUnsolicitedStatusNotifyCallback != NULL )
{
FWSBP2NotifyParams params;
params.message = buf;
params.length = len;
params.notificationEvent = kFWSBP2UnsolicitedStatus;
params.generation = fLoginGeneration;
(*fUnsolicitedStatusNotifyCallback)(fUnsolicitedStatusNotifyRefCon, ¶ms );
}
}
else
{
bool found = false;
FWAddress notificationAddress = *((FWAddress*)buf);
IOFireWireSBP2ORB * item = NULL;
fORBSetIterator->reset();
while( (found != true) && (item = (IOFireWireSBP2ORB *) fORBSetIterator->getNextObject()) )
{
FWAddress address;
item->getORBAddress( &address );
if( (notificationAddress.addressHi & 0x0000ffff) == (address.addressHi & 0x0000ffff) &&
notificationAddress.addressLo == address.addressLo )
{
found = true;
}
}
FWKLOG( ( "IOFireWireSBP2Login : solicited found = %d\n", found ) );
FWSBP2StatusBlock * statusBlock = (FWSBP2StatusBlock*)buf;
bool deadBitIsSet = statusBlock->details & 0x08;
if( found )
{
if( isORBTimerSet( item ) )
{
cancelORBTimer( item);
}
else if( item->getCommandTimeout() != 0 )
{
break;
}
if( fStatusNotifyCallback != NULL )
{
FWSBP2NotifyParams params;
params.message = buf;
params.length = len;
params.notificationEvent = kFWSBP2NormalCommandStatus;
params.generation = fLoginGeneration;
params.commandObject = item;
(*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms );
}
}
if( deadBitIsSet )
{
clearAllTasksInSet();
}
}
break;
case kLoginStateLoggingOut:
if( fLogoutTimeoutTimerSet )
{
fLogoutTimeoutCommand->cancel(kIOReturnAborted);
fLogoutTimeoutTimerSet = false;
}
if( ((fStatusBlock.details >> 4) & 3) == kFWSBP2RequestComplete &&
fStatusBlock.sbpStatus == kFWSBP2NoSense )
{
FWKLOG( ( "IOFireWireSBP2Login : successful logout\n" ) );
fLoginState = kLoginStateIdle;
fLoginID = fLoginResponse.loginID;
completeLogout( kIOReturnSuccess, buf, len );
}
else
{
FWKLOG( ( "IOFireWireSBP2Login : logout failed!?\n" ) );
fLoginState = kLoginStateIdle;
completeLogout( kIOReturnError, buf, len );
}
clearAllTasksInSet();
break;
case kLoginStateReconnect:
case kLoginStateIdle:
default:
FWKLOG( ( "IOFireWireSBP2Login : status block write on illegal state\n" ) );
break;
}
return kFWResponseComplete;
}
void IOFireWireSBP2Login::suspendedNotify( void )
{
FWKLOG( ( "IOFireWireSBP2Login : suspendedNotify\n" ) );
fSuspended = true;
switch( fLoginState )
{
case kLoginStateConnected:
startReconnectTimer();
break;
case kLoginStateReconnect:
startReconnectTimer();
break;
case kLoginStateLoggingIn:
abortLogin();
break;
case kLoginStateIdle:
case kLoginStateLoggingOut:
default:
FWKLOG( ("IOFireWireSBP2Login : suspended notify, nothing to do\n") );
break;
}
}
void IOFireWireSBP2Login::resumeNotify( void )
{
FWKLOG( ( "IOFireWireSBP2Login : resume notify\n" ) );
fSuspended = false;
executeSetBusyTimeout();
if( fLogoutPending )
{
fLogoutPending = false;
executeLogout();
}
else
{
switch( fLoginState )
{
case kLoginStateConnected:
doReconnect();
break;
case kLoginStateReconnect:
restartReconnect();
break;
case kLoginStateLoggingIn:
abortLogin();
break;
case kLoginStateIdle:
case kLoginStateLoggingOut:
default:
FWKLOG( ("IOFireWireSBP2Login : resume notify, nothing to do\n") );
break;
}
}
}
void IOFireWireSBP2Login::startReconnectTimer( void )
{
fLoginState = kLoginStateReconnect;
if( fReconnectTimeoutTimerSet )
fReconnectTimeoutCommand->cancel(kIOReturnAborted);
fReconnectTimeoutCommand->reinit( ((fManagementTimeout + 1000) * 1000),
IOFireWireSBP2Login::reconnectTimeoutStatic, this);
fReconnectTimeoutTimerSet = true;
if( fReconnectTimeoutCommand->submit() != kIOReturnSuccess )
fReconnectTimeoutTimerSet = false;
#if FWLOGGING
if( fReconnectTimeoutTimerSet )
FWKLOG( ("IOFireWireSBP2Login : reconnect timeout set for %d microseconds \n", ((fManagementTimeout + 1000) * 1000)) );
#endif
}
void IOFireWireSBP2Login::doReconnect( void )
{
FWKLOG( ("IOFireWireSBP2Login : reconnect\n") );
fReconnectWriteCommand->reinit( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)),
fReconnectWriteCommandMemory, IOFireWireSBP2Login::reconnectWriteCompleteStatic,
this, true );
UInt16 unitNode; fUnit->getNodeIDGeneration(fLoginGeneration, unitNode, fLoginNodeID);
fReconnectWriteInProgress = true;
IOReturn status = fReconnectWriteCommand->submit();
if( status != kIOReturnSuccess ) {
fLoginState = kLoginStateIdle;
fReconnectWriteInProgress = false;
sendReconnectNotification( kIOMessageFWSBP2ReconnectFailed );
}
}
void IOFireWireSBP2Login::restartReconnect( void )
{
if( fReconnectWriteInProgress )
{
fReconnectWriteInterrupted = true;
}
else
{
doReconnect();
}
}
void IOFireWireSBP2Login::reconnectWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device,
IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->reconnectWriteComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::reconnectWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ("IOFireWireSBP2Login : reconnectWriteComplete \n") );
fReconnectWriteInProgress = false;
if( fReconnectWriteInterrupted )
{
fReconnectWriteInterrupted = false;
doReconnect();
return;
}
}
void IOFireWireSBP2Login::reconnectTimeoutStatic( void *refcon, IOReturn status, IOFireWireBus *bus,
IOFWBusCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->reconnectTimeout( status, bus, fwCmd );
}
void IOFireWireSBP2Login::reconnectTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd )
{
fReconnectTimeoutTimerSet = false;
FWKLOG( ("IOFireWireSBP2Login : reconnect timeout proc, status = 0x%08lx\n", status) );
if(status == kIOReturnTimeout)
{
FWKLOG( ("IOFireWireSBP2Login : reconnect timeout\n") );
if( fLoginState == kLoginStateReconnect )
{
fLoginState = kLoginStateIdle;
if( fLogoutPending )
executeLogout();
else
sendReconnectNotification( kIOMessageFWSBP2ReconnectFailed );
}
}
}
UInt32 IOFireWireSBP2Login::reconnectStatusBlockWriteStatic(void *refcon, UInt16 nodeID, IOFWSpeed &speed,
FWAddress addr, UInt32 len, const void *buf,
IOFWRequestRefCon lockRead)
{
return ((IOFireWireSBP2Login*)refcon)->reconnectStatusBlockWrite( nodeID, speed, addr, len, buf, lockRead );
}
UInt32 IOFireWireSBP2Login::reconnectStatusBlockWrite( UInt16 nodeID, IOFWSpeed &speed, FWAddress addr,
UInt32 len, const void *buf, IOFWRequestRefCon lockRead )
{
FWKLOG( ("IOFireWireSBP2Login : reconnect status block write\n") );
if( !fReconnectTimeoutTimerSet )
{
FWKLOG( ("IOFireWireSBP2Login : reconnect status block write after timer went off\n") );
return kFWResponseComplete;
}
if( fLoginGeneration != fControl->getGeneration() )
{
FWKLOG( ("IOFireWireSBP2Login : reconnect status block write for wrong generation\n") );
return kFWResponseComplete;
}
fReconnectTimeoutCommand->cancel(kIOReturnAborted);
if( len < sizeof(fReconnectStatusBlock) )
bcopy( buf, &fReconnectStatusBlock, len);
else
bcopy( buf, &fReconnectStatusBlock, sizeof(fReconnectStatusBlock));
if( ( ( ( fReconnectStatusBlock.details >> 4 ) & 3 ) == kFWSBP2RequestComplete ) &&
( fReconnectStatusBlock.sbpStatus == kFWSBP2NoSense ) )
{
FWKLOG( ( "IOFireWireSBP2Login : successful reconnect\n" ) );
fLastORB = NULL;
fLoginState = kLoginStateConnected;
fFetchAgentWriteCommand->reinit( fFetchAgentAddress,
fFetchAgentWriteCommandMemory,
IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true );
if( fLogoutPending )
{
fLogoutPending = false;
executeLogout();
}
else
sendReconnectNotificationWithStatusBlock( kIOMessageFWSBP2ReconnectComplete );
}
else
{
FWKLOG( ( "IOFireWireSBP2Login : reconnect failed\n" ) );
fLoginState = kLoginStateIdle;
if( fLogoutPending )
{
fLogoutPending = false;
executeLogout();
}
else
sendReconnectNotificationWithStatusBlock( kIOMessageFWSBP2ReconnectFailed );
}
return kFWResponseComplete;
}
void IOFireWireSBP2Login::sendReconnectNotification( UInt32 event )
{
FWSBP2ReconnectParams params;
params.login = this;
params.generation = fLoginGeneration;
params.reconnectStatusBlock = NULL;
params.reconnectStatusBlockLength = 0;
FWKLOG( ( "IOFireWireSBP2Login : arg address 0x%08lx\n", ¶ms ) );
FWKLOG( ( "IOFireWireSBP2Login : reconnectStatusBlock 0x%08lx, reconnectStatusBlockLength 0x%08lx\n", params.reconnectStatusBlock, params.reconnectStatusBlockLength ) );
(fLUN->getTarget())->messageClients( event, ¶ms );
}
void IOFireWireSBP2Login::sendReconnectNotificationWithStatusBlock( UInt32 event )
{
FWSBP2ReconnectParams params;
params.login = this;
params.generation = fLoginGeneration;
params.reconnectStatusBlock = &fReconnectStatusBlock;
params.reconnectStatusBlockLength = sizeof(FWSBP2StatusBlock);
FWKLOG( ( "IOFireWireSBP2Login : arg address 0x%08lx\n", ¶ms ) );
FWKLOG( ( "IOFireWireSBP2Login : reconnectStatusBlock 0x%08lx, reconnectStatusBlockLength 0x%08lx\n", params.reconnectStatusBlock, params.reconnectStatusBlockLength ) );
(fLUN->getTarget())->messageClients( event, ¶ms );
}
IOReturn IOFireWireSBP2Login::submitLogout( void )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteLogout );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteLogout( OSObject *self, void *, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeLogout();
}
IOReturn IOFireWireSBP2Login::executeLogout( void )
{
FWKLOG( ( "IOFireWireSBP2Login : executeLogout\n" ) );
if( fLoginState == kLoginStateLoggingOut || fLogoutPending )
{
return kIOReturnBusy;
}
if( fSuspended )
{
fLogoutPending = true;
}
if( fLoginState == kLoginStateLoggingIn )
{
return kIOReturnBusy;
}
if( fLoginState == kLoginStateReconnect )
{
fLogoutPending = true;
}
if( fLoginState == kLoginStateIdle )
{
return kIOReturnSuccess;
}
if( fLoginState == kLoginStateConnected )
{
fLoginState = kLoginStateLoggingOut;
fLogoutORB.loginID = fLoginID;
fLogoutWriteCommand->reinit( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)),
fLogoutWriteCommandMemory, IOFireWireSBP2Login::logoutWriteCompleteStatic,
this, true );
fLogoutWriteInProgress = true;
IOReturn status = fLogoutWriteCommand->submit();
if( status != kIOReturnSuccess )
{
fLogoutWriteInProgress = false;
return status;
}
}
return kIOReturnSuccess;
}
void IOFireWireSBP2Login::logoutWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device,
IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->logoutWriteComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::logoutWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ( "IOFireWireSBP2Login : logoutWriteComplete \n" ) );
fLogoutWriteInProgress = false;
if( status == kIOReturnSuccess )
{
fLogoutTimeoutTimerSet = true;
if( fLogoutTimeoutCommand->submit() != kIOReturnSuccess )
fLogoutTimeoutTimerSet = false;
}
else
{
fLoginState = kLoginStateIdle;
completeLogout( status ); }
}
void IOFireWireSBP2Login::logoutTimeoutStatic( void *refcon, IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->logoutTimeout( status, bus, fwCmd );
}
void IOFireWireSBP2Login::logoutTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd )
{
FWKLOG( ( "IOFireWireSBP2Login : logoutTimeout \n" ) );
fLogoutTimeoutTimerSet = false;
if( status == kIOReturnTimeout )
{
FWKLOG( ("IOFireWireSBP2Login : logout timed out\n") );
fLoginState = kLoginStateIdle;
completeLogout( status );
}
}
void IOFireWireSBP2Login::clearAllTasksInSet( void )
{
IOFireWireSBP2ORB * item;
fORBSetIterator->reset();
while( (item = (IOFireWireSBP2ORB *) fORBSetIterator->getNextObject()) )
{
if( isORBTimerSet( item ) )
{
cancelORBTimer( item );
if( fStatusNotifyCallback != NULL )
{
FWSBP2NotifyParams params;
params.message = 0;
params.length = 0;
params.notificationEvent = kFWSBP2NormalCommandReset;
params.generation = fLoginGeneration;
params.commandObject = item;
(*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms );
}
}
}
}
IOFireWireSBP2ORB * IOFireWireSBP2Login::createORB( void )
{
IOFireWireSBP2ORB * orb = new IOFireWireSBP2ORB;
if( orb != NULL && !initORBWithLogin( orb, this ) )
{
orb->release();
orb = NULL;
}
else
{
addORB( orb );
}
return orb;
}
IOReturn IOFireWireSBP2Login::addORB( IOFireWireSBP2ORB * orb )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteAddORB, (void*)orb );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteAddORB( OSObject *self, void * orb, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeAddORB( (IOFireWireSBP2ORB*)orb );
}
IOReturn IOFireWireSBP2Login::executeAddORB( IOFireWireSBP2ORB * orb )
{
return fORBSet->setObject( orb );
}
IOReturn IOFireWireSBP2Login::removeORB( IOFireWireSBP2ORB * orb )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteRemoveORB, (void*)orb );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteRemoveORB( OSObject *self, void * orb, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeRemoveORB( (IOFireWireSBP2ORB*)orb );
}
IOReturn IOFireWireSBP2Login::executeRemoveORB( IOFireWireSBP2ORB * orb )
{
fORBSet->removeObject( orb );
return kIOReturnSuccess;
}
IOReturn IOFireWireSBP2Login::submitORB( IOFireWireSBP2ORB * orb )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteORB, (void*)orb );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteORB( OSObject *self, void * orb, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeORB( ( IOFireWireSBP2ORB *)orb );
}
IOReturn IOFireWireSBP2Login::executeORB( IOFireWireSBP2ORB * orb )
{
IOReturn status = kIOReturnSuccess;
UInt32 commandFlags;
if( !isConnected() )
{
status = kIOFireWireBusReset; }
if( status == kIOReturnSuccess )
{
commandFlags = orb->getCommandFlags();
}
if( status == kIOReturnSuccess )
{
if( fFetchAgentWriteCommandInUse && ( commandFlags & kFWSBP2CommandImmediate ) )
{
FWKLOG(("IOFireWireSBP2Login : fetchAgentWriteCommand still in use\n" ));
status = kIOReturnNoResources;
}
}
if( status == kIOReturnSuccess )
{
UInt32 generation = orb->getCommandGeneration();
if( commandFlags & kFWSBP2CommandCheckGeneration && !fControl->checkGeneration(generation) )
status = kIOFireWireBusReset;
}
if( status == kIOReturnSuccess )
{
prepareORBForExecution(orb);
}
#if FWDIAGNOSTICS
((IOFireWireSBP2Diagnostics*)(fLUN->getDiagnostics()))->incrementExecutedORBCount();
#endif
if( status == kIOReturnSuccess )
{
startORBTimer(orb);
}
if( status == kIOReturnSuccess )
{
if( commandFlags & kFWSBP2CommandImmediate )
{
status = appendORBImmediate( orb );
}
else
{
status = appendORB( orb );
}
}
return status;
}
bool IOFireWireSBP2Login::isConnected( void )
{
return (fLoginState == kLoginStateConnected);
}
void IOFireWireSBP2Login::setFetchAgentWriteCompletion( void * refCon, FWSBP2FetchAgentWriteCallback completion )
{
fFetchAgentWriteCompletion = completion;
fFetchAgentWriteRefCon = refCon;
}
void IOFireWireSBP2Login::fetchAgentWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->fetchAgentWriteComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::fetchAgentWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
fFetchAgentWriteCommandInUse = false;
if( fFetchAgentWriteCompletion != NULL )
(*fFetchAgentWriteCompletion)( fFetchAgentWriteRefCon, status, fLastORB );
}
bool IOFireWireSBP2Login::isFetchAgentWriteInProgress( void )
{
return fFetchAgentWriteCommandInUse;
}
void IOFireWireSBP2Login::setFetchAgentResetCompletion( void * refCon, FWSBP2StatusCallback completion )
{
fFetchAgentResetCompletion = completion;
fFetchAgentResetRefCon = refCon;
}
IOReturn IOFireWireSBP2Login::submitFetchAgentReset( void )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteFetchAgentReset );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteFetchAgentReset( OSObject *self, void *, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeFetchAgentReset();
}
IOReturn IOFireWireSBP2Login::executeFetchAgentReset( void )
{
if( isConnected() )
{
if( fFetchAgentResetInProgress )
fFetchAgentResetCommand->cancel( kIOReturnAborted );
fFetchAgentResetInProgress = true;
fFetchAgentResetCommand->reinit( fFetchAgentResetAddress,
&fFetchAgentResetBuffer, 1,
IOFireWireSBP2Login::fetchAgentResetCompleteStatic,
this, true );
fFetchAgentResetCommand->submit();
}
else
{
return kIOReturnError;
}
return kIOReturnSuccess;
}
void IOFireWireSBP2Login::fetchAgentResetCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->fetchAgentResetComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::fetchAgentResetComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ("IOFireWireSBP2Login : fetch agent reset complete\n") );
fFetchAgentResetInProgress = false;
if( status == kIOReturnSuccess )
clearAllTasksInSet();
if( fFetchAgentResetCompletion )
(*fFetchAgentResetCompletion)( fFetchAgentResetRefCon, status );
}
IOReturn IOFireWireSBP2Login::ringDoorbell( void )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteDoorbell );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteDoorbell( OSObject *self, void *, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeDoorbell();
}
IOReturn IOFireWireSBP2Login::executeDoorbell( void )
{
if( isConnected() )
{
if( fDoorbellInProgress )
{
fDoorbellRingAgain = true;
return kIOReturnSuccess;
}
fDoorbellInProgress = true;
fDoorbellCommand->reinit( fDoorbellAddress,
&fDoorbellBuffer, 1,
IOFireWireSBP2Login::doorbellCompleteStatic,
this, true );
fDoorbellCommand->submit();
}
else
return kIOReturnError;
return kIOReturnSuccess;
}
void IOFireWireSBP2Login::doorbellCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->doorbellComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::doorbellComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ("IOFireWireSBP2Login : doorbell complete\n") );
fDoorbellInProgress = false;
if( fDoorbellRingAgain )
{
fDoorbellRingAgain = false;
executeDoorbell();
}
}
IOReturn IOFireWireSBP2Login::enableUnsolicitedStatus( void )
{
IOReturn status = kIOReturnSuccess;
status = fGate->runAction( staticExecuteUnsolicitedStatusEnable );
return status;
}
IOReturn IOFireWireSBP2Login::staticExecuteUnsolicitedStatusEnable( OSObject *self, void *, void *, void *, void * )
{
return ((IOFireWireSBP2Login *)self)->executeUnsolicitedStatusEnable();
}
IOReturn IOFireWireSBP2Login::executeUnsolicitedStatusEnable( void )
{
if( isConnected() )
{
if( fUnsolicitedStatusEnableInProgress )
fUnsolicitedStatusEnableCommand->cancel( kIOReturnAborted );
fUnsolicitedStatusEnableInProgress = true;
fUnsolicitedStatusEnableCommand->reinit( fUnsolicitedStatusEnableAddress,
&fUnsolicitedStatusEnableBuffer, 1,
IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic,
this, true );
fUnsolicitedStatusEnableCommand->submit();
}
else
return kIOReturnError;
return kIOReturnSuccess;
}
void IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->unsolicitedStatusEnableComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::unsolicitedStatusEnableComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ("IOFireWireSBP2Login : unsolicitedStatusEnableComplete complete\n") );
fUnsolicitedStatusEnableInProgress = false;
}
void IOFireWireSBP2Login::setBusyTimeoutRegisterValue( UInt32 timeout )
{
fSetBusyTimeoutBuffer = timeout;
executeSetBusyTimeout();
}
IOReturn IOFireWireSBP2Login::executeSetBusyTimeout( void )
{
if( fSetBusyTimeoutInProgress )
fSetBusyTimeoutCommand->cancel( kIOReturnAborted );
fSetBusyTimeoutInProgress = true;
fSetBusyTimeoutCommand->reinit( fSetBusyTimeoutAddress,
&fSetBusyTimeoutBuffer, 1,
IOFireWireSBP2Login::setBusyTimeoutCompleteStatic,
this, true );
fSetBusyTimeoutCommand->submit();
return kIOReturnSuccess;
}
void IOFireWireSBP2Login::setBusyTimeoutCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
((IOFireWireSBP2Login*)refcon)->setBusyTimeoutComplete( status, device, fwCmd );
}
void IOFireWireSBP2Login::setBusyTimeoutComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd )
{
FWKLOG( ("IOFireWireSBP2Login : setBusyTimeoutComplete\n") );
fSetBusyTimeoutInProgress = false;
}
IOReturn IOFireWireSBP2Login::appendORBImmediate( IOFireWireSBP2ORB * orb )
{
orb->getORBAddress( &fLastORBAddress );
fLastORB = orb;
if( fFetchAgentWriteCommandInUse )
fFetchAgentWriteCommand->cancel( kIOReturnAborted );
fFetchAgentWriteCommandInUse = true;
fFetchAgentWriteCommand->reinit( fFetchAgentAddress,
fFetchAgentWriteCommandMemory,
IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true );
return fFetchAgentWriteCommand->submit();
}
IOReturn IOFireWireSBP2Login::appendORB( IOFireWireSBP2ORB * orb )
{
IOReturn status = kIOReturnSuccess;
if( fLastORB != NULL )
{
orb->getORBAddress( &fLastORBAddress );
setNextORBAddress( fLastORB, fLastORBAddress );
fLastORB = orb;
}
else
status = kIOReturnError;
return status;
}
void IOFireWireSBP2Login::sendTimeoutNotification( IOFireWireSBP2ORB * orb )
{
if( fStatusNotifyCallback != NULL )
{
FWSBP2NotifyParams params;
params.message = 0;
params.length = 0;
params.notificationEvent = kFWSBP2NormalCommandTimeout;
params.generation = fLoginGeneration;
params.commandObject = orb;
(*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms );
}
}
bool IOFireWireSBP2Login::initORBWithLogin( IOFireWireSBP2ORB * orb, IOFireWireSBP2Login * login )
{
return orb->initWithLogin( login );
}
void IOFireWireSBP2Login::setNextORBAddress( IOFireWireSBP2ORB * orb, FWAddress address )
{
orb->setNextORBAddress( address );
}
void IOFireWireSBP2Login::fetchAgentWriteComplete( IOFireWireSBP2ORB * orb, IOReturn status )
{
}
bool IOFireWireSBP2Login::isORBTimerSet( IOFireWireSBP2ORB * orb )
{
return orb->isTimerSet();
}
void IOFireWireSBP2Login::cancelORBTimer( IOFireWireSBP2ORB * orb )
{
orb->cancelTimer();
}
void IOFireWireSBP2Login::startORBTimer( IOFireWireSBP2ORB * orb )
{
orb->startTimer();
}
void IOFireWireSBP2Login::prepareORBForExecution( IOFireWireSBP2ORB * orb )
{
orb->prepareORBForExecution();
}
void IOFireWireSBP2Login::removeLogin( void )
{
fLUN->removeLogin( this);
}
IOFireWireSBP2Target * IOFireWireSBP2Login::getTarget( void )
{
return fLUN->getTarget();
}