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* Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.
24*
25* HISTORY
26* 8 June 1999 wgulland created.
27*
28*/
29/*
30	$Log: IOFireWireUserClient.cpp,v $
31	Revision 1.162  2011/12/17 00:57:00  calderon
32	<rdar://problem/9589404> IOFireWireUserClient allows arbitrarily sized stack allocations.
33
34	Revision 1.161  2009/05/08 01:10:34  calderon
35	<rdar://6863576> FireWire tracepoints should be inlined for performance
36
37	Revision 1.160  2009/03/07 00:37:23  calderon
38	Small change for 6641573 to give more useful debugging info
39	Add Firelog info.plist file
40
41	Revision 1.159  2009/03/06 18:45:15  calderon
42	<rdar://problem/6641573> Panic in IOFireWireFamily/SL 10A286 when hot-plugging Mackie Onyx 1200F
43	Add FireLog specific plist to work around XCode plist editor bug
44	Bump version
45
46	Revision 1.158  2008/12/12 04:43:57  collin
47	user space compare swap command fixes
48
49	Revision 1.157  2008/11/26 23:55:21  collin
50	fix user physical address spaces on K64
51
52	Revision 1.156  2008/11/20 01:59:12  calderon
53	More tracepoint logging
54
55	Revision 1.155  2008/11/11 01:12:03  calderon
56	First part of tracepoints logging
57
58	Revision 1.154  2008/05/07 03:27:59  collin
59	64 bit session ref support
60
61	Revision 1.153  2008/04/30 03:02:13  collin
62	publicize the exporter
63
64	Revision 1.152  2008/04/24 00:01:39  collin
65	more K640
66
67	Revision 1.151  2008/04/11 00:52:37  collin
68	some K64 changes
69
70	Revision 1.150  2008/04/02 01:42:50  collin
71	fix build failure
72
73	Revision 1.149  2007/10/16 16:50:21  ayanowit
74	Removed existing "work-in-progress" support for buffer-fill isoch.
75
76	Revision 1.148  2007/06/21 04:08:44  collin
77	*** empty log message ***
78
79	Revision 1.147  2007/05/04 06:05:26  collin
80	*** empty log message ***
81
82	Revision 1.146  2007/04/28 02:54:22  collin
83	*** empty log message ***
84
85	Revision 1.145  2007/04/28 01:42:35  collin
86	*** empty log message ***
87
88	Revision 1.144  2007/04/24 02:50:08  collin
89	*** empty log message ***
90
91	Revision 1.143  2007/03/14 01:01:13  collin
92	*** empty log message ***
93
94	Revision 1.142  2007/03/12 22:15:28  arulchan
95	mach_vm_address_t & io_user_reference_t changes
96
97	Revision 1.141  2007/03/10 07:48:25  collin
98	*** empty log message ***
99
100	Revision 1.140  2007/03/10 05:11:36  collin
101	*** empty log message ***
102
103	Revision 1.139  2007/03/10 04:15:25  collin
104	*** empty log message ***
105
106	Revision 1.138  2007/03/10 02:58:03  collin
107	*** empty log message ***
108
109	Revision 1.137  2007/03/09 23:57:53  collin
110	*** empty log message ***
111
112	Revision 1.136  2007/03/08 18:13:56  ayanowit
113	Fix for 5047793. A problem where user-space CompareSwap() was not checking lock results.
114
115	Revision 1.135  2007/03/08 02:37:09  collin
116	*** empty log message ***
117
118	Revision 1.134  2007/03/03 01:26:46  calderon
119	pico
120
121	Revision 1.133  2007/02/16 00:54:39  ayanowit
122	Working IRMAllocation callbacks from user-space :)
123
124	Revision 1.132  2007/02/16 00:28:25  ayanowit
125	More work on IRMAllocation APIs
126
127	Revision 1.131  2007/02/09 20:36:46  ayanowit
128	More Leopard IRMAllocation changes.
129
130	Revision 1.130  2007/02/07 06:35:20  collin
131	*** empty log message ***
132
133	Revision 1.129  2007/02/06 01:08:41  ayanowit
134	More work on Leopard features such as new User-space IRM allocation APIs.
135
136	Revision 1.128  2007/01/26 20:52:31  ayanowit
137	changes to user-space isoch stuff to support 64-bit apps.
138
139	Revision 1.127  2007/01/24 04:10:13  collin
140	*** empty log message ***
141
142	Revision 1.126  2007/01/05 00:11:00  ayanowit
143	yet more 64-bit changes.
144
145	Revision 1.124  2006/12/21 21:17:44  ayanowit
146	More changes necessary to eventually get support for 64-bit apps working (4222965).
147
148	Revision 1.123  2006/12/06 01:12:54  arulchan
149	AsyncStream Listener Merges to Dispatcher
150
151	Revision 1.122  2006/12/06 00:01:08  arulchan
152	Isoch Channel 31 Generic Receiver
153
154	Revision 1.121  2006/11/29 18:42:52  ayanowit
155	Modified the IOFireWireUserClient to use the Leopard externalMethod method of dispatch.
156
157	Revision 1.120  2006/09/09 01:59:56  collin
158	*** empty log message ***
159
160	Revision 1.119  2006/08/16 01:41:41  collin
161	*** empty log message ***
162
163	Revision 1.118  2006/07/07 20:18:25  calderon
164	4227201: SpeedMap and HopCount table reductions.
165
166	Revision 1.117  2006/02/27 19:03:18  niels
167	*** empty log message ***
168
169	Revision 1.116  2006/02/09 00:21:51  niels
170	merge chardonnay branch to tot
171
172	Revision 1.110.4.4  2006/01/31 04:49:51  collin
173	*** empty log message ***
174
175	Revision 1.110.4.2  2005/08/17 03:33:57  collin
176	*** empty log message ***
177
178	Revision 1.110.4.1  2005/07/23 00:30:44  collin
179	*** empty log message ***
180
181	Revision 1.110  2005/01/18 23:40:16  collin
182	Revision 1.109  2004/09/16 04:28:21  collin
183	Revision 1.108  2004/05/12 00:00:08  niels
184	3626775 - Brego 7L8: Digidesign Pro Tools LE FireWire 002 system doesn't work
185	3641955 - Digi 002 Pro Tools LE fails to launch on 10.3.4 7H46
186
187	Revision 1.107  2004/03/25 00:08:59  niels
188	fix panic allocating large physical address spaces
189
190	Revision 1.106  2004/03/25 00:00:59  niels
191	fix panic allocating large physical address spaces
192
193	Revision 1.105  2004/03/25 00:00:23  niels
194	fix panic allocating large physical address spaces
195
196	Revision 1.104  2004/02/17 23:13:23  niels
197	Revision 1.103  2004/02/17 23:12:26  niels
198	Revision 1.102  2004/02/11 22:30:02  niels
199	Revision 1.101  2004/02/11 22:13:08  niels
200	fix final cut pro panic/object leak when calling TurnOffNotification on isoch channels in user space
201
202	Revision 1.100  2004/01/28 22:13:32  niels
203	Revision 1.99  2004/01/22 01:49:59  niels
204	fix user space physical address space getPhysicalSegments
205
206	Revision 1.98  2003/12/19 22:07:46  niels
207	send force stop when channel dies/system sleeps
208
209	Revision 1.97  2003/12/18 00:42:37  niels
210	Revision 1.96  2003/11/14 01:00:53  collin
211	Revision 1.95  2003/11/07 21:24:28  niels
212	Revision 1.94  2003/11/07 21:01:18  niels
213	Revision 1.93  2003/11/05 00:29:42  niels
214	Revision 1.92  2003/11/03 19:11:35  niels
215	fix local config rom reading; fix 3401223
216
217	Revision 1.91  2003/10/31 02:40:58  niels
218	Revision 1.90  2003/09/20 00:54:17  collin
219	Revision 1.89  2003/09/16 21:40:51  collin
220	Revision 1.88  2003/09/11 20:59:46  collin
221	Revision 1.87  2003/09/04 19:43:34  collin
222	Revision 1.86  2003/09/02 23:48:12  collin
223	Revision 1.85  2003/09/02 22:58:55  collin
224	Revision 1.84  2003/08/30 00:16:45  collin
225	Revision 1.83  2003/08/26 05:23:34  niels
226	Revision 1.82  2003/08/26 05:11:21  niels
227	Revision 1.81  2003/08/25 08:39:16  niels
228	Revision 1.80  2003/08/20 18:48:43  niels
229	Revision 1.79  2003/08/19 01:48:54  niels
230	Revision 1.78  2003/08/14 19:46:06  niels
231	Revision 1.77  2003/08/14 17:47:33  niels
232	Revision 1.76  2003/08/08 22:30:32  niels
233	Revision 1.75  2003/08/08 21:03:27  gecko1
234	Merge max-rec clipping code into TOT
235
236	Revision 1.74  2003/07/26 04:47:24  collin
237	Revision 1.73  2003/07/24 20:49:48  collin
238	Revision 1.72  2003/07/24 06:30:58  collin
239	Revision 1.71  2003/07/24 03:06:27  collin
240	Revision 1.70  2003/07/22 10:49:47  niels
241	Revision 1.69  2003/07/21 07:29:48  niels
242	Revision 1.68  2003/07/21 06:52:59  niels
243	merge isoch to TOT
244
245	Revision 1.66.2.5  2003/07/21 06:44:45  niels
246	Revision 1.66.2.4  2003/07/18 00:17:42  niels
247	Revision 1.66.2.3  2003/07/11 18:15:34  niels
248	Revision 1.66.2.2  2003/07/09 21:24:01  niels
249	Revision 1.66.2.1  2003/07/01 20:54:07  niels
250	isoch merge
251
252	Revision 1.66  2003/06/12 21:27:14  collin
253	Revision 1.65  2003/06/07 01:30:40  collin
254	Revision 1.64  2003/06/05 01:19:31  niels
255	fix crash on close
256
257	Revision 1.63  2003/04/22 02:45:28  collin
258	Revision 1.62  2003/03/17 01:05:22  collin
259	Revision 1.61  2003/03/01 00:10:07  collin
260	Revision 1.60  2002/11/20 00:34:27  niels
261	fix minor bug in getAsyncTargetAndMethodForIndex
262
263	Revision 1.59  2002/10/18 23:29:45  collin
264	fix includes, fix cast which fails on new compiler
265
266	Revision 1.58  2002/10/17 00:29:44  collin
267	reenable FireLog
268
269	Revision 1.57  2002/10/16 21:42:00  niels
270	no longer panic trying to get config directory on local node.. still can't get the directory, however
271
272	Revision 1.56  2002/09/25 00:27:25  niels
273	flip your world upside-down
274
275	Revision 1.55  2002/09/12 22:41:54  niels
276	add GetIRMNodeID() to user client
277
278*/
279
280// public
281#import "IOFireWireFamilyCommon.h"
282#import "IOFireWireNub.h"
283#import "IOLocalConfigDirectory.h"
284#import "IOFireWireController.h"
285#import "IOFireWireDevice.h"
286#import "IOFWDCLProgram.h"
287
288#import <sys/proc.h>
289#import <IOKit/IOMessage.h>
290#include <IOKit/IOKitKeysPrivate.h>
291
292#if FIRELOG
293#import <IOKit/firewire/FireLog.h>
294#endif
295
296// protected
297#import <IOKit/firewire/IOFireWireLink.h>
298
299// private
300#import "IOFireWireUserClient.h"
301#import "IOFWUserPseudoAddressSpace.h"
302#import "IOFWUserPhysicalAddressSpace.h"
303#import "IOFWUserIsochChannel.h"
304#import "IOFWUserIsochPort.h"
305#import "IOFireWireLibPriv.h"
306#import "IOFireWireLocalNode.h"
307#import "IOFWUserCommand.h"
308#import "IOFWUserObjectExporter.h"
309#import "IOLocalConfigDirectory.h"
310#import "IOFWUserAsyncStreamListener.h"
311#import "IOFWUserVectorCommand.h"
312#import "IOFWUserPHYPacketListener.h"
313
314#if IOFIREWIREUSERCLIENTDEBUG > 0
315
316#undef super
317#define super OSObject
318
319OSDefineMetaClassAndStructors( IOFWUserDebugInfo, OSObject )
320
321bool
322IOFWUserDebugInfo::init( IOFireWireUserClient & userClient )
323{
324	if ( ! super::init() )
325		return false ;
326
327	fUserClient = & userClient ;
328//	fIsochCallbacks = OSNumber::withNumber( (long long unsigned)0, 64 ) ;
329//	if ( !fIsochCallbacks )
330//		return false ;
331
332	return true ;
333}
334
335bool
336IOFWUserDebugInfo::serialize (
337	OSSerialize * s ) const
338{
339	s->clearText() ;
340
341	const unsigned objectCount = 1 ;
342	const OSObject * objects[ objectCount ] =
343	{
344		fUserClient->fExporter
345//		, fIsochCallbacks
346	} ;
347
348	const OSSymbol * keys[ objectCount ] =
349	{
350		OSSymbol::withCStringNoCopy("user objects")
351//		, OSSymbol::withCStringNoCopy( "total isoch callbacks" )
352	} ;
353
354	OSDictionary * dict = OSDictionary::withObjects( objects, keys, objectCount ) ;
355	if ( !dict )
356		return false ;
357
358	bool result = dict->serialize( s ) ;
359	dict->release() ;
360
361	return result ;
362}
363
364void
365IOFWUserDebugInfo::free ()
366{
367//	if ( fIsochCallbacks )
368//		fIsochCallbacks->release() ;
369	OSObject::free() ;
370}
371
372#endif
373
374#pragma mark -
375
376#undef super
377#define super IOUserClient
378
379OSDefineMetaClassAndStructors(IOFireWireUserClient, super ) ;
380
381
382bool IOFireWireUserClient::initWithTask(
383                    task_t owningTask, void * securityToken, UInt32 type,
384                    OSDictionary * properties)
385{
386    if( properties )
387		properties->setObject( "IOUserClientCrossEndianCompatible" , kOSBooleanTrue);
388
389    bool res = IOUserClient::initWithTask( owningTask, securityToken, type, properties );
390
391	fTask = owningTask;
392
393    return res;
394}
395
396bool
397IOFireWireUserClient::start( IOService * provider )
398{
399	if (!OSDynamicCast(IOFireWireNub, provider))
400		return false ;
401
402	if ( ! super::start ( provider ) )
403		return false;
404
405	fOwner = (IOFireWireNub *)provider;
406	fOwner->retain();
407
408	FWTrace( kFWTUserClient, kTPUserClientStart, (uintptr_t)(fOwner->getController()->getLink()), 0, 0, 0 );
409
410	//
411	// init object table
412	//
413	fObjectTable[0] = NULL ;
414	fObjectTable[1] = this ;
415	fObjectTable[2] = getOwner()->getBus() ;
416
417	// initialize notification structures
418	fBusResetAsyncNotificationRef[0] = 0 ;
419	fBusResetDoneAsyncNotificationRef[0] = 0 ;
420
421	bool result = true ;
422
423	fExporter = IOFWUserObjectExporter::createWithOwner( this );
424
425	if ( ! fExporter )
426		result = false ;
427
428#if IOFIREWIREUSERCLIENTDEBUG > 0
429	if (result)
430	{
431		fDebugInfo = OSTypeAlloc( IOFWUserDebugInfo );
432		if ( fDebugInfo && ! fDebugInfo->init( *this ) )
433		{
434			fDebugInfo->release() ;
435			fDebugInfo = NULL ;
436
437			ErrorLog( "Couldn't create statistics object\n" ) ;
438		}
439
440		if ( fDebugInfo )
441			setProperty( "Debug Info", fDebugInfo ) ;
442	}
443#endif
444
445#if 0
446	// turn off because sadly the proc structure is now opaque
447
448	// borrowed from bsd/vm/vm_unix.c, function pid_for_task() which has some other weird crap
449	// going on too... I just took this part:
450	if ( result )
451	{
452		proc *				p 			= (proc *)get_bsdtask_info( fTask );
453		OSNumber*			pidProp 	= OSNumber::withNumber( p->p_pid, sizeof(p->p_pid) * 8 ) ;
454		if ( pidProp )
455		{
456			setProperty( "Owning PID", pidProp ) ;
457			pidProp->release() ;			// property table takes a reference
458		}
459		else
460			result = false ;
461	}
462#endif
463
464	return result ;
465}
466
467void
468IOFireWireUserClient::free()
469{
470	if ( fOwner ) {
471		FWTrace( kFWTUserClient, kTPUserClientFree, (uintptr_t)(fOwner->getController()->getLink()), (uintptr_t)this, 0, 0 );
472	} else {
473		FWTrace( kFWTUserClient, kTPUserClientFree, 0xdeadbeef, (uintptr_t)this, 0, 0 );
474	}
475
476	DebugLog( "free user client %p\n", this ) ;
477
478#if IOFIREWIREUSERCLIENTDEBUG > 0
479	if ( fDebugInfo )
480		fDebugInfo->release() ;
481#endif
482
483	if ( fExporter )
484	{
485		fExporter->release() ;
486		fExporter = NULL ;
487	}
488
489	if ( fOwner )
490	{
491		fOwner->release() ;
492	}
493
494	super::free () ;
495}
496
497IOReturn
498IOFireWireUserClient::clientClose ()
499{
500	FWTrace( kFWTUserClient, kTPUserClientClientClose, (uintptr_t)(fOwner->getController()->getLink()), 0, 0, 0 );
501
502	clipMaxRec2K( false );	// Make sure maxRec isn't clipped
503
504	IOReturn	result = userClose() ;
505
506	if ( getProvider() && fOwner->isOpen() )
507	{
508		DebugLog("IOFireWireUserClient::clientClose(): client left user client open, should call close. Closing...\n") ;
509	}
510	else if ( result == kIOReturnNotOpen )
511	{
512		result = kIOReturnSuccess ;
513	}
514
515	if ( !terminate() )
516	{
517		IOLog("IOFireWireUserClient::clientClose: terminate failed!, getOwner()->isOpen( this ) returned %u\n", getOwner()->isOpen(this)) ;
518	}
519
520	return kIOReturnSuccess;
521}
522
523IOReturn
524IOFireWireUserClient::clientDied ()
525{
526	if ( fOwner ) {
527		FWTrace( kFWTUserClient, kTPUserClientClientDied, (uintptr_t)(fOwner->getController()->getLink()), 1, 0, 0 );
528	} else {
529		FWTrace( kFWTUserClient, kTPUserClientClientDied, 0xdeadbeef, 1, 0, 0 );
530	}
531
532	if ( fOwner )
533	{
534		FWTrace( kFWTUserClient, kTPUserClientClientDied, (uintptr_t)(fOwner->getController()->getLink()), 2, 0, 0 );
535		fOwner->getBus()->resetBus() ;
536	}
537
538	IOReturn error = clientClose () ;
539
540	return error ;
541}
542
543IOReturn
544IOFireWireUserClient::setProperties (
545	OSObject * properties )
546{
547	IOReturn result = kIOReturnSuccess ;
548
549	OSDictionary*	dict = OSDynamicCast( OSDictionary, properties ) ;
550
551	if ( dict )
552	{
553		OSObject*	value = dict->getObject( "unsafe bus resets" ) ;
554
555		if ( value and OSDynamicCast(OSNumber, value ) )
556		{
557			fUnsafeResets = ( ((OSNumber*)value)->unsigned8BitValue() != 0 ) ;
558		}
559		else
560		{
561			result = super::setProperties ( properties ) ;
562		}
563	}
564	else
565		result = super::setProperties ( properties ) ;
566
567	return result ;
568}
569
570#pragma mark -
571
572
573static UInt32 getSelectorObjectLookupIndex(UInt32 selector)
574{
575	UInt32 selectorObjectLookupIndex = 1;  // Note: A 1 here specifies use of the IOFireWireUserClient object
576
577	/////////////////////////////////////////////////////////////////////////////////////////////////////////
578	// NOTE: If the selector is not in this lookup table, it is handled directly by the IOFireWireUserClient
579	/////////////////////////////////////////////////////////////////////////////////////////////////////////
580	switch (selector)
581	{
582		/////////////////////////////////////////////////////////////////////////
583		// The follwing selectors all are handled by the IOFireWireBus
584		/////////////////////////////////////////////////////////////////////////
585		case kCycleTime:
586		case kGetBusCycleTime:
587			selectorObjectLookupIndex = 2;  // Note: A 2 here specifies use of the IOFireWireBus object
588			break;
589
590		/////////////////////////////////////////////////////////////////////////////////
591		// The follwing selectors all are handled by object exporter managed objects
592		/////////////////////////////////////////////////////////////////////////////////
593		case kPhysicalAddrSpace_GetSegmentCount_d:			// Handled by a IOFWUserPhysicalAddressSpace object
594		case kIsochPort_AllocatePort_d:						// Handled by a IOFWUserLocalIsochPort object
595		case kIsochPort_ReleasePort_d:						// Handled by a IOFWUserLocalIsochPort object
596		case kIsochPort_Start_d:							// Handled by a IOFWUserLocalIsochPort object
597		case kIsochPort_Stop_d:								// Handled by a IOFWUserLocalIsochPort object
598		case kLocalIsochPort_ModifyJumpDCL_d:				// Handled by a IOFWUserLocalIsochPort object
599		case kLocalIsochPort_Notify_d:						// Handled by a IOFWUserLocalIsochPort object
600		case kIsochChannel_UserReleaseChannelComplete_d:	// Handled by a IOFWUserIsochChannel object
601		case kCommand_Cancel_d:								// Handled by a IOFWCommand object
602		case kIsochPort_SetIsochResourceFlags_d:			// Handled by a IOFWLocalIsochPort object
603		case kVectorCommandSubmit:							// Handled by a IOFWUserVectorCommand object
604		case kVectorCommandSetBuffers:						// Handled by a IOFWUserVectorCommand object
605		case kPHYPacketListenerSetPacketCallback:			// Handled by a IOFWUserPHYPacketListener object
606		case kPHYPacketListenerSetSkippedCallback:			// Handled by a IOFWUserPHYPacketListener object
607		case kPHYPacketListenerActivate:					// Handled by a IOFWUserPHYPacketListener object
608		case kPHYPacketListenerDeactivate:					// Handled by a IOFWUserPHYPacketListener object
609		case kPHYPacketListenerClientCommandIsComplete:		// Handled by a IOFWUserPHYPacketListener object
610			selectorObjectLookupIndex = 0;  // Note: A 0 here specifies a lookup into the object exporter!
611			break;
612
613		default:
614			// Any other selector is handled by the IOFireWireUserClient!
615			break;
616	};
617	return selectorObjectLookupIndex;
618}
619
620IOReturn
621IOFireWireUserClient::externalMethod( uint32_t selector,
622										IOExternalMethodArguments * arguments,
623										IOExternalMethodDispatch * dispatch,
624										OSObject * target,
625										void * reference)
626{
627	IOReturn result = kIOReturnBadArgument;
628	IOService *targetObject;
629
630	UInt32 actualSelector = selector & 0xFFFF ;
631	if ( actualSelector >= kNumMethods )
632		return result;
633
634	targetObject = fObjectTable[ getSelectorObjectLookupIndex(actualSelector)] ;
635
636	if ( !targetObject )
637	{
638		const OSObject * userObject = fExporter->lookupObject( (UserObjectHandle)( selector >> 16 ) ) ;
639
640		targetObject = (IOService*)userObject ;		// "interesting code" note:
641													// when we don't have an object set in our method table,
642													// the object handle is encoded in the upper 16 bits of the
643													// method index...
644													// We extract the object handle here to get the object to call...
645
646		if (targetObject)
647		{
648			(targetObject)->release() ;	// exporter retains returned objects, we have to release it here..
649										// hopefully no one will release the object until we're done..
650		}
651		else
652			return result;
653	}
654
655	// Dispatch the method call
656	switch (actualSelector)
657	{
658		case kOpen:
659			result = ((IOFireWireUserClient*) targetObject)->userOpen();
660			break;
661
662		case kOpenWithSessionRef:
663			result = ((IOFireWireUserClient*) targetObject)->userOpenWithSessionRef((IOFireWireLib::UserObjectHandle) arguments->scalarInput[0]);
664			break;
665
666		case kClose:
667			result = ((IOFireWireUserClient*) targetObject)->userClose();
668			break;
669
670		case kReadQuad:
671			result = ((IOFireWireUserClient*) targetObject)->
672									readQuad((const ReadQuadParams*) arguments->structureInput,
673											(UInt32*) arguments->structureOutput);
674			break;
675
676		case kRead:
677			result = ((IOFireWireUserClient*) targetObject)->
678											read((const ReadParams*) arguments->structureInput,
679												(IOByteCount*) arguments->structureOutput);
680			break;
681
682		case kWriteQuad:
683			result = ((IOFireWireUserClient*) targetObject)->writeQuad((const WriteQuadParams*) arguments->structureInput);
684			break;
685
686		case kWrite:
687			result = ((IOFireWireUserClient*) targetObject)->
688											write((const WriteParams*) arguments->structureInput,
689													(IOByteCount*) arguments->structureOutput);
690			break;
691
692		case kCompareSwap:
693			result = ((IOFireWireUserClient*) targetObject)->
694											compareSwap((const CompareSwapParams*) arguments->structureInput,
695													(UInt32*) arguments->structureOutput);
696			break;
697
698		case kBusReset:
699			result = ((IOFireWireUserClient*) targetObject)->busReset();
700			break;
701
702		case kCycleTime:
703		{
704			UInt32 cycleTime;
705			UInt64 upTime;
706			result = ((IOFireWireController*) targetObject)->getCycleTimeAndUpTime(cycleTime, upTime);
707			arguments->scalarOutput[0] = cycleTime;
708			arguments->scalarOutput[1] = upTime;
709		}
710			break;
711
712		case kGetGenerationAndNodeID:
713		{
714			UInt32 outGeneration;
715			UInt32 outNodeID;
716			result = ((IOFireWireUserClient*) targetObject)->getGenerationAndNodeID(&outGeneration,&outNodeID);
717			arguments->scalarOutput[0] = outGeneration;
718			arguments->scalarOutput[1] = outNodeID;
719		}
720			break;
721
722		case kGetLocalNodeID:
723		{
724			UInt32 outLocalNodeID;
725			result = ((IOFireWireUserClient*) targetObject)->getLocalNodeID(&outLocalNodeID);
726			arguments->scalarOutput[0] = outLocalNodeID;
727		}
728			break;
729
730		case kGetResetTime:
731			result = ((IOFireWireUserClient*) targetObject)->getResetTime((AbsoluteTime*) arguments->structureOutput);
732			break;
733
734		case kReleaseUserObject:
735			result = ((IOFireWireUserClient*) targetObject)->releaseUserObject((UserObjectHandle)arguments->scalarInput[0]);
736			break;
737
738		case kGetOSStringData:
739		{
740			UInt32 outTextLength;
741			result = ((IOFireWireUserClient*) targetObject)->getOSStringData((UserObjectHandle)arguments->scalarInput[0],
742																			(UInt32)arguments->scalarInput[1],
743																			(mach_vm_address_t)arguments->scalarInput[2],
744																			&outTextLength);
745			arguments->scalarOutput[0] = outTextLength;
746		}
747			break;
748
749		case kGetOSDataData:
750		{
751			IOByteCount outDataLen;
752			result = ((IOFireWireUserClient*) targetObject)->getOSDataData((UserObjectHandle)arguments->scalarInput[0],
753																			(IOByteCount)arguments->scalarInput[1],
754																			(mach_vm_address_t)arguments->scalarInput[2],
755																			&outDataLen);
756			arguments->scalarOutput[0] = outDataLen;
757		}
758			break;
759
760		case kLocalConfigDirectory_Create:
761		{
762			UserObjectHandle outDir;
763			result = ((IOFireWireUserClient*) targetObject)->localConfigDirectory_Create(&outDir);
764			arguments->scalarOutput[0] = (uint64_t) outDir;
765		}
766			break;
767
768		case kLocalConfigDirectory_AddEntry_Buffer:
769			result = ((IOFireWireUserClient*) targetObject)->
770						localConfigDirectory_addEntry_Buffer((UserObjectHandle)arguments->scalarInput[0],
771															(int)arguments->scalarInput[1],
772															(char *)arguments->scalarInput[2],
773															(UInt32)arguments->scalarInput[3],
774															(const char *)arguments->scalarInput[4],
775															(UInt32)arguments->scalarInput[5]);
776			break;
777
778		case kLocalConfigDirectory_AddEntry_UInt32:
779			result = ((IOFireWireUserClient*) targetObject)->
780						localConfigDirectory_addEntry_UInt32((UserObjectHandle)arguments->scalarInput[0],
781															(int)arguments->scalarInput[1],
782															(UInt32)arguments->scalarInput[2],
783															(const char *)arguments->scalarInput[3],
784															(UInt32)arguments->scalarInput[4]);
785			break;
786
787		case kLocalConfigDirectory_AddEntry_FWAddr:
788			result = ((IOFireWireUserClient*) targetObject)->
789				localConfigDirectory_addEntry_FWAddr((UserObjectHandle)arguments->scalarInput[0],
790													(int)arguments->scalarInput[1],
791													(const char *)arguments->scalarInput[2],
792													(UInt32)arguments->scalarInput[3],
793													(FWAddress *) arguments->structureInput);
794			break;
795
796		case kLocalConfigDirectory_AddEntry_UnitDir:
797			// TODO -  Note: This wasn't hooked-up in Tiger either!
798			break;
799
800		case kLocalConfigDirectory_Publish:
801			result = ((IOFireWireUserClient*) targetObject)->localConfigDirectory_Publish((UserObjectHandle)arguments->scalarInput[0]);
802			break;
803
804		case kLocalConfigDirectory_Unpublish:
805			result = ((IOFireWireUserClient*) targetObject)->localConfigDirectory_Unpublish((UserObjectHandle)arguments->scalarInput[0]);
806			break;
807
808		case kPseudoAddrSpace_Allocate:
809			result = ((IOFireWireUserClient*) targetObject)->
810									addressSpace_Create((AddressSpaceCreateParams *) arguments->structureInput,
811														(UserObjectHandle *) arguments->structureOutput);
812			break;
813
814		case kPseudoAddrSpace_GetFWAddrInfo:
815			result = ((IOFireWireUserClient*) targetObject)->
816								addressSpace_GetInfo((UserObjectHandle)arguments->scalarInput[0],
817											(AddressSpaceInfo *) arguments->structureOutput);
818			break;
819
820		case kPseudoAddrSpace_ClientCommandIsComplete:
821			result = ((IOFireWireUserClient*) targetObject)->
822						addressSpace_ClientCommandIsComplete((UserObjectHandle)arguments->scalarInput[0],
823															(FWClientCommandID)arguments->scalarInput[1],
824															(IOReturn)arguments->scalarInput[2]);
825			break;
826
827		case kPhysicalAddrSpace_Allocate:
828		{
829			UserObjectHandle outAddressSpaceHandle;
830			result = ((IOFireWireUserClient*) targetObject)->physicalAddressSpace_Create((mach_vm_size_t)arguments->scalarInput[0],
831																						 (mach_vm_address_t)arguments->scalarInput[1],
832																						 (UInt32)arguments->scalarInput[2],
833																						 &outAddressSpaceHandle);
834			arguments->scalarOutput[0] = (uint64_t) outAddressSpaceHandle;
835		}
836			break;
837
838		case kPhysicalAddrSpace_GetSegmentCount_d:
839		{
840			UInt32 outSegmentCount;
841			result = ((IOFWUserPhysicalAddressSpace*) targetObject)->getSegmentCount(&outSegmentCount);
842			arguments->scalarOutput[0] = outSegmentCount;
843		}
844			break;
845
846		case kPhysicalAddrSpace_GetSegments:
847		{
848			UInt32 outSegmentCount;
849			result = ((IOFireWireUserClient*) targetObject)->physicalAddressSpace_GetSegments((UserObjectHandle)arguments->scalarInput[0],
850																			 (UInt32)arguments->scalarInput[1],
851																			 (mach_vm_address_t)arguments->scalarInput[2],
852																			 &outSegmentCount);
853			arguments->scalarOutput[0] = outSegmentCount;
854		}
855			break;
856
857		case kConfigDirectory_Create:
858		{
859			UserObjectHandle outDirRef;
860			result = ((IOFireWireUserClient*) targetObject)->configDirectory_Create(&outDirRef);
861			arguments->scalarOutput[0] = (uint64_t) outDirRef;
862		}
863			break;
864
865		case kConfigDirectory_GetKeyType:
866		{
867			IOConfigKeyType outType;
868			result = ((IOFireWireUserClient*) targetObject)->configDirectory_GetKeyType((UserObjectHandle)arguments->scalarInput[0],
869																						(int)arguments->scalarInput[1],
870																						&outType);
871			arguments->scalarOutput[0] = outType;
872		}
873			break;
874
875		case kConfigDirectory_GetKeyValue_UInt32:
876		{
877			UInt32 outValue;
878			UserObjectHandle outTextHandle;
879			UInt32 outTextLength;
880			result = ((IOFireWireUserClient*) targetObject)->
881												configDirectory_GetKeyValue_UInt32((UserObjectHandle)arguments->scalarInput[0],
882																(int)arguments->scalarInput[1],
883																(UInt32)arguments->scalarInput[2],
884																&outValue,
885																&outTextHandle,
886																&outTextLength);
887			arguments->scalarOutput[0] = outValue;
888			arguments->scalarOutput[1] = (uint64_t) outTextHandle;
889			arguments->scalarOutput[2] = outTextLength;
890		}
891			break;
892
893		case kConfigDirectory_GetKeyValue_Data:
894			result = ((IOFireWireUserClient*) targetObject)->
895								configDirectory_GetKeyValue_Data((UserObjectHandle)arguments->scalarInput[0],
896																(int)arguments->scalarInput[1],
897																(UInt32)arguments->scalarInput[2],
898																(GetKeyValueDataResults *) arguments->structureOutput);
899			break;
900
901		case kConfigDirectory_GetKeyValue_ConfigDirectory:
902		{
903			UserObjectHandle outDirHandle;
904			UserObjectHandle outTextHandle;
905			UInt32 outTextLength;
906			result = ((IOFireWireUserClient*) targetObject)->configDirectory_GetKeyValue_ConfigDirectory((UserObjectHandle)arguments->scalarInput[0],
907																										 (int)arguments->scalarInput[1],
908																										 (UInt32)arguments->scalarInput[2],
909																										 &outDirHandle,
910																										 &outTextHandle,
911																										 &outTextLength);
912			arguments->scalarOutput[0] = (uint64_t) outDirHandle;
913			arguments->scalarOutput[1] = (uint64_t) outTextHandle;
914			arguments->scalarOutput[2] = outTextLength;
915		}
916			break;
917
918		case kConfigDirectory_GetKeyOffset_FWAddress:
919			result = ((IOFireWireUserClient*) targetObject)->
920								configDirectory_GetKeyOffset_FWAddress((UserObjectHandle)arguments->scalarInput[0],
921																		(int)arguments->scalarInput[1],
922																		(UInt32)arguments->scalarInput[2],
923																		(GetKeyOffsetResults *) arguments->structureOutput);
924			break;
925
926		case kConfigDirectory_GetIndexType:
927		{
928			IOConfigKeyType outType;
929			result = ((IOFireWireUserClient*) targetObject)->configDirectory_GetIndexType((UserObjectHandle)arguments->scalarInput[0],
930																						  (int)arguments->scalarInput[1],
931																						  &outType);
932			arguments->scalarOutput[0] = (IOConfigKeyType) outType;
933		}
934			break;
935
936		case kConfigDirectory_GetIndexKey:
937		{
938			int outKey;
939			result = ((IOFireWireUserClient*) targetObject)->configDirectory_GetIndexKey((UserObjectHandle)arguments->scalarInput[0],
940																						  (int)arguments->scalarInput[1],
941																						  &outKey);
942			arguments->scalarOutput[0] = outKey;
943		}
944			break;
945
946		case kConfigDirectory_GetIndexValue_UInt32:
947			// configDirectory_GetIndexValue_UInt32
948		{
949			UInt32 outKey;
950			result = ((IOFireWireUserClient*) targetObject)->configDirectory_GetIndexValue_UInt32((UserObjectHandle)arguments->scalarInput[0],
951																						 (int)arguments->scalarInput[1],
952																						 &outKey);
953			arguments->scalarOutput[0] = outKey;
954		}
955			break;
956
957		case kConfigDirectory_GetIndexValue_Data:
958		{
959			UserObjectHandle outDataHandle;
960			IOByteCount outDataLen;
961			result = ((IOFireWireUserClient*) targetObject)->
962										configDirectory_GetIndexValue_Data((UserObjectHandle)arguments->scalarInput[0],
963																			(int)arguments->scalarInput[1],
964																			&outDataHandle,
965																			&outDataLen);
966			arguments->scalarOutput[0] = (uint64_t) outDataHandle;
967			arguments->scalarOutput[1] = outDataLen;
968		}
969			break;
970
971		case kConfigDirectory_GetIndexValue_String:
972		{
973			UserObjectHandle outTextHandle;
974			UInt32 outTextLength;
975			result = ((IOFireWireUserClient*) targetObject)->
976									configDirectory_GetIndexValue_String((UserObjectHandle)arguments->scalarInput[0],
977																		(int)arguments->scalarInput[1],
978																		&outTextHandle,
979																		&outTextLength);
980			arguments->scalarOutput[0] = (uint64_t) outTextHandle;
981			arguments->scalarOutput[1] = outTextLength;
982		}
983			break;
984
985		case kConfigDirectory_GetIndexValue_ConfigDirectory:
986		{
987			UserObjectHandle outDirHandle;
988			result = ((IOFireWireUserClient*) targetObject)->
989									configDirectory_GetIndexValue_ConfigDirectory((UserObjectHandle)arguments->scalarInput[0],
990																		(int)arguments->scalarInput[1],
991																		&outDirHandle);
992			arguments->scalarOutput[0] = (uint64_t) outDirHandle;
993		}
994		break;
995
996		case kConfigDirectory_GetIndexOffset_FWAddress:
997			result = ((IOFireWireUserClient*) targetObject)->
998								configDirectory_GetIndexOffset_FWAddress((UserObjectHandle)arguments->scalarInput[0],
999																		(int)arguments->scalarInput[1],
1000																		(FWAddress *) arguments->structureOutput);
1001			break;
1002
1003		case kConfigDirectory_GetIndexOffset_UInt32:
1004		{
1005			UInt32 outValue;
1006			result = ((IOFireWireUserClient*) targetObject)->
1007									configDirectory_GetIndexOffset_UInt32((UserObjectHandle)arguments->scalarInput[0],
1008																		(int)arguments->scalarInput[1],
1009																		&outValue);
1010			arguments->scalarOutput[0] = outValue;
1011		}
1012			break;
1013
1014		case kConfigDirectory_GetIndexEntry:
1015		{
1016			UInt32 outValue;
1017			result = ((IOFireWireUserClient*) targetObject)->
1018									configDirectory_GetIndexEntry((UserObjectHandle)arguments->scalarInput[0],
1019																		(int)arguments->scalarInput[1],
1020																		&outValue);
1021			arguments->scalarOutput[0] = outValue;
1022		}
1023			break;
1024
1025		case kConfigDirectory_GetSubdirectories:
1026		{
1027			UserObjectHandle outIteratorHandle;
1028			result = ((IOFireWireUserClient*) targetObject)->
1029									configDirectory_GetSubdirectories((UserObjectHandle)arguments->scalarInput[0],
1030																		&outIteratorHandle);
1031			arguments->scalarOutput[0] = (uint64_t) outIteratorHandle;
1032		}
1033			break;
1034
1035		case kConfigDirectory_GetKeySubdirectories:
1036		{
1037			UserObjectHandle outIteratorHandle;
1038			result = ((IOFireWireUserClient*) targetObject)->
1039									configDirectory_GetKeySubdirectories((UserObjectHandle)arguments->scalarInput[0],
1040																		(int)arguments->scalarInput[1],
1041																		&outIteratorHandle);
1042			arguments->scalarOutput[0] = (uint64_t) outIteratorHandle;
1043		}
1044			break;
1045
1046		case kConfigDirectory_GetType:
1047		{
1048			int outType;
1049			result = ((IOFireWireUserClient*) targetObject)->
1050									configDirectory_GetType((UserObjectHandle)arguments->scalarInput[0],&outType);
1051			arguments->scalarOutput[0] = outType;
1052		}
1053			break;
1054
1055		case kConfigDirectory_GetNumEntries:
1056		{
1057			int outNumEntries;
1058			result = ((IOFireWireUserClient*) targetObject)->
1059									configDirectory_GetNumEntries((UserObjectHandle)arguments->scalarInput[0],&outNumEntries);
1060			arguments->scalarOutput[0] = outNumEntries;
1061		}
1062			break;
1063
1064		case kIsochPort_GetSupported:
1065		{
1066			IOFWSpeed outMaxSpeed;
1067			UInt32 outChanSupportedHi;
1068			UInt32 outChanSupportedLo;
1069			result = ((IOFireWireUserClient*) targetObject)->
1070									localIsochPort_GetSupported((UserObjectHandle)arguments->scalarInput[0],
1071																		&outMaxSpeed,
1072																		&outChanSupportedHi,
1073																		&outChanSupportedLo);
1074			arguments->scalarOutput[0] = outMaxSpeed;
1075			arguments->scalarOutput[1] = outChanSupportedHi;
1076			arguments->scalarOutput[2] = outChanSupportedLo;
1077		}
1078			break;
1079
1080		case kIsochPort_AllocatePort_d:
1081			result = ((IOFWUserLocalIsochPort*) targetObject)->allocatePort((IOFWSpeed)arguments->scalarInput[0],
1082																			(UInt32)arguments->scalarInput[1]);
1083			break;
1084
1085		case kIsochPort_ReleasePort_d:
1086			result = ((IOFWUserLocalIsochPort*) targetObject)->releasePort();
1087			break;
1088
1089		case kIsochPort_Start_d:
1090			result = ((IOFWUserLocalIsochPort*) targetObject)->start();
1091			break;
1092
1093		case kIsochPort_Stop_d:
1094			result = ((IOFWUserLocalIsochPort*) targetObject)->stop();
1095			break;
1096
1097		case kLocalIsochPort_Allocate:
1098			result = ((IOFireWireUserClient*) targetObject)->
1099								localIsochPort_Create((LocalIsochPortAllocateParams*) arguments->structureInput,
1100														(UserObjectHandle*) arguments->structureOutput);
1101			break;
1102
1103		case kLocalIsochPort_ModifyJumpDCL_d:
1104			result = ((IOFWUserLocalIsochPort*) targetObject)->modifyJumpDCL((UInt32)arguments->scalarInput[0],
1105																			(UInt32)arguments->scalarInput[1]);
1106			break;
1107
1108		case kLocalIsochPort_Notify_d:
1109			if (arguments->scalarInput[0] == kFWNuDCLModifyNotification)
1110			{
1111				IOMemoryDescriptor * userDCLExportDesc = NULL ;
1112				IOReturn error ;
1113				UInt8 *pUserImportDCLBuffer;
1114				userDCLExportDesc = IOMemoryDescriptor::withAddressRange( arguments->scalarInput[2],
1115																		 arguments->scalarInput[3],
1116																		 kIODirectionOut,
1117																		 getOwningTask() ) ;
1118				// get map of program export data
1119				if ( userDCLExportDesc )
1120				{
1121					error = userDCLExportDesc->prepare() ;
1122				}
1123				else
1124					error = kIOReturnVMError;
1125
1126				if ( !error )
1127				{
1128					pUserImportDCLBuffer = new UInt8[ arguments->scalarInput[3] ] ;
1129					if ( !pUserImportDCLBuffer )
1130					{
1131						error = kIOReturnVMError ;
1132					}
1133				}
1134
1135				if ( !error )
1136				{
1137					unsigned byteCount = userDCLExportDesc->readBytes( 0, (void*)pUserImportDCLBuffer, arguments->scalarInput[3] ) ;
1138					if ( byteCount < arguments->scalarInput[3] )
1139					{
1140						error = kIOReturnVMError ;
1141					}
1142				}
1143
1144				if ( !error )
1145				{
1146					result = ((IOFWUserLocalIsochPort*) targetObject)->userNotify((UInt32)arguments->scalarInput[0],
1147																				  (UInt32)arguments->scalarInput[1],
1148																				  (void *) pUserImportDCLBuffer,
1149																				  arguments->scalarInput[3]);
1150					userDCLExportDesc->complete() ;
1151					userDCLExportDesc->release();
1152					delete [] pUserImportDCLBuffer;
1153				}
1154				else
1155				{
1156					result = kIOReturnVMError;
1157				}
1158			}
1159			else
1160				result = ((IOFWUserLocalIsochPort*) targetObject)->
1161								userNotify((UInt32)arguments->scalarInput[0],
1162											(UInt32)arguments->scalarInput[1],
1163											(void *) arguments->structureInput,
1164											arguments->structureInputSize);
1165			break;
1166
1167		case kLocalIsochPort_SetChannel:
1168			result = ((IOFireWireUserClient*) targetObject)->
1169											localIsochPort_SetChannel((UserObjectHandle)arguments->scalarInput[0],
1170																	(UserObjectHandle)arguments->scalarInput[1]);
1171			break;
1172
1173		case kIsochChannel_Allocate:
1174		{
1175			UserObjectHandle outChannelHandle;
1176			result = ((IOFireWireUserClient*) targetObject)->
1177											isochChannel_Create((bool)arguments->scalarInput[0],
1178																	(UInt32)arguments->scalarInput[1],
1179																	(IOFWSpeed)arguments->scalarInput[2],
1180																	&outChannelHandle);
1181			arguments->scalarOutput[0] = (uint64_t) outChannelHandle;
1182		}
1183			break;
1184
1185		case kIsochChannel_UserAllocateChannelBegin:
1186		{
1187			UInt32 outSpeed;
1188			UInt32 outChannel;
1189			result = ((IOFireWireUserClient*) targetObject)->
1190											isochChannel_AllocateChannelBegin((UserObjectHandle)arguments->scalarInput[0],
1191																	(UInt32)arguments->scalarInput[1],
1192																	(UInt32)arguments->scalarInput[2],
1193																	(UInt32)arguments->scalarInput[3],
1194																	&outSpeed,
1195																	&outChannel);
1196			arguments->scalarOutput[0] = outSpeed;
1197			arguments->scalarOutput[1] = outChannel;
1198		}
1199			break;
1200
1201		case kIsochChannel_UserReleaseChannelComplete_d:
1202			result = ((IOFWUserIsochChannel*) targetObject)->releaseChannelComplete();
1203			break;
1204
1205		case kCommand_Cancel_d:
1206			result = ((IOFWCommand*) targetObject)->cancel((IOReturn)arguments->scalarInput[0]);
1207			break;
1208
1209		case kSeize:
1210			result = ((IOFireWireUserClient*) targetObject)->seize((IOOptionBits) arguments->scalarInput[0]);
1211			break;
1212
1213		case kFireLog:
1214			result = ((IOFireWireUserClient*) targetObject)->
1215							firelog((const char*) arguments->structureInput,arguments->structureInputSize);
1216			break;
1217
1218		case kGetBusCycleTime:
1219		{
1220			UInt32 busTime;
1221			UInt32 cycleTime;
1222			result = ((IOFireWireBus*) targetObject)->getBusCycleTime(busTime,cycleTime);
1223			arguments->scalarOutput[0] = busTime;
1224			arguments->scalarOutput[1] = cycleTime;
1225		}
1226			break;
1227
1228		case kGetBusGeneration:
1229		{
1230			UInt32 outGeneration;
1231			result = ((IOFireWireUserClient*) targetObject)->getBusGeneration(&outGeneration);
1232			arguments->scalarOutput[0] = outGeneration;
1233		}
1234			break;
1235
1236		case kGetLocalNodeIDWithGeneration:
1237		{
1238			UInt32 outLocalNodeID;
1239			result = ((IOFireWireUserClient*) targetObject)->
1240										getLocalNodeIDWithGeneration((UInt32)arguments->scalarInput[0],&outLocalNodeID);
1241			arguments->scalarOutput[0] = outLocalNodeID;
1242		}
1243			break;
1244
1245		case kGetRemoteNodeID:
1246		{
1247			UInt32 outRemoteNodeID;
1248			result = ((IOFireWireUserClient*) targetObject)->
1249										getRemoteNodeID((UInt32)arguments->scalarInput[0],&outRemoteNodeID);
1250			arguments->scalarOutput[0] = outRemoteNodeID;
1251		}
1252			break;
1253
1254		case kGetSpeedToNode:
1255		{
1256			UInt32 outSpeed;
1257			result = ((IOFireWireUserClient*) targetObject)->
1258										getSpeedToNode((UInt32)arguments->scalarInput[0],&outSpeed);
1259			arguments->scalarOutput[0] = outSpeed;
1260		}
1261			break;
1262
1263		case kGetSpeedBetweenNodes:
1264		{
1265			UInt32 outSpeed;
1266			result = ((IOFireWireUserClient*) targetObject)->
1267										getSpeedBetweenNodes((UInt32)arguments->scalarInput[0],
1268															(UInt32)arguments->scalarInput[1],
1269															(UInt32)arguments->scalarInput[2],
1270															&outSpeed);
1271			arguments->scalarOutput[0] = outSpeed;
1272		}
1273			break;
1274
1275		case kGetIRMNodeID:
1276		{
1277			UInt32 irmNodeID;
1278			result = ((IOFireWireUserClient*) targetObject)->
1279										getIRMNodeID((UInt32)arguments->scalarInput[0],&irmNodeID);
1280			arguments->scalarOutput[0] = irmNodeID;
1281		}
1282			break;
1283
1284		case kClipMaxRec2K:
1285			result = ((IOFireWireUserClient*) targetObject)->clipMaxRec2K((Boolean) arguments->scalarInput[0]);
1286			break;
1287
1288		case kIsochPort_SetIsochResourceFlags_d:
1289			result = ((IOFWLocalIsochPort*) targetObject)->setIsochResourceFlags((IOFWIsochResourceFlags) arguments->scalarInput[0]);
1290			break;
1291
1292		case kGetSessionRef:
1293		{
1294			IOFireWireSessionRef sessionRef=NULL;
1295			result = ((IOFireWireUserClient*) targetObject)->getSessionRef(&sessionRef);
1296			arguments->scalarOutput[0] = (uint64_t) sessionRef;
1297		}
1298			break;
1299
1300		case kAllocateIRMBandwidth:
1301			result = ((IOFireWireUserClient*) targetObject)->allocateIRMBandwidthInGeneration(arguments->scalarInput[0],arguments->scalarInput[1]);
1302			break;
1303
1304		case kReleaseIRMBandwidth:
1305			result = ((IOFireWireUserClient*) targetObject)->releaseIRMBandwidthInGeneration(arguments->scalarInput[0],arguments->scalarInput[1]);
1306			break;
1307
1308		case kAllocateIRMChannel:
1309			result = ((IOFireWireUserClient*) targetObject)->allocateIRMChannelInGeneration(arguments->scalarInput[0],arguments->scalarInput[1]);
1310			break;
1311
1312		case kReleaseIRMChannel:
1313			result = ((IOFireWireUserClient*) targetObject)->releaseIRMChannelInGeneration(arguments->scalarInput[0],arguments->scalarInput[1]);
1314			break;
1315
1316		case kAsyncStreamListener_Allocate:
1317			result = ((IOFireWireUserClient*) targetObject)->
1318								asyncStreamListener_Create((FWUserAsyncStreamListenerCreateParams*) arguments->structureInput,
1319														(UserObjectHandle*) arguments->structureOutput);
1320			break;
1321
1322		case kAsyncStreamListener_ClientCommandIsComplete:
1323			result = ((IOFireWireUserClient*) targetObject)->asyncStreamListener_ClientCommandIsComplete((UserObjectHandle)arguments->scalarInput[0],
1324																			(FWClientCommandID)arguments->scalarInput[1]);
1325			break;
1326
1327		case kAsyncStreamListener_GetOverrunCounter:
1328		{
1329			UInt32 counter = 0;
1330			result = ((IOFireWireUserClient*) targetObject)->
1331									asyncStreamListener_GetOverrunCounter((UserObjectHandle)arguments->scalarInput[0], &counter);
1332			arguments->scalarOutput[0] = counter;
1333		}
1334			break;
1335
1336		case kAsyncStreamListener_SetFlags:
1337			result = ((IOFireWireUserClient*) targetObject)->
1338											asyncStreamListener_SetFlags((UserObjectHandle)arguments->scalarInput[0],
1339																	(UInt32)arguments->scalarInput[1]);
1340			break;
1341
1342		case kAsyncStreamListener_GetFlags:
1343		{
1344			UInt32 outFlags;
1345			result = ((IOFireWireUserClient*) targetObject)->
1346									asyncStreamListener_GetFlags((UserObjectHandle)arguments->scalarInput[0], &outFlags);
1347			arguments->scalarOutput[0] = outFlags;
1348		}
1349			break;
1350
1351		case kAsyncStreamListener_TurnOnNotification:
1352			result = ((IOFireWireUserClient*) targetObject)->asyncStreamListener_TurnOnNotification((UserObjectHandle)arguments->scalarInput[0]);
1353			break;
1354
1355		case kAsyncStreamListener_TurnOffNotification:
1356			result = ((IOFireWireUserClient*) targetObject)->asyncStreamListener_TurnOffNotification((UserObjectHandle)arguments->scalarInput[0]);
1357			break;
1358
1359		case kSetAsyncRef_BusReset:
1360		{
1361			result = ((IOFireWireUserClient*) targetObject)->
1362												setAsyncRef_BusReset(arguments->asyncReference,
1363																	(mach_vm_address_t)arguments->scalarInput[0],
1364																	(io_user_reference_t)arguments->scalarInput[1],
1365																	NULL,NULL,NULL,NULL);
1366		}
1367			break;
1368
1369		case kSetAsyncRef_BusResetDone:
1370		{
1371			result = ((IOFireWireUserClient*) targetObject)->
1372										setAsyncRef_BusResetDone(arguments->asyncReference,
1373																(mach_vm_address_t)arguments->scalarInput[0],
1374																(io_user_reference_t)arguments->scalarInput[1],
1375																NULL,NULL,NULL,NULL);
1376		}
1377			break;
1378
1379		case kSetAsyncRef_Packet:
1380		{
1381			result = ((IOFireWireUserClient*) targetObject)->
1382										setAsyncRef_Packet(arguments->asyncReference,
1383															(UserObjectHandle)arguments->scalarInput[0],
1384															(mach_vm_address_t)arguments->scalarInput[1],
1385															(io_user_reference_t)arguments->scalarInput[2],
1386															NULL,NULL,NULL);
1387		}
1388			break;
1389
1390
1391		case kSetAsyncRef_SkippedPacket:
1392		{
1393			result = ((IOFireWireUserClient*) targetObject)->
1394										setAsyncRef_SkippedPacket(arguments->asyncReference,
1395																(UserObjectHandle)arguments->scalarInput[0],
1396																(mach_vm_address_t)arguments->scalarInput[1],
1397																(io_user_reference_t)arguments->scalarInput[2],
1398																NULL,NULL,NULL);
1399		}
1400			break;
1401
1402		case kSetAsyncRef_Read:
1403		{
1404			result = ((IOFireWireUserClient*) targetObject)->
1405										setAsyncRef_Read(arguments->asyncReference,
1406														(UserObjectHandle)arguments->scalarInput[0],
1407														(mach_vm_address_t)arguments->scalarInput[1],
1408														(io_user_reference_t)arguments->scalarInput[2],
1409														NULL,NULL,NULL);
1410		}
1411			break;
1412
1413		case kCommand_Submit:
1414		{
1415			result = ((IOFireWireUserClient*) targetObject)->
1416										userAsyncCommand_Submit(arguments->asyncReference,
1417																(CommandSubmitParams*)arguments->structureInput,
1418																(CommandSubmitResult*)arguments->structureOutput,
1419																(IOByteCount) arguments->structureInputSize,
1420																(IOByteCount*) &arguments->structureOutputSize);
1421			}
1422			break;
1423
1424		case kSetAsyncRef_IsochChannelForceStop:
1425		{
1426			result = ((IOFireWireUserClient*) targetObject)->
1427										setAsyncRef_IsochChannelForceStop(arguments->asyncReference,
1428																		(UserObjectHandle)arguments->scalarInput[0]);
1429		}
1430		break;
1431
1432		case kSetAsyncRef_DCLCallProc:
1433		{
1434			result = ((IOFireWireUserClient*) targetObject)->
1435										setAsyncRef_DCLCallProc(arguments->asyncReference,
1436																(UserObjectHandle)arguments->scalarInput[0]);
1437		}
1438		break;
1439
1440		case kSetAsyncStreamRef_Packet:
1441		{
1442			result = ((IOFireWireUserClient*) targetObject)->
1443										setAsyncStreamRef_Packet(arguments->asyncReference,
1444																(UserObjectHandle)arguments->scalarInput[0],
1445																(mach_vm_address_t)arguments->scalarInput[1],
1446																(io_user_reference_t)arguments->scalarInput[2],
1447																NULL,NULL,NULL);
1448		}
1449			break;
1450
1451		case kSetAsyncStreamRef_SkippedPacket:
1452		{
1453			result = ((IOFireWireUserClient*) targetObject)->
1454										setAsyncStreamRef_SkippedPacket(arguments->asyncReference,
1455																(UserObjectHandle)arguments->scalarInput[0],
1456																(mach_vm_address_t)arguments->scalarInput[1],
1457																(io_user_reference_t)arguments->scalarInput[2],
1458																NULL,NULL,NULL);
1459		}
1460			break;
1461
1462
1463		case kIRMAllocation_Allocate:
1464		{
1465			UserObjectHandle outDataHandle;
1466			result = ((IOFireWireUserClient*) targetObject)->irmAllocation_Create(arguments->scalarInput[0],&outDataHandle);
1467			arguments->scalarOutput[0] = (uint64_t) outDataHandle;
1468		}
1469			break;
1470
1471		case kIRMAllocation_AllocateResources:
1472			result = ((IOFireWireUserClient*) targetObject)->irmAllocation_AllocateResources((UserObjectHandle)arguments->scalarInput[0],
1473																							 arguments->scalarInput[1],
1474																							 arguments->scalarInput[2]);
1475			break;
1476
1477
1478		case kIRMAllocation_DeallocateResources:
1479			result = ((IOFireWireUserClient*) targetObject)->irmAllocation_DeallocateResources((UserObjectHandle)arguments->scalarInput[0]);
1480			break;
1481
1482		case kIRMAllocation_areResourcesAllocated:
1483		{
1484			UInt8 isochChannel;
1485			UInt32 bandwidthUnits;
1486			result = ((IOFireWireUserClient*) targetObject)->irmAllocation_areResourcesAllocated((UserObjectHandle)arguments->scalarInput[0], &isochChannel , &bandwidthUnits);
1487			arguments->scalarOutput[1] = (uint64_t) isochChannel;
1488			arguments->scalarOutput[2] = (uint64_t) bandwidthUnits;
1489		}
1490			break;
1491
1492		case kIRMAllocation_setDeallocateOnRelease:
1493			((IOFireWireUserClient*) targetObject)->irmAllocation_setDeallocateOnRelease((UserObjectHandle)arguments->scalarInput[0],arguments->scalarInput[1]);
1494			result = kIOReturnSuccess;
1495			break;
1496
1497		case kIRMAllocation_SetRef:
1498			result = ((IOFireWireUserClient*) targetObject)->irmAllocation_setRef(arguments->asyncReference,
1499																				  (UserObjectHandle)arguments->scalarInput[0],
1500																				  arguments->scalarInput[1],
1501																				  arguments->scalarInput[2]);
1502			break;
1503
1504		case kCommandCreateAsync:
1505			{
1506				result = ((IOFireWireUserClient*) targetObject)->
1507										createAsyncCommand( arguments->asyncReference,
1508															(CommandSubmitParams*)arguments->structureInput,
1509															(UserObjectHandle*)arguments->structureOutput );
1510			}
1511			break;
1512
1513
1514		case kVectorCommandCreate:
1515			result = ((IOFireWireUserClient*) targetObject)->createVectorCommand( (UserObjectHandle*)arguments->structureOutput );
1516			break;
1517
1518		case kVectorCommandSubmit:
1519			result = ((IOFWUserVectorCommand*)targetObject)->submit(	arguments->asyncReference,
1520																		(mach_vm_address_t)arguments->scalarInput[0],
1521																		(io_user_reference_t)arguments->scalarInput[1] );
1522			break;
1523
1524		case kVectorCommandSetBuffers:
1525			result = ((IOFWUserVectorCommand*)targetObject)->setBuffers(	(mach_vm_address_t)arguments->scalarInput[0],
1526																			(mach_vm_size_t)arguments->scalarInput[1],
1527																			(mach_vm_address_t)arguments->scalarInput[2],
1528																			(mach_vm_size_t)arguments->scalarInput[3]  );
1529			break;
1530
1531		case kPHYPacketListenerCreate:
1532			{
1533				UserObjectHandle kernel_ref;
1534				result = ((IOFireWireUserClient*) targetObject)->createPHYPacketListener( (mach_vm_address_t)arguments->scalarInput[0],
1535																						  &kernel_ref );
1536				arguments->scalarOutput[0] = (uint64_t)kernel_ref;
1537			}
1538			break;
1539
1540		case kPHYPacketListenerSetPacketCallback:
1541			result = ((IOFWUserPHYPacketListener*)targetObject)->setPacketCallback(	arguments->asyncReference,
1542																					(mach_vm_address_t)arguments->scalarInput[0],
1543																					(io_user_reference_t)arguments->scalarInput[1] );
1544			break;
1545
1546		case kPHYPacketListenerSetSkippedCallback:
1547			result = ((IOFWUserPHYPacketListener*)targetObject)->setSkippedCallback(	arguments->asyncReference,
1548																						(mach_vm_address_t)arguments->scalarInput[0],
1549																						(io_user_reference_t)arguments->scalarInput[1] );
1550			break;
1551
1552		case kPHYPacketListenerActivate:
1553			result = ((IOFWUserPHYPacketListener*)targetObject)->activate();
1554			break;
1555
1556		case kPHYPacketListenerDeactivate:
1557			((IOFWUserPHYPacketListener*)targetObject)->deactivate();
1558			result = kIOReturnSuccess;
1559			break;
1560
1561		case kPHYPacketListenerClientCommandIsComplete:
1562			((IOFWUserPHYPacketListener*)targetObject)->clientCommandIsComplete( (FWClientCommandID)arguments->scalarInput[0] );
1563			result = kIOReturnSuccess;
1564			break;
1565
1566		default:
1567			// NONE OF THE ABOVE :(
1568			break;
1569	};
1570
1571	return result;
1572}
1573
1574IOReturn
1575IOFireWireUserClient::registerNotificationPort(
1576	mach_port_t port,
1577	UInt32		/* type */,
1578	UInt32		refCon)
1579{
1580	fNotificationPort = port ;
1581	fNotificationRefCon = refCon ;
1582
1583	return( kIOReturnUnsupported);
1584}
1585
1586#pragma mark -
1587
1588IOReturn
1589IOFireWireUserClient::
1590copyUserData (
1591		mach_vm_address_t		userBuffer,
1592		mach_vm_address_t		kernBuffer,
1593		mach_vm_size_t 			bytes ) const
1594{
1595	if( (userBuffer == NULL) || (kernBuffer == NULL) )
1596	{
1597		return kIOReturnNoMemory;
1598	}
1599
1600	if( bytes == 0 )
1601	{
1602		return kIOReturnSuccess;
1603	}
1604
1605	IOMemoryDescriptor *	desc 	= IOMemoryDescriptor::withAddressRange (	userBuffer, bytes, kIODirectionOut,
1606																			fTask ) ;
1607	if ( ! desc )
1608	{
1609		ErrorLog ( "Couldn't create descriptor\n" ) ;
1610		return kIOReturnNoMemory ;
1611	}
1612
1613	// copy user space range list to in kernel list
1614	IOReturn error = desc->prepare () ;
1615
1616	if ( ! error )
1617	{
1618		if ( bytes != desc->readBytes ( 0, (void*)kernBuffer, bytes ) )
1619			error = kIOReturnVMError ;
1620
1621		desc->complete() ;
1622		desc->release() ;
1623	}
1624
1625	return error ;
1626}
1627
1628IOReturn
1629IOFireWireUserClient::copyToUserBuffer (
1630	IOVirtualAddress 		kernelBuffer,
1631	mach_vm_address_t		userBuffer,
1632	IOByteCount 			bytes,
1633	IOByteCount & 			bytesCopied )
1634{
1635	if( (userBuffer == NULL) || (kernelBuffer == NULL) )
1636	{
1637		return kIOReturnNoMemory;
1638	}
1639
1640	if( bytes == 0 )
1641	{
1642		return kIOReturnSuccess;
1643	}
1644
1645	IOMemoryDescriptor *	mem = IOMemoryDescriptor::withAddressRange( userBuffer, bytes, kIODirectionIn, fTask ) ;
1646	if ( ! mem )
1647		return kIOReturnNoMemory ;
1648
1649	IOReturn error = mem->prepare () ;
1650
1651	if ( !error )
1652	{
1653		bytesCopied = mem->writeBytes ( 0, (void*)kernelBuffer, bytes ) ;
1654		mem->complete() ;
1655	}
1656
1657	mem->release() ;
1658
1659	return error ;
1660}
1661
1662#pragma mark -
1663#pragma mark OPEN/CLOSE
1664
1665IOReturn
1666IOFireWireUserClient::userOpen ()
1667{
1668	IOReturn error = kIOReturnSuccess ;
1669
1670	// do the open...
1671
1672	IOFireWireNub * provider = OSDynamicCast( IOFireWireNub, getOwner() ) ;
1673	if ( ! provider )
1674	{
1675		ErrorLog( "Couldn't find provider!\b" ) ;
1676		return kIOReturnError ;
1677	}
1678
1679	if ( getOwner()->open( this ) )
1680	{
1681		IOFWUserObjectExporter * exporter = fOwner->getController()->getSessionRefExporter();
1682		error = exporter->addObject( this, NULL, &fSessionRef );
1683		if( error == kIOReturnSuccess )
1684		{
1685			fSelfOpenCount = 1 ;
1686			fOpenClient = this ;
1687		}
1688	}
1689	else
1690	{
1691		ErrorLog( "couldn't open provider\n" ) ;
1692		error = kIOReturnExclusiveAccess ;
1693	}
1694
1695	return error ;
1696}
1697
1698IOReturn
1699IOFireWireUserClient::userOpenWithSessionRef ( IOFireWireLib::UserObjectHandle sessionRef )
1700{
1701	IOReturn	result = kIOReturnSuccess ;
1702
1703	if (getOwner ()->isOpen())
1704	{
1705		IOFWUserObjectExporter * exporter = fOwner->getController()->getSessionRefExporter();
1706		IOService * open_client = (IOService*) exporter->lookupObjectForType( sessionRef, OSTypeID(IOService) );
1707		IOService * client = open_client;
1708
1709		if (!client)
1710			result = kIOReturnBadArgument ;
1711		else
1712		{
1713			while (client != NULL)
1714			{
1715				if (client == getOwner ())
1716				{
1717					fOpenClient = open_client ;	// sessionRef is the originally passed in user object
1718
1719					if ( fOpenClient == this )
1720					{
1721						++fSelfOpenCount ;
1722					}
1723
1724					break ;
1725				}
1726
1727				client = client->getProvider() ;
1728			}
1729		}
1730
1731		if( open_client )
1732		{
1733			open_client->release();
1734			open_client = NULL;
1735		}
1736	}
1737	else
1738		result = kIOReturnNotOpen ;
1739
1740	return result ;
1741}
1742
1743IOReturn
1744IOFireWireUserClient::userClose ()
1745{
1746	IOReturn result = kIOReturnSuccess ;
1747
1748	if ( getProvider() == NULL )
1749		return kIOReturnSuccess ;
1750
1751	if ( fOpenClient == this )
1752	{
1753		if ( !fOwner->isOpen( this ) )
1754		{
1755			result = kIOReturnNotOpen ;
1756		}
1757		else
1758		{
1759			if ( fSelfOpenCount > 0 )
1760			{
1761				if ( --fSelfOpenCount == 0 )
1762				{
1763					IOFWUserObjectExporter * exporter = fOwner->getController()->getSessionRefExporter();
1764					exporter->removeObject( fSessionRef );
1765					fSessionRef = 0;
1766					fOwner->close(this) ;
1767					fOpenClient = NULL ;
1768				}
1769			}
1770			else
1771			{
1772				return kIOReturnNotOpen ;
1773			}
1774		}
1775	}
1776
1777	return result ;
1778}
1779
1780#pragma mark -
1781#pragma mark GENERAL
1782
1783IOReturn
1784IOFireWireUserClient::readQuad ( const ReadQuadParams* params, UInt32* outVal )
1785{
1786	IOReturn 				err ;
1787	IOFWReadQuadCommand*	cmd ;
1788
1789	if ( params->isAbs )
1790		cmd = this->createReadQuadCommand( params->generation, params->addr, outVal, 1, NULL, NULL ) ;
1791	else
1792	{
1793		if ( (cmd = getOwner ()->createReadQuadCommand( params->addr, outVal, 1, NULL, NULL, params->failOnReset )) )
1794			cmd->setGeneration( params->generation ) ;
1795	}
1796
1797	if(!cmd)
1798		return kIOReturnNoMemory;
1799
1800	err = cmd->submit();        // We block here until the command finishes
1801
1802	if( !err )
1803		err = cmd->getStatus();
1804
1805	cmd->release();
1806
1807	return err;
1808}
1809
1810IOReturn
1811IOFireWireUserClient::read ( const ReadParams* params, IOByteCount* outBytesTransferred )
1812{
1813	IOReturn 					err ;
1814	IOMemoryDescriptor *		mem ;
1815	IOFWReadCommand*			cmd ;
1816
1817	*outBytesTransferred = 0 ;
1818
1819	mem = IOMemoryDescriptor::withAddressRange(params->buf, params->size, kIODirectionIn, fTask);
1820	if(!mem)
1821	{
1822		return kIOReturnNoMemory;
1823	}
1824
1825	{
1826		IOReturn error = mem->prepare() ;
1827		if ( kIOReturnSuccess != error )
1828		{
1829			mem->release() ;
1830			return error ;
1831		}
1832	}
1833
1834	if ( params->isAbs )
1835		cmd = this->createReadCommand( params->generation, params->addr, mem, NULL, NULL ) ;
1836	else
1837	{
1838		if ( (cmd = getOwner ()->createReadCommand( params->addr, mem, NULL, NULL, params->failOnReset )) )
1839			cmd->setGeneration(params->generation) ;
1840	}
1841
1842	if(!cmd)
1843	{
1844		mem->complete() ;
1845		mem->release() ;
1846		return kIOReturnNoMemory;
1847	}
1848
1849	err = mem->prepare() ;
1850
1851	if ( err )
1852		IOLog("%s %u: IOFireWireUserClient::read: prepare failed\n", __FILE__, __LINE__) ;
1853	else
1854	{
1855		err = cmd->submit();	// We block here until the command finishes
1856		mem->complete() ;
1857	}
1858
1859	if( !err )
1860		err = cmd->getStatus();
1861
1862	*outBytesTransferred = cmd->getBytesTransferred() ;
1863
1864	cmd->release();
1865	mem->release();
1866
1867	return err;
1868}
1869
1870IOReturn
1871IOFireWireUserClient::writeQuad( const WriteQuadParams* params)
1872{
1873	IOReturn 				err;
1874	IOFWWriteQuadCommand*	cmd ;
1875
1876	if ( params->isAbs )
1877		cmd = this->createWriteQuadCommand( params->generation, params->addr, (UInt32*) & params->val, 1, NULL, NULL ) ;
1878	else
1879	{
1880		cmd = getOwner ()->createWriteQuadCommand( params->addr, (UInt32*)&params->val, 1, NULL, NULL, params->failOnReset ) ;
1881		cmd->setGeneration( params->generation ) ;
1882	}
1883
1884	if(!cmd)
1885		return kIOReturnNoMemory;
1886
1887
1888	err = cmd->submit();	// We block here until the command finishes
1889
1890	if( err )
1891		err = cmd->getStatus();
1892
1893	cmd->release();
1894
1895	return err;
1896}
1897
1898IOReturn
1899IOFireWireUserClient::write( const WriteParams* params, IOByteCount* outBytesTransferred )
1900{
1901	IOMemoryDescriptor *	mem ;
1902	IOFWWriteCommand*		cmd ;
1903
1904	*outBytesTransferred = 0 ;
1905
1906	mem = IOMemoryDescriptor::withAddressRange(params->buf, params->size, kIODirectionOut, fTask);
1907	if(!mem)
1908	{
1909		return kIOReturnNoMemory;
1910	}
1911
1912	{
1913		IOReturn error = mem->prepare() ;
1914		if ( kIOReturnSuccess != error )
1915		{
1916			mem->release() ;
1917			return error ;
1918		}
1919	}
1920
1921	if ( params->isAbs )
1922	{
1923		cmd = this->createWriteCommand( params->generation, params->addr, mem, NULL, NULL ) ;
1924	}
1925	else
1926	{
1927		if ( (cmd = getOwner ()->createWriteCommand( params->addr, mem, NULL, NULL, params->failOnReset )) )
1928			cmd->setGeneration( params->generation ) ;
1929	}
1930
1931	if( !cmd )
1932	{
1933		mem->complete() ;
1934		mem->release() ;
1935		return kIOReturnNoMemory;
1936	}
1937
1938	IOReturn error ;
1939	error = cmd->submit();
1940
1941	// We block here until the command finishes
1942	if( !error )
1943		error = cmd->getStatus();
1944
1945	if ( !error )
1946		*outBytesTransferred = cmd->getBytesTransferred() ;
1947
1948	cmd->release();
1949
1950	mem->complete() ;
1951	mem->release() ;
1952
1953	return error ;
1954}
1955
1956IOReturn
1957IOFireWireUserClient::compareSwap( const CompareSwapParams* params, UInt32* oldVal )
1958{
1959	IOReturn 							err ;
1960	IOFWCompareAndSwapCommand*			cmd ;
1961
1962	if ( params->size > 2 )
1963		return kIOReturnBadArgument ;
1964
1965	if ( params->isAbs )
1966	{
1967        cmd = this->createCompareAndSwapCommand( params->generation, params->addr, (UInt32*)& params->cmpVal,
1968				(UInt32*)& params->swapVal, params->size, NULL, NULL ) ;
1969	}
1970	else
1971	{
1972        if ( (cmd = getOwner ()->createCompareAndSwapCommand( params->addr, (UInt32*)& params->cmpVal, (UInt32*)& params->swapVal,
1973				params->size, NULL, NULL, params->failOnReset )) )
1974		{
1975			cmd->setGeneration( params->generation ) ;
1976		}
1977	}
1978
1979	if(!cmd)
1980		return kIOReturnNoMemory;
1981
1982	err = cmd->submit();
1983
1984	// We block here until the command finishes
1985	if( !err )
1986	{
1987		cmd->locked(oldVal) ;
1988		err = cmd->getStatus();
1989//		if(kIOReturnSuccess == err && !cmd->locked((UInt32*)oldVal))
1990//			err = kIOReturnCannotLock;
1991	}
1992
1993	cmd->release();
1994
1995	return err ;
1996}
1997
1998IOReturn
1999IOFireWireUserClient::busReset()
2000{
2001	FWTrace( kFWTUserClient, kTPUserClientBusReset, (uintptr_t)(getOwner()->getController()->getLink()), fUnsafeResets , 0, 0);
2002
2003	if ( fUnsafeResets )
2004		return getOwner ()->getController()->getLink()->resetBus();
2005
2006	return getOwner ()->getController()->resetBus();
2007}
2008
2009IOReturn
2010IOFireWireUserClient::getGenerationAndNodeID(
2011	UInt32*					outGeneration,
2012	UInt32*					outNodeID) const
2013{
2014	UInt16	nodeID ;
2015
2016	getOwner ()->getNodeIDGeneration(*outGeneration, nodeID);
2017	if (!getOwner ()->getController()->checkGeneration(*outGeneration))
2018		return kIOReturnNotFound ;	// nodeID we got was stale...
2019
2020	*outNodeID = (UInt32)nodeID ;
2021
2022	return kIOReturnSuccess ;
2023}
2024
2025IOReturn
2026IOFireWireUserClient::getLocalNodeID(
2027	UInt32*					outLocalNodeID) const
2028{
2029	*outLocalNodeID = (UInt32)(getOwner ()->getController()->getLocalNodeID()) ;
2030	return kIOReturnSuccess ;
2031}
2032
2033IOReturn
2034IOFireWireUserClient::getResetTime(
2035	AbsoluteTime*	outResetTime) const
2036{
2037	*outResetTime = *getOwner ()->getController()->getResetTime() ;
2038
2039	return kIOReturnSuccess ;
2040}
2041
2042IOReturn
2043IOFireWireUserClient::releaseUserObject (
2044	UserObjectHandle		obj )
2045{
2046	fExporter->removeObject( obj ) ;
2047
2048	return kIOReturnSuccess ;
2049}
2050
2051#pragma mark -
2052#pragma mark CONVERSION HELPERS
2053
2054IOReturn
2055IOFireWireUserClient::getOSStringData (
2056	UserObjectHandle 			stringHandle,
2057	UInt32 						stringLen,
2058	mach_vm_address_t 			stringBuffer,
2059	UInt32 * 					outTextLength )
2060{
2061	*outTextLength = 0 ;
2062
2063	const OSObject * object = fExporter->lookupObject( stringHandle ) ;
2064	if ( !object )
2065	{
2066		return kIOReturnBadArgument ;
2067	}
2068
2069	OSString * string = OSDynamicCast ( OSString, object ) ;
2070	if ( ! string )
2071	{
2072		object->release() ;
2073		return kIOReturnBadArgument ;
2074	}
2075
2076	IOByteCount len = min( stringLen, string->getLength() ) ;
2077	IOByteCount outLen = 0;
2078	IOReturn error = copyToUserBuffer (	(IOVirtualAddress) string->getCStringNoCopy(),
2079										stringBuffer,
2080										len,
2081										outLen ) ;
2082	*outTextLength = (UInt32)outLen;
2083
2084	fExporter->removeObject( stringHandle ) ;
2085	string->release() ;
2086
2087	return error ;
2088}
2089
2090IOReturn
2091IOFireWireUserClient::getOSDataData (
2092	UserObjectHandle		dataHandle,
2093	IOByteCount				dataLen,
2094	mach_vm_address_t		dataBuffer,
2095	IOByteCount*			outDataLen)
2096{
2097	const OSObject * object = fExporter->lookupObject( dataHandle ) ;
2098	if ( !object )
2099	{
2100		return kIOReturnBadArgument ;
2101	}
2102
2103	OSData * data = OSDynamicCast( OSData, object ) ;
2104	if ( !data )
2105	{
2106		object->release() ;
2107		return kIOReturnBadArgument ;
2108	}
2109
2110	IOReturn error = copyToUserBuffer (	(IOVirtualAddress) data->getBytesNoCopy(),
2111										dataBuffer,
2112										min( data->getLength(), dataLen ),
2113										*outDataLen ) ;
2114	fExporter->removeObject( dataHandle ) ;
2115
2116	object->release() ;		// this is retained when we call lookupObject; "I must release you"
2117
2118	return error ;
2119}
2120
2121#pragma mark -
2122#pragma mark LOCAL CONFIG DIRECTORY
2123
2124//	Config Directory methods
2125
2126IOReturn
2127IOFireWireUserClient::localConfigDirectory_Create ( UserObjectHandle* outDir )
2128{
2129	IOLocalConfigDirectory * dir = IOLocalConfigDirectory::create () ;
2130
2131	if ( ! dir )
2132	{
2133		DebugLog( "IOLocalConfigDirectory::create returned NULL\n" ) ;
2134		return kIOReturnNoMemory ;
2135	}
2136
2137	IOReturn error = fExporter->addObject ( dir, (IOFWUserObjectExporter::CleanupFunction)&IOLocalConfigDirectory::exporterCleanup, outDir ) ;
2138
2139	dir->release() ;
2140
2141	return error ;
2142}
2143
2144IOReturn
2145IOFireWireUserClient::localConfigDirectory_addEntry_Buffer (
2146	UserObjectHandle		dirHandle,
2147	int 					key,
2148	char * 					buffer,
2149	UInt32 					kr_size,
2150	const char *			descCString,
2151	UInt32					descLen ) const
2152{
2153
2154	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2155	if ( !object )
2156	{
2157		return kIOReturnBadArgument ;
2158	}
2159
2160	IOLocalConfigDirectory * dir = OSDynamicCast ( IOLocalConfigDirectory, object ) ;
2161	if ( ! dir )
2162	{
2163		object->release() ;
2164		return kIOReturnBadArgument ;
2165	}
2166
2167	IOReturn error = kIOReturnSuccess ;
2168	OSData * data = OSData::withCapacity( kr_size ) ;
2169	if ( !data )
2170	{
2171		error = kIOReturnNoMemory ;
2172	}
2173	else
2174	{
2175		data->appendBytes( NULL, kr_size );  // force internal buffer allocation
2176		copyUserData( (IOVirtualAddress)buffer, (IOVirtualAddress)data->getBytesNoCopy(), kr_size ) ;
2177
2178		OSString * desc = NULL ;
2179		if ( descCString && (descLen < 1024) )
2180		{
2181			char * cStr = new char[ descLen ];
2182			if ( cStr )
2183			{
2184				copyUserData( (IOVirtualAddress)descCString, (IOVirtualAddress)cStr, descLen ) ;
2185
2186				cStr[ descLen-1 ] = 0 ;
2187				desc = OSString::withCString( cStr ) ;
2188
2189				delete [] cStr;
2190			}
2191		}
2192
2193		error = dir->addEntry ( key, data, desc ) ;
2194
2195		data->release() ;
2196	}
2197
2198	dir->release() ;
2199
2200	return error ;
2201}
2202
2203IOReturn
2204IOFireWireUserClient::localConfigDirectory_addEntry_UInt32 (
2205	UserObjectHandle 		dirHandle,
2206	int 					key,
2207	UInt32 					value,
2208	const char *			descCString,
2209	UInt32					descLen ) const
2210{
2211	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2212	if ( !object )
2213	{
2214		return kIOReturnBadArgument ;
2215	}
2216
2217	IOLocalConfigDirectory * dir = OSDynamicCast ( IOLocalConfigDirectory, object ) ;
2218	if ( ! dir )
2219	{
2220		object->release() ;
2221		return kIOReturnBadArgument ;
2222	}
2223
2224	OSString * desc = NULL ;
2225	if ( descCString && (descLen < 1024) )
2226	{
2227		char * cStr = new char[ descLen ];
2228		if ( cStr )
2229		{
2230			copyUserData( (IOVirtualAddress)descCString, (IOVirtualAddress)cStr, descLen ) ;
2231
2232			cStr[ descLen-1 ] = 0 ;
2233			desc = OSString::withCString( cStr ) ;
2234
2235			delete [] cStr;
2236		}
2237	}
2238
2239	IOReturn error = dir->addEntry(key, value, desc) ;
2240
2241	dir->release() ;
2242
2243	return error ;
2244}
2245
2246IOReturn
2247IOFireWireUserClient::localConfigDirectory_addEntry_FWAddr (
2248	UserObjectHandle	dirHandle,
2249	int					key,
2250	const char *		descCString,
2251	UInt32				descLen,
2252	FWAddress *			value ) const
2253{
2254	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2255	if ( !object )
2256	{
2257		return kIOReturnBadArgument ;
2258	}
2259
2260	IOLocalConfigDirectory * dir = OSDynamicCast ( IOLocalConfigDirectory, object ) ;
2261	if ( ! dir )
2262	{
2263		object->release() ;
2264		return kIOReturnBadArgument ;
2265	}
2266
2267	OSString * desc = NULL ;
2268	if ( descCString && (descLen < 1024) )
2269	{
2270		char * cStr = new char[ descLen ];
2271		if ( cStr )
2272		{
2273			copyUserData( (IOVirtualAddress)descCString, (IOVirtualAddress)cStr, descLen ) ;
2274
2275			cStr[ descLen-1 ] = 0 ;
2276			desc = OSString::withCString( cStr ) ;
2277
2278			delete [] cStr;
2279		}
2280	}
2281
2282	IOReturn error = dir->addEntry( key, *value, desc ) ;
2283
2284	dir->release() ;
2285
2286	return error ;
2287}
2288
2289IOReturn
2290IOFireWireUserClient::localConfigDirectory_addEntry_UnitDir (
2291	UserObjectHandle	dirHandle,
2292	int 				key,
2293	UserObjectHandle 	valueHandle,
2294	const char *		descCString,
2295	UInt32				descLen ) const
2296{
2297	IOLocalConfigDirectory * dir ;
2298	{
2299		const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2300		if ( !object )
2301		{
2302			return kIOReturnBadArgument ;
2303		}
2304
2305		dir = OSDynamicCast( IOLocalConfigDirectory, object ) ;
2306		if ( ! dir )
2307		{
2308			object->release() ;
2309			return kIOReturnBadArgument ;
2310		}
2311	}
2312
2313	IOReturn error ;
2314	IOLocalConfigDirectory * value ;
2315
2316	{
2317		const OSObject * object = fExporter->lookupObject( valueHandle ) ;
2318		if ( !object )
2319		{
2320			return kIOReturnBadArgument ;
2321		}
2322
2323		value = OSDynamicCast( IOLocalConfigDirectory, object ) ;
2324
2325		if ( ! value )
2326		{
2327			object->release() ;
2328			error = kIOReturnBadArgument ;
2329		}
2330		else
2331		{
2332			OSString * desc = NULL ;
2333
2334			if ( descCString && (descLen < 1024) )
2335			{
2336				char * cStr = new char[ descLen ];
2337				if ( cStr )
2338				{
2339					copyUserData( (IOVirtualAddress)descCString, (IOVirtualAddress)cStr, descLen ) ;
2340
2341					cStr[ descLen-1 ] = 0 ;
2342					desc = OSString::withCString( cStr ) ;
2343
2344					delete [] cStr;
2345				}
2346			}
2347
2348			error = dir->addEntry( key, value, desc ) ;
2349
2350			value->release() ;
2351		}
2352	}
2353
2354	dir->release() ;	// lookupObject retains the object
2355
2356	return error ;
2357}
2358
2359IOReturn
2360IOFireWireUserClient::localConfigDirectory_Publish ( UserObjectHandle dirHandle ) const
2361{
2362	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2363	if ( !object )
2364	{
2365		return kIOReturnBadArgument ;
2366	}
2367
2368	IOLocalConfigDirectory * dir = OSDynamicCast ( IOLocalConfigDirectory, object ) ;
2369	if ( ! dir )
2370	{
2371		object->release() ;
2372		return kIOReturnBadArgument ;
2373	}
2374
2375	IOReturn error = getOwner ()->getController()->AddUnitDirectory( dir ) ;
2376
2377	dir->release() ;	// lookupObject retains result; "I must release you"
2378
2379	return error ;
2380}
2381
2382IOReturn
2383IOFireWireUserClient::localConfigDirectory_Unpublish ( UserObjectHandle dirHandle ) const
2384{
2385	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2386	if ( !object )
2387	{
2388		return kIOReturnBadArgument ;
2389	}
2390
2391	IOLocalConfigDirectory * dir = OSDynamicCast ( IOLocalConfigDirectory, object ) ;
2392	if ( ! dir )
2393	{
2394		object->release() ;
2395		return kIOReturnBadArgument ;
2396	}
2397
2398	IOReturn error = getOwner ()->getBus()->RemoveUnitDirectory ( dir ) ;
2399
2400	dir->release() ;	// lookupObject retains result; "I must release you"
2401
2402	return error ;
2403}
2404
2405#pragma mark -
2406#pragma mark ADDRESS SPACES
2407
2408//
2409// Address Space methods
2410//
2411
2412IOReturn
2413IOFireWireUserClient::addressSpace_Create (
2414	AddressSpaceCreateParams *	params,
2415	UserObjectHandle *			outAddressSpaceHandle )
2416{
2417	IOFWUserPseudoAddressSpace * addressSpace = OSTypeAlloc( IOFWUserPseudoAddressSpace );
2418
2419	if ( addressSpace &&
2420				( params->isInitialUnits ?
2421				!addressSpace->initFixed( this, params ) : !addressSpace->initPseudo( this, params ) ) )
2422	{
2423		return kIOReturnNoMemory ;
2424	}
2425
2426	IOReturn error = addressSpace->activate() ;
2427
2428	if ( !error )
2429		error = fExporter->addObject ( addressSpace,
2430										&IOFWUserPseudoAddressSpace::exporterCleanup,
2431									   outAddressSpaceHandle ) ;		// nnn needs cleanup function?
2432
2433	if ( error )
2434		addressSpace->deactivate() ;
2435
2436	addressSpace->release() ;
2437
2438	return error ;
2439}
2440
2441IOReturn
2442IOFireWireUserClient::addressSpace_GetInfo (
2443	UserObjectHandle		addressSpaceHandle,
2444	AddressSpaceInfo *		outInfo )
2445{
2446	const OSObject *  object = fExporter->lookupObject( addressSpaceHandle ) ;
2447	if ( !object )
2448	{
2449		return kIOReturnBadArgument ;
2450	}
2451
2452	IOFWUserPseudoAddressSpace *	me 		= OSDynamicCast( IOFWUserPseudoAddressSpace, object ) ;
2453	if (!me)
2454	{
2455		object->release() ;
2456		return kIOReturnBadArgument ;
2457	}
2458
2459	outInfo->address = me->getBase() ;
2460
2461	me->release() ;
2462
2463	return kIOReturnSuccess ;
2464}
2465
2466IOReturn
2467IOFireWireUserClient::addressSpace_ClientCommandIsComplete (
2468	UserObjectHandle		addressSpaceHandle,
2469	FWClientCommandID		inCommandID,
2470	IOReturn				inResult)
2471{
2472	const OSObject * object = fExporter->lookupObject( addressSpaceHandle ) ;
2473	if ( !object )
2474	{
2475		return kIOReturnBadArgument ;
2476	}
2477
2478	IOReturn	result = kIOReturnSuccess ;
2479	IOFWUserPseudoAddressSpace *	me	= OSDynamicCast( IOFWUserPseudoAddressSpace, object ) ;
2480	if (!me)
2481	{
2482		object->release() ;
2483		return kIOReturnBadArgument ;
2484	}
2485
2486	me->clientCommandIsComplete ( inCommandID, inResult ) ;
2487	me->release() ;
2488
2489	return result ;
2490}
2491
2492IOReturn
2493IOFireWireUserClient::setAsyncRef_Packet (
2494	OSAsyncReference64		asyncRef,
2495	UserObjectHandle		addressSpaceHandle,
2496	mach_vm_address_t		inCallback,
2497	io_user_reference_t		inUserRefCon,
2498	void*,
2499	void*,
2500	void*)
2501{
2502	const OSObject * object = fExporter->lookupObject ( addressSpaceHandle ) ;
2503	if ( !object )
2504	{
2505		return kIOReturnBadArgument ;
2506	}
2507
2508	IOFWUserPseudoAddressSpace * me = OSDynamicCast ( IOFWUserPseudoAddressSpace, object ) ;
2509	if ( ! me )
2510	{
2511		object->release() ;
2512		return kIOReturnBadArgument ;
2513	}
2514
2515	if ( inCallback )
2516		super::setAsyncReference64 ( asyncRef, (mach_port_t) asyncRef[0], inCallback, inUserRefCon ) ;
2517	else
2518		asyncRef[0] = 0 ;
2519
2520	me->setAsyncRef_Packet(asyncRef) ;
2521	me->release() ;
2522
2523	return kIOReturnSuccess ;
2524}
2525
2526IOReturn
2527IOFireWireUserClient::setAsyncRef_SkippedPacket(
2528	OSAsyncReference64		asyncRef,
2529	UserObjectHandle		inAddrSpaceRef,
2530	mach_vm_address_t		inCallback,
2531	io_user_reference_t		inUserRefCon,
2532	void*,
2533	void*,
2534	void*)
2535{
2536	const OSObject * object = fExporter->lookupObject ( inAddrSpaceRef ) ;
2537	if ( !object )
2538	{
2539		return kIOReturnBadArgument ;
2540	}
2541
2542	IOReturn						result	= kIOReturnSuccess ;
2543	IOFWUserPseudoAddressSpace * me = OSDynamicCast ( IOFWUserPseudoAddressSpace, object ) ;
2544
2545	if ( !me )
2546	{
2547		object->release() ;
2548		result = kIOReturnBadArgument ;
2549	}
2550
2551	if ( kIOReturnSuccess == result )
2552	{
2553		if (inCallback)
2554			super::setAsyncReference64 ( asyncRef, (mach_port_t) asyncRef[0], (mach_vm_address_t) inCallback, (io_user_reference_t)inUserRefCon ) ;
2555		else
2556			asyncRef[0] = 0 ;
2557
2558		me->setAsyncRef_SkippedPacket(asyncRef) ;
2559	}
2560
2561	me->release();
2562
2563	return result ;
2564}
2565
2566IOReturn
2567IOFireWireUserClient::setAsyncRef_Read(
2568	OSAsyncReference64		asyncRef,
2569	UserObjectHandle		inAddrSpaceRef,
2570	mach_vm_address_t		inCallback,
2571	io_user_reference_t		inUserRefCon,
2572	void*,
2573	void*,
2574	void*)
2575{
2576	const OSObject * object = fExporter->lookupObject ( inAddrSpaceRef ) ;
2577	if ( !object )
2578	{
2579		return kIOReturnBadArgument ;
2580	}
2581
2582	IOReturn						result	= kIOReturnSuccess ;
2583	IOFWUserPseudoAddressSpace * me = OSDynamicCast ( IOFWUserPseudoAddressSpace, object ) ;
2584
2585	if ( !me )
2586	{
2587		object->release() ;
2588		result = kIOReturnBadArgument ;
2589	}
2590
2591	if ( kIOReturnSuccess == result )
2592	{
2593		if (inCallback)
2594			super::setAsyncReference64 ( asyncRef, (mach_port_t) asyncRef[0], inCallback, inUserRefCon ) ;
2595		else
2596			asyncRef[0] = 0 ;
2597
2598		me->setAsyncRef_Read(asyncRef) ;
2599	}
2600
2601	me->release();
2602
2603	return result ;
2604}
2605
2606IOReturn
2607IOFireWireUserClient::setAsyncRef_BusReset(
2608	OSAsyncReference64		asyncRef,
2609	mach_vm_address_t		inCallback,
2610	io_user_reference_t		inRefCon,
2611	void*,
2612	void*,
2613	void*,
2614	void*)
2615{
2616	super::setAsyncReference64 ( asyncRef, (mach_port_t) asyncRef[0], (mach_vm_address_t)inCallback, (io_user_reference_t)inRefCon ) ;
2617
2618	bcopy(asyncRef, fBusResetAsyncNotificationRef, sizeof(OSAsyncReference64)) ;
2619
2620	return kIOReturnSuccess ;
2621}
2622
2623IOReturn
2624IOFireWireUserClient::setAsyncRef_BusResetDone(
2625	OSAsyncReference64		inAsyncRef,
2626	mach_vm_address_t		inCallback,
2627	io_user_reference_t		inRefCon,
2628	void*,
2629	void*,
2630	void*,
2631	void*)
2632{
2633	super::setAsyncReference64 ( inAsyncRef, (mach_port_t) inAsyncRef[0], inCallback, (io_user_reference_t)inRefCon ) ;
2634
2635	bcopy(inAsyncRef, fBusResetDoneAsyncNotificationRef, sizeof(OSAsyncReference64)) ;
2636
2637	return kIOReturnSuccess ;
2638}
2639
2640#pragma mark -
2641#pragma mark PHYSICAL ADDRESS SPACES
2642//
2643// --- physical addr spaces ----------
2644//
2645
2646IOReturn
2647IOFireWireUserClient::physicalAddressSpace_Create (
2648//	PhysicalAddressSpaceCreateParams *	params,
2649	mach_vm_size_t				size,
2650	mach_vm_address_t			backingStore,
2651	UInt32						flags,
2652	UserObjectHandle * 			outAddressSpaceHandle )
2653{
2654	IOMemoryDescriptor*	mem = IOMemoryDescriptor::withAddressRange( backingStore, size, kIODirectionOutIn, fTask ) ;
2655	if ( ! mem )
2656	{
2657		DebugLog("couldn't get memory descriptor for physical address space memory\n") ;
2658		return kIOReturnNoMemory ;
2659	}
2660
2661	IOReturn error = mem->prepare( kIODirectionPrepareToPhys32 );
2662	if ( error )
2663	{
2664		DebugLog("couldn't prepare address space memory descriptor\n") ;
2665		mem->release() ;
2666		return error ;
2667	}
2668
2669	IOFWUserPhysicalAddressSpace *	addrSpace = OSTypeAlloc( IOFWUserPhysicalAddressSpace );
2670	if ( addrSpace && !addrSpace->initWithDesc( getOwner()->getController(), mem ) )
2671	{
2672		addrSpace->release() ;
2673		addrSpace = NULL ;
2674	}
2675
2676	if ( ! addrSpace )
2677	{
2678		error = kIOReturnNoMemory ;
2679	}
2680	else
2681	{
2682		error = addrSpace->activate() ;
2683
2684		if ( ! error )
2685			error = fExporter->addObject( addrSpace,
2686										  &IOFWUserPhysicalAddressSpace::exporterCleanup,
2687										  outAddressSpaceHandle );
2688
2689		addrSpace->release () ;	// fExporter will retain this
2690	}
2691
2692	mem->release() ;		// address space will retain this if it needs it.. in any case
2693							// we're done with it.
2694
2695	return error ;
2696
2697}
2698
2699IOReturn
2700IOFireWireUserClient::physicalAddressSpace_GetSegments (
2701	UserObjectHandle					addressSpaceHandle,
2702	UInt32								inSegmentCount,
2703	mach_vm_address_t					outSegments,
2704	UInt32*								outSegmentCount)
2705{
2706	const OSObject * object = fExporter->lookupObject( addressSpaceHandle ) ;
2707	if ( !object )
2708	{
2709		return kIOReturnBadArgument ;
2710	}
2711
2712	IOFWUserPhysicalAddressSpace* addressSpace = OSDynamicCast(	IOFWUserPhysicalAddressSpace, object ) ;
2713
2714	if ( ! addressSpace )
2715	{
2716		object->release() ;
2717		return kIOReturnBadArgument ;
2718	}
2719
2720	UInt32 segmentCount	;
2721	IOReturn error = addressSpace->getSegmentCount( &segmentCount ) ;
2722	if ( error == kIOReturnSuccess )
2723	{
2724		segmentCount = min( segmentCount, inSegmentCount ) ;
2725
2726		FWPhysicalSegment32 * segments = new FWPhysicalSegment32[ segmentCount ] ;
2727
2728		if ( !segments )
2729		{
2730			error = kIOReturnNoMemory ;
2731		}
2732
2733		if ( !error )
2734		{
2735			error = addressSpace->getSegments( & segmentCount, segments ) ;
2736		}
2737
2738		if ( ! error )
2739		{
2740			IOByteCount bytesCopied ;
2741			error = copyToUserBuffer( (IOVirtualAddress)segments, outSegments, sizeof( FWPhysicalSegment32 ) * segmentCount, bytesCopied ) ;
2742
2743			*outSegmentCount = bytesCopied / sizeof( FWPhysicalSegment32 ) ;
2744		}
2745
2746		delete[] segments ;
2747	}
2748
2749	addressSpace->release() ; // retained by call to lookupObject()
2750
2751	return error ;
2752}
2753
2754#pragma mark
2755#pragma mark CONFIG DIRECTORY
2756
2757IOReturn
2758IOFireWireUserClient::configDirectory_Create ( UserObjectHandle * outDirRef )
2759{
2760	IOConfigDirectory * configDir ;
2761	IOReturn error = getOwner ()->getConfigDirectoryRef ( configDir );
2762
2763	if ( error )
2764		return error ;
2765
2766	if ( !configDir )
2767		error = kIOReturnNoMemory ;
2768	else
2769	{
2770		error = fExporter->addObject ( configDir, NULL, outDirRef ) ;
2771		configDir->release () ;
2772	}
2773
2774	return error ;
2775}
2776
2777IOReturn
2778IOFireWireUserClient::configDirectory_GetKeyType (
2779	UserObjectHandle	dirHandle,
2780	int					key,
2781	IOConfigKeyType *	outType) const
2782{
2783	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2784	if ( !object )
2785	{
2786		return kIOReturnBadArgument ;
2787	}
2788
2789	IOConfigDirectory * dir = OSDynamicCast( IOConfigDirectory, object ) ;
2790	if ( !dir )
2791	{
2792		object->release() ;
2793		return kIOReturnBadArgument ;
2794	}
2795
2796	IOReturn error = dir->getKeyType(key, *outType) ;
2797
2798	dir->release() ;
2799
2800	return error ;
2801}
2802
2803IOReturn
2804IOFireWireUserClient::configDirectory_GetKeyValue_UInt32 (
2805	UserObjectHandle 		dirHandle,
2806	int 					key,
2807	UInt32 					wantText,
2808	UInt32 * 				outValue,
2809	UserObjectHandle * 		outTextHandle,
2810	UInt32 * 				outTextLength ) const
2811{
2812	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2813	if ( !object )
2814	{
2815		return kIOReturnBadArgument ;
2816	}
2817
2818	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
2819	if ( ! dir )
2820	{
2821		object->release() ;
2822		return kIOReturnBadArgument ;
2823	}
2824
2825	OSString * outString = NULL ;
2826	IOReturn error = dir->getKeyValue( key, *outValue, ((bool)wantText) ? & outString : NULL ) ;
2827
2828	if ( outString && !error )
2829	{
2830		error = fExporter->addObject( outString, NULL, outTextHandle ) ;
2831
2832		outString->release () ;
2833
2834		if ( ! error )
2835			*outTextLength = outString->getLength() ;
2836	}
2837
2838	dir->release() ;
2839
2840	return error ;
2841}
2842
2843IOReturn
2844IOFireWireUserClient::configDirectory_GetKeyValue_Data (
2845	UserObjectHandle			dirHandle,
2846	int 						key,
2847	UInt32 						wantText,
2848	GetKeyValueDataResults *	results ) const
2849{
2850	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2851	if ( !object )
2852	{
2853		return kIOReturnBadArgument ;
2854	}
2855
2856	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
2857	if ( ! dir )
2858	{
2859		object->release() ;
2860		return kIOReturnBadArgument ;
2861	}
2862
2863	OSData * outData = NULL ;
2864	OSString * outText = NULL ;
2865	IOReturn error = dir->getKeyValue ( key, outData, ((bool)wantText) ? & outText : NULL ) ;
2866
2867	if ( outText )
2868	{
2869		if ( ! error )
2870		{
2871			error = fExporter->addObject( outText, NULL, &results->text ) ;
2872			results->textLength = outText->getLength() ;
2873		}
2874
2875		outText->release() ;
2876	}
2877
2878	if ( outData )
2879	{
2880		if ( ! error )
2881		{
2882			error = fExporter->addObject( outData, NULL, &results->data ) ;
2883			results->dataLength = outData->getLength() ;
2884		}
2885
2886		outData->release() ;
2887	}
2888
2889	dir->release() ;
2890
2891	return error ;
2892}
2893
2894IOReturn
2895IOFireWireUserClient::configDirectory_GetKeyValue_ConfigDirectory(
2896		UserObjectHandle 		dirHandle,
2897		int 						key,
2898		UInt32 						wantText,
2899		UserObjectHandle * 	outDirHandle,
2900		UserObjectHandle * 			outTextHandle,
2901		UInt32 * 					outTextLength ) const
2902{
2903	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2904	if ( !object )
2905	{
2906		return kIOReturnBadArgument ;
2907	}
2908
2909	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
2910	if ( ! dir )
2911	{
2912		object->release() ;
2913		return kIOReturnBadArgument ;
2914	}
2915
2916	OSString * outText = NULL ;
2917	IOConfigDirectory * outDir = NULL ;
2918	IOReturn error = dir->getKeyValue ( key, outDir, ((bool)wantText) ? & outText : NULL ) ;
2919
2920	if ( outText )
2921	{
2922		if ( ! error )
2923		{
2924			*outTextLength = outText->getLength() ;
2925			error = fExporter->addObject( outText, NULL, outTextHandle ) ;
2926		}
2927
2928		outText->release() ;
2929	}
2930
2931	if ( outDir )
2932	{
2933		if ( ! error )
2934			error = fExporter->addObject( outDir, NULL, outDirHandle ) ;
2935
2936		outDir->release() ;
2937	}
2938
2939	dir->release() ;
2940
2941	return error ;
2942}
2943
2944IOReturn
2945IOFireWireUserClient::configDirectory_GetKeyOffset_FWAddress (
2946	UserObjectHandle	dirHandle,
2947	int 					key,
2948	UInt32 					wantText,
2949	GetKeyOffsetResults * 	results ) const
2950{
2951	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2952	if ( !object )
2953	{
2954		return kIOReturnBadArgument ;
2955	}
2956
2957	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
2958	if ( ! dir )
2959	{
2960		object->release() ;
2961		return kIOReturnBadArgument ;
2962	}
2963
2964	OSString * outText = NULL ;
2965	IOReturn error = dir->getKeyOffset ( key, results->address, ((bool)wantText) ? & outText : NULL) ;
2966
2967	if ( outText )
2968	{
2969		if ( ! error )
2970		{
2971			results->length = outText->getLength() ;
2972			error = fExporter->addObject( outText, NULL, &results->text ) ;
2973		}
2974
2975		outText->release() ;
2976	}
2977
2978	dir->release() ;
2979
2980	return error ;
2981}
2982
2983IOReturn
2984IOFireWireUserClient::configDirectory_GetIndexType (
2985	UserObjectHandle	dirHandle,
2986	int					index,
2987	IOConfigKeyType*	outType ) const
2988{
2989	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
2990	if ( !object )
2991	{
2992		return kIOReturnBadArgument ;
2993	}
2994
2995	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
2996	if ( ! dir )
2997	{
2998		object->release() ;
2999		return kIOReturnBadArgument ;
3000	}
3001
3002	IOReturn error = dir->getIndexType(index, *outType) ;
3003
3004	dir->release() ;
3005
3006	return error ;
3007}
3008
3009IOReturn
3010IOFireWireUserClient::configDirectory_GetIndexKey (
3011	UserObjectHandle	dirHandle,
3012	int					index,
3013	int *				outKey ) const
3014{
3015	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3016	if ( !object )
3017	{
3018		return kIOReturnBadArgument ;
3019	}
3020
3021	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3022	if ( ! dir )
3023	{
3024		object->release() ;
3025		return kIOReturnBadArgument ;
3026	}
3027
3028	IOReturn error = dir->getIndexKey(index, *outKey) ;
3029
3030	dir->release() ;
3031
3032	return error ;
3033}
3034
3035IOReturn
3036IOFireWireUserClient::configDirectory_GetIndexValue_UInt32 (
3037	UserObjectHandle	dirHandle,
3038	int					index,
3039	UInt32*				outKey ) const
3040{
3041	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3042	if ( !object )
3043	{
3044		return kIOReturnBadArgument ;
3045	}
3046
3047	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3048	if ( ! dir )
3049	{
3050		object->release() ;
3051		return kIOReturnBadArgument ;
3052	}
3053
3054	IOReturn error = dir->getIndexValue(index, *outKey) ;
3055
3056	dir->release() ;
3057
3058	return error ;
3059}
3060
3061IOReturn
3062IOFireWireUserClient::configDirectory_GetIndexValue_Data (
3063	UserObjectHandle		dirHandle,
3064	int						index,
3065	UserObjectHandle *		outDataHandle,
3066	IOByteCount *			outDataLen ) const
3067{
3068	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3069	if ( !object )
3070	{
3071		return kIOReturnBadArgument ;
3072	}
3073
3074	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3075	if ( ! dir )
3076	{
3077		object->release() ;
3078		return kIOReturnBadArgument ;
3079	}
3080
3081	OSData * outData = NULL ;
3082	IOReturn error = dir->getIndexValue( index, outData ) ;
3083
3084	if ( !error && outData )
3085	{
3086		error = fExporter->addObject( outData, NULL, outDataHandle ) ;
3087		*outDataLen = outData->getLength() ;
3088
3089		outData->release() ;
3090	}
3091
3092	dir->release() ;
3093
3094	return error ;
3095}
3096
3097IOReturn
3098IOFireWireUserClient::configDirectory_GetIndexValue_String (
3099	UserObjectHandle 		dirHandle,
3100	int 					index,
3101	UserObjectHandle * 		outTextHandle,
3102	UInt32 * 				outTextLength ) const
3103{
3104	InfoLog("IOFireWireUserClient<%p>::configDirectory_GetIndexValue_String, index=%d, outTextHandle=%p\n", this ) ;
3105
3106	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3107	if ( !object )
3108	{
3109		DebugLog("IOFireWireUserClient<%p>::configDirectory_GetIndexValue_String() -- dir handle is invalid\n", this ) ;
3110		return kIOReturnBadArgument ;
3111	}
3112
3113	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3114	if ( ! dir )
3115	{
3116		DebugLog("IOFireWireUserClient<%p>::configDirectory_GetIndexValue_String() -- dir handle is not a config directory object!\n", this ) ;
3117
3118		object->release() ;
3119		return kIOReturnBadArgument ;
3120	}
3121
3122	OSString * outText = NULL ;
3123	IOReturn error = dir->getIndexValue( index, outText ) ;
3124
3125	InfoLog("a. IOFireWireUserClient<%p>::configDirectory_GetIndexValue_String error=%x\n", this, error ) ;
3126
3127	if ( !error && outText )
3128	{
3129		*outTextLength = outText->getLength() ;
3130
3131		error = fExporter->addObject( outText, NULL, outTextHandle ) ;
3132
3133		outText->release() ;
3134	}
3135
3136	dir->release() ;
3137
3138	return error ;
3139}
3140
3141IOReturn
3142IOFireWireUserClient::configDirectory_GetIndexValue_ConfigDirectory (
3143	UserObjectHandle		dirHandle,
3144	int						index,
3145	UserObjectHandle *		outDirHandle ) const
3146{
3147	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3148	if ( !object )
3149	{
3150		return kIOReturnBadArgument ;
3151	}
3152
3153	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3154	if ( ! dir )
3155	{
3156		object->release() ;
3157		return kIOReturnBadArgument ;
3158	}
3159
3160	IOConfigDirectory * outDir = NULL ;
3161	IOReturn error = dir->getIndexValue( index, outDir ) ;
3162
3163	if ( ! error && outDir )
3164	{
3165		error = fExporter->addObject ( outDir, NULL, outDirHandle ) ;
3166		outDir->release() ;
3167	}
3168
3169	dir->release() ;
3170
3171	return error ;
3172}
3173
3174IOReturn
3175IOFireWireUserClient::configDirectory_GetIndexOffset_FWAddress (
3176	UserObjectHandle	dirHandle,
3177	int					index,
3178	FWAddress *			outAddress ) const
3179{
3180	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3181	if ( !object )
3182	{
3183		return kIOReturnBadArgument ;
3184	}
3185
3186	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3187	if ( ! dir )
3188	{
3189		object->release() ;
3190		return kIOReturnBadArgument ;
3191	}
3192
3193	IOReturn result = dir->getIndexOffset( index, *outAddress ) ;
3194
3195	dir->release() ;
3196
3197	return result ;
3198}
3199
3200IOReturn
3201IOFireWireUserClient::configDirectory_GetIndexOffset_UInt32 (
3202	UserObjectHandle	dirHandle,
3203	int					index,
3204	UInt32*				outValue) const
3205{
3206	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3207	if ( !object )
3208	{
3209		return kIOReturnBadArgument ;
3210	}
3211
3212	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3213	if ( ! dir )
3214	{
3215		object->release() ;
3216		return kIOReturnBadArgument ;
3217	}
3218
3219	IOReturn error = dir->getIndexOffset(index, *outValue) ;
3220
3221	dir->release() ;
3222
3223	return error ;
3224}
3225
3226IOReturn
3227IOFireWireUserClient::configDirectory_GetIndexEntry (
3228	UserObjectHandle	dirHandle,
3229	int					index,
3230	UInt32*				outValue) const
3231{
3232	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3233	if ( !object )
3234	{
3235		return kIOReturnBadArgument ;
3236	}
3237
3238	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3239	if ( ! dir )
3240	{
3241		object->release() ;
3242		return kIOReturnBadArgument ;
3243	}
3244
3245	IOReturn error = dir->getIndexEntry(index, *outValue) ;
3246
3247	dir->release() ;
3248
3249	return error ;
3250}
3251
3252IOReturn
3253IOFireWireUserClient::configDirectory_GetSubdirectories (
3254	UserObjectHandle		dirHandle,
3255	UserObjectHandle*		outIteratorHandle ) const
3256{
3257	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3258	if ( !object )
3259	{
3260		return kIOReturnBadArgument ;
3261	}
3262
3263	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3264	if ( ! dir )
3265	{
3266		object->release() ;
3267		return kIOReturnBadArgument ;
3268	}
3269
3270	OSIterator * outIterator = NULL ;
3271	IOReturn error = dir->getSubdirectories( outIterator ) ;
3272
3273	if ( outIterator )
3274	{
3275		if ( ! error )
3276			error = fExporter->addObject( outIterator, NULL, outIteratorHandle ) ;
3277
3278		outIterator->release () ;
3279	}
3280
3281	dir->release() ;
3282
3283	return error ;
3284}
3285
3286IOReturn
3287IOFireWireUserClient::configDirectory_GetKeySubdirectories (
3288	UserObjectHandle		dirHandle ,
3289	int							key,
3290	UserObjectHandle*			outIteratorHandle ) const
3291{
3292	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3293	if ( !object )
3294	{
3295		return kIOReturnBadArgument ;
3296	}
3297
3298	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3299	if ( ! dir )
3300	{
3301		object->release() ;
3302		return kIOReturnBadArgument ;
3303	}
3304
3305	OSIterator * outIterator = NULL ;
3306	IOReturn error = dir->getKeySubdirectories( key, outIterator ) ;
3307
3308	if ( outIterator )
3309	{
3310		if ( ! error )
3311			error = fExporter->addObject( outIterator, NULL, outIteratorHandle ) ;
3312
3313		outIterator->release() ;
3314	}
3315
3316	dir->release() ;
3317
3318	return error ;
3319}
3320
3321IOReturn
3322IOFireWireUserClient::configDirectory_GetType (
3323	UserObjectHandle		dirHandle,
3324	int*					outType) const
3325{
3326	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3327	if ( !object )
3328	{
3329		return kIOReturnBadArgument ;
3330	}
3331
3332	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3333	if ( ! dir )
3334	{
3335		object->release() ;
3336		return kIOReturnBadArgument ;
3337	}
3338
3339	*outType = dir->getType();
3340
3341	dir->release() ;
3342
3343	return kIOReturnSuccess ;
3344}
3345
3346IOReturn
3347IOFireWireUserClient::configDirectory_GetNumEntries (
3348	UserObjectHandle		dirHandle,
3349	int*					outNumEntries) const
3350{
3351	const OSObject * object = fExporter->lookupObject( dirHandle ) ;
3352	if ( !object )
3353	{
3354		return kIOReturnBadArgument ;
3355	}
3356
3357	IOConfigDirectory * dir = OSDynamicCast ( IOConfigDirectory, object ) ;
3358	if ( ! dir )
3359	{
3360		object->release() ;
3361		return kIOReturnBadArgument ;
3362	}
3363
3364	*outNumEntries = dir->getNumEntries() ;
3365	dir->release() ;
3366
3367	return kIOReturnSuccess ;
3368}
3369
3370#pragma mark -
3371#pragma mark LOCAL ISOCH PORT
3372
3373IOReturn
3374IOFireWireUserClient::localIsochPort_GetSupported(
3375	UserObjectHandle		portHandle,
3376	IOFWSpeed*				outMaxSpeed,
3377	UInt32*					outChanSupportedHi,
3378	UInt32*					outChanSupportedLo) const
3379{
3380	const OSObject * object = fExporter->lookupObject( portHandle ) ;
3381	if ( !object )
3382	{
3383		return kIOReturnBadArgument ;
3384	}
3385
3386	IOFWUserLocalIsochPort * port = OSDynamicCast ( IOFWUserLocalIsochPort, object ) ;
3387	if ( ! port )
3388	{
3389		object->release() ;
3390		return kIOReturnBadArgument ;
3391	}
3392
3393	UInt64		chanSupported ;
3394	IOReturn	result			= kIOReturnSuccess ;
3395
3396	result = port->getSupported( *outMaxSpeed, chanSupported ) ;
3397
3398	*outChanSupportedHi = (UInt32)( chanSupported >> 32 ) ;
3399	*outChanSupportedLo	= (UInt32)( chanSupported & 0xFFFFFFFF ) ;
3400
3401	port->release() ;
3402
3403	return result ;
3404}
3405
3406
3407IOReturn
3408IOFireWireUserClient::localIsochPort_Create (
3409	LocalIsochPortAllocateParams*	params,
3410	UserObjectHandle*				outPortHandle )
3411{
3412	IOFWUserLocalIsochPort * port = OSTypeAlloc( IOFWUserLocalIsochPort );
3413	if ( port && ! port->initWithUserDCLProgram( params, *this, *getOwner()->getController() ) )
3414	{
3415		port->release() ;
3416		port = NULL ;
3417	}
3418
3419	if ( !port )
3420	{
3421		DebugLog( "couldn't create local isoch port\n" ) ;
3422		return kIOReturnError ;
3423	}
3424
3425	IOReturn error = fExporter->addObject( port,
3426			&IOFWUserLocalIsochPort::exporterCleanup,
3427			outPortHandle ) ;
3428
3429	port->release() ;
3430
3431	return error ;
3432}
3433
3434IOReturn
3435IOFireWireUserClient::localIsochPort_SetChannel (
3436	UserObjectHandle	portHandle,
3437	UserObjectHandle	channelHandle )
3438{
3439	InfoLog("IOFireWireUserClient<%p>::localIsochPort_SetChannel\n", this ) ;
3440
3441	const OSObject * object1 = fExporter->lookupObject( portHandle ) ;
3442	IOFWUserLocalIsochPort * port = OSDynamicCast ( IOFWUserLocalIsochPort, object1 ) ;
3443	IOReturn error = kIOReturnSuccess ;
3444
3445	if ( !port )
3446	{
3447		error = kIOReturnBadArgument ;
3448	}
3449
3450	const OSObject * object2 = NULL ;
3451	IOFWUserIsochChannel * channel = NULL ;
3452
3453	if ( !error )
3454	{
3455		object2 = fExporter->lookupObject( channelHandle ) ;
3456
3457		channel = OSDynamicCast( IOFWUserIsochChannel, object2 ) ;
3458
3459		if ( !channel )
3460		{
3461			error = kIOReturnBadArgument ;
3462		}
3463	}
3464
3465	if ( !error )
3466	{
3467		IODCLProgram * program = port->getProgramRef() ;
3468		if ( program )
3469		{
3470			program->setForceStopProc( (IOFWIsochChannel::ForceStopNotificationProc*)&IOFWUserIsochChannel::isochChannel_ForceStopHandler, channel, channel ) ;
3471
3472			program->release() ;
3473		}
3474	}
3475
3476	if ( object1 )
3477	{
3478		object1->release() ;
3479	}
3480
3481	if ( object2 )
3482	{
3483		object2->release() ;
3484	}
3485
3486	return error ;
3487}
3488
3489IOReturn
3490IOFireWireUserClient::setAsyncRef_DCLCallProc (
3491		OSAsyncReference64 			asyncRef,
3492		UserObjectHandle 			portHandle )
3493{
3494	InfoLog("IOFireWireUserClient<%p>::setAsyncRef_DCLCallProc\n", this ) ;
3495
3496	const OSObject * object =  fExporter->lookupObject( portHandle ) ;
3497	if ( !object )
3498	{
3499		return kIOReturnBadArgument ;
3500	}
3501
3502	IOFWUserLocalIsochPort * port = OSDynamicCast( IOFWUserLocalIsochPort, object ) ;
3503	if ( ! port )
3504	{
3505		object->release() ;
3506		return kIOReturnBadArgument ;
3507	}
3508
3509	IOReturn error = port->setAsyncRef_DCLCallProc( asyncRef ) ;
3510
3511	port->release() ;	// loopkupObject retains the return value for thread safety
3512
3513	return error ;
3514}
3515
3516#pragma mark -
3517#pragma mark ISOCH CHANNEL
3518
3519IOReturn
3520IOFireWireUserClient::isochChannel_Create (
3521	bool					inDoIRM,
3522	UInt32					inPacketSize,
3523	IOFWSpeed				inPrefSpeed,
3524	UserObjectHandle *	outChannelHandle )
3525{
3526	// this code the same as IOFireWireController::createIsochChannel
3527	// must update this code when controller changes. We do this because
3528	// we are making IOFWUserIsochChannel objects, not IOFWIsochChannel
3529	// objects
3530
3531	IOReturn error = kIOReturnSuccess ;
3532	IOFWUserIsochChannel * channel = OSTypeAlloc( IOFWUserIsochChannel );
3533	if ( channel )
3534	{
3535		if ( channel->init(	getOwner()->getController(), inDoIRM, inPacketSize, inPrefSpeed ) )
3536		{
3537			fExporter->addObject( channel,
3538					(IOFWUserObjectExporter::CleanupFunction) & IOFWUserIsochChannel::s_exporterCleanup,
3539					outChannelHandle ) ;
3540		}
3541
3542		channel->release() ;	// addObject retains the object
3543	}
3544	else
3545	{
3546		error = kIOReturnNoMemory ;
3547	}
3548
3549	return error ;
3550}
3551
3552IOReturn
3553IOFireWireUserClient::isochChannel_AllocateChannelBegin(
3554	UserObjectHandle		channelRef,
3555	UInt32 					speed,
3556	UInt32 					chansHi,
3557	UInt32 					chansLo,
3558	UInt32 * 				outSpeed,
3559	UInt32 * 				outChannel )
3560{
3561	InfoLog("IOFireWireUserClient<%p>::isochChannel_AllocateChannelBegin\n", this ) ;
3562
3563	IOReturn error = kIOReturnSuccess ;
3564	const OSObject * object = fExporter->lookupObject( channelRef ) ;
3565
3566	IOFWUserIsochChannel * channel = OSDynamicCast( IOFWUserIsochChannel, object ) ;
3567
3568	if ( ! channel )
3569	{
3570		error = kIOReturnBadArgument ;
3571	}
3572
3573	if ( !error )
3574	{
3575		UInt64 allowedChans = ((UInt64)chansHi << 32) | (UInt64)chansLo ;
3576		error = channel->allocateChannelBegin( (IOFWSpeed)speed, allowedChans, outChannel ) ;
3577		*outSpeed = speed;
3578	}
3579
3580	if ( object )
3581	{
3582		object->release() ;	// lookup retains object, so we have to release it.
3583	}
3584
3585	return error ;
3586}
3587
3588IOReturn
3589IOFireWireUserClient::setAsyncRef_IsochChannelForceStop(
3590	OSAsyncReference64		inAsyncRef,
3591	UserObjectHandle		channelRef )
3592{
3593
3594	IOReturn error = kIOReturnSuccess;
3595
3596	const OSObject * object = fExporter->lookupObject( channelRef ) ;
3597
3598	IOFWUserIsochChannel * channel = OSDynamicCast( IOFWUserIsochChannel, object ) ;
3599
3600	if ( !channel )
3601	{
3602#if __LP64__
3603		DebugLog("IOFireWireUserClient<%p>::setAsyncRef_IsochChannelForceStop() -- invalid channel ref %llx\n", this, (UInt64)channelRef ) ;
3604#else
3605		DebugLog("IOFireWireUserClient<%p>::setAsyncRef_IsochChannelForceStop() -- invalid channel ref %lx\n", this, (UInt32)channelRef ) ;
3606#endif
3607		error = kIOReturnBadArgument ;
3608	}
3609
3610	io_user_reference_t * asyncRef = NULL;
3611	if( error == kIOReturnSuccess )
3612	{
3613		asyncRef = new io_user_reference_t[ kOSAsyncRefCount ] ;
3614
3615		if ( !asyncRef )
3616		{
3617			error = kIOReturnNoMemory ;
3618		}
3619	}
3620
3621	if( error == kIOReturnSuccess )
3622	{
3623		bcopy( inAsyncRef, asyncRef, sizeof( OSAsyncReference64 ) ) ;
3624
3625		io_user_reference_t * oldAsyncRef = channel->getUserAsyncRef() ;
3626
3627		channel->setUserAsyncRef( asyncRef ) ;
3628
3629		delete [] oldAsyncRef ;
3630	}
3631
3632	if( channel != NULL )
3633	{
3634		channel->release();
3635	}
3636
3637	return error;
3638}
3639
3640#pragma mark -
3641#pragma mark COMMAND OBJECTS
3642
3643// createAsyncCommand
3644//
3645//
3646
3647IOReturn
3648IOFireWireUserClient::createAsyncCommand(	OSAsyncReference64 asyncRef,
3649											CommandSubmitParams * params,
3650											UserObjectHandle * kernel_ref )
3651{
3652	IOReturn status = kIOReturnSuccess;
3653
3654	IOFWUserCommand * cmd = NULL;
3655	if( status == kIOReturnSuccess )
3656	{
3657		cmd = IOFWUserCommand::withSubmitParams( params, this );
3658		if( !cmd )
3659			status = kIOReturnNoMemory;
3660	}
3661
3662	if( status == kIOReturnSuccess )
3663	{
3664		status = fExporter->addObject( cmd, NULL, kernel_ref );
3665	}
3666
3667	if( status == kIOReturnSuccess )
3668	{
3669		cmd->setRefCon( (mach_vm_address_t)params->refCon);
3670	}
3671
3672	if( status == kIOReturnSuccess )
3673	{
3674		setAsyncReference64( asyncRef, (mach_port_t) asyncRef[0], (mach_vm_address_t)params->callback, (io_user_reference_t)params->refCon);
3675
3676		cmd->setAsyncReference64( asyncRef );
3677	}
3678
3679	if( cmd )
3680	{
3681		cmd->release();		// we need to release this in all cases
3682		cmd = NULL;
3683	}
3684
3685	return status;
3686}
3687
3688
3689IOReturn
3690IOFireWireUserClient::userAsyncCommand_Submit(
3691	OSAsyncReference64			asyncRef,
3692	CommandSubmitParams *		params,
3693	CommandSubmitResult *		outResult,
3694	IOByteCount					paramsSize,
3695	IOByteCount *				outResultSize)
3696{
3697	IOFWUserCommand * cmd = NULL ;
3698
3699	IOReturn error = kIOReturnSuccess ;
3700
3701	if ( params->kernCommandRef )
3702	{
3703		const OSObject * object = fExporter->lookupObject( params->kernCommandRef ) ;
3704		if ( !object )
3705		{
3706			error = kIOReturnBadArgument ;
3707		}
3708		else
3709		{
3710			cmd = OSDynamicCast( IOFWUserCommand, object ) ;
3711			if ( ! cmd )
3712			{
3713				object->release() ;
3714				error = kIOReturnBadArgument ;
3715			}
3716		}
3717	}
3718	else
3719	{
3720		cmd = IOFWUserCommand::withSubmitParams( params, this ) ;
3721
3722		if ( ! cmd )
3723			error = kIOReturnNoMemory ;
3724		else
3725		{
3726			UserObjectHandle command_ref;
3727			error = fExporter->addObject( cmd, NULL, &command_ref );
3728			outResult->kernCommandRef = command_ref;
3729		}
3730	}
3731
3732	if ( cmd )
3733	{
3734		if ( !error )
3735		{
3736			super::setAsyncReference64( asyncRef, (mach_port_t) asyncRef[0], (mach_vm_address_t)params->callback, (io_user_reference_t)params->refCon) ;
3737
3738			cmd->setAsyncReference64( asyncRef ) ;
3739			cmd->setRefCon( (mach_vm_address_t)params->refCon);
3740
3741			error = cmd->submit( params, outResult ) ;
3742		}
3743
3744		cmd->release() ;		// we need to release this in all cases
3745	}
3746
3747	return error ;
3748}
3749
3750//
3751// --- absolute address firewire commands ----------
3752//
3753IOFWReadCommand*
3754IOFireWireUserClient::createReadCommand(
3755	UInt32 					generation,
3756	FWAddress 				devAddress,
3757	IOMemoryDescriptor*		hostMem,
3758	FWDeviceCallback	 		completion,
3759	void*					refcon ) const
3760{
3761	IOFWReadCommand* result = OSTypeAlloc( IOFWReadCommand );
3762	if ( result && !result->initAll( getOwner ()->getController(), generation, devAddress, hostMem, completion, refcon ) )
3763	{
3764		result->release() ;
3765		result = NULL ;
3766	}
3767
3768	return result ;
3769}
3770
3771IOFWReadQuadCommand*
3772IOFireWireUserClient::createReadQuadCommand(
3773	UInt32 					generation,
3774	FWAddress 				devAddress,
3775	UInt32 *				quads,
3776	int 					numQuads,
3777	FWDeviceCallback 		completion,
3778	void *					refcon ) const
3779{
3780	IOFWReadQuadCommand* result = OSTypeAlloc( IOFWReadQuadCommand );
3781	if ( result && !result->initAll( getOwner ()->getController(), generation, devAddress, quads, numQuads, completion, refcon ) )
3782	{
3783		result->release() ;
3784		return NULL ;
3785	}
3786
3787	return result ;
3788}
3789
3790IOFWWriteCommand*
3791IOFireWireUserClient::createWriteCommand(
3792	UInt32 					generation,
3793	FWAddress 				devAddress,
3794	IOMemoryDescriptor*		hostMem,
3795	FWDeviceCallback 		completion,
3796	void*					refcon ) const
3797{
3798	IOFWWriteCommand* result = OSTypeAlloc( IOFWWriteCommand );
3799	if ( result && !result->initAll( getOwner ()->getController(), generation, devAddress, hostMem, completion, refcon ) )
3800	{
3801		result->release() ;
3802		return NULL ;
3803	}
3804
3805	return result ;
3806}
3807
3808IOFWWriteQuadCommand*
3809IOFireWireUserClient::createWriteQuadCommand(
3810	UInt32 					generation,
3811	FWAddress 				devAddress,
3812	UInt32 *				quads,
3813	int 					numQuads,
3814	FWDeviceCallback 		completion,
3815	void *					refcon ) const
3816{
3817	IOFWWriteQuadCommand* result = OSTypeAlloc( IOFWWriteQuadCommand );
3818	if ( result && !result->initAll( getOwner ()->getController(), generation, devAddress, quads, numQuads, completion, refcon ) )
3819	{
3820		result->release() ;
3821		return NULL ;
3822	}
3823
3824	return result ;
3825}
3826
3827	// size is 1 for 32 bit compare, 2 for 64 bit.
3828IOFWCompareAndSwapCommand*
3829IOFireWireUserClient::createCompareAndSwapCommand(
3830	UInt32 					generation,
3831	FWAddress 				devAddress,
3832	const UInt32 *			cmpVal,
3833	const UInt32 *			newVal,
3834	int 					size,
3835	FWDeviceCallback 		completion,
3836	void *					refcon ) const
3837{
3838	IOFWCompareAndSwapCommand* result = OSTypeAlloc( IOFWCompareAndSwapCommand );
3839	if ( result && !result->initAll( getOwner ()->getController(), generation, devAddress, cmpVal, newVal, size, completion, refcon ) )
3840	{
3841		result->release() ;
3842		return NULL ;
3843	}
3844
3845	return result ;
3846}
3847
3848#pragma mark -
3849
3850IOReturn
3851IOFireWireUserClient::firelog( const char* string, IOByteCount bufSize ) const
3852{
3853
3854#if FIRELOG
3855	FireLog( string ) ;
3856#endif
3857
3858	return kIOReturnSuccess;
3859}
3860
3861IOReturn
3862IOFireWireUserClient::getBusGeneration( UInt32* outGeneration )
3863{
3864	*outGeneration = getOwner () -> getController () -> getGeneration () ;
3865	return kIOReturnSuccess ;
3866}
3867
3868IOReturn
3869IOFireWireUserClient::getLocalNodeIDWithGeneration( UInt32 testGeneration, UInt32* outLocalNodeID )
3870{
3871	if ( ! getOwner () -> getController () -> checkGeneration ( testGeneration ) )
3872		return kIOFireWireBusReset ;
3873
3874	*outLocalNodeID = (UInt32) getOwner () -> getController () -> getLocalNodeID () ;
3875
3876	// did generation change when we weren't looking?
3877	if ( ! getOwner () -> getController () -> checkGeneration ( testGeneration ) )
3878		return kIOFireWireBusReset ;
3879
3880	return kIOReturnSuccess ;
3881}
3882
3883IOReturn
3884IOFireWireUserClient::getRemoteNodeID( UInt32 testGeneration, UInt32* outRemoteNodeID )
3885{
3886	UInt32 generation ;
3887	UInt16 nodeID ;
3888
3889	IOReturn error = getOwner () -> getNodeIDGeneration ( generation, nodeID ) ;
3890	if (error)
3891		return error ;
3892	if ( generation != testGeneration )
3893		return kIOFireWireBusReset ;
3894
3895	*outRemoteNodeID = (UInt32)nodeID ;
3896
3897	// did generation change when we weren't looking?
3898	if ( ! getOwner () -> getController () -> checkGeneration ( generation ) )
3899		return kIOFireWireBusReset ;
3900
3901	return error ;
3902}
3903
3904IOReturn
3905IOFireWireUserClient::getSpeedToNode( UInt32 generation, UInt32* outSpeed )
3906{
3907	if ( ! getOwner () -> getController () -> checkGeneration ( generation ) )
3908		return kIOFireWireBusReset ;
3909
3910	UInt16 nodeID ;
3911	getOwner () -> getNodeIDGeneration( generation, nodeID ) ;
3912
3913	*outSpeed = (UInt32) getOwner () -> getController () -> FWSpeed ( nodeID ) ;
3914
3915	// did generation change when we weren't looking?
3916	if ( ! getOwner () -> getController () -> checkGeneration ( generation ) )
3917		return kIOFireWireBusReset ;
3918
3919	return kIOReturnSuccess ;
3920}
3921
3922IOReturn
3923IOFireWireUserClient::getSpeedBetweenNodes( UInt32 generation, UInt32 fromNode, UInt32 toNode, UInt32* outSpeed )
3924{
3925	if ( ! getOwner () -> getController () -> checkGeneration ( generation ) )
3926		return kIOFireWireBusReset ;
3927
3928	*outSpeed = (UInt32)getOwner ()->getController()->FWSpeed( (UInt16)fromNode, (UInt16)toNode ) ;
3929	// did generation change when we weren't looking?
3930	if (!getOwner ()->getController()->checkGeneration(generation))
3931		return kIOFireWireBusReset ;
3932
3933	return kIOReturnSuccess ;
3934}
3935
3936IOReturn
3937IOFireWireUserClient::getIRMNodeID( UInt32 generation, UInt32* irmNodeID )
3938{
3939	UInt16 tempNodeID ;
3940	UInt32 tempGeneration ;
3941
3942	IOReturn error = (UInt32)getOwner ()->getController()->getIRMNodeID( tempGeneration, tempNodeID ) ;
3943	if (error)
3944		return error ;
3945
3946	if ( tempGeneration != generation )
3947		return kIOFireWireBusReset ;
3948
3949	*irmNodeID = (UInt32)tempNodeID ;
3950
3951	return kIOReturnSuccess ;
3952}
3953
3954IOReturn
3955IOFireWireUserClient::clipMaxRec2K( Boolean clipMaxRec )
3956{
3957	//IOLog("IOFireWireUserClient::clipMaxRec2K\n");
3958
3959	if( fClippedMaxRec == clipMaxRec )
3960		return kIOReturnSuccess;		// Already set the way we want, no need to do it again
3961
3962	IOReturn error = (UInt32)fOwner->getController()->clipMaxRec2K( clipMaxRec ) ;
3963	if (error)
3964		return error ;
3965
3966	fClippedMaxRec = clipMaxRec;
3967
3968	return kIOReturnSuccess ;
3969}
3970
3971IOReturn
3972IOFireWireUserClient::seize( IOOptionBits inFlags )
3973{
3974	if ( ! OSDynamicCast(IOFireWireDevice, getOwner ()))
3975		return kIOReturnUnsupported ;
3976
3977	if ( kIOReturnSuccess != clientHasPrivilege( fTask, kIOClientPrivilegeAdministrator ) )
3978		return kIOReturnNotPrivileged ;
3979
3980	// message all clients that have the device open that
3981	// the device is going away. It's not really going away, but we
3982	// want them to think so...
3983	if ( getOwner ()->isOpen() )
3984	{
3985		OSIterator*			clientIterator =  getOwner ()->getOpenClientIterator() ;
3986		if (!clientIterator)
3987		{
3988			DebugLog("IOFireWireUserClient::seize: couldn't make owner client iterator\n") ;
3989			return kIOReturnError ;
3990		}
3991
3992		{
3993			IOService*			client = (IOService*)clientIterator->getNextObject() ;
3994
3995			while ( client )
3996			{
3997				if ( client != this )
3998				{
3999					client->message( kIOFWMessageServiceIsRequestingClose, getOwner () ) ;
4000					client->message( kIOMessageServiceIsRequestingClose, getOwner () ) ;
4001
4002					client->terminate() ;
4003				}
4004
4005				client = (IOService*)clientIterator->getNextObject() ;
4006			}
4007		}
4008
4009		clientIterator->release() ;
4010	}
4011
4012	if ( getOwner ()->isOpen() )
4013	{
4014		OSIterator*			clientIterator =  getOwner ()->getClientIterator() ;
4015		if (!clientIterator)
4016		{
4017			DebugLog("IOFireWireUserClient::seize: couldn't make owner client iterator\n") ;
4018			return kIOReturnError ;
4019		}
4020
4021		{
4022			IOService*			client = (IOService*)clientIterator->getNextObject() ;
4023
4024			while ( client )
4025			{
4026				if ( client != this )
4027				{
4028					client->message( kIOFWMessageServiceIsRequestingClose, getOwner () ) ;
4029					client->message( kIOMessageServiceIsRequestingClose, getOwner () ) ;
4030
4031					client->terminate() ;
4032				}
4033
4034				client = (IOService*)clientIterator->getNextObject() ;
4035			}
4036		}
4037
4038		clientIterator->release() ;
4039	}
4040
4041	return kIOReturnSuccess ;
4042}
4043
4044IOReturn IOFireWireUserClient::message( UInt32 type, IOService * provider, void * arg )
4045{
4046	switch(type)
4047	{
4048		case kIOMessageServiceIsSuspended:
4049			if (fBusResetAsyncNotificationRef[0])
4050				sendAsyncResult64(fBusResetAsyncNotificationRef, kIOReturnSuccess, NULL, 0) ;
4051			break ;
4052		case kIOMessageServiceIsResumed:
4053			if (fBusResetDoneAsyncNotificationRef[0])
4054				sendAsyncResult64(fBusResetDoneAsyncNotificationRef, kIOReturnSuccess, NULL, 0) ;
4055			break ;
4056		case kIOFWMessageServiceIsRequestingClose:
4057			getOwner ()->messageClients(kIOMessageServiceIsRequestingClose) ;
4058			break;
4059
4060	}
4061
4062	super::message ( type, provider ) ;
4063
4064	return kIOReturnSuccess;
4065}
4066
4067IOReturn
4068IOFireWireUserClient::getSessionRef( IOFireWireSessionRef * sessionRef )
4069{
4070    IOReturn error = kIOReturnSuccess;
4071
4072    if( !fOwner->isOpen( this ) )
4073	{
4074		return kIOReturnNotOpen ;
4075	}
4076
4077	*sessionRef = (IOFireWireSessionRef)fSessionRef;
4078
4079	return error ;
4080}
4081
4082#pragma mark -
4083#pragma mark ASYNC STREAM LISTENER
4084
4085//
4086// Async Stream Listener
4087//
4088
4089IOReturn
4090IOFireWireUserClient::setAsyncStreamRef_Packet (
4091	OSAsyncReference64		asyncRef,
4092	UserObjectHandle		asyncStreamListenerHandle,
4093	mach_vm_address_t		inCallback,
4094	io_user_reference_t		inUserRefCon,
4095	void*,
4096	void*,
4097	void*
4098)
4099{
4100	IOReturn result = kIOReturnBadArgument;
4101
4102	const OSObject * object = fExporter->lookupObject ( asyncStreamListenerHandle ) ;
4103	if ( !object )
4104	{
4105		return result ;
4106	}
4107
4108	IOFWUserAsyncStreamListener * me = OSDynamicCast ( IOFWUserAsyncStreamListener, object ) ;
4109	if ( ! me )
4110	{
4111		object->release() ;
4112		return result ;
4113	}
4114
4115	if ( inCallback )
4116		super::setAsyncReference64 ( asyncRef, (mach_port_t) asyncRef[0], inCallback, inUserRefCon ) ;
4117	else
4118		asyncRef[0] = 0 ;
4119
4120	me->setAsyncStreamRef_Packet(asyncRef) ;
4121	me->release() ;
4122
4123	return kIOReturnSuccess ;
4124}
4125
4126IOReturn
4127IOFireWireUserClient::setAsyncStreamRef_SkippedPacket (
4128	OSAsyncReference64		asyncRef,
4129	UserObjectHandle		inAsyncStreamListenerRef,
4130	mach_vm_address_t		inCallback,
4131	io_user_reference_t		inUserRefCon,
4132	void*,
4133	void*,
4134	void*)
4135{
4136	IOReturn result = kIOReturnBadArgument;
4137
4138	const OSObject * object = fExporter->lookupObject ( inAsyncStreamListenerRef ) ;
4139	if ( !object )
4140	{
4141		return result ;
4142	}
4143
4144	result	= kIOReturnSuccess ;
4145	IOFWUserAsyncStreamListener * me = OSDynamicCast ( IOFWUserAsyncStreamListener, object ) ;
4146
4147	if ( !me )
4148	{
4149		object->release() ;
4150		result = kIOReturnBadArgument ;
4151	}
4152
4153	if ( kIOReturnSuccess == result )
4154	{
4155		if (inCallback)
4156			super::setAsyncReference64 ( asyncRef, (mach_port_t) asyncRef[0], inCallback, inUserRefCon ) ;
4157		else
4158			asyncRef[0] = 0 ;
4159
4160		me->setAsyncStreamRef_SkippedPacket(asyncRef) ;
4161	}
4162
4163	me->release();
4164
4165	return result ;
4166}
4167
4168IOReturn
4169IOFireWireUserClient::asyncStreamListener_Create (
4170	FWUserAsyncStreamListenerCreateParams*	params,
4171	UserObjectHandle*						outAsyncStreamListenerHandle )
4172{
4173	IOFWUserAsyncStreamListener * asyncStreamListener = OSTypeAlloc( IOFWUserAsyncStreamListener );
4174
4175	if ( asyncStreamListener == NULL )
4176		return kIOReturnNoMemory ;
4177
4178	if ( not asyncStreamListener->initAsyncStreamListener( this, params ) )
4179	{
4180		asyncStreamListener->release();
4181		return kIOReturnNoMemory ;
4182	}
4183
4184	IOReturn error = fExporter->addObject ( asyncStreamListener,
4185									(IOFWUserObjectExporter::CleanupFunction)&IOFWUserAsyncStreamListener::exporterCleanup,
4186									outAsyncStreamListenerHandle ) ;		// nnn needs cleanup function?
4187
4188	if ( error )
4189		asyncStreamListener->deactivate() ;
4190
4191	asyncStreamListener->release() ;
4192
4193	return error ;
4194}
4195
4196IOReturn
4197IOFireWireUserClient::asyncStreamListener_ClientCommandIsComplete (
4198	UserObjectHandle		asyncStreamListenerHandle,
4199	FWClientCommandID		inCommandID )
4200{
4201	const OSObject * object = fExporter->lookupObject( asyncStreamListenerHandle ) ;
4202	if ( !object )
4203	{
4204		return kIOReturnBadArgument ;
4205	}
4206
4207	IOReturn	result = kIOReturnSuccess ;
4208	IOFWUserAsyncStreamListener *me	= OSDynamicCast( IOFWUserAsyncStreamListener, object ) ;
4209	if (!me)
4210	{
4211		object->release() ;
4212		return kIOReturnBadArgument ;
4213	}
4214
4215	me->clientCommandIsComplete ( inCommandID ) ;
4216	me->release() ;
4217
4218	return result ;
4219}
4220
4221IOReturn
4222IOFireWireUserClient::asyncStreamListener_GetOverrunCounter (
4223	UserObjectHandle		asyncStreamListenerHandle,
4224	UInt32					*overrunCounter )
4225{
4226	IOReturn	result = kIOReturnBadArgument ;
4227
4228	const OSObject * object = fExporter->lookupObject( asyncStreamListenerHandle ) ;
4229	if ( !object )
4230	{
4231		return result ;
4232	}
4233
4234	IOFWUserAsyncStreamListener *me	= OSDynamicCast( IOFWUserAsyncStreamListener, object ) ;
4235	if ( !me )
4236	{
4237		object->release() ;
4238		return result ;
4239	}
4240
4241	*overrunCounter = me->getOverrunCounter( ) ;
4242	me->release() ;
4243
4244	result = kIOReturnSuccess;
4245
4246	return result ;
4247
4248}
4249
4250IOReturn
4251IOFireWireUserClient::asyncStreamListener_SetFlags (
4252	UserObjectHandle		asyncStreamListenerHandle,
4253	UInt32					flags )
4254{
4255	IOReturn	result = kIOReturnBadArgument ;
4256
4257	const OSObject * object = fExporter->lookupObject( asyncStreamListenerHandle ) ;
4258	if ( !object )
4259	{
4260		return result ;
4261	}
4262
4263	IOFWUserAsyncStreamListener *me	= OSDynamicCast( IOFWUserAsyncStreamListener, object ) ;
4264	if (!me)
4265	{
4266		object->release() ;
4267		return result;
4268	}
4269
4270	result = kIOReturnSuccess;
4271	me->setFlags( flags ) ;
4272	me->release() ;
4273
4274	return result ;
4275}
4276
4277IOReturn
4278IOFireWireUserClient::asyncStreamListener_GetFlags (
4279	UserObjectHandle		asyncStreamListenerHandle,
4280	UInt32					*flags )
4281{
4282	IOReturn	result = kIOReturnBadArgument ;
4283
4284	const OSObject * object = fExporter->lookupObject( asyncStreamListenerHandle ) ;
4285	if ( !object )
4286	{
4287		return result ;
4288	}
4289
4290	IOFWUserAsyncStreamListener *me	= OSDynamicCast( IOFWUserAsyncStreamListener, object ) ;
4291	if (!me)
4292	{
4293		object->release() ;
4294		return result ;
4295	}
4296
4297	result = kIOReturnSuccess;
4298	*flags = me->getFlags( ) ;
4299	me->release() ;
4300
4301	return result ;
4302}
4303
4304IOReturn
4305IOFireWireUserClient::asyncStreamListener_TurnOnNotification (
4306	UserObjectHandle		asyncStreamListenerHandle )
4307{
4308	IOReturn	result = kIOReturnBadArgument ;
4309
4310	const OSObject * object = fExporter->lookupObject( asyncStreamListenerHandle ) ;
4311	if ( !object )
4312	{
4313		return result ;
4314	}
4315
4316	IOFWUserAsyncStreamListener *me	= OSDynamicCast( IOFWUserAsyncStreamListener, object ) ;
4317	if (!me)
4318	{
4319		object->release() ;
4320		return result ;
4321	}
4322
4323	result = kIOReturnSuccess;
4324	me->TurnOnNotification() ;
4325	me->release() ;
4326
4327	return result ;
4328}
4329
4330IOReturn
4331IOFireWireUserClient::asyncStreamListener_TurnOffNotification (
4332	UserObjectHandle		asyncStreamListenerHandle )
4333{
4334	IOReturn	result = kIOReturnBadArgument ;
4335
4336	const OSObject * object = fExporter->lookupObject( asyncStreamListenerHandle ) ;
4337	if ( !object )
4338	{
4339		return result ;
4340	}
4341
4342	IOFWUserAsyncStreamListener *me	= OSDynamicCast( IOFWUserAsyncStreamListener, object ) ;
4343	if (!me)
4344	{
4345		object->release() ;
4346		return result ;
4347	}
4348
4349	result = kIOReturnSuccess;
4350	me->TurnOffNotification() ;
4351	me->release() ;
4352
4353	return result ;
4354}
4355
4356#pragma mark -
4357#pragma mark IRM ALLOCATIONS
4358
4359IOReturn
4360IOFireWireUserClient::allocateIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation)
4361{
4362	return getOwner () -> getController () -> allocateIRMBandwidthInGeneration(bandwidthUnits, generation);
4363}
4364
4365IOReturn
4366IOFireWireUserClient::releaseIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation)
4367{
4368	return getOwner () -> getController () -> releaseIRMBandwidthInGeneration(bandwidthUnits, generation);
4369}
4370
4371IOReturn
4372IOFireWireUserClient::allocateIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation)
4373{
4374	return getOwner () -> getController () -> allocateIRMChannelInGeneration(isochChannel, generation);
4375}
4376
4377IOReturn
4378IOFireWireUserClient::releaseIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation)
4379{
4380	return getOwner () -> getController () -> releaseIRMChannelInGeneration(isochChannel, generation);
4381}
4382
4383typedef struct UserIRMAllocationParamsStruct
4384{
4385	io_user_reference_t asyncRef[kOSAsyncRef64Count];
4386	Boolean userNotificationEnabled;
4387	IOFireWireUserClient *pUserClient;
4388} UserIRMAllocationParams;
4389
4390static void UserIRMAllocationCleanupFunction( const OSObject * obj )
4391{
4392	IOFireWireIRMAllocation * pIrmAllocation = (IOFireWireIRMAllocation *) obj;
4393
4394	UserIRMAllocationParams *pUserIRMAllocationParams = (UserIRMAllocationParams*) pIrmAllocation->GetRefCon();
4395	delete pUserIRMAllocationParams;
4396}
4397
4398static IOReturn UserIRMAllocationLostNotification(void* refCon, class IOFireWireIRMAllocation* allocation)
4399{
4400	UserIRMAllocationParams *pUserIRMAllocationParams = (UserIRMAllocationParams*) refCon;
4401	if (pUserIRMAllocationParams->userNotificationEnabled)
4402		pUserIRMAllocationParams->pUserClient->sendAsyncResult64(pUserIRMAllocationParams->asyncRef, kIOReturnSuccess, NULL, 0) ;
4403	return kIOReturnSuccess;
4404}
4405
4406IOReturn
4407IOFireWireUserClient::irmAllocation_Create(Boolean releaseIRMResourcesOnFree, UserObjectHandle* outIRMAllocationHandle)
4408{
4409	UserIRMAllocationParams *pUserIRMAllocationParams = new UserIRMAllocationParams;
4410	if (!pUserIRMAllocationParams)
4411		return kIOReturnNoMemory ;
4412	else
4413	{
4414		pUserIRMAllocationParams->userNotificationEnabled = false;
4415		pUserIRMAllocationParams->pUserClient = this;
4416	}
4417
4418	IOFireWireIRMAllocation * irmAllocation = OSTypeAlloc( IOFireWireIRMAllocation );
4419	if (!irmAllocation)
4420	{
4421		delete pUserIRMAllocationParams;
4422		return kIOReturnNoMemory ;
4423	}
4424
4425	if (!irmAllocation->init(getOwner()->getController(), releaseIRMResourcesOnFree, UserIRMAllocationLostNotification, pUserIRMAllocationParams))
4426	{
4427		irmAllocation->release();
4428		delete pUserIRMAllocationParams;
4429		return kIOReturnNoMemory ;
4430	}
4431
4432	IOReturn error = fExporter->addObject ( irmAllocation, UserIRMAllocationCleanupFunction, outIRMAllocationHandle ) ;
4433	irmAllocation->release() ;
4434
4435	return error ;
4436}
4437
4438IOReturn
4439IOFireWireUserClient::irmAllocation_AllocateResources(UserObjectHandle irmAllocationHandle, UInt8 isochChannel, UInt32 bandwidthUnits)
4440{
4441	IOReturn	result = kIOReturnBadArgument ;
4442
4443	const OSObject * object = fExporter->lookupObject( irmAllocationHandle ) ;
4444	if ( !object )
4445	{
4446		return result ;
4447	}
4448
4449	IOFireWireIRMAllocation *me	= OSDynamicCast( IOFireWireIRMAllocation, object ) ;
4450	if (!me)
4451	{
4452		object->release() ;
4453		return result ;
4454	}
4455
4456	result = me->allocateIsochResources(isochChannel, bandwidthUnits) ;
4457
4458	me->release() ;
4459
4460	return result ;
4461}
4462
4463IOReturn
4464IOFireWireUserClient::irmAllocation_DeallocateResources(UserObjectHandle irmAllocationHandle)
4465{
4466	IOReturn	result = kIOReturnBadArgument ;
4467
4468	const OSObject * object = fExporter->lookupObject( irmAllocationHandle ) ;
4469	if ( !object )
4470	{
4471		return result ;
4472	}
4473
4474	IOFireWireIRMAllocation *me	= OSDynamicCast( IOFireWireIRMAllocation, object ) ;
4475	if (!me)
4476	{
4477		object->release() ;
4478		return result ;
4479	}
4480
4481	result = me->deallocateIsochResources();
4482
4483	me->release() ;
4484
4485	return result ;
4486}
4487
4488Boolean
4489IOFireWireUserClient::irmAllocation_areResourcesAllocated(UserObjectHandle irmAllocationHandle, UInt8 *pIsochChannel, UInt32 *pBandwidthUnits)
4490{
4491	Boolean	result = false ;
4492
4493	const OSObject * object = fExporter->lookupObject( irmAllocationHandle ) ;
4494	if ( !object )
4495	{
4496		return false ;
4497	}
4498
4499	IOFireWireIRMAllocation *me	= OSDynamicCast( IOFireWireIRMAllocation, object ) ;
4500	if (!me)
4501	{
4502		object->release() ;
4503		return false ;
4504	}
4505
4506	result = me->areIsochResourcesAllocated(pIsochChannel, pBandwidthUnits);
4507
4508	me->release() ;
4509
4510	return result ;
4511}
4512
4513void
4514IOFireWireUserClient::irmAllocation_setDeallocateOnRelease(UserObjectHandle irmAllocationHandle, Boolean doDeallocationOnRelease)
4515{
4516	const OSObject * object = fExporter->lookupObject( irmAllocationHandle ) ;
4517	if ( !object )
4518	{
4519		return;
4520	}
4521
4522	IOFireWireIRMAllocation *me	= OSDynamicCast( IOFireWireIRMAllocation, object ) ;
4523	if (!me)
4524	{
4525		object->release() ;
4526		return;
4527	}
4528
4529	me->setReleaseIRMResourcesOnFree(doDeallocationOnRelease);
4530
4531	me->release() ;
4532
4533	return;
4534}
4535
4536IOReturn
4537IOFireWireUserClient::irmAllocation_setRef(OSAsyncReference64 asyncRef,
4538											 UserObjectHandle irmAllocationHandle,
4539											 io_user_reference_t inCallback,
4540											 io_user_reference_t inUserRefCon)
4541{
4542	IOReturn	result = kIOReturnBadArgument ;
4543
4544	const OSObject * object = fExporter->lookupObject( irmAllocationHandle ) ;
4545	if ( !object )
4546	{
4547		return result ;
4548	}
4549
4550	IOFireWireIRMAllocation *me	= OSDynamicCast( IOFireWireIRMAllocation, object ) ;
4551	if (!me)
4552	{
4553		object->release() ;
4554		return result ;
4555	}
4556
4557	UserIRMAllocationParams *pUserIRMAllocationParams = (UserIRMAllocationParams*) me->GetRefCon();
4558
4559	for (UInt32 i=0;i<kOSAsyncRef64Count;i++)
4560		pUserIRMAllocationParams->asyncRef[i] = asyncRef[i];
4561	pUserIRMAllocationParams->asyncRef[ kIOAsyncCalloutFuncIndex ] = (mach_vm_address_t)inCallback ;
4562	pUserIRMAllocationParams->asyncRef[ kIOAsyncCalloutRefconIndex ] = inUserRefCon ;
4563	if (inCallback)
4564		pUserIRMAllocationParams->userNotificationEnabled = true;
4565	else
4566		pUserIRMAllocationParams->userNotificationEnabled = false;
4567
4568	me->release() ;
4569
4570	return result ;
4571}
4572
4573// createVectorCommand
4574//
4575//
4576
4577IOReturn
4578IOFireWireUserClient::createVectorCommand( UserObjectHandle * kernel_ref )
4579{
4580	IOReturn status = kIOReturnSuccess;
4581
4582	IOFWUserVectorCommand * cmd = NULL;
4583	if( status == kIOReturnSuccess )
4584	{
4585		cmd = IOFWUserVectorCommand::withUserClient( this );
4586		if( !cmd )
4587			status = kIOReturnNoMemory;
4588	}
4589
4590	if( status == kIOReturnSuccess )
4591	{
4592		status = fExporter->addObject( cmd, NULL, kernel_ref );
4593	}
4594
4595	if( cmd )
4596	{
4597		cmd->release();		// we need to release this in all cases
4598		cmd = NULL;
4599	}
4600
4601	return status;
4602}
4603
4604// createPHYPacketListener
4605//
4606//
4607
4608IOReturn
4609IOFireWireUserClient::createPHYPacketListener( UInt32 queue_count, UserObjectHandle * kernel_ref )
4610{
4611	IOReturn status = kIOReturnSuccess;
4612
4613	IOFWUserPHYPacketListener * listener = NULL;
4614	if( status == kIOReturnSuccess )
4615	{
4616		listener = IOFWUserPHYPacketListener::withUserClient( this, queue_count );
4617		if( !listener )
4618			status = kIOReturnNoMemory;
4619	}
4620
4621	if( status == kIOReturnSuccess )
4622	{
4623		status = fExporter->addObject( listener, (IOFWUserObjectExporter::CleanupFunction)&IOFWUserPHYPacketListener::exporterCleanup, kernel_ref );
4624	}
4625
4626	if( listener )
4627	{
4628		listener->release();		// we need to release this in all cases
4629		listener = NULL;
4630	}
4631
4632	return status;
4633}
4634