1/*
2 *  IOFWDCL.cpp
3 *  IOFireWireFamily
4 *
5 *  Created by Niels on Fri Feb 21 2003.
6 *  Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
7 *
8 *	$ Log:IOFWDCL.cpp,v $
9 */
10
11#import "IOFWDCL.h"
12#import "FWDebugging.h"
13#import "IOFWUserIsochPort.h"
14
15#import "IOFireWireLibNuDCL.h"
16
17#import <libkern/c++/OSCollectionIterator.h>
18
19#if FIRELOG
20#import <IOKit/firewire/FireLog.h>
21#define FIRELOG_MSG(x) FireLog x
22#else
23#define FIRELOG_MSG(x) do {} while (0)
24#endif
25
26using namespace IOFireWireLib ;
27
28OSDefineMetaClassAndAbstractStructors( IOFWDCL, OSObject )
29
30bool
31IOFWDCL::initWithRanges (
32	OSSet * 				updateSet,
33	unsigned 				rangesCount,
34	IOVirtualRange 			ranges [] )
35{
36	if ( ! OSObject::init() )
37		return false ;
38
39	if ( updateSet )
40	{
41		updateSet->setObject( this ) ;
42	}
43
44	if ( kIOReturnSuccess != setRanges( rangesCount, ranges ) )
45	{
46		return false ;
47	}
48
49	return true ;
50}
51
52void
53IOFWDCL::setBranch( IOFWDCL* branch )
54{
55	fLoLevel->lastBranch = fBranch ;
56	fBranch = branch ;
57}
58
59IOFWDCL *
60IOFWDCL::getBranch() const
61{
62	return fBranch ;
63}
64
65void
66IOFWDCL::setTimeStampPtr ( UInt32* timeStampPtr )
67{
68	fTimeStampPtr = timeStampPtr ;
69}
70
71UInt32 *
72IOFWDCL::getTimeStampPtr () const
73{
74	return (UInt32*)fTimeStampPtr ;
75}
76
77void
78IOFWDCL::setCallback( Callback callback )
79{
80	fCallback = callback ;
81}
82
83IOFWDCL::Callback
84IOFWDCL::getCallback() const
85{
86	return fCallback ;
87}
88
89void
90IOFWDCL::setStatusPtr( UInt32* statusPtr )
91{
92	fUserStatusPtr = statusPtr ;
93}
94
95UInt32*
96IOFWDCL::getStatusPtr() const
97{
98	return (UInt32*) fUserStatusPtr ;
99}
100
101void
102IOFWDCL::setRefcon( void * refcon )
103{
104	fRefcon = refcon ;
105}
106
107void *
108IOFWDCL::getRefcon() const
109{
110	return fRefcon ;
111}
112
113const OSSet *
114IOFWDCL::getUpdateList() const
115{
116	return fUpdateList ;
117}
118
119IOReturn
120IOFWDCL::addRange ( IOVirtualRange & range )
121{
122	IOVirtualRange * newRanges = new IOVirtualRange[ fRangeCount + 1 ] ;
123	if ( !newRanges )
124	{
125		return kIOReturnNoMemory ;
126	}
127
128	bcopy( fRanges, newRanges, sizeof( IOVirtualRange ) * fRangeCount ) ;
129	delete[] fRanges ;
130
131	fRanges = newRanges ;
132	fRanges[ fRangeCount ] = range ;
133	++fRangeCount ;
134
135	return kIOReturnSuccess ;
136}
137
138IOReturn
139IOFWDCL::setRanges ( UInt32 numRanges, IOVirtualRange ranges[] )
140{
141	delete[] fRanges ;
142
143	fRanges = ( numRanges && ranges ) ? new IOVirtualRange[ numRanges ] : NULL ;
144
145	if ( !fRanges )
146	{
147		return kIOReturnNoMemory ;
148	}
149
150	bcopy( ranges, fRanges, numRanges * sizeof( IOVirtualRange ) ) ;
151	fRangeCount = numRanges ;
152
153	return kIOReturnSuccess ;
154}
155
156UInt32
157IOFWDCL::getRanges( UInt32 maxRanges, IOVirtualRange ranges[] ) const
158{
159	unsigned count = min( maxRanges, fRangeCount ) ;
160	for( unsigned index=0; index < count; ++index )
161	{
162		ranges[ index ] = fRanges[ index ] ;
163	}
164
165	return count ;
166}
167
168UInt32
169IOFWDCL::countRanges()
170{
171	return fRangeCount ;
172}
173
174IOReturn
175IOFWDCL::getSpan( IOVirtualRange& result ) const
176{
177	if ( fRangeCount == 0 )
178	{
179		result.address = 0 ;
180		result.length = 0 ;
181		return kIOReturnSuccess ;
182	}
183
184	IOVirtualAddress lowAddress = fRanges[0].address ;
185	IOVirtualAddress highAddress = lowAddress + fRanges[0].length ;
186
187	for( unsigned index=1; index < fRangeCount; ++index )
188	{
189		lowAddress = min( fRanges[index].address, lowAddress ) ;
190		highAddress = min( lowAddress + fRanges[ index ].length, highAddress ) ;
191	}
192
193	result.address = lowAddress ;
194	result.length = highAddress - lowAddress ;
195
196	return kIOReturnSuccess ;
197}
198
199IOByteCount
200IOFWDCL::getSize() const
201{
202	IOByteCount size = 0 ;
203	for( unsigned index=0; index < fRangeCount; ++index )
204		size += fRanges[ index ].length ;
205
206	return size ;
207}
208
209IOReturn
210IOFWDCL::setUpdateList( OSSet* updateList )
211{
212	if ( updateList )
213	{
214		updateList->retain() ;
215	}
216
217	if ( fUpdateList )
218	{
219		fUpdateList->release() ;
220		fUpdateList = NULL ;
221	}
222
223	if ( fUpdateIterator )
224	{
225		fUpdateIterator->release() ;
226		fUpdateIterator = NULL ;
227	}
228
229	if ( updateList )
230	{
231		fUpdateList = updateList ;
232		fUpdateIterator = OSCollectionIterator::withCollection( fUpdateList ) ;
233	}
234
235	return kIOReturnSuccess ;
236}
237
238void
239IOFWDCL::setFlags( UInt32 flags )
240{
241	fFlags = flags ;
242}
243
244UInt32
245IOFWDCL::getFlags() const
246{
247	return fFlags ;
248}
249
250void
251IOFWDCL::debug()
252{
253	if ( fBranch )
254	{
255		FIRELOG_MSG(( "    branch --> %p\n", fBranch )) ;
256	}
257
258	if ( fCallback )
259	{
260		if ( fCallback == IOFWUserLocalIsochPort::s_nuDCLCallout )
261		{
262			#if FIRELOG
263				uint64_t * asyncRef = (uint64_t*)getRefcon() ;
264				FIRELOG_MSG(( "    callback (USER) callback=%p refcon=%p\n", asyncRef[ kIOAsyncCalloutFuncIndex ], asyncRef[ kIOAsyncCalloutRefconIndex ] )) ;
265			#endif
266		}
267		else
268		{
269			FIRELOG_MSG(( "    callback %p\n", fCallback )) ;
270		}
271	}
272
273	if ( fTimeStampPtr )
274	{
275		FIRELOG_MSG(( "    time stamp @ %p\n", fTimeStampPtr )) ;
276	}
277
278	if ( fRangeCount )
279	{
280		FIRELOG_MSG(( "    ranges\n" )) ;
281		for( unsigned index=0; index < fRangeCount; ++index )
282		{
283			FIRELOG_MSG(( "        %d: %p ( +%dd, +0x%x )\n", index, fRanges[index].address, fRanges[index].length, fRanges[index].length )) ;
284		}
285	}
286
287	if ( fUpdateList )
288	{
289		FIRELOG_MSG(( "    update" )) ;
290		OSIterator * iterator = OSCollectionIterator::withCollection( fUpdateList ) ;
291
292		if ( !iterator )
293		{
294			FIRELOG_MSG(("couldn't get iterator!\n")) ;
295		}
296		else
297		{
298#if FIRELOG
299			// bracket this to hide unused variable warning
300			unsigned count = 0 ;
301			while( OSObject * obj = iterator->getNextObject() )
302			{
303				if ( ( count++ & 0x7 ) == 0 )
304				{
305					FIRELOG_MSG(("\n" )) ;
306					FIRELOG_MSG(("        ")) ;
307				}
308				FIRELOG_MSG(( "%p ", obj )) ;
309			}
310			FIRELOG_MSG(("\n")) ;
311#endif
312			iterator->release() ;
313		}
314	}
315
316	if ( fUserStatusPtr )
317	{
318		FIRELOG_MSG(( "    status @ %p\n", fUserStatusPtr )) ;
319	}
320
321	if ( fRefcon )
322	{
323		FIRELOG_MSG(( "    refcon 0x%x\n", fRefcon )) ;
324	}
325}
326
327void
328IOFWDCL::free ()
329{
330	if ( fUpdateList )
331	{
332		fUpdateList->release() ;
333	}
334	if ( fUpdateIterator )
335	{
336		fUpdateIterator->release() ;
337	}
338
339	if ( fCallback == IOFWUserLocalIsochPort::s_nuDCLCallout )
340	{
341		delete [] (uint64_t*)fRefcon ;
342	}
343
344	delete[] fRanges ;
345
346	delete fLoLevel ;
347
348	OSObject::free() ;
349}
350
351void
352IOFWDCL::finalize ( IODCLProgram & )
353{
354	if ( fUpdateList )
355	{
356		fUpdateList->release() ;
357		fUpdateList = NULL ;
358	}
359
360	if ( fUpdateIterator )
361	{
362		fUpdateIterator->release() ;
363		fUpdateIterator = NULL ;
364	}
365}
366
367IOReturn
368IOFWDCL::importUserDCL (
369	UInt8 *					data,
370	IOByteCount &			dataSize,
371	IOMemoryMap *			bufferMap,
372	const OSArray *			dcls )
373{
374	IOVirtualAddress		kernBaseAddress = bufferMap->getVirtualAddress() ;
375	NuDCLExportData * 		sharedData = ( NuDCLExportData * )data ;
376	dataSize = sizeof( NuDCLExportData ) ;
377	data += dataSize ;
378
379	IOReturn error = kIOReturnSuccess ;
380
381	{
382		IOVirtualRange kernRanges[ sharedData->rangeCount ] ;
383		for( unsigned index=0; index < sharedData->rangeCount; ++index )
384		{
385			kernRanges[ index ].address = kernBaseAddress + sharedData->ranges[ index ].address ;
386			kernRanges[ index ].length = sharedData->ranges[ index ].length ;
387		}
388
389		error = setRanges( sharedData->rangeCount, kernRanges ) ;
390	}
391
392	if ( sharedData->updateCount )
393	{
394		// In the shared data struct for this DCL, the updateList field has
395		// been filled in with the updateList length, if any, replacing
396		// the user space CFMutableSetRef.
397		// The update list data follows the dcl shared data struct
398		// in the export data block.
399
400		uint64_t * userUpdateList = ( uint64_t * )data ;
401		dataSize += sharedData->updateCount * sizeof( uint64_t ) ;
402
403		OSSet * updateSet = OSSet::withCapacity( (unsigned)sharedData->updateCount ) ;
404
405		if ( __builtin_expect( !updateSet, false ) )
406		{
407			error = kIOReturnNoMemory ;
408		}
409		else
410		{
411			for( unsigned index=0; index < (unsigned)sharedData->updateCount; ++index )
412			{
413				updateSet->setObject( dcls->getObject( userUpdateList[ index ] - 1 ) ) ;
414			}
415
416			setUpdateList( updateSet ) ;
417			updateSet->release() ;
418		}
419	}
420
421	if ( !error )
422	{
423		setFlags( IOFWDCL::kUser | sharedData->flags ) ;
424	}
425
426	if ( !error )
427	{
428		if ( sharedData->callback )
429		{
430			setCallback( sharedData->callback ? IOFWUserLocalIsochPort::s_nuDCLCallout : NULL ) ;
431
432			uint64_t * asyncRef = (uint64_t *) getRefcon() ;
433
434			if ( !asyncRef )
435			{
436				asyncRef = new uint64_t[ kOSAsyncRef64Count ] ;
437			}
438
439			if ( !asyncRef )
440			{
441				error = kIOReturnNoMemory ;
442			}
443			else
444			{
445				asyncRef[ kIOAsyncCalloutFuncIndex ] = (uint64_t)sharedData->callback ;
446				asyncRef[ kIOAsyncCalloutRefconIndex ] = (uint64_t)sharedData->refcon ;
447
448				setRefcon( asyncRef ) ;
449			}
450		}
451		else
452		{
453			if ( getCallback() == IOFWUserLocalIsochPort::s_nuDCLCallout )
454			{
455				delete [] (uint64_t*)getRefcon() ;
456			}
457
458			setCallback( NULL ) ;
459			setRefcon( 0 ) ;
460		}
461	}
462
463	if ( !error )
464	{
465		setTimeStampPtr( sharedData->timeStampOffset ? (UInt32*)( kernBaseAddress + sharedData->timeStampOffset - 1 ) : NULL ) ;
466		setStatusPtr( sharedData->statusOffset ? (UInt32*)( kernBaseAddress + sharedData->statusOffset - 1 ) : NULL ) ;
467	}
468
469	if ( !error )
470	{
471		if ( sharedData->branchIndex )
472		{
473			unsigned branchIndex = sharedData->branchIndex - 1 ;
474			if ( branchIndex >= dcls->getCount() )
475			{
476				DebugLog("branch index out of range\n") ;
477				error = kIOReturnBadArgument ;
478			}
479			else
480			{
481				setBranch( (IOFWDCL*)dcls->getObject( branchIndex ) ) ;
482			}
483		}
484		else
485		{
486			setBranch( NULL ) ;
487		}
488	}
489
490	return error ;
491}
492
493OSMetaClassDefineReservedUsed ( IOFWDCL, 0 ) ;
494OSMetaClassDefineReservedUnused ( IOFWDCL, 1 ) ;
495OSMetaClassDefineReservedUnused ( IOFWDCL, 2 ) ;
496OSMetaClassDefineReservedUnused ( IOFWDCL, 3 ) ;
497OSMetaClassDefineReservedUnused ( IOFWDCL, 4 ) ;		// used to be relink()
498
499#pragma mark -
500
501OSDefineMetaClassAndAbstractStructors( IOFWReceiveDCL, IOFWDCL )
502
503bool
504IOFWReceiveDCL:: initWithParams(
505	OSSet * 			updateSet,
506	UInt8 				headerBytes,
507	unsigned 			rangesCount,
508	IOVirtualRange 		ranges[] )
509{
510	// can only get 0, 1, or 2 header quads...
511	if (!( headerBytes == 0 || headerBytes == 4 || headerBytes == 8 ) )
512	{
513		DebugLog("receive DCL header bytes must be 0, 4, or 8\n") ;
514		return false ;
515	}
516
517	fHeaderBytes = headerBytes ;
518
519	return IOFWDCL::initWithRanges( updateSet, rangesCount, ranges ) ;
520}
521
522
523IOReturn
524IOFWReceiveDCL::setWaitControl( bool wait )
525{
526	fWait = wait ;
527	return kIOReturnSuccess ;
528}
529
530void
531IOFWReceiveDCL::debug ()
532{
533	FIRELOG_MSG(("%p: RECEIVE\n", this )) ;
534	FIRELOG_MSG(("    wait: %s, headerBytes: %d\n", fWait ? "YES" : "NO", fHeaderBytes )) ;
535
536	IOFWDCL::debug() ;
537}
538
539IOReturn
540IOFWReceiveDCL::importUserDCL (
541	UInt8 *					data,
542	IOByteCount &			dataSize,
543	IOMemoryMap *			bufferMap,
544	const OSArray *			dcls )
545{
546	IOReturn error = IOFWDCL::importUserDCL( data, dataSize, bufferMap, dcls ) ;
547
548	if ( !error )
549	{
550		ReceiveNuDCLExportData * rcvData = (ReceiveNuDCLExportData*)( data + dataSize ) ;
551		dataSize += sizeof( ReceiveNuDCLExportData ) ;
552
553		error = setWaitControl( rcvData->wait ) ;
554	}
555
556	return error ;
557}
558
559#pragma mark -
560
561OSDefineMetaClassAndAbstractStructors( IOFWSendDCL, IOFWDCL )
562
563void
564IOFWSendDCL::free()
565{
566	if ( fSkipCallback == IOFWUserLocalIsochPort::s_nuDCLCallout )
567	{
568		delete[] (uint64_t*)fSkipRefcon ;
569	}
570
571	IOFWDCL::free() ;
572}
573
574bool
575IOFWSendDCL::initWithParams (
576	OSSet * 				updateSet,
577	unsigned 				rangesCount,
578	IOVirtualRange 			ranges[],
579	UInt8					sync,
580	UInt8					tag )
581{
582	if ( !IOFWDCL::initWithRanges( updateSet, rangesCount, ranges ) )
583		return false ;
584
585	fSync = sync ;
586	fTag = tag ;
587
588	return true ;
589}
590
591IOReturn
592IOFWSendDCL::addRange ( IOVirtualRange & range )
593{
594	if ( fRangeCount >= 5 )
595		return kIOReturnError ;
596
597	return IOFWDCL::addRange( range ) ;
598}
599
600void
601IOFWSendDCL::setUserHeaderPtr( UInt32* userHeaderPtr, UInt32 * maskPtr )
602{
603	fUserHeaderPtr = userHeaderPtr ;
604	fUserHeaderMaskPtr = maskPtr ;
605}
606
607UInt32 *
608IOFWSendDCL::getUserHeaderPtr()
609{
610	return fUserHeaderPtr ;
611}
612
613UInt32 *
614IOFWSendDCL::getUserHeaderMask()
615{
616	return fUserHeaderMaskPtr ;
617}
618
619void
620IOFWSendDCL::setSkipBranch( IOFWDCL * skipBranchDCL )
621{
622	fSkipBranchDCL = skipBranchDCL ;
623}
624
625IOFWDCL *
626IOFWSendDCL::getSkipBranch() const
627{
628	return fSkipBranchDCL ;
629}
630
631void
632IOFWSendDCL::setSkipCallback( Callback callback )
633{
634	fSkipCallback = callback ;
635}
636
637void
638IOFWSendDCL::setSkipRefcon( void * refcon )
639{
640	fSkipRefcon = refcon ;
641}
642
643IOFWDCL::Callback
644IOFWSendDCL::getSkipCallback() const
645{
646	return fSkipCallback ;
647}
648
649void *
650IOFWSendDCL::getSkipRefcon() const
651{
652	return fSkipRefcon ;
653}
654
655void
656IOFWSendDCL::setSync( UInt8 sync )
657{
658	fSync = sync ;
659}
660
661UInt8
662IOFWSendDCL::getSync() const
663{
664	return fSync ;
665}
666
667void
668IOFWSendDCL::setTag( UInt8 tag )
669{
670	fTag = tag ;
671}
672
673UInt8
674IOFWSendDCL::getTag() const
675{
676	return fTag ;
677}
678
679IOReturn
680IOFWSendDCL::setRanges ( UInt32 numRanges, IOVirtualRange ranges[] )
681{
682	if ( numRanges > 5 )
683	{
684		DebugLog( "can't build send DCL with more than 5 ranges\n" ) ;
685		return kIOReturnBadArgument ;
686	}
687
688	return IOFWDCL::setRanges( numRanges, ranges ) ;
689}
690
691void
692IOFWSendDCL::debug ()
693{
694	FIRELOG_MSG(("%p: SEND\n", this )) ;
695	if ( fUserHeaderPtr )
696	{
697		FIRELOG_MSG(("    user hdr: %p, user hdr mask --> %p\n", fUserHeaderPtr, fUserHeaderMaskPtr )) ;
698	}
699
700	if ( fSkipBranchDCL )
701	{
702		FIRELOG_MSG(("    skip --> %p\n", fSkipBranchDCL )) ;
703	}
704
705	if ( fSkipCallback )
706	{
707		if ( fSkipCallback == IOFWUserLocalIsochPort::s_nuDCLCallout )
708		{
709			FIRELOG_MSG(("        skip callback: (USER) " )) ;
710
711			if ( fSkipRefcon )
712			{
713				FIRELOG_MSG(("callback:%p refcon:0x%lx\n", ((uint64_t*)fSkipRefcon)[ kIOAsyncCalloutFuncIndex ], ((uint64_t*)fSkipRefcon)[ kIOAsyncCalloutRefconIndex ] )) ;
714			}
715			else
716			{
717				FIRELOG_MSG(("NULL\n")) ;
718			}
719		}
720		else
721		{
722			FIRELOG_MSG(("        skip callback: %p\n", fSkipCallback )) ;
723			FIRELOG_MSG(("        skip refcon: 0x%lx\n", fSkipRefcon )) ;
724		}
725	}
726
727	IOFWDCL::debug() ;
728}
729
730IOReturn
731IOFWSendDCL::importUserDCL (
732	UInt8 *					data,
733	IOByteCount &			dataSize,
734	IOMemoryMap *			bufferMap,
735	const OSArray *			dcls )
736{
737	IOReturn error = IOFWDCL::importUserDCL( data, dataSize, bufferMap, dcls ) ;
738	if ( error )
739	{
740		return error ;
741	}
742
743	SendNuDCLExportData * sendData = (SendNuDCLExportData*) ( data + dataSize ) ;
744	dataSize += sizeof( SendNuDCLExportData ) ;
745
746	{
747		setSync( sendData->syncBits ) ;
748		setTag( sendData->tagBits ) ;
749	}
750
751	{
752		UInt32 * userHeaderPtr = NULL ;
753		UInt32 * userHeaderMaskPtr = NULL ;
754
755		if ( sendData->userHeaderOffset && sendData->userHeaderMaskOffset )
756		{
757			IOVirtualAddress		kernBaseAddress = bufferMap->getVirtualAddress() ;
758
759			userHeaderPtr = (UInt32*)( kernBaseAddress + sendData->userHeaderOffset - 1 ) ;
760			userHeaderMaskPtr = (UInt32*)( kernBaseAddress + sendData->userHeaderMaskOffset - 1 ) ;
761		}
762
763		setUserHeaderPtr( userHeaderPtr, userHeaderMaskPtr ) ;
764	}
765
766	if ( sendData->skipBranchIndex )
767	{
768		unsigned branchIndex = sendData->skipBranchIndex - 1 ;
769		if ( branchIndex >= dcls->getCount() )
770		{
771			DebugLog("skip branch index out of range\n") ;
772			error = kIOReturnBadArgument ;
773		}
774		else
775		{
776			setSkipBranch( (IOFWDCL*)dcls->getObject( branchIndex ) ) ;
777		}
778	}
779	else
780	{
781		setSkipBranch( NULL ) ;
782	}
783
784	{
785		if ( sendData->skipCallback )
786		{
787			setSkipCallback( sendData->skipCallback ? IOFWUserLocalIsochPort::s_nuDCLCallout : NULL ) ;
788
789			uint64_t * asyncRef = (uint64_t *) getSkipRefcon() ;
790
791			if ( !asyncRef )
792			{
793				asyncRef = new uint64_t[ kOSAsyncRef64Count ] ;
794			}
795
796			if ( !asyncRef )
797			{
798				error = kIOReturnNoMemory ;
799			}
800			else
801			{
802				asyncRef[ kIOAsyncCalloutFuncIndex ] = (uint64_t)sendData->skipCallback ;
803				asyncRef[ kIOAsyncCalloutRefconIndex ] = (uint64_t)sendData->skipRefcon ;
804
805				setSkipRefcon( asyncRef ) ;
806			}
807		}
808		else
809		{
810			if ( getSkipCallback() == IOFWUserLocalIsochPort::s_nuDCLCallout )
811			{
812				delete [] (uint64_t*)getSkipRefcon() ;
813			}
814
815			setSkipCallback( NULL ) ;
816			setSkipRefcon( 0 ) ;
817		}
818	}
819
820
821	return kIOReturnSuccess ;
822}
823
824#pragma mark -
825
826OSDefineMetaClassAndAbstractStructors( IOFWSkipCycleDCL, IOFWDCL )
827
828bool
829IOFWSkipCycleDCL::init ()
830{
831	bool result = IOFWDCL::initWithRanges( NULL, 0, NULL ) ;
832
833	return result ;
834}
835
836IOReturn
837IOFWSkipCycleDCL::addRange ( IOVirtualRange& range )
838{
839	return kIOReturnUnsupported ;
840}
841
842IOReturn
843IOFWSkipCycleDCL::setRanges ( UInt32 numRanges, IOVirtualRange ranges[] )
844{
845	if ( numRanges == 0 )
846	{
847		// init always calls setRanges.. for this DCL we will be called with 0 ranges, which
848		// is okay, so return success ;
849
850		return kIOReturnSuccess ;
851	}
852	return kIOReturnUnsupported ;
853}
854
855IOReturn
856IOFWSkipCycleDCL::getSpan ( IOVirtualRange& result )
857{
858	return kIOReturnUnsupported ;
859}
860
861void
862IOFWSkipCycleDCL::debug ()
863{
864	FIRELOG_MSG(("%p: SKIP CYCLE\n", this )) ;
865	IOFWDCL::debug() ;
866}
867