1/*
2  File: AppleSCSIEmulatorAdapterUC.cpp
3
4  Contains:
5
6  Version: 1.0.0
7
8  Copyright: Copyright (c) 2007 by Apple Inc., All Rights Reserved.
9
10Disclaimer:IMPORTANT:  This Apple software is supplied to you by Apple Inc.
11("Apple") in consideration of your agreement to the following terms, and your use,
12installation, modification or redistribution of this Apple software constitutes acceptance
13of these terms.  If you do not agree with these terms, please do not use, install, modify or
14redistribute this Apple software.
15
16In consideration of your agreement to abide by the following terms, and subject
17to these terms, Apple grants you a personal, non-exclusive license, under Apple's
18copyrights in this original Apple software (the "Apple Software"), to use, reproduce,
19modify and redistribute the Apple Software, with or without modifications, in source and/or
20binary forms; provided that if you redistribute the Apple Software in its entirety
21and without modifications, you must retain this notice and the following text
22and disclaimers in all such redistributions of the Apple Software.  Neither the
23name, trademarks, service marks or logos of Apple Inc. may be used to
24endorse or promote products derived from the Apple Software without specific prior
25written permission from Apple.  Except as expressly stated in this notice, no
26other rights or licenses, express or implied, are granted by Apple herein,
27including but not limited to any patent rights that may be infringed by your derivative
28works or by other works in which the Apple Software may be incorporated.
29
30The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES,
31EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
32MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE
33OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE
34BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
36OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
37REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
38AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT
39LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40*/
41
42
43//-----------------------------------------------------------------------------
44//	Includes
45//-----------------------------------------------------------------------------
46
47#include "AppleSCSIEmulatorAdapterUC.h"
48#include "AppleSCSIEmulatorAdapter.h"
49
50
51//-----------------------------------------------------------------------------
52//	Macros
53//-----------------------------------------------------------------------------
54
55#define DEBUG 												1
56#define DEBUG_ASSERT_COMPONENT_NAME_STRING					"AdapterUC"
57
58#if DEBUG
59#define ADAPTER_UC_DEBUGGING_LEVEL							3
60#endif
61
62#include "DebugSupport.h"
63
64#if ( ADAPTER_UC_DEBUGGING_LEVEL >= 1 )
65#define PANIC_NOW(x)		panic x
66#else
67#define PANIC_NOW(x)
68#endif
69
70#if ( ADAPTER_UC_DEBUGGING_LEVEL >= 2 )
71#define ERROR_LOG(x)		IOLog x; IOSleep(1)
72#else
73#define ERROR_LOG(x)
74#endif
75
76#if ( ADAPTER_UC_DEBUGGING_LEVEL >= 3 )
77#define STATUS_LOG(x)		IOLog x; IOSleep(1)
78#else
79#define STATUS_LOG(x)
80#endif
81
82
83// Define superclass
84#define super IOUserClient
85OSDefineMetaClassAndStructors ( AppleSCSIEmulatorAdapterUserClient, IOUserClient );
86
87
88#if 0
89#pragma mark -
90#pragma mark Public Methods
91#pragma mark -
92#endif
93
94
95//-----------------------------------------------------------------------------
96//	 initWithTask - Save task_t and validate the connection type	[PUBLIC]
97//-----------------------------------------------------------------------------
98
99bool
100AppleSCSIEmulatorAdapterUserClient::initWithTask (
101	task_t 			owningTask,
102	void * 			securityToken,
103	UInt32 			type,
104	OSDictionary *	properties )
105{
106
107	bool	result	= false;
108
109	STATUS_LOG ( ( "AppleSCSIEmulatorAdapterUserClient::initWithTask called\n" ) );
110
111	result = super::initWithTask ( owningTask, securityToken, type, properties );
112	require ( result, ErrorExit );
113
114	fTask = owningTask;
115	result = true;
116
117
118ErrorExit:
119
120
121	return result;
122
123}
124
125
126//-----------------------------------------------------------------------------
127//	 start - Start providing services								[PUBLIC]
128//-----------------------------------------------------------------------------
129
130bool
131AppleSCSIEmulatorAdapterUserClient::start ( IOService * provider )
132{
133
134	bool			result		= false;
135	IOWorkLoop *	workLoop	= NULL;
136
137	STATUS_LOG ( ( "AppleSCSIEmulatorAdapterUserClient::start\n" ) );
138
139	require ( ( fProvider == 0 ), ErrorExit );
140	require ( super::start ( provider ), ErrorExit );
141
142	// Save the provider
143	fProvider = provider;
144
145	STATUS_LOG ( ( "Creating command gate\n" ) );
146
147	fCommandGate = IOCommandGate::commandGate ( this );
148	require_nonzero ( fCommandGate, ErrorExit );
149
150	workLoop = getWorkLoop ( );
151	require_nonzero_action ( workLoop,
152							 ErrorExit,
153							 fCommandGate->release ( ) );
154
155	STATUS_LOG ( ( "Adding event source\n" ) );
156
157	workLoop->addEventSource ( fCommandGate );
158
159	STATUS_LOG ( ( "Opening provider\n" ) );
160
161	result = provider->open ( this, kSCSIEmulatorAdapterUserClientAccessMask, 0 );
162	require_action ( result,
163					 ErrorExit,
164					 workLoop->removeEventSource ( fCommandGate );
165					 fCommandGate->release ( );
166					 fCommandGate = NULL );
167
168	fWorkLoop = workLoop;
169
170
171ErrorExit:
172
173
174	return result;
175
176}
177
178
179//-----------------------------------------------------------------------------
180//	 clientClose - Called to when a client closes/dies				   [PUBLIC]
181//-----------------------------------------------------------------------------
182
183IOReturn
184AppleSCSIEmulatorAdapterUserClient::clientClose ( void )
185{
186
187	if ( fProvider != NULL )
188	{
189
190		if ( fProvider->isOpen ( this ) == true )
191		{
192
193			fProvider->close ( this, kSCSIEmulatorAdapterUserClientAccessMask );
194
195		}
196
197		detach ( fProvider );
198		fProvider = NULL;
199
200	}
201
202	return super::clientClose ( );
203
204}
205
206
207//-----------------------------------------------------------------------------
208//	 finalize - Called to finalize resources						   [PUBLIC]
209//-----------------------------------------------------------------------------
210
211bool
212AppleSCSIEmulatorAdapterUserClient::finalize ( IOOptionBits options )
213{
214
215	clientClose ( );
216	return super::finalize ( options );
217
218}
219
220
221//-----------------------------------------------------------------------------
222//	 free - Releases any items we need to release.					   [PUBLIC]
223//-----------------------------------------------------------------------------
224
225void
226AppleSCSIEmulatorAdapterUserClient::free ( void )
227{
228
229	// Remove the command gate from the workloop
230	if ( fWorkLoop != NULL )
231	{
232
233		fWorkLoop->removeEventSource ( fCommandGate );
234		fWorkLoop = NULL;
235
236	}
237
238	// Release the command gate
239	if ( fCommandGate != NULL )
240	{
241
242		fCommandGate->release ( );
243		fCommandGate = NULL;
244
245	}
246
247	super::free ( );
248
249}
250
251
252//-----------------------------------------------------------------------------
253//	 externalMethod - 	Main dispatcher.							   [PUBLIC]
254//-----------------------------------------------------------------------------
255
256IOReturn
257AppleSCSIEmulatorAdapterUserClient::externalMethod (
258					uint32_t						selector,
259					IOExternalMethodArguments * 	args,
260					IOExternalMethodDispatch * 		dispatch,
261					OSObject *						target,
262					void *							reference )
263{
264
265	IOReturn	status = kIOReturnBadArgument;
266
267	// We only have synchronous requests. If the asyncWakePort is a port,
268	// this is an async request and we should reject it.
269	require ( ( args->asyncWakePort == MACH_PORT_NULL ), ErrorExit );
270	require ( ( selector < kUserClientMethodCount ), ErrorExit );
271
272	if ( selector == kUserClientCreateLUN )
273	{
274
275		require ( ( args->structureInputSize == sizeof ( EmulatorTargetParamsStruct ) ), ErrorExit );
276		require ( ( args->structureOutputSize == 0 ), ErrorExit );
277
278		STATUS_LOG ( ( "args->structureInputSize = %u\n", args->structureInputSize ) );
279
280		status = ( ( AppleSCSIEmulatorAdapter * ) fProvider )->CreateLUN ( ( EmulatorTargetParamsStruct * ) args->structureInput, fTask );
281
282	}
283
284	else if ( selector == kUserClientDestroyLUN )
285	{
286
287		require ( ( args->scalarInputCount == 2 ), ErrorExit );
288		require ( ( args->scalarOutputCount == 0 ), ErrorExit );
289
290		STATUS_LOG ( ( "args->scalarInputCount = %u\n", args->scalarInputCount ) );
291		STATUS_LOG ( ( "args->scalarInput[0] = %qd, args->scalarInput[1] = %qd\n", args->scalarInput[0], args->scalarInput[1] ) );
292
293		status = ( ( AppleSCSIEmulatorAdapter * ) fProvider )->DestroyLUN ( args->scalarInput[0], args->scalarInput[1] );
294
295	}
296
297	else if ( selector == kUserClientDestroyTarget )
298	{
299
300		require ( ( args->scalarInputCount == 1 ), ErrorExit );
301		require ( ( args->scalarOutputCount == 0 ), ErrorExit );
302
303		STATUS_LOG ( ( "args->scalarInputCount = %u\n", args->scalarInputCount ) );
304		STATUS_LOG ( ( "args->scalarInput[0] = %qd\n", args->scalarInput[0] ) );
305
306		status = ( ( AppleSCSIEmulatorAdapter * ) fProvider )->DestroyTarget ( args->scalarInput[0] );
307
308	}
309
310
311ErrorExit:
312
313
314	STATUS_LOG ( ( "externalMethod status = 0x%08x\n", status ) );
315
316	return status;
317
318}