1/*
2 *  IOFireWireLibDevice.cpp
3 *  IOFireWireFamily
4 *
5 *  Created by Niels on Thu Feb 27 2003.
6 *  Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
7 *
8 *	$ Log:IOFireWireLibDevice.cpp,v $
9 */
10
11#import "IOFireWireLibDevice.h"
12#import "IOFireWireLibCommand.h"
13#import "IOFireWireLibUnitDirectory.h"
14#import "IOFireWireLibConfigDirectory.h"
15#import "IOFireWireLibPhysicalAddressSpace.h"
16#import "IOFireWireLibPseudoAddressSpace.h"
17#import "IOFireWireLibIsochChannel.h"
18#import "IOFireWireLibIsochPort.h"
19#import "IOFireWireLibDCLCommandPool.h"
20#import "IOFireWireLibNuDCLPool.h"
21#import "IOFireWireLibAsyncStreamListener.h"
22#import "IOFireWireLibIRMAllocation.h"
23#import "IOFireWireLibVectorCommand.h"
24#import "IOFireWireLibPHYPacketListener.h"
25
26#import <IOKit/iokitmig.h>
27#import <mach/mach.h>
28#import <System/libkern/OSCrossEndian.h>
29
30namespace IOFireWireLib {
31
32	Device::Device( const IUnknownVTbl & interface, CFDictionaryRef /*propertyTable*/, io_service_t service )
33	: IOFireWireIUnknown( interface )
34	{
35		if ( !service )
36			throw kIOReturnBadArgument ;
37
38		// mr. safety says, "initialize for safety!"
39		mConnection					= nil ;
40		mIsInited					= false ;
41		mIsOpen						= false ;
42		mNotifyIsOn					= false ;
43		mAsyncPort					= 0 ;
44		mAsyncCFPort				= 0 ;
45		mBusResetHandler 			= 0 ;
46		mBusResetDoneHandler 		= 0 ;
47
48		mRunLoop					= 0 ;
49		mRunLoopSource				= 0 ;
50		mRunLoopMode				= 0 ;
51
52		mIsochRunLoop				= 0 ;
53		mIsochRunLoopSource			= 0 ;
54		mIsochRunLoopMode			= 0 ;
55
56		//
57		// isoch related
58		//
59		mIsochAsyncPort				= 0 ;
60		mIsochAsyncCFPort			= 0 ;
61
62		mDefaultDevice = service ;
63
64		IOReturn error = OpenDefaultConnection() ;
65		if ( error )
66			throw error ;
67
68		// factory counting
69		::CFPlugInAddInstanceForFactory( kIOFireWireLibFactoryID );
70
71		mIsInited = true ;
72	}
73
74	Device::~Device()
75	{
76		if (mIsOpen)
77			Close() ;
78
79		if (mRunLoopSource)
80		{
81			RemoveDispatcherFromRunLoop( mRunLoop, mRunLoopSource, mRunLoopMode ) ;
82
83			CFRelease( mRunLoopSource ) ;
84			CFRelease( mRunLoop ) ;
85			CFRelease( mRunLoopMode ) ;
86		}
87
88		if ( mIsochRunLoopSource )
89		{
90			RemoveDispatcherFromRunLoop( mIsochRunLoop, mIsochRunLoopSource, mIsochRunLoopMode ) ;
91
92			CFRelease( mIsochRunLoopSource ) ;
93			CFRelease( mIsochRunLoop ) ;
94			CFRelease( mIsochRunLoopMode ) ;
95		}
96
97		// club ports to death
98		if ( mIsochAsyncCFPort )
99		{
100			CFMachPortInvalidate( mIsochAsyncCFPort ) ;
101			CFRelease( mIsochAsyncCFPort ) ;
102			mach_port_destroy( mach_task_self(), mIsochAsyncPort ) ;
103		}
104
105		// club ports to death
106		if ( mAsyncCFPort )
107		{
108			CFMachPortInvalidate( mAsyncCFPort ) ;
109			CFRelease( mAsyncCFPort ) ;
110			mach_port_destroy( mach_task_self(), mAsyncPort ) ;
111		}
112
113		if ( mConnection )
114		{
115			IOServiceClose( mConnection ) ;
116		}
117
118		if (mIsInited)
119		{
120			// factory counting
121			::CFPlugInRemoveInstanceForFactory( kIOFireWireLibFactoryID );
122		}
123	}
124
125	HRESULT STDMETHODCALLTYPE
126	Device::QueryInterface(REFIID iid, LPVOID* ppv)
127	{
128		HRESULT		result = S_OK ;
129		*ppv = nil ;
130
131		CFUUIDRef	interfaceID	= CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
132
133		if (	CFEqual(interfaceID, kIOFireWireDeviceInterfaceID )
134
135				// v2 interfaces...
136				||	CFEqual(interfaceID, kIOFireWireDeviceInterfaceID_v2)
137				||	CFEqual(interfaceID, kIOFireWireNubInterfaceID)
138				||	CFEqual(interfaceID, kIOFireWireUnitInterfaceID)
139
140				// v3 interfaces...
141				||	CFEqual( interfaceID, kIOFireWireNubInterfaceID_v3 )
142				||	CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v3 )
143				||	CFEqual( interfaceID, kIOFireWireUnitInterfaceID_v3 )
144
145				// v4 interfaces...
146				||	CFEqual( interfaceID, kIOFireWireNubInterfaceID_v4 )
147				||	CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v4 )
148				||	CFEqual( interfaceID, kIOFireWireUnitInterfaceID_v4 )
149
150				// v5 interfaces...
151				|| CFEqual( interfaceID, kIOFireWireNubInterfaceID_v5 )
152				|| CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v5 )
153				|| CFEqual( interfaceID, kIOFireWireUnitInterfaceID_v5 )
154
155				// v6
156
157				|| CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v6 )
158
159				// v7
160
161				|| CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v7 )
162
163				// v8
164
165				|| CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v8 )
166
167				// v9
168
169				|| CFEqual( interfaceID, kIOFireWireDeviceInterfaceID_v9 )
170				)
171		{
172			*ppv = & GetInterface() ;
173			AddRef() ;
174		}
175		else
176		{
177			*ppv = nil ;
178			result = E_NOINTERFACE ;
179		}
180
181		CFRelease(interfaceID) ;
182
183		return result ;
184	}
185
186#pragma mark -
187	IOReturn
188	Device::OpenDefaultConnection()
189	{
190		io_connect_t	connection	= 0 ;
191		IOReturn		kr			= kIOReturnSuccess ;
192
193		if ( 0 == mDefaultDevice )
194			kr = kIOReturnNoDevice ;
195
196		if (kIOReturnSuccess == kr )
197			kr = IOServiceOpen(mDefaultDevice, mach_task_self(), kIOFireWireLibConnection, & connection) ;
198
199		if (kIOReturnSuccess == kr )
200			mConnection = connection ;
201
202		return kr ;
203	}
204
205	IOReturn
206	Device::CreateAsyncPorts()
207	{
208		IOReturn result = kIOReturnSuccess ;
209
210		if (! mAsyncPort)
211		{
212			IOCreateReceivePort(kOSAsyncCompleteMessageID, & mAsyncPort) ;
213
214			Boolean shouldFreeInfo ;
215			CFMachPortContext cfPortContext	= {1, this, NULL, NULL, NULL} ;
216			mAsyncCFPort = CFMachPortCreateWithPort(
217								kCFAllocatorDefault,
218								mAsyncPort,
219								(CFMachPortCallBack) IODispatchCalloutFromMessage,
220								& cfPortContext,
221								& shouldFreeInfo) ;
222
223			if (!mAsyncCFPort)
224				result = kIOReturnNoMemory ;
225		}
226
227		return result ;
228	}
229
230	IOReturn
231	Device::CreateIsochAsyncPorts()
232	{
233		IOReturn result = kIOReturnSuccess ;
234
235		if (! mIsochAsyncPort)
236		{
237			IOCreateReceivePort(kOSAsyncCompleteMessageID, & mIsochAsyncPort) ;
238
239			Boolean shouldFreeInfo ;
240			CFMachPortContext cfPortContext	= {1, this, NULL, NULL, NULL} ;
241			mIsochAsyncCFPort = CFMachPortCreateWithPort( kCFAllocatorDefault,
242														mIsochAsyncPort,
243														(CFMachPortCallBack) IODispatchCalloutFromMessage,
244														& cfPortContext,
245														& shouldFreeInfo) ;
246			if (!mIsochAsyncCFPort)
247				result = kIOReturnNoMemory ;
248		}
249
250		return result ;
251	}
252
253	IOReturn
254	Device::Open()
255	{
256		if ( mIsOpen )
257		{
258			return kIOReturnSuccess ;
259		}
260
261		uint32_t outputCnt = 0;
262		IOReturn result = IOConnectCallScalarMethod(GetUserClientConnection(),kOpen,NULL,0,NULL,&outputCnt);
263
264		mIsOpen = (kIOReturnSuccess == result) ;
265
266		return result ;
267	}
268
269	IOReturn
270	Device::OpenWithSessionRef(IOFireWireSessionRef session)
271	{
272		if (mIsOpen)
273		{
274			return kIOReturnSuccess ;
275		}
276
277		uint32_t outputCnt = 0;
278
279		const uint64_t inputs[1]={(const uint64_t)session};
280
281		IOReturn result = IOConnectCallScalarMethod(GetUserClientConnection(), kOpenWithSessionRef,inputs,1,NULL,&outputCnt);
282
283		mIsOpen = (kIOReturnSuccess == result) ;
284
285		return result ;
286	}
287
288	IOReturn
289	Device::Seize( IOOptionBits flags )	// v3
290	{
291		if ( mIsOpen )
292		{
293			DebugLog("Device::Seize: Can't call while interface is open\n") ;
294			return kIOReturnError ;
295		}
296
297		if (!mConnection)
298			return kIOReturnNoDevice ;
299
300		uint32_t outputCnt = 0;
301		const uint64_t inputs[1]={(const uint64_t)flags};
302		IOReturn err = IOConnectCallScalarMethod(GetUserClientConnection(), kSeize,inputs,1,NULL,&outputCnt);
303
304		DebugLogCond(err, "Could not seize service! err=%x\n", err) ;
305
306		return err ;
307	}
308
309	void
310	Device::Close()
311	{
312		if (!mIsOpen)
313		{
314			DebugLog("Device::Close: interface not open\n") ;
315			return ;
316		}
317
318		uint32_t outputCnt = 0;
319		IOReturn err = kIOReturnSuccess;
320		err = IOConnectCallScalarMethod(GetUserClientConnection(),kClose,NULL,0,NULL,&outputCnt);
321
322		DebugLogCond( err, "Device::Close(): error %x returned from Close()!\n", err ) ;
323
324		mIsOpen = false ;
325	}
326
327	#pragma mark -
328	IOReturn
329	Device::AddCallbackDispatcherToRunLoopForMode(	// v3+
330		CFRunLoopRef 				runLoop,
331		CFStringRef					runLoopMode )
332	{
333		// if the client passes 0 as the runloop, that means
334		// we should remove the source instead of adding it.
335
336		if ( !runLoop || !runLoopMode )
337		{
338			DebugLog("IOFireWireLibDeviceInterfaceImp::AddCallbackDispatcherToRunLoopForMode: runLoop == 0 || runLoopMode == 0\n") ;
339			return kIOReturnBadArgument ;
340		}
341
342		IOReturn result = kIOReturnSuccess ;
343
344		if (!AsyncPortsExist())
345			result = CreateAsyncPorts() ;
346
347		if ( kIOReturnSuccess == result )
348		{
349			CFRetain( runLoop ) ;
350			CFRetain( runLoopMode ) ;
351
352			mRunLoop 		= runLoop ;
353			mRunLoopSource	= CFMachPortCreateRunLoopSource(
354									kCFAllocatorDefault,
355									GetAsyncCFPort(),
356									0) ;
357			mRunLoopMode	= runLoopMode ;
358
359			if (!mRunLoopSource)
360			{
361				CFRelease( mRunLoop ) ;
362				mRunLoop = 0 ;
363
364				CFRelease( mRunLoopMode ) ;
365				mRunLoopMode = 0 ;
366
367				result = kIOReturnNoMemory ;
368			}
369
370		#if 1
371
372			if ( kIOReturnSuccess == result )
373			{
374				if( !CFRunLoopSourceIsValid(mRunLoopSource) )
375				{
376					CFRelease(mRunLoopSource);
377
378					CFMachPortInvalidate( mAsyncCFPort );
379					CFRelease( mAsyncCFPort );
380
381					{
382						Boolean shouldFreeInfo ;
383						CFMachPortContext cfPortContext	= {1, this, NULL, NULL, NULL} ;
384						mAsyncCFPort = CFMachPortCreateWithPort(
385											kCFAllocatorDefault,
386											mAsyncPort,
387											(CFMachPortCallBack) IODispatchCalloutFromMessage,
388											& cfPortContext,
389											& shouldFreeInfo) ;
390
391						if (!mAsyncCFPort)
392							result = kIOReturnNoMemory ;
393					}
394
395					{
396						mRunLoopSource	= CFMachPortCreateRunLoopSource(
397												kCFAllocatorDefault,
398												GetAsyncCFPort(),
399												0) ;
400						if (!mRunLoopSource)
401						{
402							CFRelease( mRunLoop ) ;
403							mRunLoop = 0 ;
404
405							CFRelease( mRunLoopMode ) ;
406							mRunLoopMode = 0 ;
407
408							result = kIOReturnNoMemory ;
409						}
410					}
411
412					if( !CFRunLoopSourceIsValid(mRunLoopSource) )
413					{
414						result = kIOReturnNoResources;
415					}
416				}
417			}
418
419		#endif
420
421			if ( kIOReturnSuccess == result )
422				CFRunLoopAddSource(mRunLoop, mRunLoopSource, mRunLoopMode ) ;
423		}
424
425		return result ;
426	}
427
428	void
429	Device::RemoveDispatcherFromRunLoop(
430		CFRunLoopRef			runLoop,
431		CFRunLoopSourceRef		runLoopSource,
432		CFStringRef				mode)
433	{
434//		if ( runLoop && runLoopSource )
435//			if (CFRunLoopContainsSource( runLoop, runLoopSource, mode ))
436//				CFRunLoopRemoveSource( runLoop, runLoopSource, mode );
437		if ( runLoopSource )
438		{
439			CFRunLoopSourceInvalidate( runLoopSource ) ;
440		}
441	}
442
443	const Boolean
444	Device::TurnOnNotification(
445		void*					callBackRefCon)
446	{
447		IOReturn				result					= kIOReturnSuccess ;
448
449		if ( !mConnection )
450			result = kIOReturnNoDevice ;
451
452		if (!AsyncPortsExist())
453			result = kIOReturnError ;	// zzz  need a new error type meaning "you forgot to call AddDispatcherToRunLoop"
454
455		if ( kIOReturnSuccess == result )
456		{
457			uint64_t refrncData[kOSAsyncRef64Count];
458			refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0;
459			refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0;
460			const uint64_t inputs[2] = {(const uint64_t)& Device::BusResetHandler,(const uint64_t)callBackRefCon};
461			uint32_t outputCnt = 0;
462			result = IOConnectCallAsyncScalarMethod(mConnection,
463													kSetAsyncRef_BusReset,
464													mAsyncPort,
465													refrncData,kOSAsyncRef64Count,
466													inputs,2,
467													NULL,&outputCnt);
468		}
469
470		if ( kIOReturnSuccess == result )
471		{
472			uint64_t refrncData[kOSAsyncRef64Count];
473			refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0;
474			refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0;
475			const uint64_t inputs[2] = {(const uint64_t)& Device::BusResetDoneHandler,(const uint64_t)callBackRefCon};
476			uint32_t outputCnt = 0;
477			result = IOConnectCallAsyncScalarMethod(mConnection,
478													kSetAsyncRef_BusResetDone,
479													mAsyncPort,
480													refrncData,kOSAsyncRef64Count,
481													inputs,2,
482													NULL,&outputCnt);
483		}
484
485		if ( kIOReturnSuccess == result )
486			mNotifyIsOn = true ;
487
488		return ( kIOReturnSuccess == result ) ;
489	}
490
491	void
492	Device::TurnOffNotification()
493	{
494		IOReturn				result			= kIOReturnSuccess ;
495
496		// if notification isn't on, skip out.
497		if (!mNotifyIsOn)
498			return ;
499
500		if (!mConnection)
501			result = kIOReturnNoDevice ;
502
503		if ( kIOReturnSuccess == result )
504		{
505
506			uint64_t refrncData[kOSAsyncRef64Count];
507			refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0;
508			refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0;
509			const uint64_t inputs[2] = {0,0};
510			uint32_t outputCnt = 0;
511			result = IOConnectCallAsyncScalarMethod(mConnection,
512													kSetAsyncRef_BusReset,
513													mAsyncPort,
514													refrncData,kOSAsyncRef64Count,
515													inputs,2,
516													NULL,&outputCnt);
517
518			outputCnt = 0;
519			result = IOConnectCallAsyncScalarMethod(mConnection,
520													kSetAsyncRef_BusResetDone,
521													mAsyncPort,
522													refrncData,kOSAsyncRef64Count,
523													inputs,2,
524													NULL,&outputCnt);
525		}
526
527		mNotifyIsOn = false ;
528	}
529
530
531	const IOFireWireBusResetHandler
532	Device::SetBusResetHandler(
533		IOFireWireBusResetHandler			inBusResetHandler)
534	{
535		IOFireWireBusResetHandler	result = mBusResetHandler ;
536		mBusResetHandler = inBusResetHandler ;
537
538		return result ;
539	}
540
541	const IOFireWireBusResetDoneHandler
542	Device::SetBusResetDoneHandler(
543		IOFireWireBusResetDoneHandler		inBusResetDoneHandler)
544	{
545		IOFireWireBusResetDoneHandler	result = mBusResetDoneHandler ;
546		mBusResetDoneHandler = inBusResetDoneHandler ;
547
548		return result ;
549	}
550
551	void
552	Device::BusResetHandler(
553		void*							refCon,
554		IOReturn						result)
555	{
556		Device*	me = IOFireWireIUnknown::InterfaceMap<Device>::GetThis(refCon) ;
557
558		if (me->mBusResetHandler)
559			(me->mBusResetHandler)( (IOFireWireLibDeviceRef)refCon, (FWClientCommandID) me) ;
560	}
561
562	void
563	Device::BusResetDoneHandler(
564		void*							refCon,
565		IOReturn						result)
566	{
567		Device*	me = IOFireWireIUnknown::InterfaceMap<Device>::GetThis(refCon) ;
568
569		if (me->mBusResetDoneHandler)
570			(me->mBusResetDoneHandler)( (IOFireWireLibDeviceRef)refCon, (FWClientCommandID) me) ;
571	}
572
573#pragma mark -
574	IOReturn
575	Device::Read(
576		io_object_t				device,
577		const FWAddress &		addr,
578		void*					buf,
579		UInt32*					size,
580		Boolean					failOnReset,
581		UInt32					generation)
582	{
583		if (!mIsOpen)
584			return kIOReturnNotOpen ;
585		if ( device != mDefaultDevice && device != 0 )
586			return kIOReturnBadArgument ;
587
588		ReadParams	 			params 			= { addr, (mach_vm_address_t)buf, *size, failOnReset, generation, device == 0 /*isAbs*/ } ;
589
590#ifndef __LP64__
591		ROSETTA_ONLY(
592			{
593				params.addr.nodeID = OSSwapInt16( params.addr.nodeID );
594				params.addr.addressHi = OSSwapInt16( params.addr.addressHi );
595				params.addr.addressLo = OSSwapInt32( params.addr.addressLo );
596				params.buf = (mach_vm_address_t)OSSwapInt64(params.buf);
597				params.size = OSSwapInt32( params.size);
598			//	params.failOnReset = params.failOnReset;
599				params.generation = OSSwapInt32( params.generation );
600			//	params.isAbs = params.isAbs;
601			}
602		);
603#endif
604
605		size_t outputStructSize = sizeof( *size ) ;
606		IOReturn status = IOConnectCallStructMethod(mConnection,
607													kRead,
608													&params,sizeof(params),
609													size,&outputStructSize);
610
611#ifndef __LP64__
612		ROSETTA_ONLY(
613			{
614				*size = OSSwapInt32( *size );
615			}
616		);
617#endif
618
619		return status;
620	}
621
622	IOReturn
623	Device::ReadQuadlet( io_object_t device, const FWAddress & addr, UInt32* val, Boolean failOnReset,
624		UInt32 generation )
625	{
626		if (!mIsOpen)
627			return kIOReturnNotOpen ;
628		if ( device != mDefaultDevice && device != 0 )
629			return kIOReturnBadArgument ;
630
631		ReadQuadParams	 			params 			= { addr, (mach_vm_address_t)val, 1, failOnReset, generation, device == 0 /*isAbs*/ } ;
632
633#ifndef __LP64__
634		ROSETTA_ONLY(
635			{
636				params.addr.nodeID = OSSwapInt16( params.addr.nodeID );
637				params.addr.addressHi = OSSwapInt16( params.addr.addressHi );
638				params.addr.addressLo = OSSwapInt32( params.addr.addressLo );
639				params.buf = (mach_vm_address_t)OSSwapInt64(params.buf);
640				params.size = OSSwapInt32( params.size);
641			//	params.failOnReset = params.failOnReset; // byte
642				params.generation = OSSwapInt32( params.generation);
643			//	params.isAbs = params.isAbs; // byte
644			}
645		);
646#endif
647
648		size_t outputStructSize = sizeof( *val ) ;
649		return IOConnectCallStructMethod(mConnection,
650										 kReadQuad,
651										 &params,sizeof(params),
652										 val,&outputStructSize);
653	}
654
655	IOReturn
656	Device::Write(
657		io_object_t				device,
658		const FWAddress &		addr,
659		const void*				buf,
660		UInt32* 				size,
661		Boolean					failOnReset,
662		UInt32					generation)
663	{
664		if (!mIsOpen)
665			return kIOReturnNotOpen ;
666		if ( device != mDefaultDevice && device != 0 )
667			return kIOReturnBadArgument ;
668
669		WriteParams		 			params 			= { addr, (mach_vm_address_t)buf, *size, failOnReset, generation, device == 0 /*isAbs*/ } ;
670
671#ifndef __LP64__
672		ROSETTA_ONLY(
673			{
674				params.addr.nodeID = OSSwapInt16( params.addr.nodeID );
675				params.addr.addressHi = OSSwapInt16( params.addr.addressHi );
676				params.addr.addressLo = OSSwapInt32( params.addr.addressLo );
677				params.buf = (mach_vm_address_t)OSSwapInt64(params.buf);
678				params.size = OSSwapInt32( params.size);
679			//	params.failOnReset = params.failOnReset; // byte
680				params.generation = OSSwapInt32( params.generation);
681			//	params.isAbs = params.isAbs; // byte
682			}
683		);
684#endif
685
686		size_t outputStructSize = sizeof( *size ) ;
687		IOReturn status =  IOConnectCallStructMethod(mConnection,
688													 kWrite,
689													 &params,sizeof(params),
690													 size,&outputStructSize);
691
692#ifndef __LP64__
693		ROSETTA_ONLY(
694			{
695				if ( status == kIOReturnSuccess )
696					*size = OSSwapInt32( *size );
697			}
698		);
699#endif
700
701		return status;
702	}
703
704	IOReturn
705	Device::WriteQuadlet(
706		io_object_t				device,
707		const FWAddress &		addr,
708		const UInt32			val,
709		Boolean 				failOnReset,
710		UInt32					generation)
711	{
712		if (!mIsOpen)
713			return kIOReturnNotOpen ;
714		if ( device != mDefaultDevice && device != 0 )
715			return kIOReturnBadArgument ;
716
717		WriteQuadParams 			params 			= { addr, val, failOnReset, generation, device == 0 } ;
718
719#ifndef __LP64__
720		ROSETTA_ONLY(
721			{
722				params.addr.nodeID = OSSwapInt16( params.addr.nodeID );
723				params.addr.addressHi = OSSwapInt16( params.addr.addressHi );
724				params.addr.addressLo = OSSwapInt32( params.addr.addressLo );
725			//	params.val = params.val; // data
726			//	params.failOnReset = params.failOnReset; // byte
727				params.generation = OSSwapInt32( params.generation);
728			//	params.isAbs = params.isAbs; // byte
729			}
730		);
731#endif
732
733		size_t outputStructSize = 0 ;
734		return IOConnectCallStructMethod(mConnection,
735										 kWriteQuad,
736										 &params,sizeof(params),
737										 NULL,&outputStructSize);
738	}
739
740	IOReturn
741	Device::CompareSwap(
742		io_object_t				device,
743		const FWAddress &		addr,
744		UInt32 					cmpVal,
745		UInt32 					newVal,
746		Boolean 				failOnReset,
747		UInt32					generation)
748	{
749		if (!mIsOpen)
750			return kIOReturnNotOpen ;
751		if ( device != mDefaultDevice && device != 0 )
752			return kIOReturnBadArgument ;
753
754		UInt32						result ;
755		CompareSwapParams			params ;
756
757		params.addr					= addr ;
758		*(UInt32*)&params.cmpVal	= cmpVal ;
759		*(UInt32*)&params.swapVal	= newVal ;
760		params.size					= 1 ;
761		params.failOnReset			= failOnReset ;
762		params.generation			= generation ;
763		params.isAbs				= device == 0 ;
764
765#ifndef __LP64__
766		ROSETTA_ONLY(
767			{
768				params.addr.nodeID = OSSwapInt16( params.addr.nodeID );
769				params.addr.addressHi = OSSwapInt16( params.addr.addressHi );
770				params.addr.addressLo = OSSwapInt32( params.addr.addressLo );
771			//	params.cmpVal = params.cmpVal;	// data
772			//	params.newVal = params.newVal;	// data
773				params.size = OSSwapInt32( params.size);
774			//	params.failOnReset = params.failOnReset; // byte
775				params.generation = OSSwapInt32( params.generation);
776			//	params.isAbs = params.isAbs; // byte
777			}
778		);
779#endif
780
781		size_t outputStructSize = sizeof(UInt32) ;
782		IOReturn error = IOConnectCallStructMethod(mConnection,
783												   kCompareSwap,
784												   &params,sizeof(params),
785												   &result,&outputStructSize);
786
787		// Make sure lock transaction succeeed by
788		// checking the expected vs actual old value!
789		if ( cmpVal != result)
790			error = kIOReturnCannotLock ;
791
792		return error;
793	}
794
795	IOReturn
796	Device::CompareSwap64(
797		io_object_t				device,
798		const FWAddress &		addr,
799		UInt32*					expectedVal,
800		UInt32*					newVal,
801		UInt32*					oldVal,
802		IOByteCount				size,
803		Boolean 				failOnReset,
804		UInt32					generation)
805	{
806		if (!mIsOpen)
807			return kIOReturnNotOpen ;
808		if ( device != mDefaultDevice && device != 0 )
809			return kIOReturnBadArgument ;
810
811		CompareSwapParams			params ;
812
813		// config params
814		params.addr				= addr ;
815		if ( size==4 )
816		{
817			*(UInt32*)&params.cmpVal	= expectedVal[0] ;
818			*(UInt32*)&params.swapVal	= newVal[0] ;
819		}
820		else
821		{
822			params.cmpVal			= *(UInt64*)expectedVal ;
823			params.swapVal			= *(UInt64*)newVal ;
824		}
825
826		params.size				= size >> 2 ;
827		params.failOnReset		= failOnReset ;
828		params.generation		= generation ;
829		params.isAbs			= device == 0 ;
830
831#ifndef __LP64__
832		ROSETTA_ONLY(
833			{
834				params.addr.nodeID = OSSwapInt16( params.addr.nodeID );
835				params.addr.addressHi = OSSwapInt16( params.addr.addressHi );
836				params.addr.addressLo = OSSwapInt32( params.addr.addressLo );
837			//	params.cmpVal = params.cmpVal;	// data
838			//	params.newVal = params.newVal;	// data
839				params.size = OSSwapInt32( params.size);
840			//	params.failOnReset = params.failOnReset; // byte
841				params.generation = OSSwapInt32( params.generation);
842			//	params.isAbs = params.isAbs; // byte
843			}
844		);
845#endif
846
847		UInt64			result ;
848
849		size_t outputStructSize = sizeof(UInt64) ;
850		IOReturn error = IOConnectCallStructMethod(mConnection,
851												   kCompareSwap,
852												   &params,sizeof(params),
853												   &result,&outputStructSize);
854
855		if (size==4)
856		{
857			oldVal[0] = *(UInt32*)&result ;
858			if ( oldVal[0] != expectedVal[0] )
859				error = kIOReturnCannotLock ;
860		}
861		else
862		{
863			*(UInt64*)oldVal = result ;
864			if ( *(UInt64*)expectedVal != result )
865				error = kIOReturnCannotLock ;
866		}
867
868		return error ;
869	}
870
871	#pragma mark -
872	#pragma mark --- command objects ----------
873
874	IOFireWireLibCommandRef
875	Device::CreateReadCommand(
876		io_object_t 		device,
877		const FWAddress&	addr,
878		void* 				buf,
879		UInt32 				size,
880		IOFireWireLibCommandCallback callback,
881		Boolean 			failOnReset,
882		UInt32 				generation,
883		void*				inRefCon,
884		REFIID				iid)
885	{
886		IOFireWireLibCommandRef	result = 0 ;
887
888		IUnknownVTbl** iUnknown = ReadCmd::Alloc(*this, device, addr, buf, size, callback, failOnReset, generation, inRefCon) ;
889		if (iUnknown)
890		{
891			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
892			(*iUnknown)->Release(iUnknown) ;
893		}
894
895		return result ;
896	}
897
898	IOFireWireLibCommandRef
899	Device::CreateReadQuadletCommand(
900		io_object_t 		device,
901		const FWAddress & 	addr,
902		UInt32	 			quads[],
903		UInt32				numQuads,
904		IOFireWireLibCommandCallback callback,
905		Boolean 			failOnReset,
906		UInt32				generation,
907		void*				inRefCon,
908		REFIID				iid)
909	{
910		IOFireWireLibCommandRef	result = 0 ;
911
912		// no longer supported
913
914		return result ;
915	}
916
917	IOFireWireLibCommandRef
918	Device::CreateWriteCommand(
919		io_object_t 		device,
920		const FWAddress & 	addr,
921		void*		 		buf,
922		UInt32 				size,
923		IOFireWireLibCommandCallback callback,
924		Boolean 			failOnReset,
925		UInt32 				generation,
926		void*				inRefCon,
927		REFIID				iid)
928	{
929		IOFireWireLibCommandRef	result = 0 ;
930
931		IUnknownVTbl** iUnknown = WriteCmd::Alloc(*this, device, addr, buf, size, callback, failOnReset, generation, inRefCon) ;
932		if (iUnknown)
933		{
934			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
935			(*iUnknown)->Release(iUnknown) ;
936		}
937
938		return result ;
939
940	}
941
942	IOFireWireLibCommandRef
943	Device::CreateWriteQuadletCommand(
944		io_object_t 		device,
945		const FWAddress & 	addr,
946		UInt32		 		quads[],
947		UInt32				numQuads,
948		IOFireWireLibCommandCallback callback,
949		Boolean 			failOnReset,
950		UInt32 				generation,
951		void*				inRefCon,
952		REFIID				iid)
953	{
954		IOFireWireLibCommandRef	result = 0 ;
955
956		// no longer supported
957
958		return result ;
959	}
960
961	IOFireWireLibCommandRef
962	Device::CreateCompareSwapCommand( io_object_t device, const FWAddress & addr, UInt64 cmpVal, UInt64 newVal,
963		unsigned int quads, IOFireWireLibCommandCallback callback, Boolean failOnReset, UInt32 generation,
964		void* inRefCon, REFIID iid)
965	{
966		IOFireWireLibCommandRef	result = 0 ;
967
968		IUnknownVTbl** iUnknown = CompareSwapCmd::Alloc( *this, device, addr, cmpVal, newVal, quads, callback, failOnReset, generation, inRefCon) ;
969		if (iUnknown)
970		{
971			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
972			(*iUnknown)->Release(iUnknown) ;
973		}
974
975		return result ;
976	}
977
978	#pragma mark -
979	IOReturn
980	Device::BusReset()
981	{
982		if (!mIsOpen)
983			return kIOReturnNotOpen ;
984
985		uint32_t outputCnt = 0;
986		return IOConnectCallScalarMethod(mConnection,kBusReset,NULL,0,NULL,&outputCnt);
987	}
988
989	IOReturn
990	Device::GetCycleTime(
991		UInt32*		outCycleTime)
992	{
993		uint32_t outputCnt = 2;
994		uint64_t outputVal[2];
995		outputVal[0] = 0;
996		outputVal[1] = 0;
997		IOReturn result = IOConnectCallScalarMethod(mConnection,kCycleTime,NULL,0,outputVal,&outputCnt);
998		*outCycleTime = outputVal[0] & 0xFFFFFFFF;
999		return result;
1000	}
1001
1002	IOReturn
1003	Device::GetCycleTimeAndUpTime(
1004		UInt32*		outCycleTime,
1005		UInt64*		outUpTime )
1006	{
1007		uint32_t outputCnt = 2;
1008		uint64_t outputVal[2];
1009		outputVal[0] = 0;
1010		outputVal[1] = 0;
1011		IOReturn result = IOConnectCallScalarMethod(mConnection,kCycleTime,NULL,0,outputVal,&outputCnt);
1012		*outCycleTime = outputVal[0] & 0xFFFFFFFF;
1013		*outUpTime = outputVal[1];
1014		return result;
1015	}
1016
1017	IOReturn
1018	Device::GetBusCycleTime(
1019		UInt32*		outBusTime,
1020		UInt32*		outCycleTime)
1021	{
1022		uint32_t outputCnt = 2;
1023		uint64_t outputVal[2];
1024		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetBusCycleTime,NULL,0,outputVal,&outputCnt);
1025		*outBusTime = outputVal[0] & 0xFFFFFFFF;
1026		*outCycleTime = outputVal[1] & 0xFFFFFFFF;
1027		return result;
1028	}
1029
1030	IOReturn
1031	Device::GetGenerationAndNodeID(
1032		UInt32*		outGeneration,
1033		UInt16*		outNodeID)
1034	{
1035		uint32_t outputCnt = 2;
1036		uint64_t outputVal[2];
1037		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetGenerationAndNodeID,NULL,0,outputVal,&outputCnt);
1038		*outGeneration = outputVal[0] & 0xFFFFFFFF;
1039		*outNodeID = outputVal[1] & 0xFFFF;
1040		return result;
1041	}
1042
1043	IOReturn
1044	Device::GetLocalNodeID(
1045		UInt16*		outLocalNodeID)
1046	{
1047		uint32_t outputCnt = 1;
1048		uint64_t outputVal = 0;
1049		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetLocalNodeID,NULL,0,&outputVal,&outputCnt);
1050		*outLocalNodeID = outputVal & 0xFFFF;
1051		return result;
1052	}
1053
1054	IOReturn
1055	Device::GetResetTime(
1056		AbsoluteTime*			resetTime)
1057	{
1058
1059		size_t outputStructSize = sizeof(*resetTime) ;
1060		IOReturn status = IOConnectCallStructMethod(mConnection, kGetResetTime,
1061													NULL,0,
1062													resetTime,&outputStructSize);
1063
1064#ifndef __LP64__
1065		ROSETTA_ONLY(
1066			{
1067				(*resetTime).hi = OSSwapInt32( (*resetTime).hi );
1068				(*resetTime).lo = OSSwapInt32( (*resetTime).lo );
1069			}
1070		);
1071#endif
1072
1073		return status;
1074	}
1075
1076	#pragma mark -
1077	IOFireWireLibLocalUnitDirectoryRef
1078	Device::CreateLocalUnitDirectory( REFIID iid )
1079	{
1080		IOFireWireLibLocalUnitDirectoryRef	result = 0 ;
1081
1082		if (mIsOpen)
1083		{
1084				// we allocate a user space pseudo address space with the reference we
1085				// got from the kernel
1086			IUnknownVTbl**	iUnknown = reinterpret_cast<IUnknownVTbl**>(LocalUnitDirectory::Alloc(*this)) ;
1087
1088				// we got a new iUnknown from the object. Query it for the interface
1089				// requested in iid...
1090			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1091
1092				// we got the interface we wanted (or at least another ref to iUnknown),
1093				// so we call iUnknown.Release()
1094			(*iUnknown)->Release(iUnknown) ;
1095		}
1096
1097		return result ;
1098	}
1099
1100	IOFireWireLibConfigDirectoryRef
1101	Device::GetConfigDirectory(
1102		REFIID				iid)
1103	{
1104		IOFireWireLibConfigDirectoryRef	result = 0 ;
1105
1106		// we allocate a user space config directory space with the reference we
1107		// got from the kernel
1108		IUnknownVTbl**	iUnknown	= reinterpret_cast<IUnknownVTbl**>(ConfigDirectoryCOM::Alloc(*this)) ;
1109
1110		// we got a new iUnknown from the object. Query it for the interface
1111		// requested in iid...
1112		if (iUnknown)
1113		{
1114			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1115
1116			// we got the interface we wanted (or at least another ref to iUnknown),
1117			// so we call iUnknown.Release()
1118			(*iUnknown)->Release(iUnknown) ;
1119		}
1120
1121		return result ;
1122	}
1123
1124	IOFireWireLibConfigDirectoryRef
1125	Device::CreateConfigDirectoryWithIOObject(
1126		io_object_t			inObject,
1127		REFIID				iid)
1128	{
1129		IOFireWireLibConfigDirectoryRef	result = 0 ;
1130
1131		// we allocate a user space pseudo address space with the reference we
1132		// got from the kernel
1133		IUnknownVTbl**	iUnknown	= reinterpret_cast<IUnknownVTbl**>(ConfigDirectoryCOM::Alloc(*this, (UserObjectHandle)inObject)) ;
1134
1135		// we got a new iUnknown from the object. Query it for the interface
1136		// requested in iid...
1137		(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1138
1139		// we got the interface we wanted (or at least another ref to iUnknown),
1140		// so we call iUnknown.Release()
1141		(*iUnknown)->Release(iUnknown) ;
1142
1143		return result ;
1144	}
1145
1146	IOFireWireLibPhysicalAddressSpaceRef
1147	Device::CreatePhysicalAddressSpace(
1148		UInt32						inSize,
1149		void*						inBackingStore,
1150		UInt32						inFlags,
1151		REFIID						iid)	// flags unused
1152	{
1153		IOFireWireLibPhysicalAddressSpaceRef	result = 0 ;
1154
1155		if ( mIsOpen )
1156		{
1157			UserObjectHandle	output ;
1158			uint32_t outputCnt = 1;
1159			uint64_t outputVal = 0;
1160			const uint64_t inputs[3] = {inSize, (const uint64_t)inBackingStore, inFlags};
1161			if ( kIOReturnSuccess  == IOConnectCallScalarMethod(mConnection,kPhysicalAddrSpace_Allocate,inputs,3,&outputVal,&outputCnt) )
1162			{
1163				output = (UserObjectHandle) outputVal;
1164				if (output)
1165				{
1166					// we allocate a user space pseudo address space with the reference we
1167					// got from the kernel
1168					IUnknownVTbl**	iUnknown = PhysicalAddressSpace::Alloc(*this, output, inSize, inBackingStore, inFlags) ;
1169
1170					// we got a new iUnknown from the object. Query it for the interface
1171					// requested in iid...
1172					if (iUnknown)
1173					{
1174						(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1175
1176						// we got the interface we wanted (or at least another ref to iUnknown),
1177						// so we call iUnknown.Release()
1178						(*iUnknown)->Release(iUnknown) ;
1179					}
1180				}
1181			}
1182
1183		}
1184
1185		return result ;
1186	}
1187
1188	IOFireWireLibPseudoAddressSpaceRef
1189	Device::CreateAddressSpace(
1190		UInt32						inSize,
1191		void*						inRefCon,
1192		UInt32						inQueueBufferSize,
1193		void*						inBackingStore,
1194		UInt32						inFlags,
1195		REFIID						iid,
1196		Boolean						isInitialUnits,
1197		UInt32						inAddressLo )
1198	{
1199		if (!mIsOpen)
1200		{
1201			DebugLog( "Device::CreatePseudoAddressSpace: no connection or device is not open\n") ;
1202			return 0 ;
1203		}
1204
1205		if ( !inBackingStore && ( (inFlags & kFWAddressSpaceAutoWriteReply != 0) || (inFlags & kFWAddressSpaceAutoReadReply != 0) || (inFlags & kFWAddressSpaceAutoCopyOnWrite != 0) ) )
1206		{
1207			DebugLog( "Can't create address space with nil backing store!\n" ) ;
1208			return 0 ;
1209		}
1210
1211		IOFireWireLibPseudoAddressSpaceRef				result = 0 ;
1212
1213		void*	queueBuffer = nil ;
1214		if ( inQueueBufferSize > 0 )
1215			queueBuffer	= new Byte[inQueueBufferSize] ;
1216
1217		AddressSpaceCreateParams	params ;
1218		params.size 			= inSize ;
1219		params.queueBuffer 		= (mach_vm_address_t) queueBuffer ;
1220		params.queueSize		= (UInt32) inQueueBufferSize ;
1221		params.backingStore 	= (mach_vm_address_t) inBackingStore ;
1222		params.refCon			= (mach_vm_address_t)this ;  //zzz is this even used?
1223		params.flags			= inFlags ;
1224		params.isInitialUnits	= isInitialUnits ;
1225		params.addressLo		= inAddressLo ;
1226
1227#ifndef __LP64__
1228		ROSETTA_ONLY(
1229			{
1230				params.size = OSSwapInt64( params.size );
1231				params.queueBuffer = (mach_vm_address_t)OSSwapInt64( (UInt64)params.queueBuffer );
1232				params.queueSize = OSSwapInt64( params.queueSize );
1233				params.backingStore = (mach_vm_address_t)OSSwapInt64( (UInt64)params.backingStore );
1234				params.flags = OSSwapInt32( params.flags );
1235				// params.isInitialUnits = params.isInitialUnits // byte
1236				params.addressLo = OSSwapInt32( params.addressLo );
1237			}
1238		);
1239#endif
1240
1241		UserObjectHandle	addrSpaceRef ;
1242
1243		size_t outputStructSize = sizeof(addrSpaceRef) ;
1244		IOReturn err = IOConnectCallStructMethod(mConnection, kPseudoAddrSpace_Allocate,
1245												 &params,sizeof(params),
1246												 & addrSpaceRef,&outputStructSize);
1247
1248#ifndef __LP64__
1249		ROSETTA_ONLY(
1250			{
1251				addrSpaceRef = (UserObjectHandle)OSSwapInt32( (UInt32)addrSpaceRef );
1252			}
1253		);
1254#endif
1255
1256		if ( !err )
1257		{
1258			// we allocate a user space pseudo address space with the reference we
1259			// got from the kernel
1260			IUnknownVTbl**	iUnknown = PseudoAddressSpace::Alloc(*this, addrSpaceRef, queueBuffer, inQueueBufferSize, inBackingStore, inRefCon) ;
1261
1262			// we got a new iUnknown from the object. Query it for the interface
1263			// requested in iid...
1264			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1265
1266			// we got the interface we wanted (or at least another ref to iUnknown),
1267			// so we call iUnknown.Release()
1268			(*iUnknown)->Release(iUnknown) ;
1269
1270		}
1271
1272		return result ;
1273	}
1274
1275
1276	#pragma mark -
1277	IOReturn
1278	Device::FireBugMsg(
1279		const char *	inMsg)
1280	{
1281		IOReturn result = kIOReturnSuccess ;
1282		UInt32 size = strlen(inMsg) + 1 ;
1283
1284		if (!mIsOpen)
1285			result = kIOReturnNotOpen ;
1286
1287		{
1288			UInt32		generation = 0 ;
1289			UInt16		nodeID ;
1290
1291			if ( kIOReturnSuccess == result )
1292				result = GetGenerationAndNodeID( & generation, & nodeID ) ;
1293
1294			if (kIOReturnSuccess == result)
1295			{
1296				result = Write(0, FWAddress(0x4242, 0x42424242, 0x4242), inMsg, & size, true, generation) ;
1297
1298				// firebug never responds, so just change a timeout err into success
1299				if ( kIOReturnTimeout == result )
1300					result = kIOReturnSuccess ;
1301			}
1302		}
1303
1304		return result ;
1305	}
1306
1307	IOReturn
1308	Device::FireLog(
1309		const char *	format,
1310		va_list			ap )
1311	{
1312		char		msg[128] ;
1313		vsnprintf( msg, 127, format, ap ) ;
1314
1315		size_t outputStructSize = 0 ;
1316		IOReturn err = IOConnectCallStructMethod(GetUserClientConnection(),
1317												 kFireLog,
1318												 msg,strlen( msg )+1,
1319												 NULL,&outputStructSize);
1320		return err ;
1321	}
1322
1323	IOReturn
1324	Device::FireLog( const char* format, ... )
1325	{
1326		IOReturn error = kIOReturnSuccess;
1327
1328		va_list		ap ;
1329		va_start( ap, format ) ;
1330
1331		error = FireLog( format, ap ) ;
1332
1333		va_end( ap ) ;
1334
1335		return error ;
1336	}
1337
1338	IOReturn
1339	Device::CreateCFStringWithOSStringRef(
1340		UserObjectHandle	inStringRef,
1341		UInt32				inStringLen,
1342		CFStringRef*&		text)
1343	{
1344		char*				textBuffer = new char[inStringLen+1] ;
1345		//io_connect_t		connection = GetUserClientConnection() ;
1346		UInt32				stringSize ;
1347
1348		if (!textBuffer)
1349			return kIOReturnNoMemory ;
1350
1351		uint32_t outputCnt = 1;
1352		uint64_t outputVal = 0;
1353		const uint64_t inputs[3] = {(uint64_t)inStringRef, inStringLen, (uint64_t)textBuffer};
1354		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetOSStringData,inputs,3,&outputVal,&outputCnt);
1355		stringSize = outputVal & 0xFFFFFFFF;
1356
1357		textBuffer[inStringLen] = 0 ;
1358
1359		if (text && (kIOReturnSuccess == result))
1360			*text = CFStringCreateWithCString(kCFAllocatorDefault, textBuffer, kCFStringEncodingASCII) ;
1361
1362		delete[] textBuffer ;
1363
1364		return result ;
1365	}
1366
1367	IOReturn
1368	Device::CreateCFDataWithOSDataRef(
1369		UserObjectHandle		inDataRef,
1370		IOByteCount			inDataSize,
1371		CFDataRef*&			data)
1372	{
1373		UInt8*			buffer = new UInt8[inDataSize] ;
1374		IOByteCount		dataSize ;
1375
1376		if (!buffer)
1377			return kIOReturnNoMemory ;
1378
1379		if (!mConnection)
1380			return kIOReturnError ;
1381
1382		uint32_t outputCnt = 1;
1383		uint64_t outputVal = 0;
1384		const uint64_t inputs[3] = {(uint64_t)inDataRef, inDataSize, (uint64_t)buffer};
1385		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetOSDataData,inputs,3,&outputVal,&outputCnt);
1386		dataSize = outputVal & 0xFFFFFFFF;
1387
1388		if (data && (kIOReturnSuccess == result))
1389			*data = CFDataCreate(kCFAllocatorDefault, buffer, inDataSize) ;
1390
1391		if (!data)
1392			result = kIOReturnNoMemory ;
1393
1394		delete[] buffer ;
1395
1396		return result ;
1397	}
1398
1399	//
1400	// --- isoch related
1401	//
1402	IOReturn
1403	Device::AddIsochCallbackDispatcherToRunLoopForMode( // v3+
1404		CFRunLoopRef			runLoop,
1405		CFStringRef 			runLoopMode )
1406	{
1407		IOReturn result = kIOReturnSuccess ;
1408
1409		if ( !runLoop || !runLoopMode )
1410		{
1411			DebugLog("Device::AddIsochCallbackDispatcherToRunLoopForMode: runLoop==0 || runLoopMode==0\n") ;
1412			return kIOReturnBadArgument ;
1413		}
1414
1415		if (!IsochAsyncPortsExist())
1416			result = CreateIsochAsyncPorts() ;
1417
1418		if ( kIOReturnSuccess == result )
1419		{
1420			CFRetain(runLoop) ;
1421			CFRetain(runLoopMode) ;
1422
1423			mIsochRunLoop 			= runLoop ;
1424			mIsochRunLoopSource		= CFMachPortCreateRunLoopSource( kCFAllocatorDefault,
1425																	GetIsochAsyncCFPort() ,
1426																	0) ;
1427			mIsochRunLoopMode		= runLoopMode ;
1428
1429			if (!mIsochRunLoopSource)
1430			{
1431				CFRelease( mIsochRunLoop ) ;
1432				CFRelease( mIsochRunLoopMode ) ;
1433				result = kIOReturnNoMemory ;
1434			}
1435
1436		#if 1
1437
1438			if ( kIOReturnSuccess == result )
1439			{
1440				if( !CFRunLoopSourceIsValid(mIsochRunLoopSource) )
1441				{
1442					CFRelease( mIsochRunLoopSource );
1443
1444					CFMachPortInvalidate( mIsochAsyncCFPort );
1445					CFRelease( mIsochAsyncCFPort );
1446
1447					{
1448						Boolean shouldFreeInfo;
1449						CFMachPortContext cfPortContext	= {1, this, NULL, NULL, NULL};
1450						mIsochAsyncCFPort = CFMachPortCreateWithPort( kCFAllocatorDefault,
1451																	mIsochAsyncPort,
1452																	(CFMachPortCallBack) IODispatchCalloutFromMessage,
1453																	& cfPortContext,
1454																	& shouldFreeInfo);
1455						if (!mIsochAsyncCFPort)
1456							result = kIOReturnNoMemory ;
1457
1458					}
1459
1460					{
1461						mIsochRunLoopSource	 = CFMachPortCreateRunLoopSource( kCFAllocatorDefault,
1462																	GetIsochAsyncCFPort() ,
1463																	0) ;
1464						if (!mIsochRunLoopSource)
1465						{
1466							CFRelease( mIsochRunLoop ) ;
1467							CFRelease( mIsochRunLoopMode ) ;
1468							result = kIOReturnNoMemory ;
1469						}
1470					}
1471
1472					if( !CFRunLoopSourceIsValid(mIsochRunLoopSource) )
1473					{
1474						result = kIOReturnNoResources;
1475					}
1476				}
1477			}
1478
1479		#endif
1480
1481			if ( kIOReturnSuccess == result )
1482				::CFRunLoopAddSource( mIsochRunLoop, mIsochRunLoopSource, mIsochRunLoopMode ) ;
1483		}
1484
1485		return result ;
1486	}
1487
1488	void
1489	Device::RemoveIsochCallbackDispatcherFromRunLoop()
1490	{
1491		RemoveDispatcherFromRunLoop( mIsochRunLoop, mIsochRunLoopSource, mIsochRunLoopMode ) ;
1492
1493		CFRelease(mIsochRunLoop) ;
1494		mIsochRunLoop = 0 ;
1495
1496		CFRelease( mIsochRunLoopSource ) ;
1497		mIsochRunLoopSource = 0 ;
1498
1499		CFRelease( mIsochRunLoopMode );
1500		mIsochRunLoopMode = 0 ;
1501	}
1502
1503	IOFireWireLibRemoteIsochPortRef
1504	Device::CreateRemoteIsochPort(
1505		Boolean					inTalking,
1506		REFIID 					iid)
1507	{
1508		IOFireWireLibRemoteIsochPortRef		result = 0 ;
1509
1510		IUnknownVTbl** iUnknown = RemoteIsochPortCOM::Alloc(*this, inTalking) ;
1511		if (iUnknown)
1512		{
1513			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1514			(*iUnknown)->Release(iUnknown) ;
1515		}
1516
1517		return result ;
1518	}
1519
1520	IOFireWireLibLocalIsochPortRef
1521	Device::CreateLocalIsochPortWithOptions(
1522		Boolean					talking,
1523		DCLCommand*				dclProgram,
1524		UInt32					startEvent,
1525		UInt32					startState,
1526		UInt32					startMask,
1527		IOVirtualRange			dclProgramRanges[],			// optional optimization parameters
1528		UInt32					dclProgramRangeCount,
1529		IOVirtualRange			bufferRanges[],
1530		UInt32					bufferRangeCount,
1531		IOFWIsochPortOptions	options,
1532		REFIID 					iid)
1533	{
1534		IOFireWireLibLocalIsochPortRef	result = 0 ;
1535
1536		IUnknownVTbl** iUnknown = LocalIsochPortCOM::Alloc(*this, talking, dclProgram, startEvent, startState,
1537															startMask, dclProgramRanges, dclProgramRangeCount, bufferRanges, bufferRangeCount, options ) ;
1538		if (iUnknown)
1539		{
1540			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1541			(*iUnknown)->Release(iUnknown) ;
1542		}
1543
1544		return result ;
1545	}
1546
1547	IOReturn
1548	Device::GetBusGeneration( UInt32* outGeneration )
1549	{
1550		uint32_t outputCnt = 1;
1551		uint64_t outputVal = 0;
1552		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetBusGeneration,NULL,0,&outputVal,&outputCnt);
1553		*outGeneration = outputVal & 0xFFFFFFFF;
1554		return result;
1555	}
1556
1557	IOReturn
1558	Device::GetLocalNodeIDWithGeneration( UInt32 checkGeneration, UInt16* outLocalNodeID )
1559	{
1560		uint32_t outputCnt = 1;
1561		uint64_t outputVal = 0;
1562		const uint64_t inputs[1]={(const uint64_t)checkGeneration};
1563
1564		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetLocalNodeIDWithGeneration,inputs,1,&outputVal,&outputCnt);
1565		*outLocalNodeID = outputVal & 0xFFFF;
1566		return result;
1567	}
1568
1569	IOReturn
1570	Device::GetRemoteNodeID( UInt32 checkGeneration, UInt16* outRemoteNodeID )
1571	{
1572		uint32_t outputCnt = 1;
1573		uint64_t outputVal = 0;
1574		const uint64_t inputs[1]={(const uint64_t)checkGeneration};
1575
1576		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetRemoteNodeID,inputs,1,&outputVal,&outputCnt);
1577		*outRemoteNodeID = outputVal & 0xFFFF;
1578		return result;
1579	}
1580
1581	IOReturn
1582	Device::GetSpeedToNode( UInt32 checkGeneration, IOFWSpeed* outSpeed)
1583	{
1584		uint32_t outputCnt = 1;
1585		uint64_t outputVal = 0;
1586		const uint64_t inputs[1]={(const uint64_t)checkGeneration};
1587
1588		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetSpeedToNode,inputs,1,&outputVal,&outputCnt);
1589		*outSpeed = (IOFWSpeed)(outputVal & 0xFFFFFFFF);
1590		return result;
1591	}
1592
1593	IOReturn
1594	Device::GetSpeedBetweenNodes( UInt32 checkGeneration, UInt16 srcNodeID, UInt16 destNodeID, IOFWSpeed* outSpeed)
1595	{
1596		uint32_t outputCnt = 1;
1597		uint64_t outputVal = 0;
1598		const uint64_t inputs[3] = {checkGeneration, srcNodeID, destNodeID};
1599		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetSpeedBetweenNodes,inputs,3,&outputVal,&outputCnt);
1600		*outSpeed = (IOFWSpeed)(outputVal & 0xFFFFFFFF);
1601		return result;
1602	}
1603
1604	IOReturn
1605	Device::GetIRMNodeID( UInt32 checkGeneration, UInt16* outIRMNodeID )
1606	{
1607		uint32_t outputCnt = 1;
1608		uint64_t outputVal = 0;
1609		const uint64_t inputs[1]={(const uint64_t)checkGeneration};
1610
1611		IOReturn result = IOConnectCallScalarMethod(mConnection,kGetIRMNodeID,inputs,1,&outputVal,&outputCnt);
1612		*outIRMNodeID = outputVal & 0xFFFF;
1613		return result;
1614	}
1615
1616	IOReturn
1617	Device::ClipMaxRec2K( Boolean clipMaxRec )
1618	{
1619		//fprintf(stderr, "Device::ClipMaxRec2K\n") ;
1620
1621		uint32_t outputCnt = 0;
1622		const uint64_t inputs[1]={(const uint64_t)clipMaxRec};
1623		IOReturn result = IOConnectCallScalarMethod(mConnection,kClipMaxRec2K,inputs,1,NULL,&outputCnt);
1624		return result;
1625	}
1626
1627	IOFireWireSessionRef
1628	Device::GetSessionRef()
1629	{
1630		uint32_t outputCnt = 1;
1631		uint64_t outputVal = 0;
1632		IOReturn error = kIOReturnSuccess;
1633		error = IOConnectCallScalarMethod(mConnection,kGetSessionRef,NULL,0,&outputVal,&outputCnt);
1634		DebugLogCond( error, "Device::GetSessionRef error=%x\n", error ) ;
1635		return (IOFireWireSessionRef) outputVal;
1636	}
1637
1638	IOFireWireLibVectorCommandRef
1639	Device::CreateVectorCommand(
1640		IOFireWireLibCommandCallback callback,
1641		void* inRefCon,
1642		REFIID iid )
1643	{
1644		IOFireWireLibVectorCommandRef	result = 0;
1645
1646		IUnknownVTbl** iUnknown = VectorCommand::Alloc( *this, callback, inRefCon );
1647		if( iUnknown )
1648		{
1649			(*iUnknown)->QueryInterface( iUnknown, iid, (void**)&result );
1650			(*iUnknown)->Release( iUnknown );
1651		}
1652
1653		return result;
1654	}
1655
1656	IOFireWireLibCommandRef
1657	Device::CreatePHYCommand(
1658		UInt32							data1,
1659		UInt32							data2,
1660		IOFireWireLibCommandCallback	callback,
1661		Boolean							failOnReset,
1662		UInt32							generation,
1663		void*							inRefCon,
1664		REFIID							iid )
1665	{
1666		IOFireWireLibCommandRef	result = 0;
1667
1668		IUnknownVTbl** iUnknown = PHYCmd::Alloc( *this, data1, data2, callback, failOnReset, generation, inRefCon );
1669		if( iUnknown )
1670		{
1671			(*iUnknown)->QueryInterface( iUnknown, iid, (void**)&result );
1672			(*iUnknown)->Release( iUnknown );
1673		}
1674
1675		return result;
1676	}
1677
1678	IOFireWireLibPHYPacketListenerRef
1679	Device::CreatePHYPacketListener(
1680		UInt32	queueCount,
1681		REFIID iid )
1682	{
1683		IOFireWireLibPHYPacketListenerRef	result = 0;
1684
1685		IUnknownVTbl** iUnknown = PHYPacketListener::Alloc( *this, queueCount );
1686		if( iUnknown )
1687		{
1688			(*iUnknown)->QueryInterface( iUnknown, iid, (void**)&result );
1689			(*iUnknown)->Release( iUnknown );
1690		}
1691
1692		return result;
1693	}
1694
1695	IOReturn Device::AllocateIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation)
1696	{
1697		uint32_t outputCnt = 0;
1698		const uint64_t inputs[2]={bandwidthUnits,generation};
1699		IOReturn result = IOConnectCallScalarMethod(mConnection,kAllocateIRMBandwidth,inputs,2,NULL,&outputCnt);
1700		return result;
1701	}
1702
1703	IOReturn Device::ReleaseIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation)
1704	{
1705		uint32_t outputCnt = 0;
1706		const uint64_t inputs[2]={bandwidthUnits,generation};
1707		IOReturn result = IOConnectCallScalarMethod(mConnection,kReleaseIRMBandwidth,inputs,2,NULL,&outputCnt);
1708		return result;
1709	}
1710
1711	IOReturn Device::AllocateIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation)
1712	{
1713		uint32_t outputCnt = 0;
1714		const uint64_t inputs[2]={isochChannel,generation};
1715		IOReturn result = IOConnectCallScalarMethod(mConnection,kAllocateIRMChannel,inputs,2,NULL,&outputCnt);
1716		return result;
1717	}
1718
1719	IOReturn Device::ReleaseIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation)
1720	{
1721		uint32_t outputCnt = 0;
1722		const uint64_t inputs[2]={isochChannel,generation};
1723		IOReturn result = IOConnectCallScalarMethod(mConnection,kReleaseIRMChannel,inputs,2,NULL,&outputCnt);
1724		return result;
1725	}
1726
1727	IOFireWireLibIRMAllocationRef Device::CreateIRMAllocation(Boolean releaseIRMResourcesOnFree,
1728															  IOFireWireLibIRMAllocationLostNotificationProc callback,
1729															  void *pLostNotificationProcRefCon,
1730															  REFIID iid)
1731	{
1732		if (!mIsOpen)
1733		{
1734			DebugLog( "Device::CreateIRMAllocation: no connection or device is not open\n") ;
1735			return 0 ;
1736		}
1737
1738		IOFireWireLibIRMAllocationRef returnInterface = 0 ;
1739		IOReturn result;
1740		const uint64_t inputs[1] = {releaseIRMResourcesOnFree};
1741		uint32_t outputCnt = 1;
1742		uint64_t outputVal = 0;
1743		UserObjectHandle userObjectRef ;
1744
1745		result = IOConnectCallScalarMethod(mConnection,
1746										   kIRMAllocation_Allocate,
1747										   inputs,1,
1748										   &outputVal,&outputCnt);
1749
1750		if (result == kIOReturnSuccess)
1751		{
1752			userObjectRef = (UserObjectHandle) outputVal;
1753
1754			IUnknownVTbl**	iUnknown = IRMAllocationCOM::Alloc(*this, userObjectRef, (void*)callback, pLostNotificationProcRefCon) ;
1755
1756			// we got a new iUnknown from the object. Query it for the interface
1757			// requested in iid...
1758			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & returnInterface) ;
1759
1760			// we got the interface we wanted (or at least another ref to iUnknown),
1761			// so we call iUnknown.Release()
1762			(*iUnknown)->Release(iUnknown) ;
1763		}
1764
1765		return returnInterface;
1766	}
1767
1768	IOFWAsyncStreamListenerInterfaceRef Device::CreateAsyncStreamListener( UInt32							channel,
1769  																		   IOFWAsyncStreamListenerHandler	callback,
1770																		   void *							inRefCon,
1771																		   UInt32							inQueueBufferSize,
1772																		   REFIID							iid )
1773	{
1774		if (!mIsOpen)
1775		{
1776			DebugLog( "Device::CreateAsyncStreamListener: no connection or device is not open\n") ;
1777			return 0 ;
1778		}
1779
1780		IOFWAsyncStreamListenerInterfaceRef		result = 0 ;
1781
1782		void*	queueBuffer = nil ;
1783		if ( inQueueBufferSize > 0 )
1784			queueBuffer	= new Byte[inQueueBufferSize] ;
1785
1786		FWUserAsyncStreamListenerCreateParams	params ;
1787
1788		params.channel			= channel;
1789		params.queueBuffer 		= (mach_vm_address_t) queueBuffer ;
1790		params.queueSize		= (UInt32) inQueueBufferSize ;
1791		params.flags			= 0 ;
1792		params.callback			= (mach_vm_address_t)callback;
1793		params.refCon			= (mach_vm_address_t)this ;
1794
1795#ifndef __LP64__
1796		ROSETTA_ONLY(
1797			{
1798				params.channel	   = OSSwapInt32( params.channel );
1799				params.queueBuffer = (mach_vm_address_t)OSSwapInt32( (UInt32)params.queueBuffer );
1800				params.queueSize = OSSwapInt32( params.queueSize );
1801				params.flags = OSSwapInt32( params.flags );
1802			}
1803		);
1804#endif
1805
1806		UserObjectHandle	asyncStreamListenerRef ;
1807
1808		size_t outputStructSize = sizeof(asyncStreamListenerRef) ;
1809		IOReturn err = IOConnectCallStructMethod(mConnection,
1810												 kAsyncStreamListener_Allocate,
1811												 &params,sizeof(params),
1812												 &asyncStreamListenerRef,&outputStructSize);
1813
1814		//IOByteCount			size	= sizeof(asyncStreamListenerRef) ;
1815		// call the routine which creates a pseudo address space in the kernel.
1816		//IOReturn err = ::IOConnectMethodStructureIStructureO( mConnection, kAsyncStreamListener_Allocate,
1817		//									sizeof(params), & size, & params, & asyncStreamListenerRef ) ;
1818
1819#ifndef __LP64__
1820		ROSETTA_ONLY(
1821			{
1822				asyncStreamListenerRef = (UserObjectHandle)OSSwapInt32( (UInt32)asyncStreamListenerRef );
1823			}
1824		);
1825#endif
1826
1827		if ( !err )
1828		{
1829			// we allocate a async stream listener with the reference we
1830			// got from the kernel
1831			IUnknownVTbl**	iUnknown = AsyncStreamListenerCOM::Alloc(*this, asyncStreamListenerRef, queueBuffer, inQueueBufferSize, (void*)callback, inRefCon) ;
1832
1833			// we got a new iUnknown from the object. Query it for the interface
1834			// requested in iid...
1835			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
1836
1837			// we got the interface we wanted (or at least another ref to iUnknown),
1838			// so we call iUnknown.Release()
1839			(*iUnknown)->Release(iUnknown) ;
1840
1841		}
1842
1843		return result ;
1844	}
1845
1846	IOFireWireLibCommandRef	Device::CreateAsyncStreamCommand(	UInt32							channel,
1847																UInt32							sync,
1848																UInt32							tag,
1849																void*							buf,
1850																UInt32							size,
1851																IOFireWireLibCommandCallback	callback,
1852																Boolean							failOnReset,
1853																UInt32							generation,
1854																void*							inRefCon,
1855																REFIID							iid)
1856	{
1857		IOFireWireLibCommandRef	result = 0;
1858
1859		IUnknownVTbl** iUnknown = AsyncStreamCmd::Alloc( *this, channel, sync, tag, buf, size, callback, failOnReset, generation, inRefCon );
1860		if( iUnknown )
1861		{
1862			(*iUnknown)->QueryInterface( iUnknown, iid, (void**)&result );
1863			(*iUnknown)->Release( iUnknown );
1864		}
1865
1866		return result;
1867	}
1868
1869
1870#pragma mark -
1871	const IOFireWireDeviceInterface DeviceCOM::sInterface =
1872	{
1873		INTERFACEIMP_INTERFACE,
1874		8, 0, // version/revision
1875
1876		& DeviceCOM::SInterfaceIsInited,
1877		& DeviceCOM::SGetDevice,
1878		& DeviceCOM::SOpen,
1879		& DeviceCOM::SOpenWithSessionRef,
1880		& DeviceCOM::SClose,
1881		& DeviceCOM::SNotificationIsOn,
1882		& DeviceCOM::SAddCallbackDispatcherToRunLoop,
1883		& DeviceCOM::SRemoveCallbackDispatcherFromRunLoop,
1884		& DeviceCOM::STurnOnNotification,
1885		& DeviceCOM::STurnOffNotification,
1886		& DeviceCOM::SSetBusResetHandler,
1887		& DeviceCOM::SSetBusResetDoneHandler,
1888		& DeviceCOM::SClientCommandIsComplete,
1889
1890		// --- FireWire send/recv methods --------------
1891		& DeviceCOM::SRead,
1892		& DeviceCOM::SReadQuadlet,
1893		& DeviceCOM::SWrite,
1894		& DeviceCOM::SWriteQuadlet,
1895		& DeviceCOM::SCompareSwap,
1896
1897		// --- firewire commands -----------------------
1898		& DeviceCOM::SCreateReadCommand,
1899		& DeviceCOM::SCreateReadQuadletCommand,
1900		& DeviceCOM::SCreateWriteCommand,
1901		& DeviceCOM::SCreateWriteQuadletCommand,
1902		& DeviceCOM::SCreateCompareSwapCommand,
1903
1904			// --- other methods ---------------------------
1905		& DeviceCOM::SBusReset,
1906		& DeviceCOM::SGetCycleTime,
1907		& DeviceCOM::SGetGenerationAndNodeID,
1908		& DeviceCOM::SGetLocalNodeID,
1909		& DeviceCOM::SGetResetTime,
1910
1911			// --- unit directory support ------------------
1912		& DeviceCOM::SCreateLocalUnitDirectory,
1913
1914		& DeviceCOM::SGetConfigDirectory,
1915		& DeviceCOM::SCreateConfigDirectoryWithIOObject,
1916			// --- address space support -------------------
1917		& DeviceCOM::SCreatePseudoAddressSpace,
1918		& DeviceCOM::SCreatePhysicalAddressSpace,
1919
1920			// --- debugging -------------------------------
1921		& DeviceCOM::SFireBugMsg,
1922
1923			// --- isoch -----------------------------------
1924		& DeviceCOM::SAddIsochCallbackDispatcherToRunLoop,
1925		& DeviceCOM::SCreateRemoteIsochPort,
1926		& DeviceCOM::S_CreateLocalIsochPort,
1927		& DeviceCOM::SCreateIsochChannel,
1928		& DeviceCOM::SCreateDCLCommandPool,
1929
1930			// --- refcon ----------------------------------
1931		& DeviceCOM::SGetRefCon,
1932		& DeviceCOM::SSetRefCon,
1933
1934			// --- debugging -------------------------------
1935		// do not use this function
1936	//	& DeviceCOM::SGetDebugProperty,
1937		NULL,
1938		& DeviceCOM::SPrintDCLProgram,
1939
1940			// --- initial units address space -------------
1941		& DeviceCOM::SCreateInitialUnitsPseudoAddressSpace,
1942
1943			// --- callback dispatcher utils (cont.) -------
1944		& DeviceCOM::SAddCallbackDispatcherToRunLoopForMode,
1945		& DeviceCOM::SAddIsochCallbackDispatcherToRunLoopForMode,
1946		& DeviceCOM::SRemoveIsochCallbackDispatcherFromRunLoop,
1947
1948			// --- seize service ---------------------------
1949		& DeviceCOM::SSeize,
1950
1951			// --- more debugging --------------------------
1952		& DeviceCOM::SFireLog,
1953
1954			// --- other methods --- new in v3
1955		& DeviceCOM::SGetBusCycleTime,
1956
1957		//
1958		// v4
1959		//
1960		& DeviceCOM::SCreateCompareSwapCommand64,
1961		& DeviceCOM::SCompareSwap64,
1962		& DeviceCOM::SGetBusGeneration,
1963		& DeviceCOM::SGetLocalNodeIDWithGeneration,
1964		& DeviceCOM::SGetRemoteNodeID,
1965		& DeviceCOM::SGetSpeedToNode,
1966		& DeviceCOM::SGetSpeedBetweenNodes,
1967
1968		//
1969		// v5/
1970		//
1971
1972		& DeviceCOM::S_GetIRMNodeID
1973
1974		//
1975		// v6
1976		//
1977
1978		,& DeviceCOM::S_ClipMaxRec2K
1979		,& DeviceCOM::S_CreateNuDCLPool
1980
1981		//
1982		// v7
1983		//
1984
1985		, & DeviceCOM::S_GetSessionRef
1986
1987		//
1988		// v8
1989		//
1990
1991		, & DeviceCOM::S_CreateLocalIsochPortWithOptions
1992
1993		//
1994		// v9
1995		//
1996
1997		, &DeviceCOM::S_CreateVectorCommand
1998
1999		, &DeviceCOM::S_AllocateIRMBandwidthInGeneration
2000
2001		, &DeviceCOM::S_ReleaseIRMBandwidthInGeneration
2002
2003		, &DeviceCOM::S_AllocateIRMChannelInGeneration
2004
2005		, &DeviceCOM::S_ReleaseIRMChannelInGeneration
2006
2007		, &DeviceCOM::S_CreateIRMAllocation
2008
2009		, &DeviceCOM::S_CreateAsyncStreamListener
2010
2011		, &DeviceCOM::S_GetIsochAsyncPort
2012
2013		, &DeviceCOM::S_CreatePHYCommand
2014
2015		, &DeviceCOM::S_CreatePHYPacketListener
2016
2017		, &DeviceCOM::S_CreateAsyncStreamCommand
2018
2019		, &DeviceCOM::SGetCycleTimeAndUpTime
2020	} ;
2021
2022	DeviceCOM::DeviceCOM( CFDictionaryRef propertyTable, io_service_t service )
2023	: Device( reinterpret_cast<const IUnknownVTbl &>( sInterface ), propertyTable, service )
2024	{
2025	}
2026
2027	// ============================================================
2028	// static allocator
2029	// ============================================================
2030
2031	IOFireWireDeviceInterface**
2032	DeviceCOM::Alloc( CFDictionaryRef propertyTable, io_service_t service )
2033	{
2034		DeviceCOM*	me = nil ;
2035
2036		try {
2037			me = new DeviceCOM( propertyTable, service ) ;
2038		} catch ( ... ) {
2039		}
2040
2041		if( !me )
2042			return nil ;
2043
2044		return reinterpret_cast<IOFireWireDeviceInterface**>(&me->GetInterface()) ;
2045	}
2046
2047	Boolean
2048	DeviceCOM::SInterfaceIsInited(IOFireWireLibDeviceRef self)
2049	{
2050		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->mIsInited;
2051	}
2052
2053	io_object_t
2054	DeviceCOM::SGetDevice(IOFireWireLibDeviceRef self)
2055	{
2056		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->mDefaultDevice;
2057	}
2058
2059	IOReturn
2060	DeviceCOM::SOpen(IOFireWireLibDeviceRef self)
2061	{
2062		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->Open() ;
2063	}
2064
2065	IOReturn
2066	DeviceCOM::SOpenWithSessionRef(IOFireWireLibDeviceRef self, IOFireWireSessionRef session)
2067	{
2068		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->OpenWithSessionRef(session) ;
2069	}
2070
2071	IOReturn
2072	DeviceCOM::SSeize(		// v3+
2073		IOFireWireLibDeviceRef	 	self,
2074		IOOptionBits				flags,
2075		... )
2076	{
2077		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->Seize( flags ) ;
2078	}
2079
2080	void
2081	DeviceCOM::SClose(IOFireWireLibDeviceRef self)
2082	{
2083		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->Close() ;
2084	}
2085
2086	// --- FireWire notification methods --------------
2087	const Boolean
2088	DeviceCOM::SNotificationIsOn(IOFireWireLibDeviceRef self)
2089	{
2090		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->mNotifyIsOn;
2091	}
2092
2093	const IOReturn
2094	DeviceCOM::SAddCallbackDispatcherToRunLoop(IOFireWireLibDeviceRef self, CFRunLoopRef runLoop)
2095	{
2096		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->AddCallbackDispatcherToRunLoop(runLoop) ;
2097	}
2098
2099	IOReturn
2100	DeviceCOM::SAddCallbackDispatcherToRunLoopForMode(	// v3+
2101		IOFireWireLibDeviceRef 		self,
2102		CFRunLoopRef 				runLoop,
2103		CFStringRef					runLoopMode )
2104	{
2105		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->AddCallbackDispatcherToRunLoopForMode( runLoop, runLoopMode ) ;
2106	}
2107
2108	const void
2109	DeviceCOM::SRemoveCallbackDispatcherFromRunLoop(IOFireWireLibDeviceRef self)
2110	{
2111		DeviceCOM*	me = IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis( self ) ;
2112		me->RemoveDispatcherFromRunLoop( me->mRunLoop, me->mRunLoopSource, me->mRunLoopMode ) ;
2113
2114		if ( me->mRunLoop )
2115		{
2116			CFRelease( me->mRunLoop ) ;
2117			me->mRunLoop = 0 ;
2118		}
2119
2120		if ( me->mRunLoopSource )
2121		{
2122			CFRelease( me->mRunLoopSource ) ;
2123			me->mRunLoopSource = 0 ;
2124		}
2125
2126		if ( me->mRunLoopMode )
2127		{
2128			CFRelease( me->mRunLoopMode) ;
2129			me->mRunLoopMode = 0 ;
2130		}
2131	}
2132
2133	// Makes notification active. Returns false if notification could not be activated.
2134	const Boolean
2135	DeviceCOM::STurnOnNotification(IOFireWireLibDeviceRef self)
2136	{
2137		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->TurnOnNotification( self ) ;
2138	}
2139
2140	// Notification callbacks will no longer be called.
2141	void
2142	DeviceCOM::STurnOffNotification(IOFireWireLibDeviceRef self)
2143	{
2144		IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->TurnOffNotification() ;
2145	}
2146
2147	const IOFireWireBusResetHandler
2148	DeviceCOM::SSetBusResetHandler(IOFireWireLibDeviceRef self, IOFireWireBusResetHandler inBusResetHandler)
2149	{
2150		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->SetBusResetHandler(inBusResetHandler) ;
2151	}
2152
2153	const IOFireWireBusResetDoneHandler
2154	DeviceCOM::SSetBusResetDoneHandler(IOFireWireLibDeviceRef self, IOFireWireBusResetDoneHandler inBusResetDoneHandler)
2155	{
2156		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->SetBusResetDoneHandler(inBusResetDoneHandler) ;
2157	}
2158
2159	void
2160	DeviceCOM::SClientCommandIsComplete(IOFireWireLibDeviceRef self, FWClientCommandID commandID, IOReturn status)
2161	{
2162		IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->ClientCommandIsComplete(commandID, status);
2163	}
2164
2165	IOReturn
2166	DeviceCOM::SRead(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress * addr, void* buf,
2167		UInt32* size, Boolean failOnReset, UInt32 generation)
2168	{
2169		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->Read(device, *addr, buf, size, failOnReset, generation) ;
2170	}
2171
2172	IOReturn
2173	DeviceCOM::SReadQuadlet(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress * addr,
2174		UInt32* val, Boolean failOnReset, UInt32 generation)
2175	{
2176		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->ReadQuadlet(device, *addr, val, failOnReset, generation);
2177	}
2178
2179	IOReturn
2180	DeviceCOM::SWrite(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress * addr, const void* buf, UInt32* size,
2181		Boolean failOnReset, UInt32 generation)
2182	{
2183		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->Write(device, *addr, buf, size, failOnReset, generation) ;
2184	}
2185
2186	IOReturn
2187	DeviceCOM::SWriteQuadlet(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress* addr, const UInt32 val,
2188		Boolean failOnReset, UInt32 generation)
2189	{
2190		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->WriteQuadlet(device, *addr, val, failOnReset, generation) ;
2191	}
2192
2193	IOReturn
2194	DeviceCOM::SCompareSwap(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress* addr, UInt32 cmpVal, UInt32 newVal, Boolean failOnReset, UInt32 generation)
2195	{
2196		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CompareSwap(device, *addr, cmpVal, newVal, failOnReset, generation) ;
2197	}
2198
2199	//
2200	// v4
2201	//
2202	IOReturn
2203	DeviceCOM::SCompareSwap64( IOFireWireLibDeviceRef self, io_object_t device, const FWAddress* addr,
2204			UInt32* expectedVal, UInt32* newVal, UInt32* oldVal, IOByteCount size, Boolean failOnReset,
2205			UInt32 generation)
2206	{
2207		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CompareSwap64( device, *addr, expectedVal,
2208				newVal, oldVal, size, failOnReset, generation ) ;
2209	}
2210
2211	//
2212	// v4
2213	//
2214	IOFireWireLibCommandRef
2215	DeviceCOM::SCreateCompareSwapCommand64(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress* addr, UInt64 cmpVal,
2216		UInt64 newVal, IOFireWireLibCommandCallback callback, Boolean failOnReset, UInt32 generation, void* inRefCon,
2217		REFIID iid )
2218	{
2219		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateCompareSwapCommand(device,
2220				addr ? *addr : FWAddress(), cmpVal, newVal, 2, callback, failOnReset, generation, inRefCon, iid) ;
2221	}
2222
2223	IOReturn
2224	DeviceCOM::SGetBusGeneration( IOFireWireLibDeviceRef self, UInt32* outGeneration )
2225	{
2226		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetBusGeneration( outGeneration ) ;
2227	}
2228
2229	IOReturn
2230	DeviceCOM::SGetLocalNodeIDWithGeneration( IOFireWireLibDeviceRef self, UInt32 checkGeneration, UInt16* outLocalNodeID )
2231	{
2232		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetLocalNodeIDWithGeneration( checkGeneration, outLocalNodeID ) ;
2233	}
2234
2235	IOReturn
2236	DeviceCOM::SGetRemoteNodeID( IOFireWireLibDeviceRef self, UInt32 checkGeneration, UInt16* outRemoteNodeID )
2237	{
2238		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetRemoteNodeID( checkGeneration, outRemoteNodeID ) ;
2239	}
2240
2241	IOReturn
2242	DeviceCOM::SGetSpeedToNode( IOFireWireLibDeviceRef self, UInt32 checkGeneration, IOFWSpeed* outSpeed)
2243	{
2244		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetSpeedToNode( checkGeneration, outSpeed ) ;
2245	}
2246
2247	IOReturn
2248	DeviceCOM::SGetSpeedBetweenNodes( IOFireWireLibDeviceRef self, UInt32 checkGeneration, UInt16 srcNodeID, UInt16 destNodeID,  IOFWSpeed* outSpeed)
2249	{
2250		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetSpeedBetweenNodes( checkGeneration, srcNodeID, destNodeID, outSpeed ) ;
2251	}
2252
2253#pragma mark -
2254	IOFireWireLibCommandRef
2255	DeviceCOM::SCreateReadCommand(IOFireWireLibDeviceRef self,
2256		io_object_t 		device,
2257		const FWAddress*	addr,
2258		void* 				buf,
2259		UInt32 				size,
2260		IOFireWireLibCommandCallback callback,
2261		Boolean 			failOnReset,
2262		UInt32 				generation,
2263		void*				inRefCon,
2264		REFIID				iid)
2265	{
2266		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateReadCommand(device, addr ? *addr : FWAddress(), buf, size, callback, failOnReset, generation, inRefCon, iid) ;
2267	}
2268
2269	IOFireWireLibCommandRef
2270	DeviceCOM::SCreateReadQuadletCommand(IOFireWireLibDeviceRef self, io_object_t device,
2271		const FWAddress* addr, UInt32 val[], const UInt32 numQuads, IOFireWireLibCommandCallback callback,
2272		Boolean failOnReset, UInt32 generation, void* inRefCon, REFIID iid)
2273	{
2274		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateReadQuadletCommand(device, addr ? *addr : FWAddress(), val, numQuads, callback, failOnReset, generation, inRefCon, iid) ;
2275	}
2276
2277	IOFireWireLibCommandRef
2278	DeviceCOM::SCreateWriteCommand(IOFireWireLibDeviceRef self, io_object_t device,
2279		const FWAddress* addr, void* buf, UInt32 size, IOFireWireLibCommandCallback callback,
2280		Boolean failOnReset, UInt32 generation, void* inRefCon, REFIID iid)
2281	{
2282		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateWriteCommand( device, addr ? *addr : FWAddress(), buf, size, callback, failOnReset, generation, inRefCon, iid) ;
2283	}
2284
2285	IOFireWireLibCommandRef
2286	DeviceCOM::SCreateWriteQuadletCommand(IOFireWireLibDeviceRef self, io_object_t device,
2287		const FWAddress* addr, UInt32 quads[], const UInt32 numQuads, IOFireWireLibCommandCallback callback,
2288		Boolean failOnReset, UInt32 generation, void* inRefCon, REFIID iid)
2289	{
2290		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateWriteQuadletCommand(device, addr ? *addr : FWAddress(), quads, numQuads, callback, failOnReset, generation, inRefCon, iid) ;
2291	}
2292
2293	IOFireWireLibCommandRef
2294	DeviceCOM::SCreateCompareSwapCommand(IOFireWireLibDeviceRef self, io_object_t device, const FWAddress* addr, UInt32 cmpVal, UInt32 newVal,
2295		IOFireWireLibCommandCallback callback, Boolean failOnReset, UInt32 generation, void* inRefCon, REFIID iid)
2296	{
2297		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateCompareSwapCommand(device,
2298				addr ? *addr : FWAddress(), cmpVal, newVal, 1, callback, failOnReset, generation, inRefCon, iid) ;
2299	}
2300
2301	IOReturn
2302	DeviceCOM::SBusReset(IOFireWireLibDeviceRef self)
2303	{
2304		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->BusReset() ;
2305	}
2306
2307
2308#pragma mark -
2309	//
2310	// --- local unit directory support ------------------
2311	//
2312	IOFireWireLibLocalUnitDirectoryRef
2313	DeviceCOM::SCreateLocalUnitDirectory(IOFireWireLibDeviceRef self, REFIID iid)
2314	{
2315		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateLocalUnitDirectory(iid);
2316	}
2317
2318	IOFireWireLibConfigDirectoryRef
2319	DeviceCOM::SGetConfigDirectory(IOFireWireLibDeviceRef self, REFIID iid)
2320	{
2321		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetConfigDirectory(iid) ;
2322	}
2323
2324	IOFireWireLibConfigDirectoryRef
2325	DeviceCOM::SCreateConfigDirectoryWithIOObject(IOFireWireLibDeviceRef self, io_object_t inObject, REFIID iid)
2326	{
2327		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateConfigDirectoryWithIOObject(inObject, iid) ;
2328	}
2329
2330#pragma mark -
2331	//
2332	// --- address space support ------------------
2333	//
2334	IOFireWireLibPseudoAddressSpaceRef
2335	DeviceCOM::SCreatePseudoAddressSpace(IOFireWireLibDeviceRef self, UInt32 inLength, void* inRefCon, UInt32 inQueueBufferSize,
2336		void* inBackingStore, UInt32 inFlags, REFIID iid)
2337	{
2338		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreatePseudoAddressSpace(inLength, inRefCon, inQueueBufferSize, inBackingStore, inFlags, iid);
2339	}
2340
2341	IOFireWireLibPhysicalAddressSpaceRef
2342	DeviceCOM::SCreatePhysicalAddressSpace(IOFireWireLibDeviceRef self, UInt32 inLength, void* inBackingStore, UInt32 flags, REFIID iid)
2343	{
2344		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreatePhysicalAddressSpace(inLength, inBackingStore, flags, iid);
2345	}
2346
2347	IOFireWireLibPseudoAddressSpaceRef
2348	DeviceCOM::SCreateInitialUnitsPseudoAddressSpace(
2349		IOFireWireLibDeviceRef  	self,
2350		UInt32						inAddressLo,
2351		UInt32  					inSize,
2352		void*  						inRefCon,
2353		UInt32  					inQueueBufferSize,
2354		void*  						inBackingStore,
2355		UInt32  					inFlags,
2356		REFIID  					iid)
2357	{
2358		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateInitialUnitsPseudoAddressSpace( inAddressLo, inSize, inRefCon, inQueueBufferSize, inBackingStore, inFlags, iid ) ;
2359	}
2360
2361	//
2362	// --- FireLog -----------------------------------
2363	//
2364	IOReturn
2365	DeviceCOM::SFireLog(
2366		IOFireWireLibDeviceRef self,
2367		const char *		format,
2368		... )
2369	{
2370		va_list		ap ;
2371		va_start( ap, format ) ;
2372
2373		IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->FireLog( format, ap ) ;
2374
2375		va_end( ap ) ;
2376
2377		return kIOReturnSuccess ;
2378	}
2379
2380	//
2381	// --- isoch -----------------------------------
2382	//
2383	IOReturn
2384	DeviceCOM::SAddIsochCallbackDispatcherToRunLoop(
2385		IOFireWireLibDeviceRef	self,
2386		CFRunLoopRef			runLoop)
2387	{
2388		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->AddIsochCallbackDispatcherToRunLoopForMode( runLoop, kCFRunLoopCommonModes ) ;
2389	}
2390
2391	IOReturn
2392	DeviceCOM::SAddIsochCallbackDispatcherToRunLoopForMode( // v3+
2393		IOFireWireLibDeviceRef 	self,
2394		CFRunLoopRef			runLoop,
2395		CFStringRef 			runLoopMode )
2396	{
2397		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->AddIsochCallbackDispatcherToRunLoopForMode( runLoop, runLoopMode ) ;
2398	}
2399
2400	void
2401	DeviceCOM::SRemoveIsochCallbackDispatcherFromRunLoop(	// v3+
2402		IOFireWireLibDeviceRef 	self)
2403	{
2404		IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->RemoveIsochCallbackDispatcherFromRunLoop() ;
2405	}
2406
2407	IOFireWireLibRemoteIsochPortRef
2408	DeviceCOM::SCreateRemoteIsochPort(
2409		IOFireWireLibDeviceRef 	self,
2410		Boolean					inTalking,
2411		REFIID					iid)
2412	{
2413		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateRemoteIsochPort(inTalking, iid) ;
2414	}
2415
2416	IOFireWireLibLocalIsochPortRef
2417	DeviceCOM::S_CreateLocalIsochPort(
2418		IOFireWireLibDeviceRef 	self,
2419		Boolean					talking,
2420		DCLCommand*				dclProgram,
2421		UInt32					startEvent,
2422		UInt32					startState,
2423		UInt32					startMask,
2424		IOVirtualRange			dclProgramRanges[],			// optional optimization parameters
2425		UInt32					dclProgramRangeCount,
2426		IOVirtualRange			bufferRanges[],
2427		UInt32					bufferRangeCount,
2428		REFIID 					iid)
2429	{
2430		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateLocalIsochPortWithOptions( talking, dclProgram, startEvent, startState, startMask,
2431												dclProgramRanges, dclProgramRangeCount, bufferRanges,
2432												bufferRangeCount, kFWIsochPortDefaultOptions, iid) ;
2433	}
2434
2435	IOFireWireLibIsochChannelRef
2436	DeviceCOM::SCreateIsochChannel( IOFireWireLibDeviceRef self, Boolean doIRM, UInt32 packetSize,
2437			IOFWSpeed prefSpeed, REFIID iid )
2438	{
2439		IOFireWireLibIsochChannelRef result = 0 ;
2440
2441		IUnknownVTbl** iUnknown = reinterpret_cast<IUnknownVTbl**>(IsochChannelCOM::Alloc(*IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self), doIRM, packetSize, prefSpeed)) ;
2442		if (iUnknown)
2443		{
2444			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
2445			(*iUnknown)->Release(iUnknown) ;
2446		}
2447
2448		return result ;
2449	}
2450
2451	IOFireWireLibDCLCommandPoolRef
2452	DeviceCOM::SCreateDCLCommandPool( IOFireWireLibDeviceRef self, IOByteCount size, REFIID iid )
2453	{
2454		IOFireWireLibDCLCommandPoolRef result = 0 ;
2455
2456		IUnknownVTbl** iUnknown = TraditionalDCLCommandPoolCOM::Alloc(*IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self), size ) ;
2457		if (iUnknown)
2458		{
2459			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
2460			(*iUnknown)->Release(iUnknown) ;
2461		}
2462
2463		return result ;
2464	}
2465
2466	void
2467	DeviceCOM::SPrintDCLProgram( IOFireWireLibDeviceRef self, const DCLCommand* dcl, UInt32 inDCLCount )
2468	{
2469		const DCLCommand*		currentDCL	= dcl ;
2470		UInt32						index		= 0 ;
2471
2472#ifdef __LP64__
2473		printf( "IsochPort::printDCLProgram: dcl=%p, inDCLCount=%ud\n", dcl, inDCLCount) ;
2474#else
2475		printf( "IsochPort::printDCLProgram: dcl=%p, inDCLCount=%lud\n", dcl, inDCLCount) ;
2476#endif
2477		while ( (inDCLCount == 0 || index < inDCLCount ) && currentDCL )
2478		{
2479#ifdef __LP64__
2480			printf( "\n#0x%04X  @%p   next=%p, cmplrData=0x%08X, op=%u ",
2481				index,
2482				currentDCL,
2483				currentDCL->pNextDCLCommand,
2484				currentDCL->compilerData,
2485				currentDCL->opcode) ;
2486#else
2487			printf( "\n#0x%04lX  @%p   next=%p, cmplrData=0x%08lX, op=%lu ",
2488				index,
2489				currentDCL,
2490				currentDCL->pNextDCLCommand,
2491				currentDCL->compilerData,
2492				currentDCL->opcode) ;
2493#endif
2494			switch(currentDCL->opcode & ~kFWDCLOpFlagMask)
2495			{
2496				case kDCLSendPacketStartOp:
2497				//case kDCLSendPacketWithHeaderStartOp:
2498				case kDCLSendPacketOp:
2499				case kDCLReceivePacketStartOp:
2500				case kDCLReceivePacketOp:
2501#ifdef __LP64__
2502					printf( "(DCLTransferPacket) buffer=%p, size=%u",
2503						((DCLTransferPacket*)currentDCL)->buffer,
2504						((DCLTransferPacket*)currentDCL)->size) ;
2505#else
2506					printf( "(DCLTransferPacket) buffer=%p, size=%lu",
2507						((DCLTransferPacket*)currentDCL)->buffer,
2508						((DCLTransferPacket*)currentDCL)->size) ;
2509#endif
2510					break ;
2511
2512				case kDCLSendBufferOp:
2513				case kDCLReceiveBufferOp:
2514#ifdef __LP64__
2515					printf( "(DCLTransferBuffer) buffer=%p, size=%u, packetSize=0x%x, bufferOffset=%08X",
2516						((DCLTransferBuffer*)currentDCL)->buffer,
2517						((DCLTransferBuffer*)currentDCL)->size,
2518						((DCLTransferBuffer*)currentDCL)->packetSize,
2519						((DCLTransferBuffer*)currentDCL)->bufferOffset) ;
2520#else
2521					printf( "(DCLTransferBuffer) buffer=%p, size=%lu, packetSize=0x%x, bufferOffset=%08lX",
2522						((DCLTransferBuffer*)currentDCL)->buffer,
2523						((DCLTransferBuffer*)currentDCL)->size,
2524						((DCLTransferBuffer*)currentDCL)->packetSize,
2525						((DCLTransferBuffer*)currentDCL)->bufferOffset) ;
2526#endif
2527					break ;
2528
2529				case kDCLCallProcOp:
2530#ifdef __LP64__
2531					printf( "(DCLCallProc) proc=%p, procData=%08llX",
2532						((DCLCallProc*)currentDCL)->proc,
2533						(UInt64)((DCLCallProc*)currentDCL)->procData) ;
2534#else
2535					printf( "(DCLCallProc) proc=%p, procData=%08lX",
2536						((DCLCallProc*)currentDCL)->proc,
2537						((DCLCallProc*)currentDCL)->procData) ;
2538#endif
2539					break ;
2540
2541				case kDCLLabelOp:
2542					printf( "(DCLLabel)") ;
2543					break ;
2544
2545				case kDCLJumpOp:
2546					printf( "(DCLJump) pJumpDCLLabel=%p",
2547						((DCLJump*)currentDCL)->pJumpDCLLabel) ;
2548					break ;
2549
2550				case kDCLSetTagSyncBitsOp:
2551					printf( "(DCLSetTagSyncBits) tagBits=%04x, syncBits=%04x",
2552						((DCLSetTagSyncBits*)currentDCL)->tagBits,
2553						((DCLSetTagSyncBits*)currentDCL)->syncBits) ;
2554					break ;
2555
2556				case kDCLUpdateDCLListOp:
2557#ifdef __LP64__
2558					printf( "(DCLUpdateDCLList) dclCommandList=%p, numDCLCommands=%ud \n",
2559						((DCLUpdateDCLList*)currentDCL)->dclCommandList,
2560						((DCLUpdateDCLList*)currentDCL)->numDCLCommands) ;
2561#else
2562					printf( "(DCLUpdateDCLList) dclCommandList=%p, numDCLCommands=%lud \n",
2563						((DCLUpdateDCLList*)currentDCL)->dclCommandList,
2564						((DCLUpdateDCLList*)currentDCL)->numDCLCommands) ;
2565#endif
2566					for(UInt32 listIndex=0; listIndex < ((DCLUpdateDCLList*)currentDCL)->numDCLCommands; ++listIndex)
2567					{
2568						printf( "%p ", (((DCLUpdateDCLList*)currentDCL)->dclCommandList)[listIndex]) ;
2569					}
2570
2571					break ;
2572
2573				case kDCLPtrTimeStampOp:
2574					printf( "(DCLPtrTimeStamp) timeStampPtr=%p",
2575						((DCLPtrTimeStamp*)currentDCL)->timeStampPtr) ;
2576					break ;
2577
2578				case kDCLSkipCycleOp:
2579					printf( "(DCLSkipCycle)") ;
2580					break ;
2581
2582				case kDCLNuDCLLeaderOp:
2583					printf( "(DCLNuDCLLeaderOp) DCL pool=%p", ((DCLNuDCLLeader*)currentDCL)->program ) ;
2584					break ;
2585			}
2586
2587			currentDCL = currentDCL->pNextDCLCommand ;
2588			++index ;
2589		}
2590
2591		printf( "\n") ;
2592
2593		if ( inDCLCount > 0 && index != inDCLCount)
2594			printf( "unexpected end of program\n") ;
2595
2596		if ( inDCLCount > 0 && currentDCL != NULL)
2597			printf( "program too long for count\n") ;
2598	}
2599
2600	IOReturn
2601	DeviceCOM::S_GetIRMNodeID( IOFireWireLibDeviceRef self, UInt32 checkGeneration, UInt16* outIRMNodeID )
2602	{
2603		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis( self )->GetIRMNodeID( checkGeneration, outIRMNodeID ) ;
2604	}
2605
2606	IOReturn
2607	DeviceCOM::S_ClipMaxRec2K( IOFireWireLibDeviceRef self, Boolean clipMaxRec )
2608	{
2609		//fprintf(stderr, "DeviceCOM::S_ClipMaxRec2K\n") ;
2610		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->ClipMaxRec2K( clipMaxRec) ;
2611	}
2612
2613	IOFireWireLibNuDCLPoolRef
2614	DeviceCOM::S_CreateNuDCLPool( IOFireWireLibDeviceRef self, UInt32 capacity, REFIID iid )
2615	{
2616		IOFireWireLibNuDCLPoolRef	result = 0 ;
2617
2618		const IUnknownVTbl** iUnknown = NuDCLPoolCOM::Alloc( *IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis( self ), capacity ) ;
2619		if (iUnknown)
2620		{
2621			(*iUnknown)->QueryInterface(iUnknown, iid, (void**) & result) ;
2622			(*iUnknown)->Release(iUnknown) ;
2623		}
2624
2625		return result ;
2626	}
2627
2628	IOFireWireSessionRef
2629	DeviceCOM::S_GetSessionRef( IOFireWireLibDeviceRef self )
2630	{
2631		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->GetSessionRef() ;
2632	}
2633
2634	IOFireWireLibLocalIsochPortRef
2635	DeviceCOM::S_CreateLocalIsochPortWithOptions(
2636		IOFireWireLibDeviceRef 	self,
2637		Boolean					talking,
2638		DCLCommand*				dclProgram,
2639		UInt32					startEvent,
2640		UInt32					startState,
2641		UInt32					startMask,
2642		IOVirtualRange			dclProgramRanges[],			// optional optimization parameters
2643		UInt32					dclProgramRangeCount,
2644		IOVirtualRange			bufferRanges[],
2645		UInt32					bufferRangeCount,
2646		IOFWIsochPortOptions	options,
2647		REFIID 					iid)
2648	{
2649		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateLocalIsochPortWithOptions( talking, dclProgram, startEvent, startState, startMask,
2650												dclProgramRanges, dclProgramRangeCount, bufferRanges,
2651												bufferRangeCount, options, iid) ;
2652	}
2653
2654	IOFireWireLibVectorCommandRef
2655	DeviceCOM::S_CreateVectorCommand(
2656		IOFireWireLibDeviceRef self,
2657		IOFireWireLibCommandCallback callback,
2658		void* inRefCon,
2659		REFIID iid)
2660	{
2661			return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateVectorCommand( callback, inRefCon, iid );
2662	}
2663
2664	IOFireWireLibCommandRef
2665	DeviceCOM::S_CreatePHYCommand(
2666		IOFireWireLibDeviceRef			self,
2667		UInt32							data1,
2668		UInt32							data2,
2669		IOFireWireLibCommandCallback	callback,
2670		Boolean							failOnReset,
2671		UInt32							generation,
2672		void*							inRefCon,
2673		REFIID							iid )
2674	{
2675		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreatePHYCommand( data1, data2, callback, failOnReset, generation, inRefCon, iid );
2676	}
2677
2678	IOFireWireLibPHYPacketListenerRef
2679	DeviceCOM::S_CreatePHYPacketListener(
2680		IOFireWireLibDeviceRef self,
2681		UInt32	queueCount,
2682		REFIID iid)
2683	{
2684			return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreatePHYPacketListener( queueCount, iid );
2685	}
2686
2687	IOReturn DeviceCOM::S_AllocateIRMBandwidthInGeneration(IOFireWireLibDeviceRef self, UInt32 bandwidthUnits, UInt32 generation)
2688	{
2689		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->AllocateIRMBandwidthInGeneration(bandwidthUnits, generation);
2690	}
2691
2692	IOReturn DeviceCOM::S_ReleaseIRMBandwidthInGeneration(IOFireWireLibDeviceRef self, UInt32 bandwidthUnits, UInt32 generation)
2693	{
2694		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->ReleaseIRMBandwidthInGeneration(bandwidthUnits, generation);
2695	}
2696
2697	IOReturn DeviceCOM::S_AllocateIRMChannelInGeneration(IOFireWireLibDeviceRef self, UInt8 isochChannel, UInt32 generation)
2698	{
2699		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->AllocateIRMChannelInGeneration(isochChannel, generation);
2700	}
2701
2702	IOReturn DeviceCOM::S_ReleaseIRMChannelInGeneration(IOFireWireLibDeviceRef self, UInt8 isochChannel, UInt32 generation)
2703	{
2704		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->ReleaseIRMChannelInGeneration(isochChannel, generation);
2705	}
2706
2707	IOFireWireLibIRMAllocationRef DeviceCOM::S_CreateIRMAllocation( IOFireWireLibDeviceRef self,
2708																	Boolean releaseIRMResourcesOnFree,
2709																	IOFireWireLibIRMAllocationLostNotificationProc callback,
2710																	void *pLostNotificationProcRefCon,
2711																	REFIID iid)
2712	{
2713		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateIRMAllocation(releaseIRMResourcesOnFree,
2714																								callback,
2715																								pLostNotificationProcRefCon,
2716																								iid);
2717	}
2718
2719	IOFWAsyncStreamListenerInterfaceRef
2720	DeviceCOM::S_CreateAsyncStreamListener(
2721		IOFireWireLibDeviceRef			self,
2722		UInt32							channel,
2723		IOFWAsyncStreamListenerHandler	callback,
2724		void*							inRefCon,
2725		UInt32							inQueueBufferSize,
2726		REFIID							iid )
2727	{
2728		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateAsyncStreamListener( channel,
2729																									  callback,
2730																									  inRefCon,
2731																									  inQueueBufferSize,
2732																									  iid );
2733	}
2734
2735	mach_port_t DeviceCOM::S_GetIsochAsyncPort( IOFireWireLibDeviceRef	self )
2736	{
2737		IOReturn status = kIOReturnSuccess;
2738		mach_port_t port = NULL;
2739
2740		Device * device = IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self);
2741
2742		if( !device->IsochAsyncPortsExist() )
2743		{
2744			status = device->CreateIsochAsyncPorts();
2745		}
2746
2747		if( status == kIOReturnSuccess )
2748		{
2749			port = device->GetIsochAsyncPort();
2750		}
2751
2752		return port;
2753	}
2754
2755	IOFireWireLibCommandRef	DeviceCOM::S_CreateAsyncStreamCommand(	IOFireWireLibDeviceRef			self,
2756																	UInt32							channel,
2757																	UInt32							sync,
2758																	UInt32							tag,
2759																	void*							buf,
2760																	UInt32							size,
2761																	IOFireWireLibCommandCallback	callback,
2762																	Boolean							failOnReset,
2763																	UInt32							generation,
2764																	void*							inRefCon,
2765																	REFIID							iid)
2766	{
2767		return IOFireWireIUnknown::InterfaceMap<DeviceCOM>::GetThis(self)->CreateAsyncStreamCommand( channel,
2768																									 sync,
2769																									 tag,
2770																									 buf,
2771																									 size,
2772																									 callback,
2773																									 failOnReset,
2774																									 generation,
2775																									 inRefCon,
2776																									 iid );
2777	}
2778
2779} // namespace
2780