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/*
24 *
25 *	IOFWAddressSpace.cpp
26 *
27 * Classes which describe addresses in the local node which are accessable to other nodes
28 * via firewire asynchronous read/write/lock requests.
29 *
30 * HISTORY
31 *
32 */
33
34#include <IOKit/firewire/IOFWAddressSpace.h>
35#include <IOKit/firewire/IOFireWireController.h>
36#include <IOKit/firewire/IOFireWireDevice.h>
37
38#include "FWDebugging.h"
39
40OSDefineMetaClassAndStructors(IOFWAddressSpaceAux, OSObject);
41
42OSMetaClassDefineReservedUsed(IOFWAddressSpaceAux, 0);			// intersects
43OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 1);
44OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 2);
45OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 3);
46OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 4);
47OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 5);
48OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 6);
49OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 7);
50OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 8);
51OSMetaClassDefineReservedUnused(IOFWAddressSpaceAux, 9);
52
53#pragma mark -
54
55// init
56//
57//
58
59bool IOFWAddressSpaceAux::init( IOFWAddressSpace * primary )
60{
61	bool success = true;		// assume success
62
63	// init super
64
65    if( !OSObject::init() )
66        success = false;
67
68	fExclusive = false;
69
70	if( success )
71	{
72		fPrimary = primary;
73		fControl = fPrimary->fControl;
74
75		//
76		// create node set
77		//
78
79		fTrustedNodeSet = OSSet::withCapacity(1);
80		if( fTrustedNodeSet == NULL )
81			success = false;
82	}
83
84	if( success )
85	{
86		fTrustedNodeSetIterator = OSCollectionIterator::withCollection( fTrustedNodeSet );
87		if( fTrustedNodeSetIterator == NULL )
88			success = false;
89	}
90
91	if( !success )
92	{
93		if( fTrustedNodeSet != NULL )
94		{
95			fTrustedNodeSet->release();
96			fTrustedNodeSet = NULL;
97		}
98
99		if( fTrustedNodeSetIterator != NULL )
100		{
101			fTrustedNodeSetIterator->release();
102			fTrustedNodeSetIterator = NULL;
103		}
104	}
105
106	return success;
107}
108
109// free
110//
111//
112
113void IOFWAddressSpaceAux::free()
114{
115	if( fTrustedNodeSet != NULL )
116	{
117		fTrustedNodeSet->release();
118		fTrustedNodeSet = NULL;
119	}
120
121	if( fTrustedNodeSetIterator != NULL )
122	{
123		fTrustedNodeSetIterator->release();
124		fTrustedNodeSetIterator = NULL;
125	}
126
127	OSObject::free();
128}
129
130// isTrustedNode
131//
132//
133
134bool IOFWAddressSpaceAux::isTrustedNode( UInt16 nodeID )
135{
136	bool	trusted = false;
137
138#if 1
139	//
140	// trusted if not in secure mode
141	//
142
143	if( fControl->getSecurityMode() == kIOFWSecurityModeNormal )
144		trusted = true;
145#endif
146
147	//
148	// trusted if the local node
149	// trusted if no nodes in set (no source node ID verification)
150	//
151
152	if( !trusted )
153	{
154		UInt16 localNodeID = fControl->getLocalNodeID();
155
156//		FWKLOG(( "IOFWAddressSpaceAux::isTrustedNode - localNodeID = 0x%x\n", localNodeID ));
157
158		if( nodeID == localNodeID || fTrustedNodeSet->getCount() == 0 )
159			trusted = true;
160	}
161
162	//
163	// check node id of all devices in set
164	//
165
166	IOFireWireDevice * item = NULL;
167	fTrustedNodeSetIterator->reset();
168	while( !trusted && (item = (IOFireWireDevice *) fTrustedNodeSetIterator->getNextObject()) )
169	{
170		UInt32 generation = 0;
171		UInt16 deviceNodeID = 0;
172
173		item->getNodeIDGeneration( generation, deviceNodeID );
174
175	//	FWKLOG(( "IOFWAddressSpaceAux::isTrustedNode - deviceNodeID = 0x%x\n", deviceNodeID ));
176
177		if( deviceNodeID == nodeID )
178			trusted = true;
179	}
180
181//	FWKLOG(( "IOFWAddressSpaceAux::isTrustedNode - nodeID = 0x%x, trusted = %d\n", nodeID, trusted ));
182
183	return trusted;
184}
185
186// addTrustedNode
187//
188//
189
190void IOFWAddressSpaceAux::addTrustedNode( IOFireWireDevice * device )
191{
192	fTrustedNodeSet->setObject( device );
193}
194
195// removeTrustedNode
196//
197//
198
199void IOFWAddressSpaceAux::removeTrustedNode( IOFireWireDevice * device )
200{
201	fTrustedNodeSet->removeObject( device );
202}
203
204// removeAllTrustedNodes
205//
206//
207
208void IOFWAddressSpaceAux::removeAllTrustedNodes( void )
209{
210	fTrustedNodeSet->flushCollection();
211}
212
213// isExclusive
214//
215//
216
217bool IOFWAddressSpaceAux::isExclusive( void )
218{
219	return fExclusive;
220}
221
222// setExclusive
223//
224//
225
226void IOFWAddressSpaceAux::setExclusive( bool exclusive )
227{
228	fExclusive = exclusive;
229}
230
231// intersects
232//
233//
234
235bool IOFWAddressSpaceAux::intersects( IOFWAddressSpace * space )
236{
237	return false;
238}
239
240#pragma mark -
241
242/*
243 * Base class for FireWire address space objects
244 */
245
246OSDefineMetaClass( IOFWAddressSpace, OSObject )
247OSDefineAbstractStructors(IOFWAddressSpace, OSObject)
248
249//OSMetaClassDefineReservedUnused(IOFWAddressSpace, 0);
250//OSMetaClassDefineReservedUnused(IOFWAddressSpace, 1);
251
252// init
253//
254//
255
256bool IOFWAddressSpace::init(IOFireWireBus *bus)
257{
258	bool success = true;		// assume success
259
260	// init super
261
262    if( !OSObject::init() )
263        success = false;
264
265	// get controller
266
267	if( success )
268	{
269		fControl = OSDynamicCast(IOFireWireController, bus);
270		if( fControl == NULL )
271			success = false;
272	}
273
274	// create expansion data
275
276	if( success )
277	{
278		fIOFWAddressSpaceExpansion = (ExpansionData*) IOMalloc( sizeof(ExpansionData) );
279		if( fIOFWAddressSpaceExpansion == NULL )
280			success = false;
281	}
282
283	// zero expansion data
284
285	if( success )
286	{
287		bzero( fIOFWAddressSpaceExpansion, sizeof(ExpansionData) );
288		fIOFWAddressSpaceExpansion->fAuxiliary = createAuxiliary();
289		if( fIOFWAddressSpaceExpansion->fAuxiliary == NULL )
290			success = false;
291	}
292
293	// clean up on failure
294
295	if( !success )
296	{
297		if( fIOFWAddressSpaceExpansion->fAuxiliary != NULL )
298		{
299			fIOFWAddressSpaceExpansion->fAuxiliary->release();
300			fIOFWAddressSpaceExpansion->fAuxiliary = NULL;
301		}
302
303		if( fIOFWAddressSpaceExpansion != NULL )
304		{
305			IOFree ( fIOFWAddressSpaceExpansion, sizeof(ExpansionData) );
306			fIOFWAddressSpaceExpansion = NULL;
307		}
308	}
309
310    return success;
311}
312
313// createAuxiliary
314//
315// virtual method for creating auxiliary object.  subclasses needing to subclass
316// the auxiliary object can override this.
317
318IOFWAddressSpaceAux * IOFWAddressSpace::createAuxiliary( void )
319{
320	IOFWAddressSpaceAux * auxiliary;
321
322	auxiliary = OSTypeAlloc( IOFWAddressSpaceAux );
323
324    if( auxiliary != NULL && !auxiliary->init(this) )
325	{
326        auxiliary->release();
327        auxiliary = NULL;
328    }
329
330    return auxiliary;
331}
332
333// free
334//
335//
336
337void IOFWAddressSpace::free()
338{
339	if( fIOFWAddressSpaceExpansion != NULL )
340	{
341		// release auxiliary object
342
343		if( fIOFWAddressSpaceExpansion->fAuxiliary != NULL )
344		{
345			fIOFWAddressSpaceExpansion->fAuxiliary->release();
346			fIOFWAddressSpaceExpansion->fAuxiliary = NULL;
347		}
348
349		// free expansion data
350
351		IOFree ( fIOFWAddressSpaceExpansion, sizeof(ExpansionData) );
352		fIOFWAddressSpaceExpansion = NULL;
353	}
354
355    OSObject::free();
356}
357
358// doLock
359//
360//
361
362UInt32 IOFWAddressSpace::doLock(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 inLen,
363                        const UInt32 *newVal, UInt32 &outLen, UInt32 *oldVal, UInt32 type,
364                          IOFWRequestRefCon refcon)
365{
366    UInt32 ret = kFWResponseAddressError;
367    bool ok;
368    int size;
369    int i;
370    IOMemoryDescriptor *desc = NULL;
371    IOByteCount offset;
372
373    size = inLen/8;	// Depends on type, right for 'compare and swap'
374    outLen = inLen/2;	// right for 'compare and swap'
375
376	ret = doRead(nodeID, speed, addr, size*4, &desc, &offset, refcon);
377	if(ret != kFWResponseComplete)
378		return ret;
379
380    desc->readBytes(offset, oldVal, size*4);
381
382    switch (type)
383	{
384        case kFWExtendedTCodeCompareSwap:
385            ok = true;
386			for(i=0; i<size; i++)
387                ok = ok && oldVal[i] == newVal[i];
388			if(ok)
389                ret = doWrite(nodeID, speed, addr, size*4, newVal+size, refcon);
390			break;
391
392        default:
393            ret = kFWResponseTypeError;
394    }
395    return ret;
396}
397
398// activate
399//
400//
401
402IOReturn IOFWAddressSpace::activate()
403{
404    return fControl->allocAddress(this);
405}
406
407// deactivate
408//
409//
410
411void IOFWAddressSpace::deactivate()
412{
413    fControl->freeAddress(this);
414}
415
416// contains
417//
418//
419
420UInt32 IOFWAddressSpace::contains(FWAddress addr)
421{
422    return 0;
423}
424