1/*
2 *  IOFireWireLibIRMAllocation.cpp
3 *  IOFireWireFamily
4 *
5 *  Created by Andy on 02/06/07.
6 *  Copyright (c) 2007 Apple Computer, Inc. All rights reserved.
7 *
8 *	$ Log:  $
9 */
10
11#import "IOFireWireLibIRMAllocation.h"
12#import "IOFireWireLibDevice.h"
13#import "IOFireWireLibPriv.h"
14
15#import <IOKit/iokitmig.h>
16
17namespace IOFireWireLib {
18
19#pragma mark IRMAllocation -
20
21	// ============================================================
22	// IRMAllocation
23	// ============================================================
24	IRMAllocation::IRMAllocation( const IUnknownVTbl& interface,
25								 Device& userclient,
26								 UserObjectHandle inKernIRMAllocationRef,
27								 void* inCallBack,
28								 void* inRefCon	)
29	: IOFireWireIUnknown( interface ),
30		mNotifyIsOn(false),
31		mUserClient(userclient),
32		mKernIRMAllocationRef(inKernIRMAllocationRef),
33		mLostHandler( (IOFireWireLibIRMAllocationLostNotificationProc) inCallBack ),
34		mUserRefCon(inRefCon),
35		mRefInterface( reinterpret_cast<IOFireWireLibIRMAllocationRef>( & GetInterface() ) )
36	{
37		userclient.AddRef() ;
38	}
39
40
41	IRMAllocation::~IRMAllocation()
42	{
43		uint32_t outputCnt = 0;
44		const uint64_t inputs[1]={(const uint64_t)mKernIRMAllocationRef};
45
46		IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
47								  kReleaseUserObject,
48								  inputs,1,
49								  NULL,&outputCnt);
50
51		mUserClient.Release() ;
52	}
53
54	Boolean
55	IRMAllocation::NotificationIsOn ( IOFireWireLibIRMAllocationRef self )
56	{
57		return mNotifyIsOn ;
58	}
59
60	Boolean
61	IRMAllocation::TurnOnNotification ( IOFireWireLibIRMAllocationRef self )
62	{
63		IOReturn				err					= kIOReturnSuccess ;
64		io_connect_t			connection			= mUserClient.GetUserClientConnection() ;
65
66		// if notification is already on, skip out.
67		if (mNotifyIsOn)
68			return true ;
69
70		if (!connection)
71			err = kIOReturnNoDevice ;
72
73		if ( kIOReturnSuccess == err )
74		{
75			uint64_t refrncData[kOSAsyncRef64Count];
76			refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0;
77			refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0;
78			const uint64_t inputs[3] = {(const uint64_t)mKernIRMAllocationRef,(const uint64_t)&IRMAllocation::LostProc,(const uint64_t)self};
79			uint32_t outputCnt = 0;
80			err = IOConnectCallAsyncScalarMethod(connection,
81												 kIRMAllocation_SetRef,
82												 mUserClient.GetAsyncPort(),
83												 refrncData,kOSAsyncRef64Count,
84												 inputs,3,
85												 NULL,&outputCnt);
86		}
87
88		if ( kIOReturnSuccess == err )
89			mNotifyIsOn = true ;
90
91		return ( kIOReturnSuccess == err ) ;
92	}
93
94	void
95	IRMAllocation::TurnOffNotification ( IOFireWireLibIRMAllocationRef self )
96	{
97		IOReturn				err			= kIOReturnSuccess ;
98		io_connect_t			connection	= mUserClient.GetUserClientConnection() ;
99
100		// if notification isn't on, skip out.
101		if (!mNotifyIsOn)
102			return ;
103
104		if (!connection)
105			err = kIOReturnNoDevice ;
106
107		if ( kIOReturnSuccess == err )
108		{
109			uint64_t refrncData[kOSAsyncRef64Count];
110			refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0;
111			refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0;
112			const uint64_t inputs[3] = {(const uint64_t)mKernIRMAllocationRef,0,(const uint64_t)self};
113			uint32_t outputCnt = 0;
114
115			// set callback for writes to 0
116			err = IOConnectCallAsyncScalarMethod(connection,
117												 kIRMAllocation_SetRef,
118												 mUserClient.GetIsochAsyncPort(),
119												 refrncData,kOSAsyncRef64Count,
120												 inputs,3,
121												 NULL,&outputCnt);
122
123		}
124
125		mNotifyIsOn = false ;
126	}
127
128	void IRMAllocation::SetReleaseIRMResourcesOnFree ( IOFireWireLibIRMAllocationRef self,  Boolean doRelease)
129	{
130		uint32_t outputCnt = 0;
131		const uint64_t inputs[2]={(const uint64_t)mKernIRMAllocationRef,doRelease};
132
133		IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
134								  kIRMAllocation_setDeallocateOnRelease,
135								  inputs,2,
136								  NULL,&outputCnt);
137	}
138
139	IOReturn IRMAllocation::AllocateIsochResources(IOFireWireLibIRMAllocationRef self, UInt8 isochChannel, UInt32 bandwidthUnits)
140	{
141		uint32_t outputCnt = 0;
142		const uint64_t inputs[3]={(const uint64_t)mKernIRMAllocationRef,isochChannel,bandwidthUnits};
143
144		return IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
145										 kIRMAllocation_AllocateResources,
146										 inputs,3,
147										 NULL,&outputCnt);
148	}
149
150	IOReturn IRMAllocation::DeallocateIsochResources(IOFireWireLibIRMAllocationRef self)
151	{
152		uint32_t outputCnt = 0;
153		const uint64_t inputs[1]={(const uint64_t)mKernIRMAllocationRef};
154
155		return IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
156										 kIRMAllocation_DeallocateResources,
157										 inputs,1,
158										 NULL,&outputCnt);
159	}
160
161	Boolean IRMAllocation::AreIsochResourcesAllocated(IOFireWireLibIRMAllocationRef self, UInt8 *pAllocatedIsochChannel, UInt32 *pAllocatedBandwidthUnits)
162	{
163		uint32_t outputCnt = 2;
164		uint64_t outputVal[2];
165		const uint64_t inputs[1]={(const uint64_t)mKernIRMAllocationRef};
166		Boolean result;
167
168		result = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
169										   kIRMAllocation_areResourcesAllocated,
170										   inputs,1,
171										   outputVal,&outputCnt);
172
173		if (result)
174		{
175			*pAllocatedIsochChannel = outputVal[0];
176			*pAllocatedBandwidthUnits = outputVal[1];
177		}
178		return result;
179	}
180
181	void IRMAllocation::SetRefCon(IOFireWireLibIRMAllocationRef self, void* refCon)
182	{
183		mUserRefCon = refCon;
184	}
185
186	void* IRMAllocation::GetRefCon(IOFireWireLibIRMAllocationRef self)
187	{
188		return mUserRefCon;
189	}
190
191	void IRMAllocation::LostProc( IOFireWireLibIRMAllocationRef refcon, IOReturn result, void** args, int numArgs)
192	{
193		IRMAllocation* me = IOFireWireIUnknown::InterfaceMap<IRMAllocation>::GetThis(refcon) ;
194		if (me->mLostHandler)
195			me->mLostHandler(refcon,me->mUserRefCon);
196	}
197
198
199#pragma mark IRMAllocationCOM -
200
201	IRMAllocationCOM::Interface IRMAllocationCOM::sInterface =
202	{
203		INTERFACEIMP_INTERFACE,
204		1, 0,
205		&IRMAllocationCOM::SSetReleaseIRMResourcesOnFree,
206		&IRMAllocationCOM::SAllocateIsochResources,
207		&IRMAllocationCOM::SDeallocateIsochResources,
208		&IRMAllocationCOM::SAreIsochResourcesAllocated,
209		&IRMAllocationCOM::SNotificationIsOn,
210		&IRMAllocationCOM::STurnOnNotification,
211		&IRMAllocationCOM::STurnOffNotification,
212		&IRMAllocationCOM::SSetRefCon,
213		&IRMAllocationCOM::SGetRefCon
214	} ;
215
216	//
217	// --- ctor/dtor -----------------------
218	//
219
220	IRMAllocationCOM::IRMAllocationCOM( Device& userclient,
221									   UserObjectHandle inKernIRMAllocationRef,
222									   void* inCallBack,
223									   void* inRefCon )
224	: IRMAllocation( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, inKernIRMAllocationRef, inCallBack, inRefCon )
225	{
226	}
227
228	IRMAllocationCOM::~IRMAllocationCOM()
229	{
230	}
231
232	//
233	// --- IUNKNOWN support ----------------
234	//
235
236	IUnknownVTbl**
237	IRMAllocationCOM::Alloc(Device& userclient,
238							UserObjectHandle inKernIRMAllocationRef,
239							void* inCallBack,
240							void* inRefCon )
241	{
242		IRMAllocationCOM*	me = nil ;
243
244		try {
245			me = new IRMAllocationCOM( userclient, inKernIRMAllocationRef, inCallBack, inRefCon ) ;
246		} catch(...) {
247		}
248
249		return ( nil == me ) ? nil : reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ;
250	}
251
252	HRESULT
253	IRMAllocationCOM::QueryInterface(REFIID iid, void ** ppv )
254	{
255		HRESULT		result = S_OK ;
256		*ppv = nil ;
257
258		CFUUIDRef	interfaceID	= CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
259
260		if ( CFEqual(interfaceID, IUnknownUUID) ||  CFEqual(interfaceID, kIOFireWireIRMAllocationInterfaceID) )
261		{
262			*ppv = & GetInterface() ;
263			AddRef() ;
264		}
265		else
266		{
267			*ppv = nil ;
268			result = E_NOINTERFACE ;
269		}
270
271		CFRelease(interfaceID) ;
272		return result ;
273	}
274
275	//
276	// --- static methods ------------------
277	//
278	const void IRMAllocationCOM::SSetReleaseIRMResourcesOnFree (IOFireWireLibIRMAllocationRef self, Boolean doRelease )
279	{
280		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->SetReleaseIRMResourcesOnFree( self, doRelease ) ;
281	}
282
283	IOReturn IRMAllocationCOM::SAllocateIsochResources(IOFireWireLibIRMAllocationRef self, UInt8 isochChannel, UInt32 bandwidthUnits)
284	{
285		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->AllocateIsochResources( self, isochChannel, bandwidthUnits) ;
286	}
287
288	IOReturn IRMAllocationCOM::SDeallocateIsochResources(IOFireWireLibIRMAllocationRef self)
289	{
290		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->DeallocateIsochResources(self) ;
291	}
292
293	Boolean IRMAllocationCOM::SAreIsochResourcesAllocated(IOFireWireLibIRMAllocationRef self, UInt8 *pAllocatedIsochChannel, UInt32 *pAllocatedBandwidthUnits)
294	{
295		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->AreIsochResourcesAllocated(self, pAllocatedIsochChannel, pAllocatedBandwidthUnits) ;
296	}
297
298	Boolean IRMAllocationCOM::SNotificationIsOn(IOFireWireLibIRMAllocationRef self)
299	{
300		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->NotificationIsOn(self) ;
301	}
302
303	Boolean IRMAllocationCOM::STurnOnNotification(IOFireWireLibIRMAllocationRef self)
304	{
305		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->TurnOnNotification(self) ;
306	}
307
308	void IRMAllocationCOM::STurnOffNotification(IOFireWireLibIRMAllocationRef self)
309	{
310		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->TurnOffNotification(self);
311	}
312
313	void  IRMAllocationCOM::SSetRefCon(IOFireWireLibIRMAllocationRef self, void* refCon)
314	{
315		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->SetRefCon(self,refCon);
316	}
317
318	void*  IRMAllocationCOM::SGetRefCon(IOFireWireLibIRMAllocationRef self)
319	{
320		return IOFireWireIUnknown::InterfaceMap<IRMAllocationCOM>::GetThis(self)->GetRefCon(self);
321	}
322}