IOReturn IOFireWireSBP2LibORB::init( io_connect_t connection, mach_port_t asyncPort ) { IOReturn status = kIOReturnSuccess; fConnection = connection; fAsyncPort = asyncPort; FWLOG(( "IOFireWireSBP2LibORB : fConnection %d, fAsyncPort %d\n", fConnection, fAsyncPort )); if( !fConnection || !fAsyncPort ) status = kIOReturnError; if( status == kIOReturnSuccess ) { uint32_t len = 1; status = IOConnectCallScalarMethod( connection, kIOFWSBP2UserClientCreateORB, NULL, 0, &fORBRef, &len ); if( status != kIOReturnSuccess ) fORBRef = 0; // just to make sure FWLOG(( "IOFireWireSBP2LibORB : status = 0x%08x = fORBRef 0x%08lx\n", status, fORBRef )); } return status; }
void SBP2SampleLoginController::loginCompletion( FWSBP2LoginCompleteParams * params ) { FWLOG(( "SBP2SampleLoginController : loginCompletion\n" )); // NOTE: the param block and any pointers in the param block // are only guaranteed to be valid until this function returns // NOTE: do not modify the loginResponse block or the statusBlock // check params->status for success // if params->statusBlock != NULL, the status block was received; check for further status // login response is supplied in params->loginResponse on a successful login FWSBP2StatusBlock * statusBlock = params->statusBlock; //zzz may want to check device specific status for success as well if( params->status == kIOReturnSuccess && (statusBlock->details & 0x30) == 0 && // resp == REQUEST_COMPLETE statusBlock->sbpStatus == 0 ) // sbp_status == No additional info { FWLOG(( "SBP2SampleLoginController : login successful\n" )); fLoggedIn = true; loginResumed(); } else { // we just retry a bunch of times if we didn't get good status //zzz we could look at the status and determine if there is any chance a retry will succeed //zzz may want to check device specific errors as well FWLOG( ( "SBP2SampleLoginController : login unsuccessful, status = 0x%08x\n", params->status ) ); if( fPhysicallyConnected ) { if( fLoginRetries > 0 ) { fLoginRetries--; (*fSBP2LoginInterface)->submitLogin( fSBP2LoginInterface ); } else { fNeedLogin = true; loginLost(); } } else { fNeedLogin = true; } } }
void IOFireWireSBP2LibLUN::messageCallback( IOReturn result, io_user_reference_t *args, int numArgs ) { FWLOG(( "IOFireWireSBP2LibLUN : messageCallback numArgs = %d\n", numArgs )); FWSBP2ReconnectParams params; void * outArgs = NULL; UInt32 type = (UInt32)args[11]; if( type == kIOMessageFWSBP2ReconnectComplete || type == kIOMessageFWSBP2ReconnectFailed ) { UInt32 statusBlock[8]; { int i; for( i = 0; i < 8; i++ ) { IF_ROSETTA() { statusBlock[i] = OSSwapInt32( (UInt32)args[3+i] ); } else { statusBlock[i] = (UInt32)args[3+i]; } } }
void SBP2SampleLoginController::logoutCompletion( FWSBP2LogoutCompleteParams * params ) { FWLOG(( "SBP2SampleLoginController : logoutCompletion\n" )); fLoggedIn = false; SBP2SampleSBP2LibGlue::logoutCompletion( params ); }
void *IOFireWireSBP2LibFactory( CFAllocatorRef allocator, CFUUIDRef typeID ) { FWLOG(( "IOFireWireSBP2LibFactory called\n" )); if( CFEqual(typeID, kIOFireWireSBP2LibTypeID) ) return (void *) IOFireWireSBP2LibLUN::alloc(); else return NULL; }
IOReturn IOFireWireSBP2LibORB::setCommandBuffersAsRanges( FWSBP2VirtualRange * ranges, UInt32 withCount, UInt32 withDirection, UInt32 offset, UInt32 length ) { IOReturn status = kIOReturnSuccess; uint32_t len = 0; uint64_t params[6]; FWLOG(( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" )); // printf( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" ); // // create or grow range scratch // UInt32 range_length = withCount * sizeof(FWSBP2PrivateVirtualRange); if( fRangeScratchLength < range_length ) { if( fRangeScratch != NULL ) { // delete it vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength ); fRangeScratch = NULL; fRangeScratchLength = 0; } // alloc a bigger one vm_allocate( mach_task_self(), (vm_address_t*)&fRangeScratch, range_length, true /*anywhere*/ ); if( fRangeScratch != NULL ) { fRangeScratchLength = range_length; } } // // fill range scratch // if( fRangeScratch != NULL ) { for( UInt32 i = 0; i < withCount; i++ ) { fRangeScratch[i].address = (uint64_t)ranges[i].address; fRangeScratch[i].length = ranges[i].length; ROSETTA_ONLY( fRangeScratch[i].address = OSSwapInt64( fRangeScratch[i].address ); fRangeScratch[i].length = OSSwapInt64( fRangeScratch[i].length ); ); } }
void IOFireWireSBP2LibORB::setToDummy( void ) { IOReturn status = kIOReturnSuccess; FWLOG(( "IOFireWireSBP2LibORB : setToDummy\n" )); uint32_t len = 0; status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientSetToDummy, &fORBRef, 1, NULL, &len ); }
void IOFireWireSBP2LibLUN::close( void ) { if( !fConnection ) return; FWLOG(( "IOFireWireSBP2LUN : close\n" )); uint32_t len = 0; IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientClose, NULL, 0, NULL, &len ); }
IOReturn IOFireWireSBP2LibLUN::start( CFDictionaryRef propertyTable, io_service_t service ) { IOReturn status = kIOReturnSuccess; FWLOG(( "IOFireWireSBP2LibLUN : start\n" )); fService = service; status = IOServiceOpen( fService, mach_task_self(), kIOFireWireSBP2LibConnection, &fConnection ); if( !fConnection ) status = kIOReturnNoDevice; if( status == kIOReturnSuccess ) { status = IOCreateReceivePort( kOSAsyncCompleteMessageID, &fAsyncPort ); } FWLOG(( "IOFireWireSBP2LibLUN : IOServiceOpen status = 0x%08lx, connection = %d\n", (UInt32) status, fConnection )); return status; }
IOReturn IOFireWireSBP2LibLUN::addIODispatcherToRunLoop( CFRunLoopRef cfRunLoopRef ) { IOReturn status = kIOReturnSuccess; FWLOG(( "IOFireWireSBP2LibLUN : addIODispatcherToRunLoop\n" )); if( !fConnection ) return kIOReturnNoDevice; if( status == kIOReturnSuccess ) { CFMachPortContext context; Boolean shouldFreeInfo; // zzz what's this for? context.version = 1; context.info = this; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; fCFAsyncPort = CFMachPortCreateWithPort( kCFAllocatorDefault, fAsyncPort, (CFMachPortCallBack) IODispatchCalloutFromMessage, &context, &shouldFreeInfo ); if( !fCFAsyncPort ) status = kIOReturnNoMemory; } if( status == kIOReturnSuccess ) { fCFRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, fCFAsyncPort, 0 ); if( !fCFRunLoopSource ) status = kIOReturnNoMemory; } if( status == kIOReturnSuccess ) { fCFRunLoop = cfRunLoopRef; CFRunLoopAddSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopCommonModes ); } if( status == kIOReturnSuccess ) { io_async_ref64_t asyncRef; mach_msg_type_number_t size = 0; asyncRef[kIOAsyncCalloutFuncIndex] = (uint64_t)&IOFireWireSBP2LibLUN::staticMessageCallback; asyncRef[kIOAsyncCalloutRefconIndex] = (uint64_t)this; status = IOConnectCallAsyncScalarMethod( fConnection, kIOFWSBP2UserClientSetMessageCallback, fAsyncPort, asyncRef, kOSAsyncRef64Count, NULL, 0, NULL, &size ); } return status; }
void SBP2SampleLoginController::logoutOfDevice( void ) { IOReturn status = kIOReturnSuccess; FWLOG(( "SBP2SampleLoginController : logoutOfDevice\n")); // allow the driver to unload fMaintainLogin = false; // we don't want to start logging in if we receive a resume messsage during logout fNeedLogin = false; FWLOG(( "SBP2SampleLoginController : submitLogout\n" )); status = (*fSBP2LoginInterface)->submitLogout(fSBP2LoginInterface); //zzz there is a bug in MacOS X 1.0 where we will return kIOReturnBusy when we mean kIOReturnSuccess if( status == kIOReturnBusy ) status = kIOReturnSuccess; fLoggedIn = false; // we do this in the completion too }
IOFireWireSBP2LibORB::~IOFireWireSBP2LibORB() { if( fORBRef ) { IOReturn status = kIOReturnSuccess; uint32_t len = 0; status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientReleaseORB, &fORBRef, 1, NULL, &len ); FWLOG(( "IOFireWireSBP2LibORB : release orb status = 0x%08x\n", status )); } }
IOReturn IOFireWireSBP2LibLUN::stop( void ) { FWLOG(( "IOFireWireSBP2LibLUN : stop\n" )); removeIODispatcherFromRunLoop(); if( fConnection ) { FWLOG(( "IOFireWireSBP2LibLUN : IOServiceClose connection = %d\n", fConnection )); IOServiceClose( fConnection ); fConnection = MACH_PORT_NULL; } if( fAsyncPort != MACH_PORT_NULL ) { FWLOG(( "IOFireWireSBP2LibLUN : release fAsyncPort\n" )); mach_port_destroy( mach_task_self(), fAsyncPort ); fAsyncPort = MACH_PORT_NULL; } return kIOReturnSuccess; }
void IOFireWireSBP2LibORB::setCommandGeneration( UInt32 generation ) { FWLOG(( "IOFireWireSBP2LibORB : setCommandGeneration = %ld\n", generation )); uint32_t len = 0; uint64_t params[2]; params[0] = fORBRef; params[1] = generation; IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientSetCommandGeneration, params, 2, NULL, &len ); }
void IOFireWireSBP2LibORB::setCommandTimeout( UInt32 timeout ) { FWLOG(( "IOFireWireSBP2LibORB : setCommandTimeout = %ld\n", timeout )); uint32_t len = 0; uint64_t params[2]; params[0] = fORBRef; params[1] = timeout; IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientSetCommandTimeout, params, 2, NULL, &len ); }
void IOFireWireSBP2LibORB::setMaxORBPayloadSize( UInt32 size ) { FWLOG(( "IOFireWireSBP2LibORB : setMaxORBPayloadSize = %ld\n", size )); uint32_t len = 0; uint64_t params[2]; params[0] = fORBRef; params[1] = size; IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientSetMaxORBPayloadSize, params, 2, NULL, &len ); }
void IOFireWireSBP2LibORB::setCommandFlags( UInt32 flags ) { FWLOG(( "IOFireWireSBP2LibORB : setCommandFlags = %ld\n", flags )); uint32_t len = 0; uint64_t params[2]; params[0] = fORBRef; params[1] = flags; IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientSetCommandFlags, params, 2, NULL, &len ); }
IOReturn IOFireWireSBP2LibLUN::open( void ) { IOReturn status = kIOReturnSuccess; if( !fConnection ) return kIOReturnNoDevice; FWLOG(( "IOFireWireSBP2LUN : open\n" )); uint32_t len = 0; status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientOpen, NULL, 0, NULL, &len ); return status; }
void SBP2SampleLoginController::loginToDevice( void ) { IOReturn status = kIOReturnSuccess; FWLOG(( "SBP2SampleLoginController : loginToDevice\n")); // // submit login // if( status == kIOReturnSuccess ) { // don't allow driver to unload fMaintainLogin = true; // when this is set we attempt to login to the device when we recieve a resume message // since we are about to login we don't want this to happen fNeedLogin = false; fLoggedIn = false; FWLOG(( "SBP2SampleLoginController : submitLogin\n" )); fLoginRetries = kMaxLoginRetries; (*fSBP2LoginInterface)->setLoginFlags( fSBP2LoginInterface, kFWSBP2ExclusiveLogin ); status = (*fSBP2LoginInterface)->submitLogin(fSBP2LoginInterface); //zzz there is a bug in MacOS X 1.0 where we will return kIOReturnBusy when we mean kIOReturnSuccess if( status == kIOReturnBusy ) status = kIOReturnSuccess; } if( status != kIOReturnSuccess ) { fNeedLogin = true; loginSuspended(); } }
void IOFireWireSBP2LibORB::setRefCon( void * refCon ) { FWLOG(( "IOFireWireSBP2LibORB : setRefCon\n")); fRefCon = refCon; uint32_t len = 0; uint64_t params[2]; params[0] = fORBRef; params[1] = (uint64_t)refCon; IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientSetORBRefCon, params, 2, NULL, &len ); }
IOReturn IOFireWireSBP2LibLUN::openWithSessionRef( IOFireWireSessionRef sessionRef ) { IOReturn status = kIOReturnSuccess; if( !fConnection ) return kIOReturnNoDevice; FWLOG(( "IOFireWireSBP2LUN : openWithSessionRef\n" )); uint32_t len = 0; uint64_t session_ref_64 = (uint64_t)sessionRef; status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientOpenWithSessionRef, &session_ref_64, 1, NULL, &len ); return status; }
void IOFireWireSBP2LibLUN::removeIODispatcherFromRunLoop( void ) { if( fCFRunLoopSource != NULL ) { CFRunLoopRemoveSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopCommonModes ); CFRelease( fCFRunLoopSource ); fCFRunLoopSource = NULL; } if( fCFAsyncPort != NULL ) { FWLOG(( "IOFireWireSBP2LibLUN : release fCFAsyncPort\n" )); CFMachPortInvalidate( fCFAsyncPort ); CFRelease( fCFAsyncPort ); fCFAsyncPort = NULL; } }
IOFireWireSessionRef IOFireWireSBP2LibLUN::getSessionRef( void ) { IOReturn status = kIOReturnSuccess; uint64_t sessionRef = 0; if( !fConnection ) return (IOFireWireSessionRef)sessionRef; FWLOG(( "IOFireWireSBP2LUN : getSessionRef\n" )); uint32_t len = 1; status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientGetSessionRef, NULL, 0, &sessionRef, &len ); if( status != kIOReturnSuccess ) sessionRef = 0; // just to make sure return (IOFireWireSessionRef)sessionRef; }
void SBP2SampleLoginController::message( UInt32 type, void * arg ) { FWLOG(( "SBP2SampleLoginController : message type = 0x%08lx\n", type )); FWSBP2ReconnectParams * params; // arg and any pointers in it are only valid until this function returns // do not modify and data in the reconnectStatusBlock switch (type) { case kIOMessageServiceIsSuspended: // a bus reset occured FWLOG( ( "SBP2SampleLoginController : kIOMessageServiceIsSuspended\n" ) ); fPhysicallyConnected = false; if( fLoggedIn ) { fLoggedIn = false; loginSuspended(); } break; case kIOMessageServiceIsResumed: // we have processed the self-ids and rediscovered this device FWLOG( ( "SBP2SampleLoginController : kIOMessageServiceIsResumed\n" ) ); fPhysicallyConnected = true; if( fNeedLogin ) { fNeedLogin = false; fLoginRetries = kMaxLoginRetries; (*fSBP2LoginInterface)->submitLogin(fSBP2LoginInterface); } break; case kIOMessageFWSBP2ReconnectComplete: // we reconnected sucessfully to this device // status block is supplied in params->statusBlock for further status params = (FWSBP2ReconnectParams*)arg; fLoggedIn = true; FWLOG(( "SBP2SampleORBTransport : kIOMessageFWSBP2ReconnectComplete\n" )); loginResumed(); break; case kIOMessageFWSBP2ReconnectFailed: FWLOG(( "SBP2SampleORBTransport : kIOMessageFWSBP2ReconnectFailed\n" )); // we did not reconnect successfully to this device // check params->status for error // if params->statusBlock != NULL, the status block was received; check for further status if( fPhysicallyConnected ) { fLoginRetries = kMaxLoginRetries; //zzz could decide if this has any chance of success from returned status (*fSBP2LoginInterface)->submitLogin(fSBP2LoginInterface); } else { fNeedLogin = true; } params = (FWSBP2ReconnectParams*)arg; break; case kIOMessageServiceIsRequestingClose: // we have processsed the self-ids and did not rediscover this device FWLOG( ( "SBP2SampleORBTransport : kIOMessageServiceIsRequestingClose\n" )); // firewire is requesting to close this driver, calling close on the provider here // results in terminiation loginLost(); break; case kIOMessageServiceIsTerminated: // the driver has been terminated FWLOG( ( "SBP2SampleORBTransport : kIOMessageServiceIsTerminated\n" ) ); break; default: break; } }