/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include "FWDebugging.h" #include #include #include #include OSDefineMetaClassAndStructors(IOFireWireSBP2UserClient, IOUserClient) ////////////////////////////////////////////////////////////////////////////////////////////////// // ctor // // 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; } // start // // 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; } // free // // void IOFireWireSBP2UserClient::free() { if( fExporter ) { fExporter->release(); fExporter = NULL; } IOUserClient::free(); } // externalMethod // // IOReturn IOFireWireSBP2UserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args, IOExternalMethodDispatch * dispatch, OSObject * target, void * reference ) { IOReturn status = kIOReturnSuccess; // IOLog( "IOFireWireSBP2UserClient::externalMethod - selector = %d, scalarIn = %d, scalarOut = %d structInDesc = 0x%08lx structIn = %d structOutDesc = 0x%08lx structOut = %d\n", // selector, args->scalarInputCount, args->scalarOutputCount, args->structureInputDescriptor, args->structureInputSize, args->structureOutputDescriptor, args->structureOutputSize); 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; } // IOLog( "IOFireWireSBP2UserClient::externalMethod - selector = %d, status = 0x%08lx\n", selector, status ); return status; } // checkArguments // // 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; //IOLog( "IOFireWireSBP2UserClient::checkArguments - (1) failed\n" ); } if( (kIOUCVariableStructureSize != structInCount) && (structInCount != ((args->structureInputDescriptor) ? args->structureInputDescriptor->getLength() : args->structureInputSize)) ) { status = kIOReturnBadArgument; //IOLog( "IOFireWireSBP2UserClient::checkArguments - (2) failed\n" ); } if ((kIOUCVariableStructureSize != scalarOutCount) && (scalarOutCount != args->scalarOutputCount)) { status = kIOReturnBadArgument; //IOLog( "IOFireWireSBP2UserClient::checkArguments - (3) failed\n" ); } if ((kIOUCVariableStructureSize != structOutCount) && (structOutCount != ((args->structureOutputDescriptor) ? args->structureOutputDescriptor->getLength() : args->structureOutputSize))) { status = kIOReturnBadArgument; //IOLog( "IOFireWireSBP2UserClient::checkArguments - (4) failed\n" ); } return status; } // clientClose / clientDied // // IOReturn IOFireWireSBP2UserClient::clientClose( void ) { FWKLOG(( "IOFireWireSBP2UserClient : clientClose\n" )); if( fExporter ) { fExporter->removeAllObjects(); } if( fLogin ) { // releasing the login flushes all orbs fLogin->release(); fLogin = NULL; } if( fOpened ) { // as long as we have the provider open we should not get terminated IOService * provider = getProvider(); if( provider ) { flushAllManagementORBs(); IOFireWireController * control = (((IOFireWireSBP2LUN*)provider)->getFireWireUnit())->getController(); // reset bus - aborts orbs control->resetBus(); provider->close(this); } fOpened = false; } // from here on we cannot assume our provider is valid fStarted = false; terminate( kIOServiceRequired ); return kIOReturnSuccess; } IOReturn IOFireWireSBP2UserClient::clientDied( void ) { FWKLOG(( "IOFireWireSBP2UserClient : clientDied\n" )); return clientClose(); } ////////////////////////////////////////////////////////////////////////////////////////////////// // // IOFireWireSBP2LUN // 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; // look for us in provider chain while( fProviderLUN != service_object && service_object != NULL ) service_object = service_object->getProvider(); // were we found 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; } // message callback methods // // 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 ); // for compatibility 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; // fill out return parameters 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)); // load up status block 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: // default the action to return kIOReturnUnsupported break; } } return status; } ///////////////////////////////////////////////// // IOFireWireSBP2Login // login callback methods // // 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 // if( fLoginCallbackAsyncRef[0] != 0 ) { UInt64 args[16]; UInt32 i; // fill out return parameters args[0] = (UInt64)params->generation; args[1] = (UInt64)params->status; // load up loginResponse 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)); // load up status block 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 ); } } // logout callback methods // // 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; // fill out return parameters args[0] = (UInt64)params->generation; args[1] = (UInt64)params->status; args[2] = (UInt64)(entries * sizeof(UInt32)); // load up status block 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 ); } } // unsolicited status notify callback // // 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; // fill out return parameters args[0] = (UInt64)params->notificationEvent; args[1] = (UInt64)params->generation; args[2] = (UInt64)(entries * sizeof(UInt32)); // load up status block 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 ); } } // status notify static // // 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; // fill out return parameters args[0] = (UInt64)params->notificationEvent; args[1] = (UInt64)params->generation; args[2] = (UInt64)(entries * sizeof(UInt32)); args[3] = ((IOFireWireSBP2ORB*)(params->commandObject))->getRefCon64(); // load up status block 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 ); } } // createLogin / releaseLogin // // 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 ) { // remove the login fExporter->removeObject( arguments->scalarInput[0] ); // remove all orbs, since login holds a reference to them 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 ); // release login (will do final release of ORBs) 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; } // fetch agent reset // // 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 ); } } // ringDoorbell // // 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; } // enableUnsolicitedStatus // // 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; } // setBusyTimeoutRegisterValue // // 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; } // fetch agent write completion // // 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 ); } } // setPassword // // 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; } ////////////////////////////////////////////////////////////////////////////////////////////////// // // IOFireWireSBP2ORB // 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; } // submitORB // // 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; } // setCommandFlags // // 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; } // setMaxORBPayloadSize // // 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; } // setORBRefCon // // 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; } // setCommandTimeout // // 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; } // setCommandGeneration // // 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; } // setToDummy // // 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 ) { //zzz why is this turned off? // orb->setToDummy(); } if( orb ) { orb->release(); orb = NULL; } return status; } // setCommandBuffersAsRanges // // 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]; // IODirection withDirection = (IODirection)arguments->scalarInput[3]; offset = arguments->scalarInput[4]; length = arguments->scalarInput[5]; rangeSize = sizeof(IOAddressRange) * withCount; // IOLog( "IOFWSBPUC::setBuf - withCount = %lld length = %lld\n", withCount, length ); } 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; } // releaseCommandBuffers // // 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; } // setCommandBlock // // 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; } // setCommandBuffersAsRanges // // 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 ); // NOP return status; } IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSyncBuffersForInput ( IOExternalMethodArguments * arguments ) { IOReturn status = checkArguments( arguments, 1, 0, 0, 0 ); // NOP return status; } ///////////////////////////////////////////////// // IOFireWireSBP2MgmtORB 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; } // submitORB // // 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; } // setMgmtORBCommandFunction // // 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; } // setMgmtORBManageeORB // // 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; } // setMgmtORBManageeLogin // // 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; } // setMgmtORBResponseBuffer // // 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; } // orb callback methods // // 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 ); } } /////////////////////////////////////////////////////////////////////////////////////// // friend class wrapper functions // IOFireWireSBP2ManagementORB friend class wrappers void IOFireWireSBP2UserClient::flushAllManagementORBs( void ) { fProviderLUN->flushAllManagementORBs(); } // IOFireWireSBP2MgmtORB friend class wrappers void IOFireWireSBP2UserClient::setMgmtORBAsyncCallbackReference( IOFireWireSBP2ManagementORB * orb, void * asyncRef ) { orb->setAsyncCallbackReference( asyncRef ); } void IOFireWireSBP2UserClient::getMgmtORBAsyncCallbackReference( IOFireWireSBP2ManagementORB * orb, void * asyncRef ) { orb->getAsyncCallbackReference( asyncRef ); }