1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include "FWDebugging.h"
24#include <IOKit/sbp2/IOFireWireSBP2UserClient.h>
25#include <IOKit/sbp2/IOFireWireSBP2LUN.h>
26#include <IOKit/sbp2/IOFireWireSBP2LSIWorkaroundDescriptor.h>
27#include <IOKit/IOMessage.h>
28
29OSDefineMetaClassAndStructors(IOFireWireSBP2UserClient, IOUserClient)
30
31
32//////////////////////////////////////////////////////////////////////////////////////////////////
33
34// ctor
35//
36//
37
38bool IOFireWireSBP2UserClient::initWithTask(
39                    task_t owningTask, void * securityToken, UInt32 type,
40                    OSDictionary * properties)
41{
42    if( properties )
43		properties->setObject( "IOUserClientCrossEndianCompatible" , kOSBooleanTrue);
44
45    bool res = IOUserClient::initWithTask(owningTask, securityToken, type, properties);
46
47    fOpened = false;
48	fStarted = false;
49    fLogin = NULL;
50    fTask = owningTask;
51
52    fMessageCallbackAsyncRef[0] = 0;
53    fLoginCallbackAsyncRef[0] = 0;
54    fLogoutCallbackAsyncRef[0] = 0;
55    fUnsolicitedStatusNotifyAsyncRef[0] = 0;
56    fStatusNotifyAsyncRef[0] = 0;
57    fFetchAgentWriteAsyncRef[0] = 0;
58	fFetchAgentResetAsyncRef[0] = 0;
59
60    return res;
61}
62
63// start
64//
65//
66
67bool IOFireWireSBP2UserClient::start( IOService * provider )
68{
69    FWKLOG(( "IOFireWireSBP2UserClient : starting\n" ));
70
71	if( fStarted )
72		return false;
73
74    fProviderLUN = OSDynamicCast(IOFireWireSBP2LUN, provider);
75    if (fProviderLUN == NULL)
76        return false;
77
78	if( !IOUserClient::start(provider) )
79         return false;
80
81	fExporter = IOFWUserObjectExporter::createWithOwner( this );
82	if( fExporter == NULL )
83		return false;
84
85	fStarted = true;
86
87	return true;
88}
89
90// free
91//
92//
93
94void
95IOFireWireSBP2UserClient::free()
96{
97	if( fExporter )
98	{
99		fExporter->release();
100		fExporter = NULL;
101	}
102
103	IOUserClient::free();
104}
105
106// externalMethod
107//
108//
109
110
111IOReturn IOFireWireSBP2UserClient::externalMethod(	uint32_t selector,
112										IOExternalMethodArguments * args,
113										IOExternalMethodDispatch * dispatch,
114										OSObject * target,
115										void * reference )
116{
117	IOReturn status = kIOReturnSuccess;
118
119//	IOLog( "IOFireWireSBP2UserClient::externalMethod - selector = %d, scalarIn = %d, scalarOut = %d structInDesc = 0x%08lx structIn = %d structOutDesc = 0x%08lx structOut = %d\n",
120//					selector, args->scalarInputCount, args->scalarOutputCount, args->structureInputDescriptor, args->structureInputSize, args->structureOutputDescriptor, args->structureOutputSize);
121
122    switch( selector )
123    {
124    	case kIOFWSBP2UserClientOpen:
125    		status = open( args );
126    		break;
127
128    	case kIOFWSBP2UserClientClose:
129    		status = close( args );
130    		break;
131
132    	case kIOFWSBP2UserClientCreateLogin:
133    		status = createLogin( args );
134    		break;
135
136    	case kIOFWSBP2UserClientReleaseLogin:
137    		status = releaseLogin( args );
138    		break;
139
140    	case kIOFWSBP2UserClientSubmitLogin:
141    		status = submitLogin( args );
142    		break;
143
144    	case kIOFWSBP2UserClientSubmitLogout:
145    		status = submitLogout( args );
146    		break;
147
148  		case kIOFWSBP2UserClientSetLoginFlags:
149  			status = setLoginFlags( args );
150  			break;
151
152    	case kIOFWSBP2UserClientGetMaxCommandBlockSize:
153    		status = getMaxCommandBlockSize( args );
154    		break;
155
156    	case kIOFWSBP2UserClientGetLoginID:
157    		status = getLoginID( args );
158    		break;
159
160    	case kIOFWSBP2UserClientSetReconnectTime:
161    		status = setReconnectTime( args );
162    		break;
163
164    	case kIOFWSBP2UserClientSetMaxPayloadSize:
165    		status = setMaxPayloadSize( args );
166    		break;
167
168    	case kIOFWSBP2UserClientCreateORB:
169    		status = createORB( args );
170    		break;
171
172    	case kIOFWSBP2UserClientReleaseORB:
173    		status = releaseORB( args );
174    		break;
175
176    	case kIOFWSBP2UserClientSubmitORB:
177    		status = submitORB( args );
178    		break;
179
180    	case kIOFWSBP2UserClientSetCommandFlags:
181    		status = setCommandFlags( args );
182    		break;
183
184    	case kIOFWSBP2UserClientSetMaxORBPayloadSize:
185    		status = setMaxORBPayloadSize( args );
186    		break;
187
188    	case kIOFWSBP2UserClientSetCommandTimeout:
189    		status = setCommandTimeout( args );
190    		break;
191
192    	case kIOFWSBP2UserClientSetCommandGeneration:
193    		status = setCommandGeneration( args );
194    		break;
195
196    	case kIOFWSBP2UserClientSetToDummy:
197    		status = setToDummy( args );
198    		break;
199
200    	case kIOFWSBP2UserClientSetCommandBuffersAsRanges:
201    		status = setCommandBuffersAsRanges( args );
202    		break;
203
204    	case kIOFWSBP2UserClientReleaseCommandBuffers:
205    		status = releaseCommandBuffers( args );
206    		break;
207
208    	case kIOFWSBP2UserClientSetCommandBlock:
209    		status = setCommandBlock( args );
210    		break;
211
212		case kIOFWSBP2UserClientCreateMgmtORB:
213			status = createMgmtORB( args );
214			break;
215
216		case kIOFWSBP2UserClientReleaseMgmtORB:
217			status = releaseMgmtORB( args );
218			break;
219
220		case kIOFWSBP2UserClientSubmitMgmtORB:
221			status = submitMgmtORB( args );
222			break;
223
224		case kIOFWSBP2UserClientMgmtORBSetCommandFunction:
225			status = setMgmtORBCommandFunction( args );
226			break;
227
228		case kIOFWSBP2UserClientMgmtORBSetManageeORB:
229			status = setMgmtORBManageeORB( args );
230			break;
231
232		case kIOFWSBP2UserClientMgmtORBSetManageeLogin:
233			status = setMgmtORBManageeLogin( args );
234			break;
235
236		case kIOFWSBP2UserClientMgmtORBSetResponseBuffer:
237			status = setMgmtORBResponseBuffer( args );
238			break;
239
240		case kIOFWSBP2UserClientLSIWorkaroundSetCommandBuffersAsRanges:
241			status = LSIWorkaroundSetCommandBuffersAsRanges( args );
242			break;
243
244		case kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForOutput:
245			status = LSIWorkaroundSyncBuffersForOutput( args );
246			break;
247
248		case kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForInput:
249			status = LSIWorkaroundSyncBuffersForInput( args );
250			break;
251
252    	case kIOFWSBP2UserClientOpenWithSessionRef:
253    		status = openWithSessionRef( args );
254    		break;
255
256		case kIOFWSBP2UserClientGetSessionRef:
257			status = getSessionRef( args );
258			break;
259
260		case kIOFWSBP2UserClientRingDoorbell:
261			status = ringDoorbell( args );
262			break;
263
264		case kIOFWSBP2UserClientEnableUnsolicitedStatus:
265			status = enableUnsolicitedStatus( args );
266			break;
267
268		case kIOFWSBP2UserClientSetBusyTimeoutRegisterValue:
269			status = setBusyTimeoutRegisterValue( args );
270			break;
271
272		case kIOFWSBP2UserClientSetORBRefCon:
273			status = setORBRefCon( args );
274			break;
275
276		case kIOFWSBP2UserClientSetPassword:
277			status = setPassword( args );
278			break;
279
280    	case kIOFWSBP2UserClientSetMessageCallback:
281    		status = setMessageCallback( args );
282    		break;
283
284   		case kIOFWSBP2UserClientSetLoginCallback:
285   			status = setLoginCallback( args );
286   			break;
287
288    	case kIOFWSBP2UserClientSetLogoutCallback:
289    		status = setLogoutCallback( args );
290    		break;
291
292    	case kIOFWSBP2UserClientSetUnsolicitedStatusNotify:
293    		status = setUnsolicitedStatusNotify( args );
294    		break;
295
296    	case kIOFWSBP2UserClientSetStatusNotify:
297    		status = setStatusNotify( args );
298    		break;
299
300		case kIOFWSBP2UserClientSetMgmtORBCallback:
301			status = setMgmtORBCallback( args );
302			break;
303
304		case kIOFWSBP2UserClientSubmitFetchAgentReset:
305			status = submitFetchAgentReset( args );
306			break;
307
308		case kIOFWSBP2UserClientSetFetchAgentWriteCompletion:
309			status = setFetchAgentWriteCompletion( args );
310			break;
311
312		default:
313			status = kIOReturnBadArgument;
314	}
315
316//	IOLog( "IOFireWireSBP2UserClient::externalMethod - selector = %d, status = 0x%08lx\n", selector, status );
317
318	return status;
319}
320
321// checkArguments
322//
323//
324
325IOReturn IOFireWireSBP2UserClient::checkArguments( IOExternalMethodArguments * args,
326												uint32_t scalarInCount, uint32_t structInCount,
327    										    uint32_t scalarOutCount, uint32_t structOutCount )
328{
329	IOReturn status = kIOReturnSuccess;
330
331	if( (kIOUCVariableStructureSize != scalarInCount) && (scalarInCount != args->scalarInputCount) )
332	{
333		status = kIOReturnBadArgument;
334		//IOLog( "IOFireWireSBP2UserClient::checkArguments - (1) failed\n" );
335	}
336
337	if( (kIOUCVariableStructureSize != structInCount)
338		&& (structInCount != ((args->structureInputDescriptor)
339				? args->structureInputDescriptor->getLength() : args->structureInputSize)) )
340	{
341		status = kIOReturnBadArgument;
342		//IOLog( "IOFireWireSBP2UserClient::checkArguments - (2) failed\n" );
343	}
344
345	if ((kIOUCVariableStructureSize != scalarOutCount) && (scalarOutCount != args->scalarOutputCount))
346	{
347		status = kIOReturnBadArgument;
348		//IOLog( "IOFireWireSBP2UserClient::checkArguments - (3) failed\n" );
349	}
350
351	if ((kIOUCVariableStructureSize != structOutCount)
352		&& (structOutCount != ((args->structureOutputDescriptor)
353				? args->structureOutputDescriptor->getLength() : args->structureOutputSize)))
354	{
355		status = kIOReturnBadArgument;
356		//IOLog( "IOFireWireSBP2UserClient::checkArguments - (4) failed\n" );
357	}
358
359	return status;
360}
361
362// clientClose / clientDied
363//
364//
365
366IOReturn IOFireWireSBP2UserClient::clientClose( void )
367{
368    FWKLOG(( "IOFireWireSBP2UserClient : clientClose\n" ));
369
370	if( fExporter )
371	{
372		fExporter->removeAllObjects();
373	}
374
375    if( fLogin )
376    {
377		// releasing the login flushes all orbs
378        fLogin->release();
379        fLogin = NULL;
380    }
381
382    if( fOpened )
383    {
384		// as long as we have the provider open we should not get terminated
385
386		IOService * provider = getProvider();
387
388		if( provider )
389		{
390			flushAllManagementORBs();
391
392			IOFireWireController * control = (((IOFireWireSBP2LUN*)provider)->getFireWireUnit())->getController();
393
394			// reset bus - aborts orbs
395			control->resetBus();
396
397			provider->close(this);
398        }
399
400		fOpened = false;
401    }
402
403	// from here on we cannot assume our provider is valid
404
405	fStarted = false;
406
407    terminate( kIOServiceRequired );
408
409	return kIOReturnSuccess;
410}
411
412IOReturn IOFireWireSBP2UserClient::clientDied( void )
413{
414    FWKLOG(( "IOFireWireSBP2UserClient : clientDied\n" ));
415
416    return clientClose();
417}
418
419
420//////////////////////////////////////////////////////////////////////////////////////////////////
421//
422// IOFireWireSBP2LUN
423//
424
425IOReturn IOFireWireSBP2UserClient::open(  IOExternalMethodArguments * arguments )
426{
427    IOReturn status = kIOReturnSuccess;
428
429	FWKLOG(( "IOFireWireSBP2UserClient : open\n" ));
430
431	status = checkArguments( arguments, 0, 0, 0, 0 );
432
433    if( status == kIOReturnSuccess )
434    {
435    	if( fOpened )
436        	status = kIOReturnError;
437	}
438
439    if( status == kIOReturnSuccess )
440    {
441        if( fProviderLUN->open(this) )
442		{
443            fOpened = true;
444
445			IOFireWireController * control = fProviderLUN->getFireWireUnit()->getController();
446			IOFWUserObjectExporter * exporter = control->getSessionRefExporter();
447			status = exporter->addObject( this, NULL, &fSessionRef );
448			if( status != kIOReturnSuccess )
449			{
450				fProviderLUN->close(this);
451				fOpened = false;
452			}
453		}
454		else
455            status = kIOReturnExclusiveAccess;
456    }
457
458    return status;
459}
460
461IOReturn IOFireWireSBP2UserClient::openWithSessionRef(  IOExternalMethodArguments * arguments )
462{
463    IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
464
465	IOService * service = NULL;
466
467    FWKLOG(( "IOFireWireSBP2UserClient : open\n" ));
468
469	if( status == kIOReturnSuccess )
470	{
471		if( fOpened || !fProviderLUN->isOpen() )
472			status = kIOReturnError;
473	}
474
475	if( status == kIOReturnSuccess )
476	{
477		IOFireWireController * control = fProviderLUN->getFireWireUnit()->getController();
478		IOFWUserObjectExporter * exporter = control->getSessionRefExporter();
479		service = (IOService*) exporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOService) );
480		if( service == NULL )
481			status = kIOReturnBadArgument;
482	}
483
484	if( status == kIOReturnSuccess )
485	{
486		IOService * service_object = service;
487
488		// look for us in provider chain
489		while( fProviderLUN != service_object && service_object != NULL )
490			service_object = service_object->getProvider();
491
492		// were we found
493		if( service_object == NULL )
494			status = kIOReturnBadArgument;
495	}
496
497	if( service )
498	{
499		service->release();
500		service = NULL;
501	}
502
503	return status;
504}
505
506IOReturn IOFireWireSBP2UserClient::getSessionRef(  IOExternalMethodArguments * arguments )
507{
508    IOReturn status = checkArguments( arguments, 0, 0, 1, 0 );
509
510    FWKLOG(( "IOFireWireSBP2UserClient : getSessionRef\n" ));
511
512	if( status == kIOReturnSuccess )
513	{
514		if( !fOpened )
515			status = kIOReturnError;
516	}
517
518    if( status == kIOReturnSuccess )
519    {
520		arguments->scalarOutput[0] = (uint64_t)fSessionRef;
521	}
522
523	return status;
524}
525
526IOReturn IOFireWireSBP2UserClient::close(  IOExternalMethodArguments * arguments )
527{
528    IOReturn status = kIOReturnSuccess;
529
530    FWKLOG(( "IOFireWireSBP2UserClient : close\n" ));
531
532    status = checkArguments( arguments, 0, 0, 0, 0 );
533
534	if( status == kIOReturnSuccess )
535	{
536		if( fOpened )
537		{
538			IOFireWireController * control = fProviderLUN->getFireWireUnit()->getController();
539			IOFWUserObjectExporter * exporter = control->getSessionRefExporter();
540			exporter->removeObject( fSessionRef );
541			fSessionRef = 0;
542
543			fProviderLUN->close(this);
544			fOpened = false;
545		}
546	}
547
548    return status;
549}
550
551// message callback methods
552//
553//
554
555IOReturn IOFireWireSBP2UserClient::setMessageCallback
556	(  IOExternalMethodArguments * arguments )
557{
558	IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
559
560	if( status == kIOReturnSuccess )
561	{
562		bcopy( arguments->asyncReference, fMessageCallbackAsyncRef, sizeof(OSAsyncReference64) );
563	}
564
565    return status;
566}
567
568IOReturn IOFireWireSBP2UserClient::message( UInt32 type, IOService * provider, void * arg )
569{
570    IOReturn status = kIOReturnUnsupported;
571    UInt32 entries;
572    FWSBP2ReconnectParams * params;
573    io_user_reference_t args[16];
574
575    FWKLOG(( "IOFireWireSBP2UserClient : message 0x%x, arg 0x%08lx\n", type, arg ));
576
577    status = IOService::message( type, provider, arg );
578    if( status == kIOReturnUnsupported )
579    {
580        switch( type )
581        {
582			case kIOFWMessageServiceIsRequestingClose:
583				args[11] = (io_user_reference_t)kIOFWMessageServiceIsRequestingClose;
584                sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
585
586				// for compatibility
587				args[11] = (io_user_reference_t)kIOMessageServiceIsRequestingClose;
588                sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
589                status = kIOReturnSuccess;
590                break;
591
592            case kIOMessageServiceIsRequestingClose:
593            case kIOMessageServiceIsTerminated:
594            case kIOMessageServiceIsSuspended:
595            case kIOMessageServiceIsResumed:
596                args[11] = (io_user_reference_t)type;
597                sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
598                status = kIOReturnSuccess;
599                break;
600
601            case kIOMessageFWSBP2ReconnectComplete:
602            case kIOMessageFWSBP2ReconnectFailed:
603                params = (FWSBP2ReconnectParams*)arg;
604                entries = params->reconnectStatusBlockLength;
605                if( entries > sizeof(FWSBP2StatusBlock) )
606                {
607                    entries = sizeof(FWSBP2StatusBlock);
608                }
609                entries /= sizeof( UInt32 );
610
611#if 0
612                FWKLOG(( "IOFireWireSBP2UserClient : login 0x%08lx\n", (UInt32)params->login ));
613                FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
614                FWKLOG(( "IOFireWireSBP2UserClient : status 0x%08x\n", params->status ));
615
616                if( params->reconnectStatusBlock)
617                {
618                    FWKLOG(( "IOFireWireSBP2UserClient : details 0x%02x sbpStatus 0x%02x orbOffsetHi 0x%04x\n",
619                        ((FWSBP2StatusBlock*)params->reconnectStatusBlock)->details,
620                        ((FWSBP2StatusBlock*)params->reconnectStatusBlock)->sbpStatus,
621                        ((FWSBP2StatusBlock*)params->reconnectStatusBlock)->orbOffsetHi ));
622                    FWKLOG(( "IOFireWireSBP2UserClient : orbOffsetLo 0x%08lx\n",
623                        ((FWSBP2StatusBlock*)params->reconnectStatusBlock)->orbOffsetLo ));
624                }
625#endif
626
627                if( fMessageCallbackAsyncRef[0] != 0 )
628                {
629                    UInt32 i;
630
631                    // fill out return parameters
632                    args[0] = (io_user_reference_t)params->generation;
633                    args[1] = (io_user_reference_t)params->status;
634                    args[2] = (io_user_reference_t)(entries * sizeof(UInt64));
635
636                    // load up status block
637                    UInt32 * statusBlock = (UInt32 *)params->reconnectStatusBlock;
638                    for( i = 0; i < entries; i++ )
639                    {
640                        if( statusBlock )
641                            args[3+i] = (io_user_reference_t)statusBlock[i];
642                        else
643                            args[3+i] = 0;
644                    }
645                    args[11] = (io_user_reference_t)type;
646                    sendAsyncResult64( fMessageCallbackAsyncRef, kIOReturnSuccess, args, 12 );
647                }
648
649                status = kIOReturnSuccess;
650                break;
651
652            default: // default the action to return kIOReturnUnsupported
653                break;
654        }
655    }
656
657    return status;
658}
659
660/////////////////////////////////////////////////
661// IOFireWireSBP2Login
662
663
664// login callback methods
665//
666//
667
668IOReturn IOFireWireSBP2UserClient::setLoginCallback
669	(  IOExternalMethodArguments * arguments )
670{
671	IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
672
673	if( status == kIOReturnSuccess )
674	{
675		bcopy( arguments->asyncReference, fLoginCallbackAsyncRef, sizeof(OSAsyncReference64) );
676	}
677
678    return status;
679}
680
681void IOFireWireSBP2UserClient::staticLoginCallback( void * refCon, FWSBP2LoginCompleteParamsPtr params )
682{
683    ((IOFireWireSBP2UserClient*)refCon)->loginCallback( params );
684}
685
686void IOFireWireSBP2UserClient::loginCallback( FWSBP2LoginCompleteParamsPtr params )
687{
688    UInt32 entries = params->statusBlockLength;
689    if( entries > sizeof(FWSBP2StatusBlock) )
690        entries = sizeof(FWSBP2StatusBlock);
691    entries /= sizeof( UInt32 );
692
693    FWKLOG(( "IOFireWireSBP2UserClient : loginCompletion\n" ));
694
695#if 1
696    FWKLOG(( "IOFireWireSBP2UserClient : login %p\n", params->login ));
697    FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
698    FWKLOG(( "IOFireWireSBP2UserClient : status 0x%08x\n", params->status ));
699
700    if( params->loginResponse )
701    {
702    FWKLOG(( "IOFireWireSBP2UserClient : length %d login %d\n", params->loginResponse->length,
703                                                                                       params->loginResponse->loginID ));
704    FWKLOG(( "IOFireWireSBP2UserClient : commandBlockAgentAddressHi 0x%08lx\n",
705                                                                    params->loginResponse->commandBlockAgentAddressHi ));
706    FWKLOG(( "IOFireWireSBP2UserClient : commandBlockAgentAddressLo 0x%08lx\n",
707                                                                    params->loginResponse->commandBlockAgentAddressLo ));
708    FWKLOG(( "IOFireWireSBP2UserClient : reserved %d reconnectHold %d\n", params->loginResponse->reserved,
709                                                                    params->loginResponse->reconnectHold ));
710
711    }
712
713    if( params->statusBlock )
714    {
715    FWKLOG(( "IOFireWireSBP2UserClient : details 0x%02x sbpStatus 0x%02x orbOffsetHi 0x%04x\n",
716                 ((FWSBP2StatusBlock*)params->statusBlock)->details,
717                 ((FWSBP2StatusBlock*)params->statusBlock)->sbpStatus,
718                 ((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetHi ));
719    FWKLOG(( "IOFireWireSBP2UserClient : orbOffsetLo 0x%08lx\n", ((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetLo ));
720    }
721#endif
722
723//    if( fLoginCallbackAsyncRef[0] != 0 )
724    {
725        UInt64 args[16];
726        UInt32 i;
727
728        // fill out return parameters
729        args[0] = (UInt64)params->generation;
730        args[1] = (UInt64)params->status;
731
732        // load up loginResponse
733        UInt32 * loginResponse = (UInt32 *)params->loginResponse;
734        for( i = 0; i < sizeof(FWSBP2LoginResponse) / sizeof(UInt32); i++ )
735        {
736            if( loginResponse )
737                args[2+i] = (UInt64)loginResponse[i];
738            else
739                args[2+i] = 0;
740        }
741
742        args[6] = (UInt64)(entries * sizeof(UInt32));
743
744        // load up status block
745        UInt32 * statusBlock = (UInt32 *)params->statusBlock;
746        for( i = 0; i < 8; i++ )
747        {
748            if( statusBlock && i < entries )
749                args[7+i] = (UInt64)statusBlock[i];
750            else
751                args[7+i] = 0;
752        }
753
754        sendAsyncResult64( fLoginCallbackAsyncRef, kIOReturnSuccess, args, 15 );
755    }
756
757}
758
759// logout callback methods
760//
761//
762
763IOReturn IOFireWireSBP2UserClient::setLogoutCallback
764	(  IOExternalMethodArguments * arguments )
765{
766	IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
767
768	if( status == kIOReturnSuccess )
769	{
770		bcopy( arguments->asyncReference, fLogoutCallbackAsyncRef, sizeof(OSAsyncReference64) );
771	}
772
773    return status;
774}
775
776void IOFireWireSBP2UserClient::staticLogoutCallback( void * refCon, FWSBP2LogoutCompleteParamsPtr params )
777{
778    ((IOFireWireSBP2UserClient*)refCon)->logoutCallback( params );
779}
780
781void IOFireWireSBP2UserClient::logoutCallback( FWSBP2LogoutCompleteParamsPtr params )
782{
783    FWKLOG(( "IOFireWireSBP2UserClient : logoutCompletion\n" ));
784
785    UInt32 entries = params->statusBlockLength;
786    if( entries > sizeof(FWSBP2StatusBlock) )
787        entries = sizeof(FWSBP2StatusBlock);
788    entries /= sizeof( UInt32 );
789
790#if 0
791    FWKLOG(( "IOFireWireSBP2UserClient : login 0x%08lx\n", (UInt32)params->login ));
792    FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
793    FWKLOG(( "IOFireWireSBP2UserClient : status 0x%08x\n", params->status ));
794
795    if( params->statusBlock )
796    {
797    FWKLOG(( "IOFireWireSBP2UserClient : details 0x%02x sbpStatus 0x%02x orbOffsetHi 0x%04x\n",
798              ((FWSBP2StatusBlock*)params->statusBlock)->details,
799              ((FWSBP2StatusBlock*)params->statusBlock)->sbpStatus,
800              ((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetHi ));
801    FWKLOG(( "IOFireWireSBP2UserClient : orbOffsetLo 0x%08lx\n", ((FWSBP2StatusBlock*)params->statusBlock)->orbOffsetLo ));
802    }
803#endif
804
805    if( fLogoutCallbackAsyncRef[0] != 0 )
806    {
807        UInt64 args[16];
808        UInt32 i;
809
810        // fill out return parameters
811        args[0] = (UInt64)params->generation;
812        args[1] = (UInt64)params->status;
813        args[2] = (UInt64)(entries * sizeof(UInt32));
814
815        // load up status block
816        UInt32 * statusBlock = (UInt32 *)params->statusBlock;
817        for( i = 0; i < entries; i++ )
818        {
819            if( statusBlock )
820                args[3+i] = (UInt64)statusBlock[i];
821            else
822                args[3+i] = 0;
823        }
824
825        sendAsyncResult64( fLogoutCallbackAsyncRef, kIOReturnSuccess, args, 11 );
826    }
827
828}
829
830// unsolicited status notify callback
831//
832//
833
834IOReturn IOFireWireSBP2UserClient::setUnsolicitedStatusNotify
835	(  IOExternalMethodArguments * arguments )
836{
837	IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
838
839    FWKLOG(( "IOFireWireSBP2UserClient : setUnsolicitedStatusNotify\n" ));
840
841	if( status == kIOReturnSuccess )
842	{
843		bcopy( arguments->asyncReference, fUnsolicitedStatusNotifyAsyncRef, sizeof(OSAsyncReference64) );
844	}
845
846    return status;
847}
848
849void IOFireWireSBP2UserClient::staticUnsolicitedNotify( void * refCon, FWSBP2NotifyParams * params )
850{
851    ((IOFireWireSBP2UserClient*)refCon)->unsolicitedNotify( params );
852}
853
854void IOFireWireSBP2UserClient::unsolicitedNotify( FWSBP2NotifyParams * params )
855{
856    UInt32 entries = params->length;
857    if( entries > sizeof(FWSBP2StatusBlock) )
858        entries = sizeof(FWSBP2StatusBlock);
859    entries /= sizeof( UInt32 );
860
861    FWKLOG(( "IOFireWireSBP2UserClient : unsolicitedNotify\n" ));
862
863#if 0
864    FWKLOG(( "IOFireWireSBP2UserClient : notificationEvent 0x%08x\n", params->notificationEvent ));
865    FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
866#endif
867
868    if( fUnsolicitedStatusNotifyAsyncRef[0] != 0 )
869    {
870        UInt64 args[16];
871        UInt32 i;
872
873        // fill out return parameters
874        args[0] = (UInt64)params->notificationEvent;
875        args[1] = (UInt64)params->generation;
876        args[2] = (UInt64)(entries * sizeof(UInt32));
877
878        // load up status block
879        UInt32 * statusBlock = (UInt32 *)params->message;
880        for( i = 0; i < 8; i++ )
881        {
882            if( statusBlock && i < entries )
883                args[3+i] = (UInt32)statusBlock[i];
884            else
885                args[3+i] = 0;
886        }
887
888        sendAsyncResult64( fUnsolicitedStatusNotifyAsyncRef, kIOReturnSuccess, args, 11 );
889    }
890}
891
892// status notify static
893//
894//
895
896IOReturn IOFireWireSBP2UserClient::setStatusNotify
897	(  IOExternalMethodArguments * arguments )
898{
899	IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
900
901    FWKLOG(( "IOFireWireSBP2UserClient : setStatusNotify\n" ));
902
903	if( status == kIOReturnSuccess )
904	{
905		bcopy( arguments->asyncReference, fStatusNotifyAsyncRef, sizeof(OSAsyncReference64) );
906	}
907
908    return status;
909}
910
911void IOFireWireSBP2UserClient::staticStatusNotify( void * refCon, FWSBP2NotifyParams * params )
912{
913    FWKLOG(( "IOFireWireSBP2UserClient : staticStatusNotify\n" ));
914
915    ((IOFireWireSBP2UserClient*)refCon)->statusNotify( params );
916}
917
918void IOFireWireSBP2UserClient::statusNotify( FWSBP2NotifyParams * params )
919{
920    UInt32 entries = params->length;
921    if( entries > sizeof(FWSBP2StatusBlock) )
922        entries = sizeof(FWSBP2StatusBlock);
923    entries /= sizeof( UInt32 );
924
925    FWKLOG(( "IOFireWireSBP2UserClient : statusNotify\n" ));
926
927#if 0
928    FWKLOG(( "IOFireWireSBP2UserClient : notificationEvent 0x%08x\n", params->notificationEvent ));
929    FWKLOG(( "IOFireWireSBP2UserClient : generation %ld\n", params->generation ));
930#endif
931
932    if( fStatusNotifyAsyncRef[0] != 0 )
933    {
934        UInt64 args[16];
935        UInt32 i;
936
937        // fill out return parameters
938        args[0] = (UInt64)params->notificationEvent;
939        args[1] = (UInt64)params->generation;
940        args[2] = (UInt64)(entries * sizeof(UInt32));
941		args[3] = ((IOFireWireSBP2ORB*)(params->commandObject))->getRefCon64();
942
943        // load up status block
944        UInt32 * statusBlock = (UInt32 *)params->message;
945        for( i = 0; i < 8; i++ )
946        {
947            if( statusBlock && i < entries )
948                args[4+i] = (UInt32)statusBlock[i];
949            else
950                args[4+i] = 0;
951        }
952
953        sendAsyncResult64( fStatusNotifyAsyncRef, kIOReturnSuccess, args, 12 );
954    }
955}
956
957// createLogin / releaseLogin
958//
959//
960
961IOReturn IOFireWireSBP2UserClient::createLogin
962	(  IOExternalMethodArguments * arguments )
963{
964    IOReturn status = kIOReturnSuccess;
965
966    status = checkArguments( arguments, 0, 0, 1, 0 );
967
968    if( status == kIOReturnSuccess )
969    {
970		if( fLogin )
971			status = kIOReturnError;
972	}
973
974    if( status == kIOReturnSuccess )
975    {
976        fLogin = fProviderLUN->createLogin();
977        if( !fLogin )
978            status = kIOReturnError;
979    }
980
981    if( status == kIOReturnSuccess )
982    {
983		IOFireWireLib::UserObjectHandle outHandle = 0;
984
985		status = fExporter->addObject( fLogin, NULL, &outHandle );
986
987		arguments->scalarOutput[0] = (uint64_t)outHandle;
988	}
989
990    if( status == kIOReturnSuccess )
991    {
992        fLogin->setLoginCompletion( this, staticLoginCallback );
993    }
994
995    if( status == kIOReturnSuccess )
996    {
997        fLogin->setLogoutCompletion( this, staticLogoutCallback );
998    }
999
1000    if( status == kIOReturnSuccess )
1001    {
1002        fLogin->setUnsolicitedStatusNotifyProc( this, staticUnsolicitedNotify );
1003    }
1004
1005    if( status == kIOReturnSuccess )
1006    {
1007        fLogin->setStatusNotifyProc( this, staticStatusNotify );
1008    }
1009
1010	if( status == kIOReturnSuccess )
1011	{
1012		fLogin->setFetchAgentWriteCompletion( this, staticFetchAgentWriteComplete );
1013	}
1014
1015    return status;
1016}
1017
1018IOReturn IOFireWireSBP2UserClient::releaseLogin
1019	(  IOExternalMethodArguments * arguments )
1020{
1021    IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1022
1023	IOFireWireSBP2Login * login = NULL;
1024	if( status == kIOReturnSuccess )
1025	{
1026		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1027		if( !login || fLogin != login )
1028		{
1029			status = kIOReturnBadArgument;
1030		}
1031	}
1032
1033	if( status == kIOReturnSuccess )
1034	{
1035		// remove the login
1036		fExporter->removeObject( arguments->scalarInput[0] );
1037
1038		// remove all orbs, since login holds a reference to them
1039		IOFireWireSBP2ORB * item = NULL;
1040		do
1041		{
1042            fLogin->fORBSetIterator->reset();
1043			item = (IOFireWireSBP2ORB *)fLogin->fORBSetIterator->getNextObject();
1044			if( item )
1045			{
1046				IOFireWireLib::UserObjectHandle	handle = fExporter->lookupHandle( item );
1047				if( handle )
1048				{
1049					fExporter->removeObject( handle );
1050				}
1051			}
1052		} while( item );
1053
1054		// release login (will do final release of ORBs)
1055		fLogin->release();
1056		fLogin = NULL;
1057	}
1058
1059	if( login )
1060	{
1061		login->release();
1062		login = NULL;
1063	}
1064
1065    return status;
1066}
1067
1068IOReturn IOFireWireSBP2UserClient::submitLogin
1069	(  IOExternalMethodArguments * arguments )
1070{
1071    IOReturn status = kIOReturnSuccess;
1072
1073	FWKLOG(( "IOFireWireSBP2UserClient : submitLogin\n" ));
1074
1075	status = checkArguments( arguments, 1, 0, 0, 0 );
1076
1077	IOFireWireSBP2Login * login = NULL;
1078	if( status == kIOReturnSuccess )
1079	{
1080		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1081		if( !login || fLogin != login )
1082		{
1083			status = kIOReturnBadArgument;
1084		}
1085	}
1086
1087    if( status == kIOReturnSuccess )
1088    {
1089    	status = login->submitLogin();
1090	}
1091
1092	if( login )
1093	{
1094		login->release();
1095		login = NULL;
1096	}
1097
1098    return status;
1099}
1100
1101IOReturn IOFireWireSBP2UserClient::submitLogout
1102	(  IOExternalMethodArguments * arguments )
1103{
1104    IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1105
1106    FWKLOG(( "IOFireWireSBP2UserClient : submitLogout\n" ));
1107
1108	IOFireWireSBP2Login * login = NULL;
1109	if( status == kIOReturnSuccess )
1110	{
1111		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1112		if( !login || fLogin != login )
1113		{
1114			status = kIOReturnBadArgument;
1115		}
1116	}
1117
1118    if( status == kIOReturnSuccess )
1119    {
1120	    status = login->submitLogout();
1121	}
1122
1123	if( login )
1124	{
1125		login->release();
1126		login = NULL;
1127	}
1128
1129    return status;
1130}
1131
1132IOReturn IOFireWireSBP2UserClient::setLoginFlags
1133	(  IOExternalMethodArguments * arguments )
1134{
1135	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1136
1137	IOFireWireSBP2Login * login = NULL;
1138	if( status == kIOReturnSuccess )
1139	{
1140		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1141		if( !login || fLogin != login )
1142		{
1143			status = kIOReturnBadArgument;
1144		}
1145	}
1146
1147    if( status == kIOReturnSuccess )
1148    {
1149 		FWKLOG(( "IOFireWireSBP2UserClient : setLoginFlags : 0x%08lx\n", (UInt32)arguments->scalarInput[1] ));
1150
1151		UInt32 flags = (UInt32)arguments->scalarInput[1];
1152        login->setLoginFlags( flags );
1153    }
1154
1155	if( login )
1156	{
1157		login->release();
1158		login = NULL;
1159	}
1160
1161    return status;
1162}
1163
1164IOReturn IOFireWireSBP2UserClient::getMaxCommandBlockSize
1165	(  IOExternalMethodArguments * arguments )
1166{
1167	IOReturn status = checkArguments( arguments, 1, 0, 1, 0 );
1168
1169    FWKLOG(( "IOFireWireSBP2UserClient : getMaxCommandBlockSize\n" ));
1170
1171	IOFireWireSBP2Login * login = NULL;
1172	if( status == kIOReturnSuccess )
1173	{
1174		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1175		if( !login || fLogin != login )
1176		{
1177			status = kIOReturnBadArgument;
1178		}
1179	}
1180
1181    if( status == kIOReturnSuccess )
1182    {
1183        arguments->scalarOutput[0] = login->getMaxCommandBlockSize();
1184    }
1185
1186	if( login )
1187	{
1188		login->release();
1189		login = NULL;
1190	}
1191
1192    return status;
1193}
1194
1195IOReturn IOFireWireSBP2UserClient::getLoginID
1196	(  IOExternalMethodArguments * arguments )
1197{
1198	IOReturn status = checkArguments( arguments, 1, 0, 1, 0 );
1199
1200    FWKLOG(( "IOFireWireSBP2UserClient : getLoginID\n" ));
1201
1202	IOFireWireSBP2Login * login = NULL;
1203	if( status == kIOReturnSuccess )
1204	{
1205		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1206		if( !login || fLogin != login )
1207		{
1208			status = kIOReturnBadArgument;
1209		}
1210	}
1211
1212    if( status == kIOReturnSuccess )
1213    {
1214		arguments->scalarOutput[0] = login->getLoginID();
1215    }
1216
1217	if( login )
1218	{
1219		login->release();
1220		login = NULL;
1221	}
1222
1223	return status;
1224}
1225
1226IOReturn IOFireWireSBP2UserClient::setReconnectTime
1227	(  IOExternalMethodArguments * arguments )
1228{
1229	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1230
1231	IOFireWireSBP2Login * login = NULL;
1232	if( status == kIOReturnSuccess )
1233	{
1234		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1235		if( !login || fLogin != login )
1236		{
1237			status = kIOReturnBadArgument;
1238		}
1239	}
1240
1241    if( status == kIOReturnSuccess )
1242    {
1243		FWKLOG(( "IOFireWireSBP2UserClient : setReconnectTime = %d\n", (UInt32)arguments->scalarInput[1] ));
1244
1245        login->setReconnectTime( (UInt32)arguments->scalarInput[1] );
1246    }
1247
1248	if( login )
1249	{
1250		login->release();
1251		login = NULL;
1252	}
1253
1254    return status;
1255}
1256
1257IOReturn IOFireWireSBP2UserClient::setMaxPayloadSize
1258	(  IOExternalMethodArguments * arguments )
1259{
1260	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1261
1262	IOFireWireSBP2Login * login = NULL;
1263	if( status == kIOReturnSuccess )
1264	{
1265		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1266		if( !login || fLogin != login )
1267		{
1268			status = kIOReturnBadArgument;
1269		}
1270	}
1271
1272    if( status == kIOReturnSuccess )
1273    {
1274		FWKLOG(( "IOFireWireSBP2UserClient : setMaxPayloadSize = %d\n", (UInt32)arguments->scalarInput[1] ));
1275
1276		login->setMaxPayloadSize( (UInt32)arguments->scalarInput[1] );
1277    }
1278
1279	if( login )
1280	{
1281		login->release();
1282		login = NULL;
1283	}
1284
1285    return status;
1286}
1287
1288// fetch agent reset
1289//
1290//
1291
1292IOReturn IOFireWireSBP2UserClient::submitFetchAgentReset(  IOExternalMethodArguments * arguments )
1293{
1294	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1295
1296    FWKLOG(( "IOFireWireSBP2UserClient : submitFetchAgentReset\n" ));
1297
1298	IOFireWireSBP2Login * login = NULL;
1299	if( status == kIOReturnSuccess )
1300	{
1301		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1302		if( !login || fLogin != login )
1303		{
1304			status = kIOReturnBadArgument;
1305		}
1306	}
1307
1308	if( status == kIOReturnSuccess )
1309	{
1310		bcopy( arguments->asyncReference, fFetchAgentResetAsyncRef, sizeof(OSAsyncReference64) );
1311	}
1312
1313	if( status == kIOReturnSuccess )
1314	{
1315		login->setFetchAgentResetCompletion( this, staticFetchAgentResetComplete );
1316		login->submitFetchAgentReset();
1317	}
1318
1319	if( login )
1320	{
1321		login->release();
1322		login = NULL;
1323	}
1324
1325    return status;
1326
1327}
1328
1329void IOFireWireSBP2UserClient::staticFetchAgentResetComplete( void * refCon, IOReturn status )
1330{
1331   ((IOFireWireSBP2UserClient*)refCon)->fetchAgentResetComplete( status );
1332}
1333
1334void IOFireWireSBP2UserClient::fetchAgentResetComplete( IOReturn status )
1335{
1336	if( fFetchAgentResetAsyncRef[0] != 0 )
1337    {
1338        UInt64 args[1];
1339		args[0] = (UInt64)status;
1340        sendAsyncResult64( fFetchAgentResetAsyncRef, kIOReturnSuccess, args, 1 );
1341    }
1342
1343}
1344
1345// ringDoorbell
1346//
1347//
1348
1349IOReturn IOFireWireSBP2UserClient::ringDoorbell(  IOExternalMethodArguments * arguments )
1350{
1351	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1352
1353    FWKLOG(( "IOFireWireSBP2UserClient : ringDoorbell\n" ));
1354
1355	IOFireWireSBP2Login * login = NULL;
1356	if( status == kIOReturnSuccess )
1357	{
1358		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1359		if( !login || fLogin != login )
1360		{
1361			status = kIOReturnBadArgument;
1362		}
1363	}
1364
1365	if( status == kIOReturnSuccess )
1366	{
1367		login->ringDoorbell();
1368	}
1369
1370	if( login )
1371	{
1372		login->release();
1373		login = NULL;
1374	}
1375
1376    return status;
1377
1378}
1379
1380// enableUnsolicitedStatus
1381//
1382//
1383
1384IOReturn IOFireWireSBP2UserClient::enableUnsolicitedStatus(  IOExternalMethodArguments * arguments )
1385{
1386	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1387
1388    FWKLOG(( "IOFireWireSBP2UserClient : enableUnsolicitedStatus\n" ));
1389
1390	IOFireWireSBP2Login * login = NULL;
1391	if( status == kIOReturnSuccess )
1392	{
1393		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1394		if( !login || fLogin != login )
1395		{
1396			status = kIOReturnBadArgument;
1397		}
1398	}
1399
1400	if( status == kIOReturnSuccess )
1401	{
1402		login->enableUnsolicitedStatus();
1403	}
1404
1405	if( login )
1406	{
1407		login->release();
1408		login = NULL;
1409	}
1410
1411    return status;
1412
1413}
1414
1415// setBusyTimeoutRegisterValue
1416//
1417//
1418
1419IOReturn IOFireWireSBP2UserClient::setBusyTimeoutRegisterValue(  IOExternalMethodArguments * arguments )
1420{
1421	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1422
1423    FWKLOG(( "IOFireWireSBP2UserClient : setBusyTimeoutRegisterValue\n" ));
1424
1425	IOFireWireSBP2Login * login = NULL;
1426	if( status == kIOReturnSuccess )
1427	{
1428		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1429		if( !login || fLogin != login )
1430		{
1431			status = kIOReturnBadArgument;
1432		}
1433	}
1434
1435	if( status == kIOReturnSuccess )
1436	{
1437		login->setBusyTimeoutRegisterValue( (UInt32)arguments->scalarInput[1] );
1438	}
1439
1440	if( login )
1441	{
1442		login->release();
1443		login = NULL;
1444	}
1445
1446    return status;
1447}
1448
1449// fetch agent write completion
1450//
1451//
1452
1453IOReturn IOFireWireSBP2UserClient::setFetchAgentWriteCompletion(  IOExternalMethodArguments * arguments )
1454{
1455	IOReturn status = checkArguments( arguments, 0, 0, 0, 0 );
1456
1457	if( status == kIOReturnSuccess )
1458	{
1459		bcopy( arguments->asyncReference, fFetchAgentWriteAsyncRef, sizeof(OSAsyncReference64) );
1460	}
1461
1462    FWKLOG(( "IOFireWireSBP2UserClient : setFetchAgentWriteCompletion\n" ));
1463
1464    return status;
1465
1466}
1467
1468void IOFireWireSBP2UserClient::staticFetchAgentWriteComplete( void * refCon, IOReturn status, IOFireWireSBP2ORB * orb )
1469{
1470   ((IOFireWireSBP2UserClient*)refCon)->fetchAgentWriteComplete( status, orb );
1471}
1472
1473void IOFireWireSBP2UserClient::fetchAgentWriteComplete( IOReturn status, IOFireWireSBP2ORB * orb )
1474{
1475	if( fFetchAgentWriteAsyncRef[0] != 0 )
1476    {
1477        uint64_t args[2];
1478		args[0] = (uint64_t)status;
1479		args[1] = (uint64_t)fExporter->lookupHandle( orb );
1480
1481        sendAsyncResult64( fFetchAgentWriteAsyncRef, kIOReturnSuccess, args, 2 );
1482    }
1483
1484}
1485
1486// setPassword
1487//
1488//
1489
1490IOReturn IOFireWireSBP2UserClient::setPassword(  IOExternalMethodArguments * arguments )
1491{
1492    IOReturn status = checkArguments( arguments, 3, 0, 0, 0 );
1493
1494    IOMemoryDescriptor *	memory = NULL;
1495
1496    FWKLOG(( "IOFireWireSBP2UserClient : setPassword\n" ));
1497
1498	IOFireWireSBP2Login * login = NULL;
1499	if( status == kIOReturnSuccess )
1500	{
1501		login = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2Login) );
1502		if( !login || fLogin != login )
1503		{
1504			status = kIOReturnBadArgument;
1505		}
1506	}
1507
1508	mach_vm_address_t buffer = 0;
1509	mach_vm_size_t length = 0;
1510
1511	if( status == kIOReturnSuccess )
1512	{
1513		buffer = arguments->scalarInput[1];
1514		length = arguments->scalarInput[2];
1515	}
1516
1517	if( status == kIOReturnSuccess )
1518    {
1519		memory = IOMemoryDescriptor::withAddressRange(	buffer,
1520														length,
1521														kIODirectionOutIn, fTask );
1522        if( !memory )
1523            status = kIOReturnNoMemory;
1524    }
1525
1526    if( status == kIOReturnSuccess )
1527    {
1528        login->setPassword( memory );
1529    }
1530
1531    if( memory )
1532    {
1533	    memory->release();
1534	}
1535
1536	if( login )
1537	{
1538		login->release();
1539		login = NULL;
1540	}
1541
1542    return status;
1543}
1544
1545//////////////////////////////////////////////////////////////////////////////////////////////////
1546//
1547// IOFireWireSBP2ORB
1548//
1549
1550IOReturn IOFireWireSBP2UserClient::createORB
1551	(  IOExternalMethodArguments * arguments )
1552{
1553	IOReturn status = checkArguments( arguments, 0, 0, 1, 0 );
1554	IOFireWireSBP2ORB * orb = NULL;
1555
1556    if( status == kIOReturnSuccess )
1557    {
1558		if( !fLogin )
1559			status = kIOReturnError;
1560	}
1561
1562    if( status == kIOReturnSuccess )
1563    {
1564        orb = fLogin->createORB();
1565        if( !orb )
1566            status = kIOReturnError;
1567    }
1568
1569	if( status == kIOReturnSuccess )
1570    {
1571		IOFireWireLib::UserObjectHandle outHandle = 0;
1572
1573		status = fExporter->addObject( orb, NULL, &outHandle );
1574
1575		arguments->scalarOutput[0] = (uint64_t)outHandle;
1576
1577		orb->release();
1578	}
1579
1580    return status;
1581}
1582
1583IOReturn IOFireWireSBP2UserClient::releaseORB
1584	(  IOExternalMethodArguments * arguments )
1585{
1586	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1587
1588	FWKLOG(( "IOFireWireSBP2UserClient : releaseORB\n" ));
1589
1590	IOFireWireSBP2ORB * orb = NULL;
1591	if( status == kIOReturnSuccess )
1592	{
1593		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1594		if( !orb )
1595		{
1596			status = kIOReturnBadArgument;
1597		}
1598	}
1599
1600	if( status == kIOReturnSuccess )
1601	{
1602		fExporter->removeObject( arguments->scalarInput[0] );
1603	}
1604
1605	if( orb )
1606	{
1607		orb->release();
1608		orb = NULL;
1609	}
1610
1611
1612
1613    return kIOReturnSuccess;
1614}
1615
1616// submitORB
1617//
1618//
1619
1620IOReturn IOFireWireSBP2UserClient::submitORB
1621	(  IOExternalMethodArguments * arguments )
1622{
1623	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1624
1625    FWKLOG(( "IOFireWireSBP2UserClient : submitORB\n" ));
1626
1627	IOFireWireSBP2ORB * orb = NULL;
1628	if( status == kIOReturnSuccess )
1629	{
1630		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1631		if( !orb )
1632		  status = kIOReturnError;
1633	}
1634
1635    if( status == kIOReturnSuccess )
1636    {
1637         status = fLogin->submitORB(orb);
1638    }
1639
1640	if( orb )
1641	{
1642		orb->release();
1643		orb = NULL;
1644	}
1645
1646    return status;
1647}
1648
1649// setCommandFlags
1650//
1651//
1652
1653IOReturn IOFireWireSBP2UserClient::setCommandFlags
1654	(  IOExternalMethodArguments * arguments )
1655{
1656	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1657
1658    FWKLOG(( "IOFireWireSBP2UserClient : setCommandFlags\n" ));
1659
1660	IOFireWireSBP2ORB * orb = NULL;
1661	if( status == kIOReturnSuccess )
1662	{
1663		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1664		if( !orb )
1665		  status = kIOReturnError;
1666	}
1667
1668    if( status == kIOReturnSuccess )
1669    {
1670         orb->setCommandFlags( (UInt32)arguments->scalarInput[1] );
1671    }
1672
1673	if( orb )
1674	{
1675		orb->release();
1676		orb = NULL;
1677	}
1678
1679    return status;
1680}
1681
1682// setMaxORBPayloadSize
1683//
1684//
1685
1686IOReturn IOFireWireSBP2UserClient::setMaxORBPayloadSize
1687	(  IOExternalMethodArguments * arguments )
1688{
1689	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1690
1691    FWKLOG(( "IOFireWireSBP2UserClient : setMaxPayloadSize\n" ));
1692
1693	IOFireWireSBP2ORB * orb = NULL;
1694	if( status == kIOReturnSuccess )
1695	{
1696		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1697		if( !orb )
1698		  status = kIOReturnError;
1699	}
1700
1701    if( status == kIOReturnSuccess )
1702    {
1703        orb->setMaxPayloadSize( (UInt32)arguments->scalarInput[1] );
1704    }
1705
1706	if( orb )
1707	{
1708		orb->release();
1709		orb = NULL;
1710	}
1711
1712    return status;
1713}
1714
1715// setORBRefCon
1716//
1717//
1718
1719IOReturn IOFireWireSBP2UserClient::setORBRefCon
1720	(  IOExternalMethodArguments * arguments )
1721{
1722    IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1723
1724    FWKLOG(( "IOFireWireSBP2UserClient : setORBRefCon\n" ));
1725
1726	IOFireWireSBP2ORB * orb = NULL;
1727	if( status == kIOReturnSuccess )
1728	{
1729		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1730		if( !orb )
1731		  status = kIOReturnError;
1732	}
1733
1734    if( status == kIOReturnSuccess )
1735    {
1736        orb->setRefCon64( arguments->scalarInput[1] );
1737    }
1738
1739	if( orb )
1740	{
1741		orb->release();
1742		orb = NULL;
1743	}
1744
1745    return status;
1746}
1747
1748// setCommandTimeout
1749//
1750//
1751
1752IOReturn IOFireWireSBP2UserClient::setCommandTimeout
1753	(  IOExternalMethodArguments * arguments )
1754{
1755    IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1756
1757    FWKLOG(( "IOFireWireSBP2UserClient : setCommandTimeout\n" ));
1758
1759	IOFireWireSBP2ORB * orb = NULL;
1760	if( status == kIOReturnSuccess )
1761	{
1762		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1763		if( !orb )
1764		  status = kIOReturnError;
1765	}
1766
1767    if( status == kIOReturnSuccess )
1768    {
1769        orb->setCommandTimeout( (UInt32)arguments->scalarInput[1] );
1770    }
1771
1772	if( orb )
1773	{
1774		orb->release();
1775		orb = NULL;
1776	}
1777
1778    return status;
1779}
1780
1781// setCommandGeneration
1782//
1783//
1784
1785IOReturn IOFireWireSBP2UserClient::setCommandGeneration
1786	(  IOExternalMethodArguments * arguments )
1787{
1788    IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
1789
1790    FWKLOG(( "IOFireWireSBP2UserClient : setCommandGeneration\n" ));
1791
1792	IOFireWireSBP2ORB * orb = NULL;
1793	if( status == kIOReturnSuccess )
1794	{
1795		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1796		if( !orb )
1797		  status = kIOReturnError;
1798	}
1799
1800    if( status == kIOReturnSuccess )
1801    {
1802        orb->setCommandGeneration( (UInt32)arguments->scalarInput[1] );
1803    }
1804
1805	if( orb )
1806	{
1807		orb->release();
1808		orb = NULL;
1809	}
1810
1811    return status;
1812}
1813
1814// setToDummy
1815//
1816//
1817
1818IOReturn IOFireWireSBP2UserClient::setToDummy
1819	(  IOExternalMethodArguments * arguments )
1820{
1821	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1822
1823    FWKLOG(( "IOFireWireSBP2UserClient : setToDummy\n" ));
1824
1825	IOFireWireSBP2ORB * orb = NULL;
1826	if( status == kIOReturnSuccess )
1827	{
1828		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1829		if( !orb )
1830		  status = kIOReturnError;
1831	}
1832
1833    if( status == kIOReturnSuccess )
1834    {
1835		//zzz why is this turned off?
1836
1837		// orb->setToDummy();
1838    }
1839
1840	if( orb )
1841	{
1842		orb->release();
1843		orb = NULL;
1844	}
1845
1846    return status;
1847}
1848
1849// setCommandBuffersAsRanges
1850//
1851//
1852
1853IOReturn IOFireWireSBP2UserClient::setCommandBuffersAsRanges
1854		(  IOExternalMethodArguments * arguments )
1855{
1856	IOReturn status = checkArguments( arguments, 6, 0, 0, 0 );
1857
1858 	IOMemoryDescriptor * 	rangeDesc = NULL;
1859	IOFireWireSBP2ORB * 	orb = NULL;
1860	IOAddressRange * 		rangeBytes = NULL;
1861
1862    FWKLOG(( "IOFireWireSBP2UserClient : setCommandBuffersAsRanges\n" ));
1863
1864	if( status == kIOReturnSuccess )
1865	{
1866		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1867		if( !orb )
1868			status = kIOReturnError;
1869	}
1870
1871	mach_vm_address_t ranges = 0;
1872	uint64_t withCount = 0;
1873	uint64_t offset = 0;
1874	uint64_t length = 0;
1875	vm_size_t rangeSize = 0;
1876
1877	if( status == kIOReturnSuccess )
1878	{
1879		ranges = arguments->scalarInput[1];
1880		withCount = arguments->scalarInput[2];
1881	//	IODirection withDirection = (IODirection)arguments->scalarInput[3];
1882		offset = arguments->scalarInput[4];
1883		length = arguments->scalarInput[5];
1884		rangeSize = sizeof(IOAddressRange) * withCount;
1885
1886	//	IOLog( "IOFWSBPUC::setBuf - withCount = %lld length = %lld\n", withCount, length );
1887
1888	}
1889
1890	if( status == kIOReturnSuccess )
1891	{
1892		rangeDesc = IOMemoryDescriptor::withAddressRange(	ranges,
1893															rangeSize,
1894															kIODirectionOut, fTask );
1895		if( !rangeDesc )
1896            status = kIOReturnNoMemory;
1897	}
1898
1899	if( status == kIOReturnSuccess )
1900	{
1901		status = rangeDesc->prepare();
1902	}
1903
1904	if( status == kIOReturnSuccess )
1905	{
1906		rangeBytes = (IOAddressRange*)IOMalloc( rangeSize );
1907		if( rangeBytes == NULL )
1908			status = kIOReturnNoMemory;
1909	}
1910
1911	if( status == kIOReturnSuccess )
1912	{
1913		rangeDesc->readBytes( 0, rangeBytes, rangeSize );
1914	}
1915
1916	if( status == kIOReturnSuccess )
1917	{
1918	#if 0
1919		for( UInt32 i = 0; i < withCount; i++ )
1920		{
1921			IOLog( "IOFWSBPUC::setBuf - %d : addr = 0x%016llx len =  0x%016llx\n", i, rangeBytes[i].address, rangeBytes[i].length );
1922		}
1923	#endif
1924	}
1925
1926    if( status == kIOReturnSuccess )
1927    {
1928		status = orb->setCommandBuffersAsRanges64(	rangeBytes,
1929													withCount,
1930													kIODirectionOutIn,
1931													fTask,
1932													offset,
1933													length );
1934    }
1935
1936	if( rangeBytes )
1937	{
1938		IOFree( rangeBytes, rangeSize );
1939	}
1940
1941	if( rangeDesc )
1942	{
1943		rangeDesc->complete();
1944		rangeDesc->release();
1945	}
1946
1947	if( orb )
1948	{
1949		orb->release();
1950		orb = NULL;
1951	}
1952
1953    return status;
1954}
1955
1956// releaseCommandBuffers
1957//
1958//
1959
1960IOReturn IOFireWireSBP2UserClient::releaseCommandBuffers
1961	(  IOExternalMethodArguments * arguments )
1962{
1963    IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
1964
1965    FWKLOG(( "IOFireWireSBP2UserClient : releaseCommandBuffers\n" ));
1966
1967	IOFireWireSBP2ORB * orb = NULL;
1968	if( status == kIOReturnSuccess )
1969	{
1970		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
1971		if( !orb )
1972		  status = kIOReturnError;
1973	}
1974
1975    if( status == kIOReturnSuccess )
1976    {
1977        status = orb->releaseCommandBuffers();
1978    }
1979
1980	if( orb )
1981	{
1982		orb->release();
1983		orb = NULL;
1984	}
1985
1986    return status;
1987}
1988
1989// setCommandBlock
1990//
1991//
1992
1993IOReturn IOFireWireSBP2UserClient::setCommandBlock
1994	(  IOExternalMethodArguments * arguments )
1995{
1996    IOReturn status = checkArguments( arguments, 3, 0, 0, 0 );
1997
1998    IOMemoryDescriptor *	memory = NULL;
1999
2000	IOFireWireSBP2ORB * orb = NULL;
2001	if( status == kIOReturnSuccess )
2002	{
2003		FWKLOG(( "IOFireWireSBP2UserClient : setCommandBlock - ORBRef = 0x%08lx buffer = 0x%08lx length = %d\n", (UInt32)arguments->scalarInput[0], (UInt32)arguments->scalarInput[1], (UInt32)arguments->scalarInput[2] ));
2004
2005		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
2006		if( !orb )
2007		  status = kIOReturnError;
2008	}
2009
2010    if( status == kIOReturnSuccess )
2011    {
2012		mach_vm_address_t buffer = arguments->scalarInput[1];
2013		mach_vm_size_t length = arguments->scalarInput[2];
2014		memory = IOMemoryDescriptor::withAddressRange(	buffer,
2015														length,
2016														kIODirectionOut, fTask );
2017        if( !memory )
2018            status = kIOReturnNoMemory;
2019    }
2020
2021	if( status == kIOReturnSuccess )
2022	{
2023		status = memory->prepare();
2024	}
2025
2026    if( status == kIOReturnSuccess )
2027    {
2028        orb->setCommandBlock( memory );
2029    }
2030
2031    if( memory )
2032	{
2033		memory->complete();
2034        memory->release();
2035	}
2036
2037	if( orb )
2038	{
2039		orb->release();
2040		orb = NULL;
2041	}
2042
2043    return status;
2044}
2045// setCommandBuffersAsRanges
2046//
2047//
2048
2049IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSetCommandBuffersAsRanges
2050	(  IOExternalMethodArguments * arguments )
2051{
2052	IOReturn status = checkArguments( arguments, 6, 0, 0, 0 );
2053
2054	IOFireWireSBP2ORB * 	orb = NULL;
2055
2056    FWKLOG(( "IOFireWireSBP2UserClient : LSIWorkaroundSetCommandBuffersAsRanges\n" ));
2057
2058	if( status == kIOReturnSuccess )
2059	{
2060		orb = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ORB) );
2061		if( !orb )
2062			status = kIOReturnError;
2063	}
2064
2065	if( status == kIOReturnSuccess )
2066	{
2067		orb->setBufferConstraints( kFWSBP2MaxPageClusterSize, PAGE_SIZE, kFWSBP2ConstraintForceDoubleBuffer );
2068	}
2069
2070	if( status == kIOReturnSuccess )
2071	{
2072		status = setCommandBuffersAsRanges( arguments );
2073	}
2074
2075	if( orb )
2076	{
2077		orb->release();
2078		orb = NULL;
2079	}
2080
2081    return status;
2082}
2083
2084
2085IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSyncBuffersForOutput
2086						(  IOExternalMethodArguments * arguments )
2087{
2088	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
2089
2090	// NOP
2091
2092	return status;
2093}
2094
2095IOReturn IOFireWireSBP2UserClient::LSIWorkaroundSyncBuffersForInput
2096					(  IOExternalMethodArguments * arguments )
2097{
2098	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
2099
2100
2101	// NOP
2102
2103	return status;
2104}
2105
2106/////////////////////////////////////////////////
2107// IOFireWireSBP2MgmtORB
2108
2109IOReturn IOFireWireSBP2UserClient::createMgmtORB
2110	(  IOExternalMethodArguments * arguments )
2111{
2112    IOReturn status = checkArguments( arguments, 0, 0, 1, 0 );
2113
2114    IOFireWireSBP2ManagementORB * orb = NULL;
2115
2116    if( status == kIOReturnSuccess )
2117    {
2118		if( !fProviderLUN )
2119			status = kIOReturnError;
2120	}
2121
2122    if( status == kIOReturnSuccess )
2123    {
2124        orb = fProviderLUN->createManagementORB( this, staticMgmtORBCallback );
2125        if( !orb )
2126            status = kIOReturnError;
2127    }
2128
2129	if( status == kIOReturnSuccess )
2130    {
2131		IOFireWireLib::UserObjectHandle outHandle = 0;
2132
2133		status = fExporter->addObject( orb, NULL, &outHandle );
2134
2135		arguments->scalarOutput[0] = (uint64_t)outHandle;
2136
2137		orb->release();
2138	}
2139
2140    return status;
2141}
2142
2143IOReturn IOFireWireSBP2UserClient::setMgmtORBCallback
2144	(  IOExternalMethodArguments * arguments )
2145{
2146    IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
2147    IOFireWireSBP2ManagementORB * orb;
2148
2149    FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBCallback\n" ));
2150
2151    if( status == kIOReturnSuccess )
2152    {
2153		orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2154		if( !orb )
2155            status = kIOReturnError;
2156    }
2157
2158    if( status == kIOReturnSuccess )
2159    {
2160		OSAsyncReference64 asyncRef;
2161		bcopy( arguments->asyncReference, asyncRef, sizeof(OSAsyncReference64) );
2162        setMgmtORBAsyncCallbackReference( orb, asyncRef );
2163    }
2164
2165	if( orb )
2166	{
2167		orb->release();
2168		orb = NULL;
2169	}
2170
2171    return status;
2172}
2173
2174IOReturn IOFireWireSBP2UserClient::releaseMgmtORB
2175	(  IOExternalMethodArguments * arguments )
2176{
2177	IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
2178
2179    FWKLOG(( "IOFireWireSBP2UserClient : releaseMgmtORB\n" ));
2180	IOFireWireSBP2ManagementORB * orb = NULL;
2181	if( status == kIOReturnSuccess )
2182	{
2183		orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2184		if( !orb )
2185		{
2186			status = kIOReturnBadArgument;
2187		}
2188	}
2189
2190	if( status == kIOReturnSuccess )
2191	{
2192		fExporter->removeObject( arguments->scalarInput[0] );
2193	}
2194
2195	if( orb )
2196	{
2197		orb->release();
2198		orb = NULL;
2199	}
2200
2201    return status;
2202}
2203
2204// submitORB
2205//
2206//
2207
2208IOReturn IOFireWireSBP2UserClient::submitMgmtORB
2209	(  IOExternalMethodArguments * arguments )
2210{
2211    IOReturn status = checkArguments( arguments, 1, 0, 0, 0 );
2212
2213    FWKLOG(( "IOFireWireSBP2UserClient : submitManagementORB\n" ));
2214
2215	IOFireWireSBP2ManagementORB * orb = NULL;
2216	if( status == kIOReturnSuccess )
2217	{
2218		orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2219		if( !orb )
2220		  status = kIOReturnError;
2221	}
2222
2223    if( status == kIOReturnSuccess )
2224    {
2225         status = orb->submit();
2226    }
2227
2228	if( orb )
2229	{
2230		orb->release();
2231		orb = NULL;
2232	}
2233
2234    return status;
2235}
2236
2237// setMgmtORBCommandFunction
2238//
2239//
2240
2241IOReturn IOFireWireSBP2UserClient::setMgmtORBCommandFunction
2242			(  IOExternalMethodArguments * arguments )
2243{
2244  	IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
2245
2246    FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBCommandFunction\n" ));
2247
2248	IOFireWireSBP2ManagementORB * orb = NULL;
2249	if( status == kIOReturnSuccess )
2250	{
2251		orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2252		if( !orb )
2253		  status = kIOReturnError;
2254	}
2255
2256    if( status == kIOReturnSuccess )
2257    {
2258         status = orb->setCommandFunction( (UInt32)arguments->scalarInput[1] );
2259    }
2260
2261	if( orb )
2262	{
2263		orb->release();
2264		orb = NULL;
2265	}
2266
2267    return status;
2268}
2269
2270// setMgmtORBManageeORB
2271//
2272//
2273
2274IOReturn IOFireWireSBP2UserClient::setMgmtORBManageeORB
2275			(  IOExternalMethodArguments * arguments )
2276{
2277   IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
2278
2279    FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBManageeORB\n" ));
2280	IOFireWireSBP2ManagementORB * mgmtORB;
2281	IOFireWireSBP2ORB * manageeORB = NULL;
2282
2283	if( status == kIOReturnSuccess )
2284	{
2285		mgmtORB = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2286		if( !mgmtORB )
2287			status = kIOReturnError;
2288	}
2289
2290	if( status == kIOReturnSuccess )
2291	{
2292		manageeORB = (IOFireWireSBP2ORB*) fExporter->lookupObjectForType( arguments->scalarInput[1], OSTypeID(IOFireWireSBP2ORB) );
2293		if( !manageeORB )
2294			status = kIOReturnError;
2295	}
2296
2297    if( status == kIOReturnSuccess )
2298    {
2299         mgmtORB->setManageeCommand( manageeORB );
2300    }
2301
2302	if( manageeORB )
2303	{
2304		manageeORB->release();
2305		manageeORB = NULL;
2306	}
2307
2308	if( mgmtORB )
2309	{
2310		mgmtORB->release();
2311		mgmtORB = NULL;
2312	}
2313
2314    return status;
2315}
2316
2317// setMgmtORBManageeLogin
2318//
2319//
2320
2321IOReturn IOFireWireSBP2UserClient::setMgmtORBManageeLogin
2322			(  IOExternalMethodArguments * arguments )
2323{
2324   IOReturn status = checkArguments( arguments, 2, 0, 0, 0 );
2325
2326
2327    FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBManageeLogin\n" ));
2328	IOFireWireSBP2ManagementORB * orb;
2329	IOFireWireSBP2Login * manageeLogin = NULL;
2330
2331	if( status == kIOReturnSuccess )
2332	{
2333		orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2334		if( !orb )
2335			status = kIOReturnError;
2336	}
2337
2338	if( status == kIOReturnSuccess )
2339	{
2340		manageeLogin = (IOFireWireSBP2Login*) fExporter->lookupObjectForType( arguments->scalarInput[1], OSTypeID(IOFireWireSBP2Login) );
2341		if( !manageeLogin )
2342		{
2343			status = kIOReturnBadArgument;
2344		}
2345	}
2346
2347    if( status == kIOReturnSuccess )
2348    {
2349         orb->setManageeCommand( manageeLogin );
2350    }
2351
2352	if( manageeLogin )
2353	{
2354		manageeLogin->release();
2355		manageeLogin = NULL;
2356	}
2357
2358	if( orb )
2359	{
2360		orb->release();
2361		orb = NULL;
2362	}
2363
2364    return status;
2365}
2366
2367// setMgmtORBResponseBuffer
2368//
2369//
2370
2371IOReturn IOFireWireSBP2UserClient::setMgmtORBResponseBuffer
2372			(  IOExternalMethodArguments * arguments )
2373{
2374	IOReturn status = checkArguments( arguments, 3, 0, 0, 0 );
2375
2376    FWKLOG(( "IOFireWireSBP2UserClient : setMgmtORBCommandFunction\n" ));
2377
2378	IOFireWireSBP2ManagementORB * orb = NULL;
2379	if( status == kIOReturnSuccess )
2380	{
2381		orb = (IOFireWireSBP2ManagementORB*) fExporter->lookupObjectForType( arguments->scalarInput[0], OSTypeID(IOFireWireSBP2ManagementORB) );
2382		if( !orb )
2383			status = kIOReturnError;
2384	}
2385
2386	mach_vm_address_t buffer = arguments->scalarInput[1];
2387	mach_vm_size_t length = arguments->scalarInput[2];
2388
2389	if( status == kIOReturnSuccess )
2390	{
2391		if( !buffer || length == 0 )
2392		{
2393			status = orb->setResponseBuffer( NULL );
2394			return status;
2395		}
2396	}
2397
2398	IOMemoryDescriptor * memory = NULL;
2399
2400	if( status == kIOReturnSuccess )
2401    {
2402		memory = IOMemoryDescriptor::withAddressRange(	buffer,
2403														length,
2404														kIODirectionOutIn, fTask );
2405        if( !memory )
2406            status = kIOReturnNoMemory;
2407    }
2408
2409	if( status == kIOReturnSuccess )
2410	{
2411		status = memory->prepare();
2412	}
2413
2414    if( status == kIOReturnSuccess )
2415    {
2416         status = orb->setResponseBuffer( memory );
2417    }
2418
2419	if( orb )
2420	{
2421		orb->release();
2422		orb = NULL;
2423	}
2424
2425    return status;
2426}
2427
2428
2429// orb callback methods
2430//
2431//
2432
2433void IOFireWireSBP2UserClient::staticMgmtORBCallback
2434	(void * refCon, IOReturn status, IOFireWireSBP2ManagementORB * orb)
2435{
2436    ((IOFireWireSBP2UserClient*)refCon)->mgmtORBCallback( status, orb );
2437}
2438
2439void IOFireWireSBP2UserClient::mgmtORBCallback( IOReturn status, IOFireWireSBP2ManagementORB * orb )
2440{
2441    FWKLOG(( "IOFireWireSBP2UserClient : mgmtORBCallback\n" ));
2442
2443    OSAsyncReference64 asyncRef;
2444
2445	orb->setResponseBuffer( NULL );
2446    getMgmtORBAsyncCallbackReference( orb, asyncRef );
2447
2448    if( asyncRef[0] != 0 )
2449    {
2450		uint64_t args[3];
2451		args[0] = status;
2452        sendAsyncResult64( asyncRef, kIOReturnSuccess, args, 3 );
2453    }
2454}
2455
2456///////////////////////////////////////////////////////////////////////////////////////
2457// friend class wrapper functions
2458
2459// IOFireWireSBP2ManagementORB friend class wrappers
2460void IOFireWireSBP2UserClient::flushAllManagementORBs( void )
2461{
2462	fProviderLUN->flushAllManagementORBs();
2463}
2464
2465// IOFireWireSBP2MgmtORB friend class wrappers
2466void IOFireWireSBP2UserClient::setMgmtORBAsyncCallbackReference( IOFireWireSBP2ManagementORB * orb, void * asyncRef )
2467{
2468	orb->setAsyncCallbackReference( asyncRef );
2469}
2470
2471void IOFireWireSBP2UserClient::getMgmtORBAsyncCallbackReference( IOFireWireSBP2ManagementORB * orb, void * asyncRef )
2472{
2473	orb->getAsyncCallbackReference( asyncRef );
2474}
2475
2476