1/*
2 * Copyright (c) 1998-2002 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 *  IOFireWireLibIsochPort.cpp
24 *  IOFireWireFamily
25 *
26 *  Created on Mon Mar 12 2001.
27 *  Copyright (c) 2001-2002 Apple Computer, Inc. All rights reserved.
28 *
29 * $Log: IOFireWireLibIsochPort.cpp,v $
30 * Revision 1.58  2009/01/16 02:53:19  collin
31 * and finally put TOT back...
32 *
33 * Revision 1.54  2009/01/15 01:40:02  collin
34 * <rdar://problem/6400981> BRB-VERIFY: 10A222: Trying to record a movie through QT X, getting error message.
35 *
36 * Revision 1.53  2008/05/06 00:14:48  collin
37 * more k64 changes
38 *
39 * Revision 1.52  2007/03/14 01:01:14  collin
40 * *** empty log message ***
41 *
42 * Revision 1.51  2007/02/15 19:42:08  ayanowit
43 * For 4369537, eliminated support for legacy DCL SendPacketWithHeader, since it didn't work anyway, and NuDCL does support it.
44 *
45 * Revision 1.50  2007/02/15 17:18:54  ayanowit
46 * Fixed a panic found with ProIO DCL program in FCP. Related to recent changes for 64-bit app support.
47 *
48 * Revision 1.49  2007/02/07 06:35:22  collin
49 * *** empty log message ***
50 *
51 * Revision 1.48  2007/01/26 20:52:31  ayanowit
52 * changes to user-space isoch stuff to support 64-bit apps.
53 *
54 * Revision 1.47  2007/01/11 04:28:05  collin
55 * *** empty log message ***
56 *
57 * Revision 1.46  2007/01/08 18:47:20  ayanowit
58 * More 64-bit changes for isoch.
59 *
60 * Revision 1.45  2007/01/02 18:14:12  ayanowit
61 * Enabled building the plug-in lib 4-way FAT. Also, fixed compile problems for 64-bit.
62 *
63 * Revision 1.44  2006/12/21 21:17:46  ayanowit
64 * More changes necessary to eventually get support for 64-bit apps working (4222965).
65 *
66 * Revision 1.43  2006/12/16 00:07:48  ayanowit
67 * fixed some of the leopard user-lib changes. was failing on ppc systems.
68 *
69 * Revision 1.42  2006/12/13 21:34:24  ayanowit
70 * For 4222965, replaced all io async method calls with new Leopard API version.
71 *
72 * Revision 1.41  2006/12/13 01:11:23  ayanowit
73 * For 4222969, replaced the remaining calls to IOConnectMethod... struct variants.
74 *
75 * Revision 1.40  2006/12/12 22:39:05  ayanowit
76 * For radar 4222965, changed all scalar in, scalar out calls to IOConnectMethod... to use new Leopard IOConnectCall... API.
77 *
78 * Revision 1.39  2006/08/21 22:41:11  collin
79 * *** empty log message ***
80 *
81 * Revision 1.38  2006/02/09 00:21:55  niels
82 * merge chardonnay branch to tot
83 *
84 * Revision 1.37  2005/04/02 02:43:46  niels
85 * exporter works outside IOFireWireFamily
86 *
87 * Revision 1.36.4.6  2006/01/31 04:49:57  collin
88 * *** empty log message ***
89 *
90 * Revision 1.36.4.4  2006/01/17 00:35:00  niels
91 * <rdar://problem/4399365> FireWire NuDCL APIs need Rosetta support
92 *
93 * Revision 1.36.4.3  2006/01/04 00:45:54  collin
94 * *** empty log message ***
95 *
96 * Revision 1.36.4.2  2005/08/06 01:31:31  collin
97 * *** empty log message ***
98 *
99 * Revision 1.36.4.1  2005/07/23 00:30:46  collin
100 * *** empty log message ***
101 *
102 * Revision 1.36  2005/03/12 03:27:52  collin
103 * *** empty log message ***
104 *
105 * Revision 1.35  2005/02/18 03:19:05  niels
106 * fix isight
107 *
108 * Revision 1.34  2004/05/04 22:52:20  niels
109 * *** empty log message ***
110 *
111 * Revision 1.33  2004/02/17 23:13:23  niels
112 * *** empty log message ***
113 *
114 * Revision 1.32  2004/02/17 23:12:27  niels
115 * *** empty log message ***
116 *
117 * Revision 1.31  2004/02/17 20:23:58  niels
118 * keep track if local isoch port has started or not to avoid leaking when stop is called on an unstarted port
119 *
120 * Revision 1.30  2003/12/19 22:07:46  niels
121 * send force stop when channel dies/system sleeps
122 *
123 * Revision 1.29  2003/08/25 08:39:17  niels
124 * *** empty log message ***
125 *
126 * Revision 1.28  2003/08/20 23:33:37  niels
127 * *** empty log message ***
128 *
129 * Revision 1.27  2003/08/20 18:48:45  niels
130 * *** empty log message ***
131 *
132 * Revision 1.26  2003/08/18 23:18:15  niels
133 * *** empty log message ***
134 *
135 * Revision 1.25  2003/08/14 17:47:33  niels
136 * *** empty log message ***
137 *
138 * Revision 1.24  2003/07/29 22:49:25  niels
139 * *** empty log message ***
140 *
141 * Revision 1.23  2003/07/24 20:49:50  collin
142 * *** empty log message ***
143 *
144 * Revision 1.22  2003/07/24 06:30:59  collin
145 * *** empty log message ***
146 *
147 * Revision 1.21  2003/07/21 06:53:10  niels
148 * merge isoch to TOT
149 *
150 * Revision 1.20.6.6  2003/07/21 06:44:48  niels
151 * *** empty log message ***
152 *
153 * Revision 1.20.6.5  2003/07/18 00:17:47  niels
154 * *** empty log message ***
155 *
156 * Revision 1.20.6.4  2003/07/10 00:11:58  niels
157 * *** empty log message ***
158 *
159 * Revision 1.20.6.3  2003/07/09 21:24:07  niels
160 * *** empty log message ***
161 *
162 * Revision 1.20.6.2  2003/07/03 22:10:26  niels
163 * fix iidc/dv rcv
164 *
165 * Revision 1.20.6.1  2003/07/01 20:54:24  niels
166 * isoch merge
167 *
168 */
169
170#import "IOFireWireLibIsochPort.h"
171#import "IOFireWireLibDevice.h"
172#import "IOFireWireLibNuDCLPool.h"
173#import "IOFireWireLibNuDCL.h"
174#import "IOFireWireLibCoalesceTree.h"
175
176#import <IOKit/iokitmig.h>
177#import <mach/mach.h>
178#import <System/libkern/OSCrossEndian.h>
179
180#define IOFIREWIREISOCHPORTIMP_INTERFACE	\
181	& IsochPortCOM::SGetSupported,	\
182	& IsochPortCOM::SAllocatePort,	\
183	& IsochPortCOM::SReleasePort,	\
184	& IsochPortCOM::SStart,	\
185	& IsochPortCOM::SStop,	\
186	& IsochPortCOM::SSetRefCon,	\
187	& IsochPortCOM::SGetRefCon
188
189namespace IOFireWireLib {
190	RemoteIsochPort::Interface	RemoteIsochPortCOM::sInterface =
191	{
192		INTERFACEIMP_INTERFACE,
193		1, 0,
194
195		IOFIREWIREISOCHPORTIMP_INTERFACE,
196		& RemoteIsochPortCOM::SSetGetSupportedHandler,
197		& RemoteIsochPortCOM::SSetAllocatePortHandler,
198		& RemoteIsochPortCOM::SSetReleasePortHandler,
199		& RemoteIsochPortCOM::SSetStartHandler,
200		& RemoteIsochPortCOM::SSetStopHandler,
201	} ;
202
203	// ============================================================
204	// utility functions
205	// ============================================================
206
207	Boolean
208	GetDCLDataBuffer(
209		DCLCommand*	dcl,
210		IOVirtualAddress*	outDataBuffer,
211		IOByteCount*		outDataLength)
212	{
213		Boolean	result = false ;
214
215		switch(dcl->opcode & ~kFWDCLOpFlagMask)
216		{
217			case kDCLSendPacketStartOp:
218			//case kDCLSendPacketWithHeaderStartOp:
219			case kDCLSendPacketOp:
220			case kDCLReceivePacketStartOp:
221			case kDCLReceivePacketOp:
222				*outDataBuffer		= (IOVirtualAddress)((DCLTransferPacket*)dcl)->buffer ;
223				*outDataLength		= ((DCLTransferPacket*)dcl)->size ;
224				result = true ;
225				break ;
226
227			case kDCLSendBufferOp:
228			case kDCLReceiveBufferOp:
229				//zzz what should I do here?
230				break ;
231
232			case kDCLPtrTimeStampOp:
233				*outDataBuffer		= (IOVirtualAddress)((DCLPtrTimeStamp*)dcl)->timeStampPtr ;
234				*outDataLength		= sizeof( *( ((DCLPtrTimeStamp*)dcl)->timeStampPtr) ) ;
235				result = true ;
236				break ;
237
238			default:
239				break ;
240		}
241
242		return result ;
243	}
244
245	IOByteCount
246	GetDCLSize(
247		DCLCommand*	dcl)
248	{
249		IOByteCount result = 0 ;
250
251		switch(dcl->opcode & ~kFWDCLOpFlagMask)
252		{
253			case kDCLSendPacketStartOp:
254			//case kDCLSendPacketWithHeaderStartOp:
255			case kDCLSendPacketOp:
256			case kDCLReceivePacketStartOp:
257			case kDCLReceivePacketOp:
258				result = sizeof(UserExportDCLTransferPacket) ;
259				break ;
260
261			case kDCLSendBufferOp:
262			case kDCLReceiveBufferOp:
263				result = sizeof(UserExportDCLTransferBuffer) ;
264				break ;
265
266			case kDCLCallProcOp:
267				result = sizeof(UserExportDCLCallProc) ;
268				break ;
269
270			case kDCLLabelOp:
271				result = sizeof(UserExportDCLLabel) ;
272				break ;
273
274			case kDCLJumpOp:
275				result = sizeof(UserExportDCLJump) ;
276				break ;
277
278			case kDCLSetTagSyncBitsOp:
279				result = sizeof(UserExportDCLSetTagSyncBits) ;
280				break ;
281
282			case kDCLUpdateDCLListOp:
283				result = sizeof(UserExportDCLUpdateDCLList) ;
284				break ;
285
286			case kDCLPtrTimeStampOp:
287				result = sizeof(UserExportDCLPtrTimeStamp) ;
288				break;
289
290			case kDCLSkipCycleOp:
291				result = sizeof(UserExportDCLCommand) ;
292				break;
293		}
294
295		return result ;
296	}
297
298#pragma mark -
299	// ============================================================
300	//
301	// IsochPort
302	//
303	// ============================================================
304
305	IsochPort::IsochPort( const IUnknownVTbl & interface, Device & device, bool talking, bool allocateKernPort )
306	: IOFireWireIUnknown( interface ),
307	  mDevice( device ),
308	  mKernPortRef( 0 ),
309	  mTalking( talking )
310	{
311		mDevice.AddRef() ;
312	}
313
314	IsochPort::~IsochPort()
315	{
316		if ( mKernPortRef )
317		{
318			IOReturn error = kIOReturnSuccess;
319
320			uint32_t outputCnt = 0;
321			const uint64_t inputs[1]={(const uint64_t)mKernPortRef};
322			error = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
323											  kReleaseUserObject,
324											  inputs,1,NULL,&outputCnt);
325
326			DebugLogCond( error, "Couldn't release kernel port" ) ;
327		}
328
329		mDevice.Release() ;
330	}
331
332	IOReturn
333	IsochPort::GetSupported(
334		IOFWSpeed&					maxSpeed,
335		UInt64& 					chanSupported )
336	{
337		uint32_t outputCnt = 3;
338		uint64_t outputVal[3];
339		const uint64_t inputs[1]={(const uint64_t)mKernPortRef};
340		IOReturn result = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
341													kIsochPort_GetSupported,
342													inputs,1,
343													outputVal,&outputCnt);
344		maxSpeed = (IOFWSpeed)(outputVal[0] & 0xFFFFFFFF);
345		chanSupported = ((outputVal[1] & 0xFFFFFFFF)<<32)+(outputVal[2] & 0xFFFFFFFF);
346		return result;
347	}
348
349	IOReturn
350	IsochPort::AllocatePort( IOFWSpeed speed, UInt32 chan )
351	{
352		uint32_t outputCnt = 0;
353		const uint64_t inputs[2] = {speed, chan};
354		return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
355										 mDevice.MakeSelectorWithObject( kIsochPort_AllocatePort_d, mKernPortRef ),
356										 inputs,2,
357										 NULL,&outputCnt);
358	}
359
360	IOReturn
361	IsochPort::ReleasePort()
362	{
363		uint32_t outputCnt = 0;
364		return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
365										 mDevice.MakeSelectorWithObject( kIsochPort_ReleasePort_d, mKernPortRef ),
366										 NULL,0,
367										 NULL,&outputCnt);
368	}
369
370	IOReturn
371	IsochPort::Start()
372	{
373		uint32_t outputCnt = 0;
374		return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
375										 mDevice.MakeSelectorWithObject( kIsochPort_Start_d, mKernPortRef ),
376										 NULL,0,
377										 NULL,&outputCnt);
378	}
379
380	IOReturn
381	IsochPort::Stop()
382	{
383		uint32_t outputCnt = 0;
384		return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
385										 mDevice.MakeSelectorWithObject( kIsochPort_Stop_d, mKernPortRef ),
386										 NULL,0,
387										 NULL,&outputCnt);
388	}
389
390#pragma mark -
391	// ============================================================
392	//
393	// IsochPortCOM
394	//
395	// ============================================================
396
397	IsochPortCOM::IsochPortCOM( const IUnknownVTbl & interface, Device& userclient, bool talking, bool allocateKernPort )
398	:	IsochPort( interface, userclient, talking, allocateKernPort )
399	{
400	}
401
402	IsochPortCOM::~IsochPortCOM()
403	{
404	}
405
406	IOReturn
407	IsochPortCOM::SGetSupported(
408		IOFireWireLibIsochPortRef	self,
409		IOFWSpeed* 					maxSpeed,
410		UInt64* 					chanSupported )
411	{
412		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->GetSupported(*maxSpeed, *chanSupported) ;
413	}
414
415	IOReturn
416	IsochPortCOM::SAllocatePort(
417		IOFireWireLibIsochPortRef	self,
418		IOFWSpeed 					speed,
419		UInt32 						chan )
420	{
421		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->AllocatePort(speed, chan) ;
422	}
423
424	IOReturn
425	IsochPortCOM::SReleasePort(
426		IOFireWireLibIsochPortRef	self)
427	{
428		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->ReleasePort() ;
429	}
430
431	IOReturn
432	IsochPortCOM::SStart(
433		IOFireWireLibIsochPortRef	self)
434	{
435		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->Start() ;
436	}
437
438	IOReturn
439	IsochPortCOM::SStop(
440		IOFireWireLibIsochPortRef	self)
441	{
442		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->Stop() ;
443	}
444
445	void
446	IsochPortCOM::SSetRefCon(
447		IOFireWireLibIsochPortRef		self,
448		void*				inRefCon)
449	{
450		IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->SetRefCon(inRefCon) ;
451	}
452
453	void*
454	IsochPortCOM::SGetRefCon(
455		IOFireWireLibIsochPortRef		self)
456	{
457		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->GetRefCon() ;
458	}
459
460	Boolean
461	IsochPortCOM::SGetTalking(
462		IOFireWireLibIsochPortRef		self)
463	{
464		return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->GetTalking() ;
465	}
466
467#pragma mark -
468	// ============================================================
469	//
470	// RemoteIsochPort
471	//
472	// ============================================================
473
474	RemoteIsochPort::RemoteIsochPort( const IUnknownVTbl & interface, Device& userclient, bool talking )
475	:	IsochPortCOM( interface, userclient, talking ),
476		mGetSupportedHandler(0),
477		mAllocatePortHandler(0),
478		mReleasePortHandler(0),
479		mStartHandler(0),
480		mStopHandler(0),
481		mRefInterface( reinterpret_cast<IOFireWireIsochPortInterface**>(& GetInterface()) )
482	{
483	}
484
485	IOReturn
486	RemoteIsochPort::GetSupported(
487		IOFWSpeed&					maxSpeed,
488		UInt64&						chanSupported)
489	{
490		if (mGetSupportedHandler)
491			return (*mGetSupportedHandler)(mRefInterface, & maxSpeed, & chanSupported) ;
492		else
493			return kIOReturnUnsupported ;	// should we return unsupported if user proc doesn't answer?
494	}
495
496	IOReturn
497	RemoteIsochPort::AllocatePort(
498		IOFWSpeed 					speed,
499		UInt32 						chan )
500	{
501		if (mAllocatePortHandler)
502			return (*mAllocatePortHandler)(mRefInterface, speed,  chan) ;
503		else
504			return kIOReturnSuccess ;
505	}
506
507	IOReturn
508	RemoteIsochPort::ReleasePort()
509	{
510		if (mReleasePortHandler)
511			return (*mReleasePortHandler)(mRefInterface) ;
512		else
513			return kIOReturnSuccess ;
514	}
515
516	IOReturn
517	RemoteIsochPort::Start()
518	{
519		if (mStartHandler)
520			return (*mStartHandler)(mRefInterface) ;
521		else
522			return kIOReturnSuccess ;
523	}
524
525	IOReturn
526	RemoteIsochPort::Stop()
527	{
528		if (mStopHandler)
529			return (*mStopHandler)(mRefInterface) ;
530		else
531			return kIOReturnSuccess ;
532	}
533
534
535	IOFireWireLibIsochPortGetSupportedCallback
536	RemoteIsochPort::SetGetSupportedHandler(
537		IOFireWireLibIsochPortGetSupportedCallback	inHandler)
538	{
539		IOFireWireLibIsochPortGetSupportedCallback oldHandler = mGetSupportedHandler ;
540		mGetSupportedHandler = inHandler ;
541
542		return oldHandler ;
543	}
544
545	IOFireWireLibIsochPortAllocateCallback
546	RemoteIsochPort::SetAllocatePortHandler(
547		IOFireWireLibIsochPortAllocateCallback	inHandler)
548	{
549		IOFireWireLibIsochPortAllocateCallback	oldHandler	= mAllocatePortHandler ;
550		mAllocatePortHandler = inHandler ;
551
552		return oldHandler ;
553	}
554
555	IOFireWireLibIsochPortCallback
556	RemoteIsochPort::SetReleasePortHandler(
557		IOFireWireLibIsochPortCallback	inHandler)
558	{
559		IOFireWireLibIsochPortCallback	oldHandler	= mReleasePortHandler ;
560		mReleasePortHandler = inHandler ;
561
562		return oldHandler ;
563	}
564
565	IOFireWireLibIsochPortCallback
566	RemoteIsochPort::SetStartHandler(
567		IOFireWireLibIsochPortCallback	inHandler)
568	{
569		IOFireWireLibIsochPortCallback	oldHandler	= mStartHandler ;
570		mStartHandler = inHandler ;
571
572		return oldHandler ;
573	}
574
575	IOFireWireLibIsochPortCallback
576	RemoteIsochPort::SetStopHandler(
577		IOFireWireLibIsochPortCallback	inHandler)
578	{
579		IOFireWireLibIsochPortCallback	oldHandler	= mStopHandler ;
580		mStopHandler = inHandler ;
581
582		return oldHandler ;
583	}
584
585#pragma mark -
586	// ============================================================
587	//
588	// RemoteIsochPortCOM
589	//
590	// ============================================================
591	RemoteIsochPortCOM::RemoteIsochPortCOM( Device& userclient, bool talking )
592	: RemoteIsochPort( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, talking )
593	{
594	}
595
596	RemoteIsochPortCOM::~RemoteIsochPortCOM()
597	{
598	}
599
600	IUnknownVTbl**
601	RemoteIsochPortCOM::Alloc( Device& userclient, bool talking )
602	{
603		RemoteIsochPortCOM*	me = nil ;
604
605		try {
606			me = new RemoteIsochPortCOM( userclient, talking ) ;
607		} catch(...) {
608		}
609
610		return (nil==me) ? nil : reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ;
611	}
612
613
614	HRESULT
615	RemoteIsochPortCOM::QueryInterface(REFIID iid, void ** ppv )
616	{
617		HRESULT		result = S_OK ;
618		*ppv = nil ;
619
620		CFUUIDRef	interfaceID	= CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
621
622		if ( CFEqual(interfaceID, IUnknownUUID) ||  CFEqual(interfaceID, kIOFireWireRemoteIsochPortInterfaceID) )
623		{
624			*ppv = & GetInterface() ;
625			AddRef() ;
626		}
627		else
628		{
629			*ppv = nil ;
630			result = E_NOINTERFACE ;
631		}
632
633		CFRelease(interfaceID) ;
634		return result ;
635	}
636
637	IOFireWireLibIsochPortGetSupportedCallback
638	RemoteIsochPortCOM::SSetGetSupportedHandler(
639		PortRef				self,
640		IOFireWireLibIsochPortGetSupportedCallback	inHandler)
641	{
642		return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetGetSupportedHandler(inHandler) ;
643	}
644
645	IOFireWireLibIsochPortAllocateCallback
646	RemoteIsochPortCOM::SSetAllocatePortHandler(
647		PortRef		self,
648		IOFireWireLibIsochPortAllocateCallback		inHandler)
649	{
650		return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetAllocatePortHandler(inHandler) ;
651	}
652
653	IOFireWireLibIsochPortCallback
654	RemoteIsochPortCOM::SSetReleasePortHandler(
655		PortRef		self,
656		IOFireWireLibIsochPortCallback		inHandler)
657	{
658		return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetReleasePortHandler(inHandler) ;
659	}
660
661	IOFireWireLibIsochPortCallback
662	RemoteIsochPortCOM::SSetStartHandler(
663		PortRef		self,
664		IOFireWireLibIsochPortCallback		inHandler)
665	{
666		return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetStartHandler(inHandler) ;
667	}
668
669	IOFireWireLibIsochPortCallback
670	RemoteIsochPortCOM::SSetStopHandler(
671		PortRef		self,
672		IOFireWireLibIsochPortCallback		inHandler)
673	{
674		return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetStopHandler(inHandler) ;
675	}
676
677#pragma mark -
678	LocalIsochPortCOM::Interface	LocalIsochPortCOM::sInterface =
679	{
680		INTERFACEIMP_INTERFACE
681		,4,0
682
683		,IOFIREWIREISOCHPORTIMP_INTERFACE
684		,& LocalIsochPortCOM::SModifyJumpDCL
685		,& LocalIsochPortCOM::SPrintDCLProgram
686		,& LocalIsochPortCOM::SModifyTransferPacketDCLSize
687		,& LocalIsochPortCOM::SModifyTransferPacketDCLBuffer
688		,& LocalIsochPortCOM::SModifyTransferPacketDCL
689		,& LocalIsochPortCOM::S_SetFinalizeCallback
690		, & LocalIsochPortCOM::S_SetResourceUsageFlags
691		, & LocalIsochPortCOM::S_Notify
692	} ;
693
694	LocalIsochPort::LocalIsochPort( const IUnknownVTbl & interface, Device & userclient, bool talking,
695			DCLCommand* program, UInt32 startEvent, UInt32 startState, UInt32 startMask,
696			IOVirtualRange userProgramRanges[], UInt32 userProgramRangeCount,
697			IOVirtualRange userBufferRanges[], UInt32 userBufferRangeCount, IOFWIsochPortOptions options )
698	: IsochPortCOM( interface, userclient, talking, false )
699	, mDCLProgram( program )
700	, mExpectedStopTokens(0)
701	, mDeferredReleaseCount(0)
702	, mFinalizeCallback(nil)
703	, mBufferRanges( nil )
704	, mBufferAddressRanges( nil )
705	, mStarted( false )
706	{
707		// sorry about the spaghetti.. hope you're hungry:
708
709		if ( !program )
710		{
711			DebugLog( "no DCL program!\n" ) ;
712			throw kIOReturnBadArgument ;
713		}
714
715//		DeviceCOM::SPrintDCLProgram ( nil, program, 0 ) ;
716
717		IOReturn	error = kIOReturnSuccess ;
718
719		// trees used to coalesce program/data ranges
720		CoalesceTree		bufferTree ;
721
722		// check if user passed in any virtual memory ranges to start with...
723		if ( userBufferRanges )
724		{
725			for( unsigned index=0; index < userBufferRangeCount; ++index )
726				bufferTree.CoalesceRange( userBufferRanges[index]) ;
727		}
728
729		IOByteCount			programExportBytes = 0 ;
730		IOVirtualAddress	programData = 0 ;
731
732		LocalIsochPortAllocateParams params ;
733		{
734			params.programExportBytes = 0 ;
735			params.programData = 0 ;
736		}
737
738		if ( program->opcode == kDCLNuDCLLeaderOp )
739		{
740			if( !error )
741			{
742				NuDCLPool*	pool	= reinterpret_cast<NuDCLPool*>( reinterpret_cast< DCLNuDCLLeader* >( program )->program ) ;
743
744				params.version 				= kDCLExportDataNuDCLRosettaVersion ;		// new-style DCL program
745
746				pool->CoalesceBuffers( bufferTree ) ;
747
748				mBufferRangeCount = bufferTree.GetCount() ;
749				mBufferRanges = new IOVirtualRange[ mBufferRangeCount ] ;
750				if ( !mBufferRanges )
751				{
752					error = kIOReturnNoMemory ;
753				}
754				else
755				{
756					bufferTree.GetCoalesceList( mBufferRanges ) ;
757
758					mBufferAddressRanges = new FWVirtualAddressRange[ mBufferRangeCount ] ;
759					if ( !mBufferAddressRanges )
760					{
761						error = kIOReturnNoMemory ;
762					}
763					else
764						for (unsigned int i=0;i<mBufferRangeCount;i++)
765						{
766							mBufferAddressRanges[i].address = mBufferRanges[i].address;
767							mBufferAddressRanges[i].length = mBufferRanges[i].length;
768						}
769
770					programExportBytes 	= pool->Export( &programData, mBufferRanges, mBufferRangeCount ) ;
771					params.programExportBytes = programExportBytes ;
772					params.programData = programData;
773				}
774			}
775		}
776		else
777		{
778			unsigned programCount = 0 ;
779
780			params.version = kDCLExportDataLegacyVersion ;					// old-style DCL program
781
782			// count DCLs in program and coalesce buffers:
783			for( DCLCommand * dcl = mDCLProgram; dcl != nil; dcl = dcl->pNextDCLCommand )
784			{
785				IOVirtualRange tempRange ;
786				if ( GetDCLDataBuffer ( dcl, & tempRange.address, & tempRange.length ) )
787				{
788					bufferTree.CoalesceRange ( tempRange ) ;
789				}
790
791				++programCount ;
792			}
793
794			InfoLog("program count is %d\n", programCount) ;
795
796			if ( !error )
797			{
798				error = ExportDCLs( &programData, &programExportBytes ) ;
799				params.programData = programData;
800				params.programExportBytes = programExportBytes;
801			}
802
803			if ( !error )
804			{
805				mBufferRangeCount = bufferTree.GetCount() ;
806				mBufferRanges = new IOVirtualRange[ mBufferRangeCount ] ;
807
808				if ( !mBufferRanges )
809				{
810					error = kIOReturnNoMemory ;
811				}
812				else
813				{
814					bufferTree.GetCoalesceList( mBufferRanges ) ;
815
816					mBufferAddressRanges = new FWVirtualAddressRange[ mBufferRangeCount ] ;
817					if ( !mBufferAddressRanges )
818					{
819						error = kIOReturnNoMemory ;
820					}
821					else
822						for (unsigned int i=0;i<mBufferRangeCount;i++)
823						{
824							mBufferAddressRanges[i].address = mBufferRanges[i].address;
825							mBufferAddressRanges[i].length = mBufferRanges[i].length;
826						}
827				}
828			}
829		}
830
831		if ( error )
832		{
833			throw error ;
834		}
835
836//		// allocate lists to store buffer ranges
837//		// and get coalesced buffer lists
838//
839//		UInt32			bufferRangeCount					= bufferTree.GetCount() ;
840//		IOVirtualRange	bufferRanges[ bufferRangeCount ] ;
841//
842//		bufferTree.GetCoalesceList ( bufferRanges ) ;
843
844		// fill out param struct and submit to kernel
845		params.bufferRanges					= (mach_vm_address_t)mBufferAddressRanges ;
846		params.bufferRangeCount				= mBufferRangeCount ;
847		params.talking						= mTalking ;
848		params.startEvent					= startEvent ;
849		params.startState					= startState ;
850		params.startMask					= startMask ;
851		params.userObj						= (mach_vm_address_t) this ;
852		params.options						= options ;
853
854#if 0
855		params.options |= kFWIsochEnableRobustness;
856#endif
857
858		InfoLog("startEvent=%x, startState=%x, startMask=%x\n", params.startEvent, params.startState, params.startMask) ;
859
860#ifndef __LP64__
861		ROSETTA_ONLY(
862			{
863				params.version = OSSwapInt32( params.version );
864				params.talking = params.talking; // byte
865				params.startEvent = OSSwapInt32( params.startEvent );
866				params.startState = OSSwapInt32( params.startState );
867				params.startMask = OSSwapInt32( params.startMask );
868				params.programExportBytes = OSSwapInt32( params.programExportBytes );
869				params.programData = OSSwapInt64( params.programData );
870
871				for( UInt32 i = 0; i < params.bufferRangeCount; i++ )
872				{
873					IOAddressRange *pAddressRange = (IOAddressRange*) (params.bufferRanges+(i*sizeof(IOAddressRange)));
874
875					pAddressRange->address = OSSwapInt64( pAddressRange->address );
876					pAddressRange->length = OSSwapInt64( pAddressRange->length );
877
878				}
879
880				params.bufferRangeCount = OSSwapInt32( params.bufferRangeCount );
881				params.bufferRanges = OSSwapInt64(params.bufferRanges );
882				params.options = (IOFWIsochPortOptions)OSSwapInt32( params.options | kFWIsochBigEndianUpdates );
883				params.userObj = (mach_vm_address_t)OSSwapInt64((mach_vm_address_t)params.userObj );
884			}
885		);
886#endif
887
888		uint32_t outputCnt = 0;
889		size_t outputStructSize = sizeof( UserObjectHandle ) ;
890		error =  IOConnectCallMethod(mDevice.GetUserClientConnection(),
891									 kLocalIsochPort_Allocate,
892									 NULL,0,
893									 & params,sizeof (params),
894									 NULL,&outputCnt,
895									 &mKernPortRef,&outputStructSize);
896#ifndef __LP64__
897		ROSETTA_ONLY(
898			{
899				mKernPortRef = (UserObjectHandle)OSSwapInt32( (UInt32)mKernPortRef );
900			}
901		);
902#endif
903
904		if (error)
905		{
906			DebugLog ( "Couldn't create local isoch port (error=%x)\nCheck your buffers!\n", error ) ;
907			DebugLog ( "Found buffers:\n" ) ;
908
909#if IOFIREWIRELIBDEBUG
910			for( unsigned index=0; index < mBufferRangeCount; ++index )
911			{
912#ifdef __LP64__
913				DebugLog (	"\%u: <0x%x>-<0x%x>\n", index, (unsigned)mBufferRanges[index].address,
914							(unsigned)mBufferRanges[index].address + mBufferRanges[index].length ) ;
915#else
916				DebugLog (	"\%u: <0x%x>-<0x%lx>\n", index, (unsigned)mBufferRanges[index].address,
917							(unsigned)mBufferRanges[index].address + mBufferRanges[index].length ) ;
918#endif
919			}
920#endif
921
922			throw error ;
923		}
924
925		{
926			uint64_t refrncData[kOSAsyncRef64Count];
927			refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) & LocalIsochPort::s_DCLStopTokenCallProcHandler;
928			refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)this;
929			uint32_t outputCnt = 0;
930			const uint64_t inputs[1]={(const uint64_t)mKernPortRef};
931
932			error = IOConnectCallAsyncScalarMethod(mDevice.GetUserClientConnection(),
933												   kSetAsyncRef_DCLCallProc,
934												   mDevice.GetIsochAsyncPort(),
935												   refrncData,kOSAsyncRef64Count,
936												   inputs,1,
937												   NULL,&outputCnt);
938
939			if( error )
940			{
941				throw error ;
942			}
943		}
944
945		if ( params.programData )
946		{
947			vm_deallocate( mach_task_self (), (vm_address_t) programData, programExportBytes ) ;		// this is temporary storage
948		}
949
950		// make our mutex
951		pthread_mutex_init ( & mMutex, nil ) ;
952	}
953
954	LocalIsochPort::~LocalIsochPort ()
955	{
956		delete[] mBufferRanges ;
957		delete[] mBufferAddressRanges;
958
959		pthread_mutex_destroy( & mMutex ) ;
960	}
961
962	ULONG
963	LocalIsochPort::Release ()
964	{
965		Lock () ;
966
967		if ( mExpectedStopTokens > 0 )
968		{
969			Unlock () ;
970			++ mDeferredReleaseCount ;
971			return mRefCount ;
972		}
973
974		Unlock () ;
975
976//		while( true )
977//		{
978//			Lock() ;
979//			bool run = ( mExpectedStopTokens > 0 ) ;
980//			Unlock() ;
981//
982//			if ( !run )
983//			{
984//				break ;
985//			}
986//
987//			::CFRunLoopRunInMode( kCFRunLoopDefaultMode, 1, true ) ;
988//		}
989
990		return IsochPortCOM::Release() ;
991	}
992
993	IOReturn
994	LocalIsochPort::Start()
995	{
996		IOReturn error = IsochPort::Start() ;
997		if ( !error )
998		{
999			Lock() ;
1000			mStarted = true ;
1001			Unlock() ;
1002		}
1003
1004		return error ;
1005	}
1006
1007	IOReturn
1008	LocalIsochPort::Stop ()
1009	{
1010		Lock() ;
1011		if ( mStarted )
1012		{
1013			mStarted = false ;
1014			++mExpectedStopTokens ;
1015			InfoLog("waiting for %lu stop tokens\n", mExpectedStopTokens) ;
1016		}
1017		Unlock() ;
1018
1019		return IsochPortCOM::Stop() ;	// call superclass Stop()
1020	}
1021
1022	IOReturn
1023	LocalIsochPort::ModifyJumpDCL ( DCLJump* inJump, DCLLabel* inLabel )
1024	{
1025		inJump->pJumpDCLLabel = inLabel ;
1026
1027		uint32_t outputCnt = 0;
1028		const uint64_t inputs[2] = {inJump->compilerData, inLabel->compilerData};
1029		IOReturn result =  IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
1030													 mDevice.MakeSelectorWithObject( kLocalIsochPort_ModifyJumpDCL_d, mKernPortRef ),
1031													 inputs,2,
1032													 NULL,&outputCnt);
1033		return result ;
1034	}
1035
1036	IOReturn
1037	LocalIsochPort::ModifyTransferPacketDCLSize ( DCLTransferPacket* dcl, IOByteCount newSize )
1038	{
1039		//kLocalIsochPort_ModifyTransferPacketDCLSize,
1040		return kIOReturnUnsupported ;
1041	}
1042
1043	void
1044	LocalIsochPort::s_DCLStopTokenCallProcHandler ( void * self, IOReturn e )
1045	{
1046		((LocalIsochPort*)self)->DCLStopTokenCallProcHandler(e) ;
1047	}
1048
1049	void
1050	LocalIsochPort::DCLStopTokenCallProcHandler( IOReturn )
1051	{
1052		if ( mExpectedStopTokens > 0 )
1053		{
1054			Lock() ;
1055			mExpectedStopTokens-- ;
1056			Unlock() ;
1057
1058			if ( mExpectedStopTokens == 0 )
1059			{
1060				if ( mFinalizeCallback )
1061					(*mFinalizeCallback)(mRefCon) ;
1062
1063				// use a local so we don't touch "this" after release
1064				UInt32 release_count = mDeferredReleaseCount;
1065				while ( release_count > 0 )
1066				{
1067					--release_count ;
1068					Release() ;
1069				}
1070			}
1071		}
1072	}
1073#if 0
1074	void
1075	LocalIsochPort::S_DCLKernelCallout( DCLCallProc * dcl )
1076	{
1077		(*dcl->proc)(dcl->procData) ;
1078
1079		uint32_t outputCnt = 0;
1080		const uint64_t inputs[1]={(const uint64_t)dcl->compilerData};
1081
1082		IOReturn result =  IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
1083													 Device::MakeSelectorWithObject( kLocalIsochPort_RunDCLUpdateList_d, port->mKernPortRef ),
1084													 inputs,1,
1085													 NULL,&outputCnt);
1086	}
1087
1088	void
1089	LocalIsochPort::S_NuDCLKernelCallout ( NuDCL * dcl )
1090	{
1091		(*dcl->fData.callback)(dcl->fData.refcon, (NuDCLRef)dcl) ;
1092
1093		uint32_t outputCnt = 0;
1094		const uint64_t inputs[1]={(const uint64_t)dcl->fExportIndex};
1095
1096		IOReturn result =  IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
1097													 Device::MakeSelectorWithObject( kLocalIsochPort_RunNuDCLUpdateList_d, mKernPortRef ),
1098													 inputs,1,
1099													 NULL,&outputCnt);
1100	}
1101#endif
1102
1103	IOReturn
1104	LocalIsochPort::SetResourceUsageFlags (
1105				IOFWIsochResourceFlags 			flags )
1106	{
1107		uint32_t outputCnt = 0;
1108		const uint64_t inputs[1]={(const uint64_t)flags};
1109
1110		return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
1111										 mDevice.MakeSelectorWithObject( kIsochPort_SetIsochResourceFlags_d, mKernPortRef ),
1112										 inputs,1,
1113										 NULL,&outputCnt);
1114	}
1115
1116	IOReturn
1117	LocalIsochPort::ExportDCLs( IOVirtualAddress * exportBuffer, IOByteCount * exportBytes )
1118	{
1119		IOReturn error = kIOReturnSuccess ;
1120
1121		// see how much space we need for serialization...
1122
1123//		unsigned byteCount = 0 ;
1124		*exportBytes = 0 ;
1125		for( DCLCommand * dcl = mDCLProgram; dcl != NULL; dcl = dcl->pNextDCLCommand )
1126		{
1127			*exportBytes += GetDCLSize( dcl ) ;
1128
1129			switch ( dcl->opcode & ~kFWDCLOpFlagMask )
1130			{
1131				case kDCLUpdateDCLListOp :
1132				{
1133					// update DCLs store a copy of their update list in the export buffer
1134					*exportBytes += sizeof( mach_vm_address_t ) * ((DCLUpdateDCLList*)dcl)->numDCLCommands ;
1135					break ;
1136				}
1137				case kDCLCallProcOp :
1138				{
1139					*exportBytes += sizeof( uint64_t[kOSAsyncRef64Count]) ;
1140					break ;
1141				}
1142			}
1143		}
1144
1145		// buffer to hold copy of DCLs in program
1146		error = vm_allocate( mach_task_self (), (vm_address_t*)exportBuffer, *exportBytes, true /*anywhere*/ ) ;
1147
1148		if ( !*exportBuffer && !error )
1149		{
1150			error = kIOReturnNoMemory ;
1151		}
1152
1153		// start from beginning
1154		{
1155			unsigned offset = 0 ;
1156			IOVirtualAddress buffer = *exportBuffer ;
1157
1158			InfoLog("exporting DCLs, pass 1...\n") ;
1159
1160			for( DCLCommand * dcl = mDCLProgram; dcl != NULL ; dcl = dcl->pNextDCLCommand )
1161			{
1162
1163				unsigned size = GetDCLSize( dcl ) ;
1164
1165				dcl->compilerData = offset ;		// save for later.
1166
1167				// Copy the DCLs into the buffer using the ExportDCL structs
1168				switch(dcl->opcode & ~kFWDCLOpFlagMask)
1169				{
1170					case kDCLSendPacketStartOp:
1171					//case kDCLSendPacketWithHeaderStartOp:
1172					case kDCLSendPacketOp:
1173					case kDCLReceivePacketStartOp:
1174					case kDCLReceivePacketOp:
1175						{
1176							UserExportDCLTransferPacket *pUserExportDCLTransferPacket = (UserExportDCLTransferPacket*) buffer;
1177							pUserExportDCLTransferPacket->pClientDCLStruct = (mach_vm_address_t) dcl;
1178							pUserExportDCLTransferPacket->pNextDCLCommand = (mach_vm_address_t) ((DCLTransferPacket*)dcl)->pNextDCLCommand;
1179							pUserExportDCLTransferPacket->compilerData = ((DCLTransferPacket*)dcl)->compilerData;
1180							pUserExportDCLTransferPacket->opcode = ((DCLTransferPacket*)dcl)->opcode;
1181							pUserExportDCLTransferPacket->buffer = (mach_vm_address_t) ((DCLTransferPacket*)dcl)->buffer;
1182							pUserExportDCLTransferPacket->size = ((DCLTransferPacket*)dcl)->size;
1183						}
1184						break ;
1185
1186					case kDCLSendBufferOp:
1187					case kDCLReceiveBufferOp:
1188						{
1189							UserExportDCLTransferBuffer *pUserExportDCLTransferBuffer = (UserExportDCLTransferBuffer*) buffer;
1190							pUserExportDCLTransferBuffer->pClientDCLStruct = (mach_vm_address_t) dcl;
1191							pUserExportDCLTransferBuffer->pNextDCLCommand = (mach_vm_address_t) ((DCLTransferBuffer*)dcl)->pNextDCLCommand;
1192							pUserExportDCLTransferBuffer->compilerData = ((DCLTransferBuffer*)dcl)->compilerData;
1193							pUserExportDCLTransferBuffer->opcode = ((DCLTransferBuffer*)dcl)->opcode;
1194							pUserExportDCLTransferBuffer->buffer = (mach_vm_address_t) ((DCLTransferBuffer*)dcl)->buffer;
1195							pUserExportDCLTransferBuffer->size = ((DCLTransferBuffer*)dcl)->size;
1196							pUserExportDCLTransferBuffer->packetSize = ((DCLTransferBuffer*)dcl)->packetSize;
1197							pUserExportDCLTransferBuffer->reserved = ((DCLTransferBuffer*)dcl)->reserved;
1198							pUserExportDCLTransferBuffer->bufferOffset = ((DCLTransferBuffer*)dcl)->bufferOffset;
1199						}
1200						break ;
1201
1202					case kDCLCallProcOp:
1203						{
1204							UserExportDCLCallProc *pUserExportDCLCallProc = (UserExportDCLCallProc*) buffer;
1205							pUserExportDCLCallProc->pClientDCLStruct = (mach_vm_address_t) dcl;
1206							pUserExportDCLCallProc->pNextDCLCommand = (mach_vm_address_t) ((DCLCallProc*)dcl)->pNextDCLCommand;
1207							pUserExportDCLCallProc->compilerData = ((DCLCallProc*)dcl)->compilerData;
1208							pUserExportDCLCallProc->opcode = ((DCLCallProc*)dcl)->opcode;
1209							pUserExportDCLCallProc->proc = (mach_vm_address_t) ((DCLCallProc*)dcl)->proc;
1210							//pUserExportDCLCallProc->procData = (uint64_t) ((DCLCallProc*)dcl)->procData;
1211							pUserExportDCLCallProc->procData = (uint64_t)dcl ;
1212							size += sizeof( uint64_t[kOSAsyncRef64Count]) ;
1213						}
1214						break ;
1215
1216					case kDCLLabelOp:
1217						{
1218							UserExportDCLLabel *pUserExportDCLLabel = (UserExportDCLLabel*) buffer;
1219							pUserExportDCLLabel->pClientDCLStruct = (mach_vm_address_t) dcl;
1220							pUserExportDCLLabel->pNextDCLCommand = (mach_vm_address_t) ((DCLLabel*)dcl)->pNextDCLCommand;
1221							pUserExportDCLLabel->compilerData = ((DCLLabel*)dcl)->compilerData;
1222							pUserExportDCLLabel->opcode = ((DCLLabel*)dcl)->opcode;
1223						}
1224						break ;
1225
1226					case kDCLJumpOp:
1227						{
1228							UserExportDCLJump *pUserExportDCLJump = (UserExportDCLJump*) buffer;
1229							pUserExportDCLJump->pClientDCLStruct = (mach_vm_address_t) dcl;
1230							pUserExportDCLJump->pNextDCLCommand = (mach_vm_address_t) ((DCLJump*)dcl)->pNextDCLCommand;
1231							pUserExportDCLJump->compilerData = ((DCLJump*)dcl)->compilerData;
1232							pUserExportDCLJump->opcode = ((DCLJump*)dcl)->opcode;
1233							pUserExportDCLJump->pJumpDCLLabel = (mach_vm_address_t) ((DCLJump*)dcl)->pJumpDCLLabel;
1234						}
1235						break ;
1236
1237					case kDCLSetTagSyncBitsOp:
1238						{
1239							UserExportDCLSetTagSyncBits *pUserExportDCLSetTagSyncBits = (UserExportDCLSetTagSyncBits*) buffer;
1240							pUserExportDCLSetTagSyncBits->pClientDCLStruct = (mach_vm_address_t) dcl;
1241							pUserExportDCLSetTagSyncBits->pNextDCLCommand = (mach_vm_address_t) ((DCLSetTagSyncBits*)dcl)->pNextDCLCommand;
1242							pUserExportDCLSetTagSyncBits->compilerData = ((DCLSetTagSyncBits*)dcl)->compilerData;
1243							pUserExportDCLSetTagSyncBits->opcode = ((DCLSetTagSyncBits*)dcl)->opcode;
1244							pUserExportDCLSetTagSyncBits->tagBits = ((DCLSetTagSyncBits*)dcl)->tagBits;
1245							pUserExportDCLSetTagSyncBits->syncBits = ((DCLSetTagSyncBits*)dcl)->syncBits;
1246						}
1247						break ;
1248
1249					case kDCLUpdateDCLListOp:
1250						{
1251							UserExportDCLUpdateDCLList *pUserExportDCLUpdateDCLList = (UserExportDCLUpdateDCLList*) buffer;
1252							pUserExportDCLUpdateDCLList->pClientDCLStruct = (mach_vm_address_t) dcl;
1253							pUserExportDCLUpdateDCLList->pNextDCLCommand = (mach_vm_address_t) ((DCLUpdateDCLList*)dcl)->pNextDCLCommand;
1254							pUserExportDCLUpdateDCLList->compilerData = ((DCLUpdateDCLList*)dcl)->compilerData;
1255							pUserExportDCLUpdateDCLList->opcode = ((DCLUpdateDCLList*)dcl)->opcode;
1256							pUserExportDCLUpdateDCLList->dclCommandList = (mach_vm_address_t) ((DCLUpdateDCLList*)dcl)->dclCommandList;
1257							pUserExportDCLUpdateDCLList->numDCLCommands = ((DCLUpdateDCLList*)dcl)->numDCLCommands;
1258							size += ( sizeof( mach_vm_address_t ) * ((DCLUpdateDCLList*)dcl)->numDCLCommands ) ;
1259						}
1260						break ;
1261
1262					case kDCLPtrTimeStampOp:
1263						{
1264							UserExportDCLPtrTimeStamp *pUserExportDCLPtrTimeStamp = (UserExportDCLPtrTimeStamp*) buffer;
1265							pUserExportDCLPtrTimeStamp->pClientDCLStruct = (mach_vm_address_t) dcl;
1266							pUserExportDCLPtrTimeStamp->pNextDCLCommand = (mach_vm_address_t) ((DCLPtrTimeStamp*)dcl)->pNextDCLCommand;
1267							pUserExportDCLPtrTimeStamp->compilerData = ((DCLPtrTimeStamp*)dcl)->compilerData;
1268							pUserExportDCLPtrTimeStamp->opcode = ((DCLPtrTimeStamp*)dcl)->opcode;
1269							pUserExportDCLPtrTimeStamp->timeStampPtr = (mach_vm_address_t) ((DCLPtrTimeStamp*)dcl)->timeStampPtr;
1270						}
1271						break ;
1272
1273					case kDCLSkipCycleOp:
1274						{
1275							UserExportDCLCommand *pUserExportDCLCommand = (UserExportDCLCommand*) buffer;
1276							pUserExportDCLCommand->pClientDCLStruct = (mach_vm_address_t) dcl;
1277							pUserExportDCLCommand->pNextDCLCommand = (mach_vm_address_t) ((DCLCommand*)dcl)->pNextDCLCommand;
1278							pUserExportDCLCommand->compilerData = ((DCLCommand*)dcl)->compilerData;
1279							pUserExportDCLCommand->opcode = ((DCLCommand*)dcl)->opcode;
1280							pUserExportDCLCommand->operands[0] = ((DCLCommand*)dcl)->operands[0];
1281						}
1282						break ;
1283				}
1284
1285				// Account for this DCL's exported bytes
1286				buffer += size ;
1287				offset += size ;
1288			}
1289
1290			InfoLog("...done\n") ;
1291		}
1292
1293		// some DCLs (jumps and update list DCLs) refer to other DCLs with
1294		// user space pointers which makes translation a bit harder.
1295		// The 'compilerData' field of all the DCLs in our export data block
1296		// contain an offset in bytes from the beginning of the exported data
1297		// block..
1298		// We now replace any user space pointers with offsets for kernel use..
1299		{
1300			unsigned offset = 0 ;
1301
1302			InfoLog("exporting DCLs, pass 2... export size=%d bytes\n", (int)*exportBytes ) ;
1303
1304			while( offset < *exportBytes )
1305			{
1306				UserExportDCLCommand * dcl = (UserExportDCLCommand*)(*exportBuffer + offset ) ;
1307				DCLCommand *pClientDCL = (DCLCommand *) dcl->pClientDCLStruct;
1308
1309//				DebugLog("DCL=%p, offset=%x, opcode=%x\n", dcl, offset, dcl->opcode) ;
1310
1311				{
1312					unsigned opcode = dcl->opcode & ~kFWDCLOpFlagMask ;
1313					assert( opcode <= 15 || opcode == 20 ) ;
1314				}
1315
1316				unsigned size = GetDCLSize( pClientDCL ) ;
1317
1318				switch ( dcl->opcode & ~kFWDCLOpFlagMask )
1319				{
1320					case kDCLUpdateDCLListOp :
1321					{
1322						// make list of offsets from list of user space DCL pointers
1323						// List starts after DCL in question on export buffer
1324						mach_vm_address_t* list = (mach_vm_address_t*)( ((UserExportDCLUpdateDCLList*)dcl) + 1 )  ;
1325						for( unsigned index=0; index < ((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands; ++index )
1326						{
1327							list[ index ] = (mach_vm_address_t) ((DCLUpdateDCLList*)pClientDCL)->dclCommandList[ index ]->compilerData ;
1328						}
1329
1330						size += sizeof( mach_vm_address_t ) * ((DCLUpdateDCLList*)pClientDCL)->numDCLCommands ;
1331
1332						break ;
1333					}
1334
1335					case kDCLJumpOp :
1336					{
1337						((UserExportDCLJump*)dcl)->pJumpDCLLabel = (mach_vm_address_t) ((DCLJump*)pClientDCL)->pJumpDCLLabel->compilerData ;
1338						break ;
1339					}
1340
1341					case kDCLCallProcOp :
1342					{
1343						size += sizeof( uint64_t[kOSAsyncRef64Count]) ;
1344						break ;
1345					}
1346
1347					default :
1348
1349						break ;
1350				}
1351
1352#ifndef __LP64__
1353				ROSETTA_ONLY(
1354					{
1355						switch(dcl->opcode & ~kFWDCLOpFlagMask)
1356						{
1357							case kDCLSendPacketStartOp:
1358							//case kDCLSendPacketWithHeaderStartOp:
1359							case kDCLSendPacketOp:
1360							case kDCLReceivePacketStartOp:
1361							case kDCLReceivePacketOp:
1362								((UserExportDCLTransferPacket*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLTransferPacket*)dcl)->pNextDCLCommand );
1363								((UserExportDCLTransferPacket*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLTransferPacket*)dcl)->compilerData );
1364								((UserExportDCLTransferPacket*)dcl)->opcode = OSSwapInt32( ((UserExportDCLTransferPacket*)dcl)->opcode );
1365								((UserExportDCLTransferPacket*)dcl)->buffer = (mach_vm_address_t)OSSwapInt64( ((UserExportDCLTransferPacket*)dcl)->buffer );
1366								((UserExportDCLTransferPacket*)dcl)->size = OSSwapInt32( ((UserExportDCLTransferPacket*)dcl)->size );
1367								break ;
1368
1369							case kDCLSendBufferOp:
1370							case kDCLReceiveBufferOp:
1371								((UserExportDCLTransferBuffer*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLTransferBuffer*)dcl)->pNextDCLCommand );
1372								((UserExportDCLTransferBuffer*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->compilerData );
1373								((UserExportDCLTransferBuffer*)dcl)->opcode = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->opcode );
1374								((UserExportDCLTransferBuffer*)dcl)->buffer = (mach_vm_address_t)OSSwapInt64(((UserExportDCLTransferBuffer*)dcl)->buffer );
1375								((UserExportDCLTransferBuffer*)dcl)->size = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->size );
1376								((UserExportDCLTransferBuffer*)dcl)->packetSize = OSSwapInt16( ((UserExportDCLTransferBuffer*)dcl)->packetSize );
1377								((UserExportDCLTransferBuffer*)dcl)->reserved = OSSwapInt16( ((UserExportDCLTransferBuffer*)dcl)->reserved );
1378								((UserExportDCLTransferBuffer*)dcl)->bufferOffset = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->bufferOffset );
1379								break ;
1380
1381							case kDCLCallProcOp:
1382								((UserExportDCLCallProc*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLCallProc*)dcl)->pNextDCLCommand );
1383								((UserExportDCLCallProc*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLCallProc*)dcl)->compilerData );
1384								((UserExportDCLCallProc*)dcl)->opcode = OSSwapInt32( ((UserExportDCLCallProc*)dcl)->opcode );
1385								((UserExportDCLCallProc*)dcl)->proc = (mach_vm_address_t)OSSwapInt64(((UserExportDCLCallProc*)dcl)->proc );
1386								((UserExportDCLCallProc*)dcl)->procData = OSSwapInt64( ((UserExportDCLCallProc*)dcl)->procData );
1387								break ;
1388
1389							case kDCLLabelOp:
1390								((UserExportDCLLabel*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLLabel*)dcl)->pNextDCLCommand );
1391								((UserExportDCLLabel*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLLabel*)dcl)->compilerData );
1392								((UserExportDCLLabel*)dcl)->opcode = OSSwapInt32( ((UserExportDCLLabel*)dcl)->opcode );
1393								break ;
1394
1395							case kDCLJumpOp:
1396								((UserExportDCLJump*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64( ((UserExportDCLJump*)dcl)->pNextDCLCommand );
1397								((UserExportDCLJump*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLJump*)dcl)->compilerData );
1398								((UserExportDCLJump*)dcl)->opcode = OSSwapInt32( ((UserExportDCLJump*)dcl)->opcode );
1399								((UserExportDCLJump*)dcl)->pJumpDCLLabel = (mach_vm_address_t)OSSwapInt64(((UserExportDCLJump*)dcl)->pJumpDCLLabel );
1400								break ;
1401
1402							case kDCLSetTagSyncBitsOp:
1403								((UserExportDCLSetTagSyncBits*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLSetTagSyncBits*)dcl)->pNextDCLCommand );
1404								((UserExportDCLSetTagSyncBits*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLSetTagSyncBits*)dcl)->compilerData );
1405								((UserExportDCLSetTagSyncBits*)dcl)->opcode = OSSwapInt32( ((UserExportDCLSetTagSyncBits*)dcl)->opcode );
1406								((UserExportDCLSetTagSyncBits*)dcl)->tagBits = OSSwapInt16( ((UserExportDCLSetTagSyncBits*)dcl)->tagBits );
1407								((UserExportDCLSetTagSyncBits*)dcl)->syncBits = OSSwapInt16( ((UserExportDCLSetTagSyncBits*)dcl)->syncBits );
1408								break ;
1409
1410							case kDCLUpdateDCLListOp:
1411								((UserExportDCLUpdateDCLList*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLUpdateDCLList*)dcl)->pNextDCLCommand );
1412								((UserExportDCLUpdateDCLList*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLUpdateDCLList*)dcl)->compilerData );
1413								((UserExportDCLUpdateDCLList*)dcl)->opcode = OSSwapInt32( ((UserExportDCLUpdateDCLList*)dcl)->opcode );
1414
1415								{
1416									mach_vm_address_t * list = (mach_vm_address_t *)( ((UserExportDCLUpdateDCLList*)dcl) + 1 )  ;
1417									for( unsigned index=0; index < ((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands; ++index )
1418									{
1419										list[ index ] = (mach_vm_address_t)OSSwapInt64(list[ index ] );
1420									}
1421								}
1422
1423								((UserExportDCLUpdateDCLList*)dcl)->dclCommandList = (mach_vm_address_t)OSSwapInt64(((UserExportDCLUpdateDCLList*)dcl)->dclCommandList );
1424								((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands = OSSwapInt32( ((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands );
1425								break ;
1426
1427							case kDCLPtrTimeStampOp:
1428								((UserExportDCLPtrTimeStamp*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLPtrTimeStamp*)dcl)->pNextDCLCommand );
1429								((UserExportDCLPtrTimeStamp*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLPtrTimeStamp*)dcl)->compilerData );
1430								((UserExportDCLPtrTimeStamp*)dcl)->opcode = OSSwapInt32( ((UserExportDCLPtrTimeStamp*)dcl)->opcode );
1431								((UserExportDCLPtrTimeStamp*)dcl)->timeStampPtr = (mach_vm_address_t)OSSwapInt64(((UserExportDCLPtrTimeStamp*)dcl)->timeStampPtr );
1432								break;
1433
1434							case kDCLSkipCycleOp:
1435								((UserExportDCLCommand*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLCommand*)dcl)->pNextDCLCommand );
1436								((UserExportDCLCommand*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLCommand*)dcl)->compilerData );
1437								((UserExportDCLCommand*)dcl)->opcode = OSSwapInt32( ((UserExportDCLCommand*)dcl)->opcode );
1438								((UserExportDCLCommand*)dcl)->operands[0] = OSSwapInt32( ((UserExportDCLCommand*)dcl)->operands[0] );
1439								break;
1440						}
1441					}
1442				);
1443#endif
1444
1445				offset += size ;
1446
1447			}
1448
1449			InfoLog("...done\n") ;
1450
1451		}
1452
1453		// fill in DCL compiler data fields with ( program index + 1 ) ;
1454		{
1455			unsigned count = 0 ;
1456			for( DCLCommand * dcl = mDCLProgram; dcl != nil; dcl = dcl->pNextDCLCommand )
1457			{
1458				dcl->compilerData = ++count ;		// index incremented here..
1459													// compiler data for DCL should be index + 1
1460			}
1461		}
1462
1463		return error ;
1464	}
1465
1466	IOReturn
1467	LocalIsochPort::Notify (
1468		IOFWDCLNotificationType 	notificationType,
1469		void ** 					inDCLList,
1470		UInt32 						numDCLs )
1471	{
1472		IOReturn error = kIOReturnSuccess ;
1473
1474		switch( notificationType )
1475		{
1476			case kFWNuDCLModifyNotification:
1477			{
1478				IOByteCount dataSize = 0 ;
1479				for( unsigned index=0; index < numDCLs; ++index )
1480				{
1481					dataSize += 4 + ((NuDCL**)inDCLList)[ index ]->Export( NULL, NULL, 0 ) ;
1482				}
1483
1484				UInt8 *data;
1485				error = vm_allocate ( mach_task_self (), (vm_address_t *) &data, dataSize, true /*anywhere*/ ) ;
1486				if (error)
1487					break;
1488
1489				{
1490					UInt8 * exportCursor = data ;
1491					for( unsigned index=0; index < numDCLs; ++index )
1492					{
1493						NuDCL * dcl = ((NuDCL**)inDCLList)[ index ] ;
1494						*(UInt32*)exportCursor = dcl->GetExportIndex() ;
1495
1496#ifndef __LP64__
1497						ROSETTA_ONLY(
1498							{
1499								*(UInt32*)exportCursor = OSSwapInt32(*(UInt32*)exportCursor);
1500							}
1501						);
1502#endif
1503						exportCursor += sizeof( UInt32 ) ;
1504
1505						dcl->Export( (IOVirtualAddress*) & exportCursor, mBufferRanges, mBufferRangeCount ) ;
1506					}
1507				}
1508
1509				uint32_t outputCnt = 0;
1510				const uint64_t inputs[4] = {notificationType, numDCLs, (uint64_t) data, dataSize};
1511				error = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
1512												  Device::MakeSelectorWithObject( kLocalIsochPort_Notify_d, mKernPortRef ),
1513												  inputs,4,NULL,&outputCnt);
1514				vm_deallocate( mach_task_self (), (vm_address_t) data, dataSize ) ;
1515				break ;
1516			}
1517
1518			case kFWNuDCLModifyJumpNotification:
1519			{
1520				unsigned pairCount = numDCLs << 1 ;
1521
1522				unsigned dcls[ pairCount ] ;
1523
1524				{
1525					unsigned index = 0 ;
1526					unsigned pairIndex=0;
1527
1528					while( pairIndex < pairCount )
1529					{
1530						NuDCL * theDCL = ((NuDCL**)inDCLList)[ index++ ] ;
1531						dcls[ pairIndex ] = theDCL->GetExportIndex() ;
1532#ifndef __LP64__
1533						ROSETTA_ONLY(
1534							{
1535								dcls[ pairIndex ] = OSSwapInt32(dcls[ pairIndex ]);
1536							}
1537						);
1538#endif
1539						pairIndex += 1;
1540
1541
1542						if (theDCL->GetBranch())
1543							dcls[ pairIndex ] = theDCL->GetBranch()->GetExportIndex() ;
1544						else
1545							dcls[ pairIndex ] = 0;
1546#ifndef __LP64__
1547						ROSETTA_ONLY(
1548							{
1549								dcls[ pairIndex ] = OSSwapInt32(dcls[ pairIndex ]);
1550							}
1551						);
1552#endif
1553						pairIndex += 1;
1554					}
1555				}
1556
1557				uint32_t outputCnt = 0;
1558				size_t outputStructSize =  0 ;
1559				const uint64_t inputs[2] = {notificationType, numDCLs};
1560				error = IOConnectCallMethod(mDevice.GetUserClientConnection(),
1561											Device::MakeSelectorWithObject( kLocalIsochPort_Notify_d, mKernPortRef ),
1562											inputs,2,
1563											dcls,sizeof( dcls ),
1564											NULL,&outputCnt,
1565											NULL,&outputStructSize);
1566				break ;
1567			}
1568
1569			case kFWNuDCLUpdateNotification:
1570			{
1571				unsigned dcls[ numDCLs ] ;
1572
1573				for( unsigned index=0; index < numDCLs; ++index )
1574				{
1575					dcls[ index ] = ((NuDCL*)inDCLList[ index ])->GetExportIndex() ;
1576#ifndef __LP64__
1577					ROSETTA_ONLY(
1578						{
1579							dcls[ index ] = OSSwapInt32(dcls[ index ]);
1580							}
1581						);
1582#endif
1583				}
1584
1585				uint32_t outputCnt = 0;
1586				size_t outputStructSize =  0 ;
1587				const uint64_t inputs[2] = {notificationType, numDCLs};
1588				error = IOConnectCallMethod(mDevice.GetUserClientConnection(),
1589											Device::MakeSelectorWithObject( kLocalIsochPort_Notify_d, mKernPortRef ),
1590											inputs,2,
1591											dcls,sizeof( dcls ),
1592											NULL,&outputCnt,
1593											NULL,&outputStructSize);
1594				break ;
1595			}
1596
1597			case kFWDCLUpdateNotification:
1598			case kFWDCLModifyNotification:
1599			{
1600				error = kIOReturnUnsupported ;
1601			}
1602
1603			default:
1604				error = kIOReturnBadArgument ;
1605		}
1606
1607		return error ;
1608	}
1609
1610#pragma mark -
1611	// ============================================================
1612	//
1613	// LocalIsochPortCOM
1614	//
1615	// ============================================================
1616
1617	LocalIsochPortCOM::LocalIsochPortCOM( Device& userclient, bool talking, DCLCommand* program, UInt32 startEvent,
1618			UInt32 startState, UInt32 startMask, IOVirtualRange programRanges[], UInt32 programRangeCount,
1619			IOVirtualRange bufferRanges[], UInt32 bufferRangeCount, IOFWIsochPortOptions options )
1620	: LocalIsochPort( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, talking, program,
1621			startEvent, startState, startMask, programRanges,
1622			programRangeCount, bufferRanges, bufferRangeCount, options )
1623	{
1624	}
1625
1626	LocalIsochPortCOM::~LocalIsochPortCOM()
1627	{
1628	}
1629
1630	IUnknownVTbl**
1631	LocalIsochPortCOM::Alloc( Device & userclient, Boolean talking, DCLCommand * program,
1632			UInt32 startEvent, UInt32 startState, UInt32 startMask,
1633			IOVirtualRange programRanges[], UInt32 programRangeCount,
1634			IOVirtualRange bufferRanges[], UInt32 bufferRangeCount,
1635			IOFWIsochPortOptions options )
1636	{
1637		LocalIsochPortCOM*	me = nil ;
1638
1639		try
1640		{
1641			me = new LocalIsochPortCOM (	userclient, (bool)talking, program, startEvent, startState, startMask,
1642											programRanges, programRangeCount, bufferRanges, bufferRangeCount, options ) ;
1643		}
1644		catch(...)
1645		{
1646		}
1647
1648		return ( nil == me ) ? nil : reinterpret_cast < IUnknownVTbl ** > ( & me->GetInterface () ) ;
1649	}
1650
1651	HRESULT
1652	LocalIsochPortCOM::QueryInterface (	REFIID iid, void ** ppv )
1653	{
1654		HRESULT		result			= S_OK ;
1655		CFUUIDRef	interfaceID		= CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
1656
1657		*ppv = nil ;
1658
1659		if ( CFEqual(interfaceID, IUnknownUUID)
1660				|| CFEqual(interfaceID, kIOFireWireLocalIsochPortInterfaceID )
1661				|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v2 )
1662#if 0
1663				|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v3 )	// don't support this yet...
1664#endif
1665				|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v4 )
1666				|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v5 )
1667			)
1668		{
1669			* ppv = & GetInterface () ;
1670			AddRef () ;
1671		}
1672		else
1673		{
1674			DebugLog("unknown local isoch port interface UUID\n") ;
1675
1676			* ppv = nil ;
1677			result = E_NOINTERFACE ;
1678		}
1679
1680		:: CFRelease ( interfaceID ) ;
1681		return result ;
1682	}
1683
1684	IOReturn
1685	LocalIsochPortCOM::SModifyJumpDCL(
1686				IOFireWireLibLocalIsochPortRef 	self,
1687				DCLJump *	 					jump,
1688				DCLLabel *		 				label)
1689	{
1690		return IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis ( self )->ModifyJumpDCL ( jump, label ) ;
1691	}
1692
1693	//
1694	// utility functions
1695	//
1696
1697	void
1698	LocalIsochPortCOM::SPrintDCLProgram (
1699				IOFireWireLibLocalIsochPortRef 	self ,
1700				const DCLCommand *				program ,
1701				UInt32							length )
1702	{
1703		DeviceCOM::SPrintDCLProgram ( nil, program, length ) ;
1704	}
1705
1706	IOReturn
1707	LocalIsochPortCOM::SModifyTransferPacketDCLSize (
1708				PortRef 				self,
1709				DCLTransferPacket * 	dcl,
1710				IOByteCount 			newSize )
1711	{
1712		IOReturn error = kIOReturnBadArgument ;
1713
1714		switch ( dcl->opcode )
1715		{
1716			case kDCLSendPacketStartOp:
1717			//case kDCLSendPacketWithHeaderStartOp:
1718			case kDCLSendPacketOp:
1719			case kDCLReceivePacketStartOp:
1720			case kDCLReceivePacketOp:
1721			case kDCLReceiveBufferOp:
1722				error = IOFireWireIUnknown::InterfaceMap<LocalIsochPortCOM>::GetThis( self )->ModifyTransferPacketDCLSize( dcl, newSize ) ;
1723		}
1724
1725		return error ;
1726	}
1727
1728	IOReturn
1729	LocalIsochPortCOM::SModifyTransferPacketDCLBuffer (
1730				PortRef 				self,
1731				DCLTransferPacket * 	dcl,
1732				void * 					newBuffer )
1733	{
1734		return kIOReturnUnsupported ;
1735	}
1736
1737	IOReturn
1738	LocalIsochPortCOM::SModifyTransferPacketDCL ( PortRef self, DCLTransferPacket * dcl, void * newBuffer, IOByteCount newSize )
1739	{
1740		return kIOReturnUnsupported ;
1741	}
1742
1743	//
1744	// v4
1745	//
1746
1747	IOReturn
1748	LocalIsochPortCOM::S_SetFinalizeCallback(
1749				IOFireWireLibLocalIsochPortRef 				self,
1750				IOFireWireLibIsochPortFinalizeCallback	 	finalizeCallback )
1751	{
1752		LocalIsochPortCOM * 	me = IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis( self ) ;
1753
1754		me->mFinalizeCallback = finalizeCallback ;
1755
1756		return kIOReturnSuccess ;
1757	}
1758
1759	//
1760	// v5 (panther)
1761	//
1762
1763	IOReturn
1764	LocalIsochPortCOM::S_SetResourceUsageFlags (
1765				IOFireWireLibLocalIsochPortRef	self,
1766				IOFWIsochResourceFlags 			flags )
1767	{
1768		return IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis( self )->SetResourceUsageFlags( flags ) ;
1769	}
1770
1771	IOReturn
1772	LocalIsochPortCOM::S_Notify(
1773				IOFireWireLibLocalIsochPortRef self,
1774				IOFWDCLNotificationType notificationType,
1775				void ** inDCLList,
1776				UInt32 numDCLs )
1777	{
1778		return  IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis( self )->Notify( notificationType, inDCLList, numDCLs ) ;
1779	}
1780}
1781