IOFireWireSBP2UserClient.cpp [plain text]
#include "FWDebugging.h"
#include <IOKit/sbp2/IOFireWireSBP2UserClient.h>
#include <IOKit/sbp2/IOFireWireSBP2LUN.h>
#include <IOKit/sbp2/IOFireWireSBP2LSIWorkaroundDescriptor.h>
#include <IOKit/IOMessage.h>
OSDefineMetaClassAndStructors(IOFireWireSBP2UserClient, IOUserClient)
bool IOFireWireSBP2UserClient::initWithTask(
task_t owningTask, void * securityToken, UInt32 type,
OSDictionary * properties)
{
if( properties )
properties->setObject( "IOUserClientCrossEndianCompatible" , kOSBooleanTrue);
bool res = IOUserClient::initWithTask(owningTask, securityToken, type, properties);
fOpened = false;
fStarted = false;
fLogin = NULL;
fTask = owningTask;
fMessageCallbackAsyncRef[0] = 0;
fLoginCallbackAsyncRef[0] = 0;
fLogoutCallbackAsyncRef[0] = 0;
fUnsolicitedStatusNotifyAsyncRef[0] = 0;
fStatusNotifyAsyncRef[0] = 0;
fFetchAgentWriteAsyncRef[0] = 0;
fFetchAgentResetAsyncRef[0] = 0;
return res;
}
bool IOFireWireSBP2UserClient::start( IOService * provider )
{
FWKLOG(( "IOFireWireSBP2UserClient : starting\n" ));
if( fStarted )
return false;
fProviderLUN = OSDynamicCast(IOFireWireSBP2LUN, provider);
if (fProviderLUN == NULL)
return false;
if( !IOUserClient::start(provider) )
return false;
fExporter = IOFWUserObjectExporter::createWithOwner( this );
if( fExporter == NULL )
return false;
fStarted = true;
return true;
}
void
IOFireWireSBP2UserClient::free()
{
if( fExporter )
{
fExporter->release();
fExporter = NULL;
}
IOUserClient::free();
}
IOReturn IOFireWireSBP2UserClient::externalMethod( uint32_t selector,
IOExternalMethodArguments * args,
IOExternalMethodDispatch * dispatch,
OSObject * target,
void * reference )
{
IOReturn status = kIOReturnSuccess;
switch( selector )
{
case kIOFWSBP2UserClientOpen:
status = open( args );
break;
case kIOFWSBP2UserClientClose:
status = close( args );
break;
case kIOFWSBP2UserClientCreateLogin:
status = createLogin( args );
break;
case kIOFWSBP2UserClientReleaseLogin:
status = releaseLogin( args );
break;
case kIOFWSBP2UserClientSubmitLogin:
status = submitLogin( args );
break;
case kIOFWSBP2UserClientSubmitLogout:
status = submitLogout( args );
break;
case kIOFWSBP2UserClientSetLoginFlags:
status = setLoginFlags( args );
break;
case kIOFWSBP2UserClientGetMaxCommandBlockSize:
status = getMaxCommandBlockSize( args );
break;
case kIOFWSBP2UserClientGetLoginID:
status = getLoginID( args );
break;
case kIOFWSBP2UserClientSetReconnectTime:
status = setReconnectTime( args );
break;
case kIOFWSBP2UserClientSetMaxPayloadSize:
status = setMaxPayloadSize( args );
break;
case kIOFWSBP2UserClientCreateORB:
status = createORB( args );
break;
case kIOFWSBP2UserClientReleaseORB:
status = releaseORB( args );
break;
case kIOFWSBP2UserClientSubmitORB:
status = submitORB( args );
break;
case kIOFWSBP2UserClientSetCommandFlags:
status = setCommandFlags( args );
break;
case kIOFWSBP2UserClientSetMaxORBPayloadSize:
status = setMaxORBPayloadSize( args );
break;
case kIOFWSBP2UserClientSetCommandTimeout:
status = setCommandTimeout( args );
break;
case kIOFWSBP2UserClientSetCommandGeneration:
status = setCommandGeneration( args );
break;
case kIOFWSBP2UserClientSetToDummy:
status = setToDummy( args );
break;
case kIOFWSBP2UserClientSetCommandBuffersAsRanges:
status = setCommandBuffersAsRanges( args );
break;
case kIOFWSBP2UserClientReleaseCommandBuffers:
status = releaseCommandBuffers( args );
break;
case kIOFWSBP2UserClientSetCommandBlock:
status = setCommandBlock( args );
break;
case kIOFWSBP2UserClientCreateMgmtORB:
status = createMgmtORB( args );
break;
case kIOFWSBP2UserClientReleaseMgmtORB:
status = releaseMgmtORB( args );
break;
case kIOFWSBP2UserClientSubmitMgmtORB:
status = submitMgmtORB( args );
break;
case kIOFWSBP2UserClientMgmtORBSetCommandFunction:
status = setMgmtORBCommandFunction( args );
break;
case kIOFWSBP2UserClientMgmtORBSetManageeORB:
status = setMgmtORBManageeORB( args );
break;
case kIOFWSBP2UserClientMgmtORBSetManageeLogin:
status = setMgmtORBManageeLogin( args );
break;
case kIOFWSBP2UserClientMgmtORBSetResponseBuffer:
status = setMgmtORBResponseBuffer( args );
break;
case kIOFWSBP2UserClientLSIWorkaroundSetCommandBuffersAsRanges:
status = LSIWorkaroundSetCommandBuffersAsRanges( args );
break;
case kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForOutput:
status = LSIWorkaroundSyncBuffersForOutput( args );
break;
case kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForInput:
status = LSIWorkaroundSyncBuffersForInput( args );
break;
case kIOFWSBP2UserClientOpenWithSessionRef:
status = openWithSessionRef( args );
break;
case kIOFWSBP2UserClientGetSessionRef:
status = getSessionRef( args );
break;
case kIOFWSBP2UserClientRingDoorbell:
status = ringDoorbell( args );
break;
case kIOFWSBP2UserClientEnableUnsolicitedStatus:
status = enableUnsolicitedStatus( args );
break;
case kIOFWSBP2UserClientSetBusyTimeoutRegisterValue:
status = setBusyTimeoutRegisterValue( args );
break;
case kIOFWSBP2UserClientSetORBRefCon:
status = setORBRefCon( args );
break;
case kIOFWSBP2UserClientSetPassword:
status = setPassword( args );
break;
case kIOFWSBP2UserClientSetMessageCallback:
status = setMessageCallback( args );
break;
case kIOFWSBP2UserClientSetLoginCallback:
status = setLoginCallback( args );
break;
case kIOFWSBP2UserClientSetLogoutCallback:
status = setLogoutCallback( args );
break;
case kIOFWSBP2UserClientSetUnsolicitedStatusNotify:
status = setUnsolicitedStatusNotify( args );
break;
case kIOFWSBP2UserClientSetStatusNotify:
status = setStatusNotify( args );
break;
case kIOFWSBP2UserClientSetMgmtORBCallback:
status = setMgmtORBCallback( args );
break;
case kIOFWSBP2UserClientSubmitFetchAgentReset:
status = submitFetchAgentReset( args );
break;
case kIOFWSBP2UserClientSetFetchAgentWriteCompletion:
status = setFetchAgentWriteCompletion( args );
break;
default:
status = kIOReturnBadArgument;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::checkArguments( IOExternalMethodArguments * args,
uint32_t scalarInCount, uint32_t structInCount,
uint32_t scalarOutCount, uint32_t structOutCount )
{
IOReturn status = kIOReturnSuccess;
if( (kIOUCVariableStructureSize != scalarInCount) && (scalarInCount != args->scalarInputCount) )
{
status = kIOReturnBadArgument;
}
if( (kIOUCVariableStructureSize != structInCount)
&& (structInCount != ((args->structureInputDescriptor)
? args->structureInputDescriptor->getLength() : args->structureInputSize)) )
{
status = kIOReturnBadArgument;
}
if ((kIOUCVariableStructureSize != scalarOutCount) && (scalarOutCount != args->scalarOutputCount))
{
status = kIOReturnBadArgument;
}
if ((kIOUCVariableStructureSize != structOutCount)
&& (structOutCount != ((args->structureOutputDescriptor)
? args->structureOutputDescriptor->getLength() : args->structureOutputSize)))
{
status = kIOReturnBadArgument;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::clientClose( void )
{
FWKLOG(( "IOFireWireSBP2UserClient : clientClose\n" ));
if( fExporter )
{
fExporter->removeAllObjects();
}
if( fLogin )
{
fLogin->release();
fLogin = NULL;
}
if( fOpened )
{
IOService * provider = getProvider();
if( provider )
{
flushAllManagementORBs();
IOFireWireController * control = (((IOFireWireSBP2LUN*)provider)->getFireWireUnit())->getController();
control->resetBus();
provider->close(this);
}
fOpened = false;
}
fStarted = false;
terminate( kIOServiceRequired );
return kIOReturnSuccess;
}
IOReturn IOFireWireSBP2UserClient::clientDied( void )
{
FWKLOG(( "IOFireWireSBP2UserClient : clientDied\n" ));
return clientClose();
}
IOReturn IOFireWireSBP2UserClient::open( IOExternalMethodArguments * arguments )
{
IOReturn status = kIOReturnSuccess;
FWKLOG(( "IOFireWireSBP2UserClient : open\n" ));
status = checkArguments( arguments, 0, 0, 0, 0 );
if( status == kIOReturnSuccess )
{
if( fOpened )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
if( fProviderLUN->open(this) )
{
fOpened = true;
IOFireWireController * control = fProviderLUN->getFireWireUnit()->getController();
IOFWUserObjectExporter * exporter = control->getSessionRefExporter();
status = exporter->addObject( this, NULL, &fSessionRef );
if( status != kIOReturnSuccess )
{
fProviderLUN->close(this);
fOpened = false;
}
}
else
status = kIOReturnExclusiveAccess;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::openWithSessionRef( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
IOService * service = NULL;
FWKLOG(( "IOFireWireSBP2UserClient : open\n" ));
if( status == kIOReturnSuccess )
{
if( fOpened || !fProviderLUN->isOpen() )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
IOFireWireController * control = fProviderLUN->getFireWireUnit()->getController();
IOFWUserObjectExporter * exporter = control->getSessionRefExporter();
service = (IOService*) exporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOService) );
if( service == NULL )
status = kIOReturnBadArgument;
}
if( status == kIOReturnSuccess )
{
IOService * service_object = service;
while( fProviderLUN != service_object && service_object != NULL )
service_object = service_object->getProvider();
if( service_object == NULL )
status = kIOReturnBadArgument;
}
if( service )
{
service->release();
service = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::getSessionRef( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 1, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : getSessionRef\n" ));
if( status == kIOReturnSuccess )
{
if( !fOpened )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
arguments->scalarOutput[0] = (uint64_t)fSessionRef;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::close( IOExternalMethodArguments * arguments )
{
IOReturn status = kIOReturnSuccess;
FWKLOG(( "IOFireWireSBP2UserClient : close\n" ));
status = checkArguments( arguments, 0, 0, 0, 0 );
if( status == kIOReturnSuccess )
{
if( fOpened )
{
IOFireWireController * control = fProviderLUN->getFireWireUnit()->getController();
IOFWUserObjectExporter * exporter = control->getSessionRefExporter();
exporter->removeObject( fSessionRef );
fSessionRef = 0;
fProviderLUN->close(this);
fOpened = false;
}
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMessageCallback
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fMessageCallbackAsyncRef, sizeof(OSAsyncReference64) );
}
return status;
}
IOReturn IOFireWireSBP2UserClient::message( UInt32 type, IOService * provider, void * arg )
{
IOReturn status = kIOReturnUnsupported;
UInt32 entries;
FWSBP2ReconnectParams * params;
io_user_reference_t args[16];
FWKLOG(( "IOFireWireSBP2UserClient : message 0x%x, arg 0x%08lx\n", type, arg ));
status = IOService::message( type, provider, arg );
if( status == kIOReturnUnsupported )
{
switch( type )
{
case kIOFWMessageServiceIsRequestingClose:
args[11] = (io_user_reference_t)kIOFWMessageServiceIsRequestingClose;
sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
args[11] = (io_user_reference_t)kIOMessageServiceIsRequestingClose;
sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
status = kIOReturnSuccess;
break;
case kIOMessageServiceIsRequestingClose:
case kIOMessageServiceIsTerminated:
case kIOMessageServiceIsSuspended:
case kIOMessageServiceIsResumed:
args[11] = (io_user_reference_t)type;
sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
status = kIOReturnSuccess;
break;
case kIOMessageFWSBP2ReconnectComplete:
case kIOMessageFWSBP2ReconnectFailed:
params = (FWSBP2ReconnectParams*)arg;
entries = params->reconnectStatusBlockLength;
if( entries > sizeof(FWSBP2StatusBlock) )
{
entries = sizeof(FWSBP2StatusBlock);
}
entries /= sizeof( UInt32 );
#if 0
FWKLOG(( "IOFireWireSBP2UserClient : login 0x%08lx\n", (UInt32)params->login ));
FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
FWKLOG(( "IOFireWireSBP2UserClient : status 0x%08x\n", params->status ));
if( params->reconnectStatusBlock)
{
FWKLOG(( "IOFireWireSBP2UserClient : details 0x%02x sbpStatus 0x%02x orbOffsetHi 0x%04x\n",
((FWSBP2StatusBlock*)params->reconnectStatusBlock)->details,
((FWSBP2StatusBlock*)params->reconnectStatusBlock)->sbpStatus,
((FWSBP2StatusBlock*)params->reconnectStatusBlock)->orbOffsetHi ));
FWKLOG(( "IOFireWireSBP2UserClient : orbOffsetLo 0x%08lx\n",
((FWSBP2StatusBlock*)params->reconnectStatusBlock)->orbOffsetLo ));
}
#endif
if( fMessageCallbackAsyncRef[0] != 0 )
{
UInt32 i;
args[0] = (io_user_reference_t)params->generation;
args[1] = (io_user_reference_t)params->status;
args[2] = (io_user_reference_t)(entries * sizeof(UInt64));
UInt32 * statusBlock = (UInt32 *)params->reconnectStatusBlock;
for( i = 0; i < entries; i++ )
{
if( statusBlock )
args[3+i] = (io_user_reference_t)statusBlock[i];
else
args[3+i] = 0;
}
args[11] = (io_user_reference_t)type;
sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
}
status = kIOReturnSuccess;
break;
default: break;
}
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setLoginCallback
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fLoginCallbackAsyncRef, sizeof(OSAsyncReference64) );
}
return status;
}
void IOFireWireSBP2UserClient::staticLoginCallback( void * refCon, FWSBP2LoginCompleteParamsPtr params )
{
((IOFireWireSBP2UserClient*)refCon)->loginCallback( params );
}
void IOFireWireSBP2UserClient::loginCallback( FWSBP2LoginCompleteParamsPtr params )
{
UInt32 entries = params->statusBlockLength;
if( entries > sizeof(FWSBP2StatusBlock) )
entries = sizeof(FWSBP2StatusBlock);
entries /= sizeof( UInt32 );
FWKLOG(( "IOFireWireSBP2UserClient : loginCompletion\n" ));
#if 1
FWKLOG(( "IOFireWireSBP2UserClient : login %p\n", params->login ));
FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
FWKLOG(( "IOFireWireSBP2UserClient : status 0x%08x\n", params->status ));
if( params->loginResponse )
{
FWKLOG(( "IOFireWireSBP2UserClient : length %d login %d\n", params->loginResponse->length,
params->loginResponse->loginID ));
FWKLOG(( "IOFireWireSBP2UserClient : commandBlockAgentAddressHi 0x%08lx\n",
params->loginResponse->commandBlockAgentAddressHi ));
FWKLOG(( "IOFireWireSBP2UserClient : commandBlockAgentAddressLo 0x%08lx\n",
params->loginResponse->commandBlockAgentAddressLo ));
FWKLOG(( "IOFireWireSBP2UserClient : reserved %d reconnectHold %d\n", params->loginResponse->reserved,
params->loginResponse->reconnectHold ));
}
if( params->statusBlock )
{
FWKLOG(( "IOFireWireSBP2UserClient : details 0x%02x sbpStatus 0x%02x orbOffsetHi 0x%04x\n",
((FWSBP2StatusBlock*)params->statusBlock)->details,
((FWSBP2StatusBlock*)params->statusBlock)->sbpStatus,
((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetHi ));
FWKLOG(( "IOFireWireSBP2UserClient : orbOffsetLo 0x%08lx\n", ((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetLo ));
}
#endif
{
UInt64 args[16];
UInt32 i;
args[0] = (UInt64)params->generation;
args[1] = (UInt64)params->status;
UInt32 * loginResponse = (UInt32 *)params->loginResponse;
for( i = 0; i < sizeof(FWSBP2LoginResponse) / sizeof(UInt32); i++ )
{
if( loginResponse )
args[2+i] = (UInt64)loginResponse[i];
else
args[2+i] = 0;
}
args[6] = (UInt64)(entries * sizeof(UInt32));
UInt32 * statusBlock = (UInt32 *)params->statusBlock;
for( i = 0; i < 8; i++ )
{
if( statusBlock && i < entries )
args[7+i] = (UInt64)statusBlock[i];
else
args[7+i] = 0;
}
sendAsyncResult64( fLoginCallbackAsyncRef, kIOReturnSuccess, args, 15 );
}
}
IOReturn IOFireWireSBP2UserClient::setLogoutCallback
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fLogoutCallbackAsyncRef, sizeof(OSAsyncReference64) );
}
return status;
}
void IOFireWireSBP2UserClient::staticLogoutCallback( void * refCon, FWSBP2LogoutCompleteParamsPtr params )
{
((IOFireWireSBP2UserClient*)refCon)->logoutCallback( params );
}
void IOFireWireSBP2UserClient::logoutCallback( FWSBP2LogoutCompleteParamsPtr params )
{
FWKLOG(( "IOFireWireSBP2UserClient : logoutCompletion\n" ));
UInt32 entries = params->statusBlockLength;
if( entries > sizeof(FWSBP2StatusBlock) )
entries = sizeof(FWSBP2StatusBlock);
entries /= sizeof( UInt32 );
#if 0
FWKLOG(( "IOFireWireSBP2UserClient : login 0x%08lx\n", (UInt32)params->login ));
FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
FWKLOG(( "IOFireWireSBP2UserClient : status 0x%08x\n", params->status ));
if( params->statusBlock )
{
FWKLOG(( "IOFireWireSBP2UserClient : details 0x%02x sbpStatus 0x%02x orbOffsetHi 0x%04x\n",
((FWSBP2StatusBlock*)params->statusBlock)->details,
((FWSBP2StatusBlock*)params->statusBlock)->sbpStatus,
((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetHi ));
FWKLOG(( "IOFireWireSBP2UserClient : orbOffsetLo 0x%08lx\n", ((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetLo ));
}
#endif
if( fLogoutCallbackAsyncRef[0] != 0 )
{
UInt64 args[16];
UInt32 i;
args[0] = (UInt64)params->generation;
args[1] = (UInt64)params->status;
args[2] = (UInt64)(entries * sizeof(UInt32));
UInt32 * statusBlock = (UInt32 *)params->statusBlock;
for( i = 0; i < entries; i++ )
{
if( statusBlock )
args[3+i] = (UInt64)statusBlock[i];
else
args[3+i] = 0;
}
sendAsyncResult64( fLogoutCallbackAsyncRef, kIOReturnSuccess, args, 11 );
}
}
IOReturn IOFireWireSBP2UserClient::setUnsolicitedStatusNotify
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setUnsolicitedStatusNotify\n" ));
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fUnsolicitedStatusNotifyAsyncRef, sizeof(OSAsyncReference64) );
}
return status;
}
void IOFireWireSBP2UserClient::staticUnsolicitedNotify( void * refCon, FWSBP2NotifyParams * params )
{
((IOFireWireSBP2UserClient*)refCon)->unsolicitedNotify( params );
}
void IOFireWireSBP2UserClient::unsolicitedNotify( FWSBP2NotifyParams * params )
{
UInt32 entries = params->length;
if( entries > sizeof(FWSBP2StatusBlock) )
entries = sizeof(FWSBP2StatusBlock);
entries /= sizeof( UInt32 );
FWKLOG(( "IOFireWireSBP2UserClient : unsolicitedNotify\n" ));
#if 0
FWKLOG(( "IOFireWireSBP2UserClient : notificationEvent 0x%08x\n", params->notificationEvent ));
FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
#endif
if( fUnsolicitedStatusNotifyAsyncRef[0] != 0 )
{
UInt64 args[16];
UInt32 i;
args[0] = (UInt64)params->notificationEvent;
args[1] = (UInt64)params->generation;
args[2] = (UInt64)(entries * sizeof(UInt32));
UInt32 * statusBlock = (UInt32 *)params->message;
for( i = 0; i < 8; i++ )
{
if( statusBlock && i < entries )
args[3+i] = (UInt32)statusBlock[i];
else
args[3+i] = 0;
}
sendAsyncResult64( fUnsolicitedStatusNotifyAsyncRef, kIOReturnSuccess, args, 11 );
}
}
IOReturn IOFireWireSBP2UserClient::setStatusNotify
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setStatusNotify\n" ));
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fStatusNotifyAsyncRef, sizeof(OSAsyncReference64) );
}
return status;
}
void IOFireWireSBP2UserClient::staticStatusNotify( void * refCon, FWSBP2NotifyParams * params )
{
FWKLOG(( "IOFireWireSBP2UserClient : staticStatusNotify\n" ));
((IOFireWireSBP2UserClient*)refCon)->statusNotify( params );
}
void IOFireWireSBP2UserClient::statusNotify( FWSBP2NotifyParams * params )
{
UInt32 entries = params->length;
if( entries > sizeof(FWSBP2StatusBlock) )
entries = sizeof(FWSBP2StatusBlock);
entries /= sizeof( UInt32 );
FWKLOG(( "IOFireWireSBP2UserClient : statusNotify\n" ));
#if 0
FWKLOG(( "IOFireWireSBP2UserClient : notificationEvent 0x%08x\n", params->notificationEvent ));
FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
#endif
if( fStatusNotifyAsyncRef[0] != 0 )
{
UInt64 args[16];
UInt32 i;
args[0] = (UInt64)params->notificationEvent;
args[1] = (UInt64)params->generation;
args[2] = (UInt64)(entries * sizeof(UInt32));
args[3] = ((IOFireWireSBP2ORB*)(params->commandObject))->getRefCon64();
UInt32 * statusBlock = (UInt32 *)params->message;
for( i = 0; i < 8; i++ )
{
if( statusBlock && i < entries )
args[4+i] = (UInt32)statusBlock[i];
else
args[4+i] = 0;
}
sendAsyncResult64( fStatusNotifyAsyncRef, kIOReturnSuccess, args, 12 );
}
}
IOReturn IOFireWireSBP2UserClient::createLogin
( IOExternalMethodArguments * arguments )
{
IOReturn status = kIOReturnSuccess;
status = checkArguments( arguments, 0, 0, 1, 0 );
if( status == kIOReturnSuccess )
{
if( fLogin )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
fLogin = fProviderLUN->createLogin();
if( !fLogin )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
IOFireWireLib::UserObjectHandle outHandle = 0;
status = fExporter->addObject( fLogin, NULL, &outHandle );
arguments->scalarOutput[0] = (uint64_t)outHandle;
}
if( status == kIOReturnSuccess )
{
fLogin->setLoginCompletion( this, staticLoginCallback );
}
if( status == kIOReturnSuccess )
{
fLogin->setLogoutCompletion( this, staticLogoutCallback );
}
if( status == kIOReturnSuccess )
{
fLogin->setUnsolicitedStatusNotifyProc( this, staticUnsolicitedNotify );
}
if( status == kIOReturnSuccess )
{
fLogin->setStatusNotifyProc( this, staticStatusNotify );
}
if( status == kIOReturnSuccess )
{
fLogin->setFetchAgentWriteCompletion( this, staticFetchAgentWriteComplete );
}
return status;
}
IOReturn IOFireWireSBP2UserClient::releaseLogin
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
fExporter->removeObject( arguments->scalarInput[0] );
IOFireWireSBP2ORB * item = NULL;
do
{
fLogin->fORBSetIterator->reset();
item = (IOFireWireSBP2ORB *)fLogin->fORBSetIterator->getNextObject();
if( item )
{
IOFireWireLib::UserObjectHandle handle = fExporter->lookupHandle( item );
if( handle )
{
fExporter->removeObject( handle );
}
}
} while( item );
fLogin->release();
fLogin = NULL;
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::submitLogin
( IOExternalMethodArguments * arguments )
{
IOReturn status = kIOReturnSuccess;
FWKLOG(( "IOFireWireSBP2UserClient : submitLogin\n" ));
status = checkArguments( arguments, 1, 0, 0, 0 );
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
status = login->submitLogin();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::submitLogout
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : submitLogout\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
status = login->submitLogout();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setLoginFlags
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
FWKLOG(( "IOFireWireSBP2UserClient : setLoginFlags : 0x%08lx\n", (UInt32)arguments->scalarInput[1] ));
UInt32 flags = (UInt32)arguments->scalarInput[1];
login->setLoginFlags( flags );
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::getMaxCommandBlockSize
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 1, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : getMaxCommandBlockSize\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
arguments->scalarOutput[0] = login->getMaxCommandBlockSize();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::getLoginID
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 1, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : getLoginID\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
arguments->scalarOutput[0] = login->getLoginID();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setReconnectTime
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
FWKLOG(( "IOFireWireSBP2UserClient : setReconnectTime = %d\n", (UInt32)arguments->scalarInput[1] ));
login->setReconnectTime( (UInt32)arguments->scalarInput[1] );
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMaxPayloadSize
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
FWKLOG(( "IOFireWireSBP2UserClient : setMaxPayloadSize = %d\n", (UInt32)arguments->scalarInput[1] ));
login->setMaxPayloadSize( (UInt32)arguments->scalarInput[1] );
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::submitFetchAgentReset( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : submitFetchAgentReset\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fFetchAgentResetAsyncRef, sizeof(OSAsyncReference64) );
}
if( status == kIOReturnSuccess )
{
login->setFetchAgentResetCompletion( this, staticFetchAgentResetComplete );
login->submitFetchAgentReset();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
void IOFireWireSBP2UserClient::staticFetchAgentResetComplete( void * refCon, IOReturn status )
{
((IOFireWireSBP2UserClient*)refCon)->fetchAgentResetComplete( status );
}
void IOFireWireSBP2UserClient::fetchAgentResetComplete( IOReturn status )
{
if( fFetchAgentResetAsyncRef[0] != 0 )
{
UInt64 args[1];
args[0] = (UInt64)status;
sendAsyncResult64( fFetchAgentResetAsyncRef, kIOReturnSuccess, args, 1 );
}
}
IOReturn IOFireWireSBP2UserClient::ringDoorbell( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : ringDoorbell\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
login->ringDoorbell();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::enableUnsolicitedStatus( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : enableUnsolicitedStatus\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
login->enableUnsolicitedStatus();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setBusyTimeoutRegisterValue( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setBusyTimeoutRegisterValue\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
login->setBusyTimeoutRegisterValue( (UInt32)arguments->scalarInput[1] );
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setFetchAgentWriteCompletion( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
if( status == kIOReturnSuccess )
{
bcopy( arguments->asyncReference, fFetchAgentWriteAsyncRef, sizeof(OSAsyncReference64) );
}
FWKLOG(( "IOFireWireSBP2UserClient : setFetchAgentWriteCompletion\n" ));
return status;
}
void IOFireWireSBP2UserClient::staticFetchAgentWriteComplete( void * refCon, IOReturn status, IOFireWireSBP2ORB * orb )
{
((IOFireWireSBP2UserClient*)refCon)->fetchAgentWriteComplete( status, orb );
}
void IOFireWireSBP2UserClient::fetchAgentWriteComplete( IOReturn status, IOFireWireSBP2ORB * orb )
{
if( fFetchAgentWriteAsyncRef[0] != 0 )
{
uint64_t args[2];
args[0] = (uint64_t)status;
args[1] = (uint64_t)fExporter->lookupHandle( orb );
sendAsyncResult64( fFetchAgentWriteAsyncRef, kIOReturnSuccess, args, 2 );
}
}
IOReturn IOFireWireSBP2UserClient::setPassword( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 3, 0, 0, 0 );
IOMemoryDescriptor * memory = NULL;
FWKLOG(( "IOFireWireSBP2UserClient : setPassword\n" ));
IOFireWireSBP2Login * login = NULL;
if( status == kIOReturnSuccess )
{
login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
if( !login || fLogin != login )
{
status = kIOReturnBadArgument;
}
}
mach_vm_address_t buffer = 0;
mach_vm_size_t length = 0;
if( status == kIOReturnSuccess )
{
buffer = arguments->scalarInput[1];
length = arguments->scalarInput[2];
}
if( status == kIOReturnSuccess )
{
memory = IOMemoryDescriptor::withAddressRange( buffer,
length,
kIODirectionOutIn, fTask );
if( !memory )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
login->setPassword( memory );
}
if( memory )
{
memory->release();
}
if( login )
{
login->release();
login = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::createORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 1, 0 );
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
if( !fLogin )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb = fLogin->createORB();
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
IOFireWireLib::UserObjectHandle outHandle = 0;
status = fExporter->addObject( orb, NULL, &outHandle );
arguments->scalarOutput[0] = (uint64_t)outHandle;
orb->release();
}
return status;
}
IOReturn IOFireWireSBP2UserClient::releaseORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : releaseORB\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
fExporter->removeObject( arguments->scalarInput[0] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return kIOReturnSuccess;
}
IOReturn IOFireWireSBP2UserClient::submitORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : submitORB\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
status = fLogin->submitORB(orb);
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setCommandFlags
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setCommandFlags\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb->setCommandFlags( (UInt32)arguments->scalarInput[1] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMaxORBPayloadSize
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setMaxPayloadSize\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb->setMaxPayloadSize( (UInt32)arguments->scalarInput[1] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setORBRefCon
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setORBRefCon\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb->setRefCon64( arguments->scalarInput[1] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setCommandTimeout
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setCommandTimeout\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb->setCommandTimeout( (UInt32)arguments->scalarInput[1] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setCommandGeneration
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setCommandGeneration\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb->setCommandGeneration( (UInt32)arguments->scalarInput[1] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setToDummy
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setToDummy\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setCommandBuffersAsRanges
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 6, 0, 0, 0 );
IOMemoryDescriptor * rangeDesc = NULL;
IOFireWireSBP2ORB * orb = NULL;
IOAddressRange * rangeBytes = NULL;
FWKLOG(( "IOFireWireSBP2UserClient : setCommandBuffersAsRanges\n" ));
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
mach_vm_address_t ranges = 0;
uint64_t withCount = 0;
uint64_t offset = 0;
uint64_t length = 0;
vm_size_t rangeSize = 0;
if( status == kIOReturnSuccess )
{
ranges = arguments->scalarInput[1];
withCount = arguments->scalarInput[2];
offset = arguments->scalarInput[4];
length = arguments->scalarInput[5];
rangeSize = sizeof(IOAddressRange) * withCount;
}
if( status == kIOReturnSuccess )
{
rangeDesc = IOMemoryDescriptor::withAddressRange( ranges,
rangeSize,
kIODirectionOut, fTask );
if( !rangeDesc )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = rangeDesc->prepare();
}
if( status == kIOReturnSuccess )
{
rangeBytes = (IOAddressRange*)IOMalloc( rangeSize );
if( rangeBytes == NULL )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
rangeDesc->readBytes( 0, rangeBytes, rangeSize );
}
if( status == kIOReturnSuccess )
{
#if 0
for( UInt32 i = 0; i < withCount; i++ )
{
IOLog( "IOFWSBPUC::setBuf - %d : addr = 0x%016llx len = 0x%016llx\n", i, rangeBytes[i].address, rangeBytes[i].length );
}
#endif
}
if( status == kIOReturnSuccess )
{
status = orb->setCommandBuffersAsRanges64( rangeBytes,
withCount,
kIODirectionOutIn,
fTask,
offset,
length );
}
if( rangeBytes )
{
IOFree( rangeBytes, rangeSize );
}
if( rangeDesc )
{
rangeDesc->complete();
rangeDesc->release();
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::releaseCommandBuffers
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : releaseCommandBuffers\n" ));
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
status = orb->releaseCommandBuffers();
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setCommandBlock
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 3, 0, 0, 0 );
IOMemoryDescriptor * memory = NULL;
IOFireWireSBP2ORB * orb = NULL;
if( status == kIOReturnSuccess )
{
FWKLOG(( "IOFireWireSBP2UserClient : setCommandBlock - ORBRef = 0x%08lx buffer = 0x%08lx length = %d\n", (UInt32)arguments->scalarInput[0], (UInt32)arguments->scalarInput[1], (UInt32)arguments->scalarInput[2] ));
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
mach_vm_address_t buffer = arguments->scalarInput[1];
mach_vm_size_t length = arguments->scalarInput[2];
memory = IOMemoryDescriptor::withAddressRange( buffer,
length,
kIODirectionOut, fTask );
if( !memory )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = memory->prepare();
}
if( status == kIOReturnSuccess )
{
orb->setCommandBlock( memory );
}
if( memory )
{
memory->complete();
memory->release();
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSetCommandBuffersAsRanges
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 6, 0, 0, 0 );
IOFireWireSBP2ORB * orb = NULL;
FWKLOG(( "IOFireWireSBP2UserClient : LSIWorkaroundSetCommandBuffersAsRanges\n" ));
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb->setBufferConstraints( kFWSBP2MaxPageClusterSize, PAGE_SIZE, kFWSBP2ConstraintForceDoubleBuffer );
}
if( status == kIOReturnSuccess )
{
status = setCommandBuffersAsRanges( arguments );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSyncBuffersForOutput
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
return status;
}
IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSyncBuffersForInput
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
return status;
}
IOReturn IOFireWireSBP2UserClient::createMgmtORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 0, 0, 1, 0 );
IOFireWireSBP2ManagementORB * orb = NULL;
if( status == kIOReturnSuccess )
{
if( !fProviderLUN )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
orb = fProviderLUN->createManagementORB( this, staticMgmtORBCallback );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
IOFireWireLib::UserObjectHandle outHandle = 0;
status = fExporter->addObject( orb, NULL, &outHandle );
arguments->scalarOutput[0] = (uint64_t)outHandle;
orb->release();
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMgmtORBCallback
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
IOFireWireSBP2ManagementORB * orb;
FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBCallback\n" ));
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
OSAsyncReference64 asyncRef;
bcopy( arguments->asyncReference, asyncRef, sizeof(OSAsyncReference64) );
setMgmtORBAsyncCallbackReference( orb, asyncRef );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::releaseMgmtORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : releaseMgmtORB\n" ));
IOFireWireSBP2ManagementORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !orb )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
fExporter->removeObject( arguments->scalarInput[0] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::submitMgmtORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : submitManagementORB\n" ));
IOFireWireSBP2ManagementORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
status = orb->submit();
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMgmtORBCommandFunction
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBCommandFunction\n" ));
IOFireWireSBP2ManagementORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
status = orb->setCommandFunction( (UInt32)arguments->scalarInput[1] );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMgmtORBManageeORB
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBManageeORB\n" ));
IOFireWireSBP2ManagementORB * mgmtORB;
IOFireWireSBP2ORB * manageeORB = NULL;
if( status == kIOReturnSuccess )
{
mgmtORB = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !mgmtORB )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
manageeORB = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[1], OSTypeID(IOFireWireSBP2ORB) );
if( !manageeORB )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
mgmtORB->setManageeCommand( manageeORB );
}
if( manageeORB )
{
manageeORB->release();
manageeORB = NULL;
}
if( mgmtORB )
{
mgmtORB->release();
mgmtORB = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMgmtORBManageeLogin
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBManageeLogin\n" ));
IOFireWireSBP2ManagementORB * orb;
IOFireWireSBP2Login * manageeLogin = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !orb )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
manageeLogin = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[1], OSTypeID(IOFireWireSBP2Login) );
if( !manageeLogin )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
orb->setManageeCommand( manageeLogin );
}
if( manageeLogin )
{
manageeLogin->release();
manageeLogin = NULL;
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
IOReturn IOFireWireSBP2UserClient::setMgmtORBResponseBuffer
( IOExternalMethodArguments * arguments )
{
IOReturn status = checkArguments( arguments, 3, 0, 0, 0 );
FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBCommandFunction\n" ));
IOFireWireSBP2ManagementORB * orb = NULL;
if( status == kIOReturnSuccess )
{
orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
if( !orb )
status = kIOReturnError;
}
mach_vm_address_t buffer = arguments->scalarInput[1];
mach_vm_size_t length = arguments->scalarInput[2];
if( status == kIOReturnSuccess )
{
if( !buffer || length == 0 )
{
status = orb->setResponseBuffer( NULL );
return status;
}
}
IOMemoryDescriptor * memory = NULL;
if( status == kIOReturnSuccess )
{
memory = IOMemoryDescriptor::withAddressRange( buffer,
length,
kIODirectionOutIn, fTask );
if( !memory )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = memory->prepare();
}
if( status == kIOReturnSuccess )
{
status = orb->setResponseBuffer( memory );
}
if( orb )
{
orb->release();
orb = NULL;
}
return status;
}
void IOFireWireSBP2UserClient::staticMgmtORBCallback
(void * refCon, IOReturn status, IOFireWireSBP2ManagementORB * orb)
{
((IOFireWireSBP2UserClient*)refCon)->mgmtORBCallback( status, orb );
}
void IOFireWireSBP2UserClient::mgmtORBCallback( IOReturn status, IOFireWireSBP2ManagementORB * orb )
{
FWKLOG(( "IOFireWireSBP2UserClient : mgmtORBCallback\n" ));
OSAsyncReference64 asyncRef;
orb->setResponseBuffer( NULL );
getMgmtORBAsyncCallbackReference( orb, asyncRef );
if( asyncRef[0] != 0 )
{
uint64_t args[3];
args[0] = status;
sendAsyncResult64( asyncRef, kIOReturnSuccess, args, 3 );
}
}
void IOFireWireSBP2UserClient::flushAllManagementORBs( void )
{
fProviderLUN->flushAllManagementORBs();
}
void IOFireWireSBP2UserClient::setMgmtORBAsyncCallbackReference( IOFireWireSBP2ManagementORB * orb, void * asyncRef )
{
orb->setAsyncCallbackReference( asyncRef );
}
void IOFireWireSBP2UserClient::getMgmtORBAsyncCallbackReference( IOFireWireSBP2ManagementORB * orb, void * asyncRef )
{
orb->getAsyncCallbackReference( asyncRef );
}