1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <CoreFoundation/CoreFoundation.h>
24
25#include "FWDebugging.h"
26#include "IOFireWireSBP2LibORB.h"
27
28#include <System/libkern/OSCrossEndian.h>
29
30__BEGIN_DECLS
31#include <IOKit/iokitmig.h>
32#include <mach/mach.h>
33__END_DECLS
34
35//
36// static interface table for IOFireWireSBP2LibORBInterface
37//
38
39IOFireWireSBP2LibORBInterface IOFireWireSBP2LibORB::sIOFireWireSBP2LibORBInterface =
40{
41    0,
42	&IOFireWireSBP2LibORB::staticQueryInterface,
43	&IOFireWireSBP2LibORB::staticAddRef,
44	&IOFireWireSBP2LibORB::staticRelease,
45	1, 0, // version/revision
46	&IOFireWireSBP2LibORB::staticSetRefCon,
47	&IOFireWireSBP2LibORB::staticGetRefCon,
48	&IOFireWireSBP2LibORB::staticSetCommandFlags,
49	&IOFireWireSBP2LibORB::staticSetMaxORBPayloadSize,
50	&IOFireWireSBP2LibORB::staticSetCommandTimeout,
51	&IOFireWireSBP2LibORB::staticSetCommandGeneration,
52	&IOFireWireSBP2LibORB::staticSetCommandBuffersAsRanges,
53	&IOFireWireSBP2LibORB::staticReleaseCommandBuffers,
54	&IOFireWireSBP2LibORB::staticSetCommandBlock,
55	&IOFireWireSBP2LibORB::staticLSIWorkaroundSetCommandBuffersAsRanges,
56	&IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForOutput,
57	&IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForInput
58};
59
60// alloc
61//
62// static allocator, called by factory method
63
64IUnknownVTbl ** IOFireWireSBP2LibORB::alloc( io_connect_t connection,
65											   mach_port_t asyncPort )
66{
67    IOReturn					status = kIOReturnSuccess;
68	IOFireWireSBP2LibORB *		me;
69	IUnknownVTbl ** 			interface = NULL;
70
71	if( status == kIOReturnSuccess )
72	{
73		me = new IOFireWireSBP2LibORB();
74		if( me == NULL )
75			status = kIOReturnError;
76	}
77
78	if( status == kIOReturnSuccess )
79	{
80		status = me->init( connection, asyncPort );
81	}
82
83	if( status != kIOReturnSuccess )
84		delete me;
85
86	if( status == kIOReturnSuccess )
87	{
88		// we return an interface here. queryInterface will not be called. call addRef here
89		me->addRef();
90		interface = (IUnknownVTbl **) &me->fIOFireWireSBP2LibORBInterface.pseudoVTable;
91	}
92
93	return interface;
94}
95
96// ctor
97//
98//
99
100IOFireWireSBP2LibORB::IOFireWireSBP2LibORB( void )
101{
102	// init cf plugin ref counting
103	fRefCount = 0;
104	fConnection = 0;
105	fORBRef = 0;
106	fRefCon = 0;
107	fRangeScratch = NULL;
108	fRangeScratchLength = 0;
109
110	// create test driver interface map
111	fIOFireWireSBP2LibORBInterface.pseudoVTable
112								= (IUnknownVTbl *) &sIOFireWireSBP2LibORBInterface;
113	fIOFireWireSBP2LibORBInterface.obj = this;
114
115}
116
117// init
118//
119//
120
121IOReturn IOFireWireSBP2LibORB::init( io_connect_t connection, mach_port_t asyncPort )
122{
123	IOReturn status = kIOReturnSuccess;
124
125	fConnection = connection;
126	fAsyncPort = asyncPort;
127
128	FWLOG(( "IOFireWireSBP2LibORB : fConnection %d, fAsyncPort %d\n",
129												fConnection, fAsyncPort ));
130
131	if( !fConnection || !fAsyncPort )
132		status = kIOReturnError;
133
134	if( status == kIOReturnSuccess )
135	{
136		uint32_t len = 1;
137		status = IOConnectCallScalarMethod( connection, kIOFWSBP2UserClientCreateORB,
138											NULL, 0, &fORBRef, &len );
139		if( status != kIOReturnSuccess )
140			fORBRef = 0; // just to make sure
141
142		FWLOG(( "IOFireWireSBP2LibORB :  status = 0x%08x = fORBRef 0x%08lx\n",
143																	status, fORBRef ));
144	}
145
146	return status;
147}
148
149// dtor
150//
151//
152
153IOFireWireSBP2LibORB::~IOFireWireSBP2LibORB()
154{
155	if( fORBRef )
156	{
157		IOReturn status = kIOReturnSuccess;
158
159		uint32_t len = 0;
160		status = IOConnectCallScalarMethod( fConnection,
161											kIOFWSBP2UserClientReleaseORB,
162											&fORBRef, 1, NULL, &len );
163		FWLOG(( "IOFireWireSBP2LibORB : release orb status = 0x%08x\n", status ));
164	}
165}
166
167
168//////////////////////////////////////////////////////////////////
169// IUnknown methods
170//
171
172// queryInterface
173//
174//
175
176HRESULT IOFireWireSBP2LibORB::staticQueryInterface( void * self, REFIID iid, void **ppv )
177{
178	return getThis(self)->queryInterface( iid, ppv );
179}
180
181HRESULT IOFireWireSBP2LibORB::queryInterface( REFIID iid, void **ppv )
182{
183    CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid);
184    HRESULT result = S_OK;
185
186	if( CFEqual(uuid, IUnknownUUID) ||  CFEqual(uuid, kIOFireWireSBP2LibORBInterfaceID) )
187	{
188        *ppv = &fIOFireWireSBP2LibORBInterface;
189        addRef();
190    }
191    else
192        *ppv = 0;
193
194    if( !*ppv )
195        result = E_NOINTERFACE;
196
197    CFRelease( uuid );
198
199    return result;
200}
201
202// addRef
203//
204//
205
206UInt32 IOFireWireSBP2LibORB::staticAddRef( void * self )
207{
208	return getThis(self)->addRef();
209}
210
211UInt32 IOFireWireSBP2LibORB::addRef()
212{
213    fRefCount += 1;
214    return fRefCount;
215}
216
217// Release
218//
219//
220
221UInt32 IOFireWireSBP2LibORB::staticRelease( void * self )
222{
223	return getThis(self)->release();
224}
225
226UInt32 IOFireWireSBP2LibORB::release( void )
227{
228	UInt32 retVal = fRefCount;
229
230	if( 1 == fRefCount-- )
231	{
232		if( fRangeScratch != NULL )
233		{
234			// delete it
235			vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength );
236			fRangeScratch = NULL;
237			fRangeScratchLength = 0;
238		}
239
240		delete this;
241    }
242
243	return retVal;
244}
245
246//////////////////////////////////////////////////////////////////
247// IOFireWireSBP2LibORB methods
248
249// setRefCon
250//
251//
252
253void IOFireWireSBP2LibORB::staticSetRefCon( void * self, void * refCon )
254{
255	getThis(self)->setRefCon( refCon );
256}
257
258void IOFireWireSBP2LibORB::setRefCon( void * refCon )
259{
260	FWLOG(( "IOFireWireSBP2LibORB : setRefCon\n"));
261
262	fRefCon = refCon;
263
264	uint32_t len = 0;
265	uint64_t params[2];
266
267	params[0] = fORBRef;
268	params[1] = (uint64_t)refCon;
269
270	IOConnectCallScalarMethod(	fConnection,
271								kIOFWSBP2UserClientSetORBRefCon,
272								params, 2, NULL, &len );
273}
274
275// getRefCon
276//
277//
278
279void * IOFireWireSBP2LibORB::staticGetRefCon( void * self )
280{
281	return getThis(self)->getRefCon();
282}
283
284void * IOFireWireSBP2LibORB::getRefCon( void )
285{
286	return fRefCon;
287}
288
289// setCommandFlags
290//
291//
292
293void IOFireWireSBP2LibORB::staticSetCommandFlags( void * self, UInt32 flags )
294{
295	getThis(self)->setCommandFlags( flags );
296}
297
298void IOFireWireSBP2LibORB::setCommandFlags( UInt32 flags )
299{
300	FWLOG(( "IOFireWireSBP2LibORB : setCommandFlags = %ld\n", flags ));
301
302	uint32_t len = 0;
303	uint64_t params[2];
304
305	params[0] = fORBRef;
306	params[1] = flags;
307
308	IOConnectCallScalarMethod(	fConnection,
309								kIOFWSBP2UserClientSetCommandFlags,
310								params, 2, NULL, &len );
311}
312
313
314// setMaxORBPayloadSize
315//
316//
317
318void IOFireWireSBP2LibORB::staticSetMaxORBPayloadSize( void * self, UInt32 size )
319{
320	getThis(self)->setMaxORBPayloadSize( size );
321}
322
323void IOFireWireSBP2LibORB::setMaxORBPayloadSize( UInt32 size )
324{
325	FWLOG(( "IOFireWireSBP2LibORB : setMaxORBPayloadSize = %ld\n", size ));
326
327	uint32_t len = 0;
328	uint64_t params[2];
329
330	params[0] = fORBRef;
331	params[1] = size;
332
333	IOConnectCallScalarMethod( fConnection,
334									   kIOFWSBP2UserClientSetMaxORBPayloadSize,
335									   params, 2, NULL, &len );
336}
337
338// setCommandTimeout
339//
340//
341
342void IOFireWireSBP2LibORB::staticSetCommandTimeout( void * self, UInt32 timeout )
343{
344	getThis(self)->setCommandTimeout( timeout );
345}
346
347void IOFireWireSBP2LibORB::setCommandTimeout( UInt32 timeout )
348{
349	FWLOG(( "IOFireWireSBP2LibORB : setCommandTimeout = %ld\n", timeout ));
350
351	uint32_t len = 0;
352	uint64_t params[2];
353
354	params[0] = fORBRef;
355	params[1] = timeout;
356
357	IOConnectCallScalarMethod(	fConnection,
358								kIOFWSBP2UserClientSetCommandTimeout,
359								params, 2, NULL, &len );
360}
361
362// setCommandGeneration
363//
364//
365
366void IOFireWireSBP2LibORB::staticSetCommandGeneration( void * self, UInt32 generation )
367{
368	getThis(self)->setCommandGeneration( generation );
369}
370
371void IOFireWireSBP2LibORB::setCommandGeneration( UInt32 generation )
372{
373	FWLOG(( "IOFireWireSBP2LibORB : setCommandGeneration = %ld\n", generation ));
374
375	uint32_t len = 0;
376	uint64_t params[2];
377
378	params[0] = fORBRef;
379	params[1] = generation;
380
381	IOConnectCallScalarMethod(	fConnection,
382								kIOFWSBP2UserClientSetCommandGeneration,
383								params, 2, NULL, &len );
384}
385
386// setToDummy
387//
388//
389
390void IOFireWireSBP2LibORB::staticSetToDummy( void * self )
391{
392	getThis(self)->setToDummy();
393}
394
395void IOFireWireSBP2LibORB::setToDummy( void )
396{
397	IOReturn status = kIOReturnSuccess;
398
399	FWLOG(( "IOFireWireSBP2LibORB : setToDummy\n" ));
400
401	uint32_t len = 0;
402	status = IOConnectCallScalarMethod( fConnection,
403										kIOFWSBP2UserClientSetToDummy,
404										&fORBRef, 1, NULL, &len );
405}
406
407// setCommandBuffersAsRanges
408//
409//
410
411IOReturn IOFireWireSBP2LibORB::staticSetCommandBuffersAsRanges( void * self,
412										FWSBP2VirtualRange * ranges, UInt32 withCount,
413										UInt32 withDirection,
414										UInt32 offset, UInt32 length )
415{
416	return getThis(self)->setCommandBuffersAsRanges( ranges, withCount, withDirection,
417																	offset, length);
418}
419
420IOReturn IOFireWireSBP2LibORB::setCommandBuffersAsRanges( FWSBP2VirtualRange * ranges,
421										UInt32 withCount, UInt32 withDirection,
422										UInt32 offset,
423										UInt32 length )
424{
425	IOReturn status = kIOReturnSuccess;
426
427	uint32_t len = 0;
428	uint64_t params[6];
429
430	FWLOG(( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" ));
431//	printf( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" );
432
433	//
434	// create or grow range scratch
435	//
436
437	UInt32 range_length = withCount * sizeof(FWSBP2PrivateVirtualRange);
438
439	if( fRangeScratchLength < range_length )
440	{
441		if( fRangeScratch != NULL )
442		{
443			// delete it
444			vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength );
445			fRangeScratch = NULL;
446			fRangeScratchLength = 0;
447		}
448
449		// alloc a bigger one
450		vm_allocate( mach_task_self(), (vm_address_t*)&fRangeScratch, range_length, true /*anywhere*/ );
451		if( fRangeScratch != NULL )
452		{
453			fRangeScratchLength = range_length;
454		}
455	}
456
457	//
458	// fill range scratch
459	//
460
461	if( fRangeScratch != NULL )
462	{
463		for( UInt32 i = 0; i < withCount; i++ )
464		{
465			fRangeScratch[i].address = (uint64_t)ranges[i].address;
466			fRangeScratch[i].length = ranges[i].length;
467
468			ROSETTA_ONLY(
469				fRangeScratch[i].address = OSSwapInt64( fRangeScratch[i].address );
470				fRangeScratch[i].length = OSSwapInt64( fRangeScratch[i].length );
471			);
472		}
473	}
474
475	params[0] = fORBRef;
476	params[1] = (uint64_t)fRangeScratch;
477	params[2] = withCount;
478	params[3] = withDirection;
479	params[4] = offset;
480	params[5] = length;
481
482	status = IOConnectCallScalarMethod( fConnection,
483										kIOFWSBP2UserClientSetCommandBuffersAsRanges,
484										params, 6, NULL, &len );
485
486	return status;
487}
488
489// releaseCommandBuffers
490//
491//
492
493IOReturn IOFireWireSBP2LibORB::staticReleaseCommandBuffers( void * self )
494{
495	return getThis(self)->releaseCommandBuffers();
496}
497
498IOReturn IOFireWireSBP2LibORB::releaseCommandBuffers( void )
499{
500	IOReturn status = kIOReturnSuccess;
501
502	FWLOG(( "IOFireWireSBP2LibORB : releaseCommandBuffers\n" ));
503
504	uint32_t len = 0;
505	status = IOConnectCallScalarMethod( fConnection,
506										kIOFWSBP2UserClientReleaseCommandBuffers,
507										&fORBRef, 1, NULL, &len );
508	return status;
509}
510
511// setCommandBlock
512//
513//
514
515IOReturn IOFireWireSBP2LibORB::staticSetCommandBlock( void * self, void * buffer,
516																	UInt32 length )
517{
518	return getThis(self)->setCommandBlock( buffer, length );
519}
520
521IOReturn IOFireWireSBP2LibORB::setCommandBlock( void * buffer, UInt32 length )
522{
523	IOReturn status = kIOReturnSuccess;
524
525	FWLOG(( "IOFireWireSBP2LibORB : setCommandBlock\n" ));
526
527	uint32_t len = 0;
528	uint64_t params[3];
529
530	vm_address_t address = 0;
531
532	status = vm_allocate( mach_task_self(), &address, length, true /*anywhere*/ );
533	if( address == 0 )
534	{
535		status = kIOReturnNoMemory;
536	}
537
538	if( status == kIOReturnSuccess )
539	{
540		bcopy( buffer, (void*)address, length );
541
542		params[0] = fORBRef;
543		params[1] = address;
544		params[2] = length;
545
546		status = IOConnectCallScalarMethod( fConnection,
547											kIOFWSBP2UserClientSetCommandBlock,
548											params, 3, NULL, &len );
549	}
550
551	if( address )
552	{
553		vm_deallocate( mach_task_self(), address, length );
554	}
555
556	return status;
557}
558
559// LSIWorkaroundSetCommandBuffersAsRanges
560//
561//
562
563IOReturn IOFireWireSBP2LibORB::staticLSIWorkaroundSetCommandBuffersAsRanges
564							( void * self, FWSBP2VirtualRange * ranges, UInt32 withCount,
565									UInt32 withDirection, UInt32 offset, UInt32 length )
566{
567	return getThis( self )->LSIWorkaroundSetCommandBuffersAsRanges( ranges, withCount, withDirection,
568																	offset, length );
569}
570
571IOReturn IOFireWireSBP2LibORB::LSIWorkaroundSetCommandBuffersAsRanges
572								( FWSBP2VirtualRange * ranges, UInt32 withCount,
573									UInt32 withDirection, UInt32 offset, UInt32 length )
574{
575	IOReturn status = kIOReturnSuccess;
576
577	uint32_t len = 0;
578	uint64_t params[6];
579
580	FWLOG(( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" ));
581
582	//
583	// create or grow range scratch
584	//
585
586	UInt32 range_length = withCount * sizeof(FWSBP2PrivateVirtualRange);
587
588	if( fRangeScratchLength < range_length )
589	{
590		if( fRangeScratch != NULL )
591		{
592			// delete it
593			vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength );
594			fRangeScratch = NULL;
595			fRangeScratchLength = 0;
596		}
597
598		// alloc a bigger one
599		vm_allocate( mach_task_self(), (vm_address_t*)&fRangeScratch, range_length, true /*anywhere*/ );
600		if( fRangeScratch != NULL )
601		{
602			fRangeScratchLength = range_length;
603		}
604	}
605
606	//
607	// fill range scratch
608	//
609
610	if( fRangeScratch != NULL )
611	{
612		for( UInt32 i = 0; i < withCount; i++ )
613		{
614			fRangeScratch[i].address = (uint64_t)ranges[i].address;
615			fRangeScratch[i].length = ranges[i].length;
616
617			ROSETTA_ONLY(
618				fRangeScratch[i].address = OSSwapInt64( fRangeScratch[i].address );
619				fRangeScratch[i].length = OSSwapInt64( fRangeScratch[i].length );
620			);
621		}
622	}
623
624	params[0] = fORBRef;
625	params[1] = (uint64_t)fRangeScratch;
626	params[2] = withCount;
627	params[3] = withDirection;
628	params[4] = offset;
629	params[5] = length;
630
631	status = IOConnectCallScalarMethod( fConnection,
632										kIOFWSBP2UserClientLSIWorkaroundSetCommandBuffersAsRanges,
633										params, 6, NULL, &len );
634
635	return status;
636}
637
638// LSIWorkaroundSyncBuffersForOutput
639//
640//
641
642IOReturn IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForOutput( void * self )
643{
644	return getThis( self )->LSIWorkaroundSyncBuffersForOutput();
645}
646
647IOReturn IOFireWireSBP2LibORB::LSIWorkaroundSyncBuffersForOutput( void )
648{
649	IOReturn status = kIOReturnSuccess;
650
651	FWLOG(( "IOFireWireSBP2LibORB : LSIWorkaroundSyncBuffersForOutput\n" ));
652
653	uint32_t len = 0;
654	status = IOConnectCallScalarMethod( fConnection,
655										kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForOutput,
656										&fORBRef, 1, NULL, &len );
657	return status;
658}
659
660// LSIWorkaroundSyncBuffersForInput
661//
662//
663
664IOReturn IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForInput( void * self )
665{
666	return getThis( self )->LSIWorkaroundSyncBuffersForInput();
667}
668
669IOReturn IOFireWireSBP2LibORB::LSIWorkaroundSyncBuffersForInput( void )
670{
671	IOReturn status = kIOReturnSuccess;
672
673	FWLOG(( "IOFireWireSBP2LibORB : LSIWorkaroundSyncBuffersForInput\n" ));
674
675	uint32_t len = 0;
676	status = IOConnectCallScalarMethod( fConnection,
677										kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForInput,
678										&fORBRef, 1, NULL, &len );
679	return status;
680}
681
682// getORBRef
683//
684//
685
686UInt32 IOFireWireSBP2LibORB::getORBRef( void )
687{
688	return fORBRef;
689}
690