2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
28 #include <IOKit/assert.h>
29 #include <IOKit/IOLib.h>
30 #include <libkern/c++/OSDictionary.h>
31 #include <libkern/c++/OSNumber.h>
32 #include <libkern/c++/OSData.h>
33 #include <IOKit/network/IONetworkData.h>
35 #define super OSObject
36 OSDefineMetaClassAndStructors( IONetworkData
, OSObject
)
37 OSMetaClassDefineReservedUnused( IONetworkData
, 0);
38 OSMetaClassDefineReservedUnused( IONetworkData
, 1);
39 OSMetaClassDefineReservedUnused( IONetworkData
, 2);
40 OSMetaClassDefineReservedUnused( IONetworkData
, 3);
42 #define TAP_IS_VALID (_tapAction)
44 // All access method are serialized by a single global lock,
45 // shared among all IONetworkData instances.
47 static IOLock
* gIONDLock
= 0;
48 #define LOCK IOTakeLock(gIONDLock)
49 #define UNLOCK IOUnlock(gIONDLock)
51 static const OSSymbol
* gIONDDataKey
;
52 static const OSSymbol
* gIONDAccessKey
;
53 static const OSSymbol
* gIONDSizeKey
;
55 //---------------------------------------------------------------------------
56 // IONetworkData class initializer.
58 void IONetworkData::initialize()
60 // Allocates the global data lock.
62 gIONDLock
= IOLockAlloc();
64 IOLockInitWithState(gIONDLock
, kIOLockStateUnlocked
);
66 gIONDDataKey
= OSSymbol::withCStringNoCopy( kIONetworkDataBytes
);
67 gIONDAccessKey
= OSSymbol::withCStringNoCopy( kIONetworkDataAccessTypes
);
68 gIONDSizeKey
= OSSymbol::withCStringNoCopy( kIONetworkDataSize
);
70 assert(gIONDDataKey
&& gIONDAccessKey
&& gIONDSizeKey
);
73 //---------------------------------------------------------------------------
74 // Initialize an IONetworkData instance.
77 IONetworkData::init(const char * name
,
81 UInt32 accessTypes
= kIONetworkDataBasicAccessTypes
,
86 if ((bufferType
== kIONetworkDataBufferTypeInternal
) ||
87 (bufferType
== kIONetworkDataBufferTypeExternal
))
89 _buffer
= (bufferType
== kIONetworkDataBufferTypeInternal
) ?
90 (void *) kalloc(bufferSize
) : extBuffer
;
95 if (bufferType
== kIONetworkDataBufferTypeInternal
)
96 bzero(_buffer
, bufferSize
);
99 _bufType
= bufferType
;
100 _access
= accessTypes
;
106 // Generate a key for this object based on its assigned name.
108 if ((_key
= OSSymbol::withCString(name
)) == 0)
114 //---------------------------------------------------------------------------
115 // Factory method that will construct and initialize an IONetworkData
116 // instance with an internal buffer.
119 IONetworkData::withInternalBuffer(
122 UInt32 accessTypes
= kIONetworkDataBasicAccessTypes
,
127 IONetworkData
* aData
= new IONetworkData
;
129 if (aData
&& !aData
->init(name
,
130 kIONetworkDataBufferTypeInternal
,
144 //---------------------------------------------------------------------------
145 // Factory method that will construct and initialize an IONetworkData
146 // instance with an external buffer.
149 IONetworkData::withExternalBuffer(
153 UInt32 accessTypes
= kIONetworkDataBasicAccessTypes
,
158 IONetworkData
* aData
= new IONetworkData
;
160 if (aData
&& !aData
->init(name
,
161 kIONetworkDataBufferTypeExternal
,
175 //---------------------------------------------------------------------------
176 // Factory method that will construct and initialize an IONetworkData
177 // instance with no data buffer. The notification handler must intervene
178 // when the IONetworkData is accessed.
181 IONetworkData::withNoBuffer(const char * name
,
188 IONetworkData
* aData
= new IONetworkData
;
190 if (aData
&& !aData
->init(name
,
191 kIONetworkDataBufferTypeNone
,
205 //---------------------------------------------------------------------------
206 // Free the IONetworkData instance.
208 void IONetworkData::free()
213 if (_buffer
&& (_bufType
== kIONetworkDataBufferTypeInternal
))
214 kfree((vm_offset_t
) _buffer
, _size
);
219 //---------------------------------------------------------------------------
220 // Return the type of buffer managed by this instance.
221 // See IONetworkDataBufferType enum definition
223 UInt32
IONetworkData::getBufferType() const
228 //---------------------------------------------------------------------------
229 // Change the supported access types.
231 #define kIONetworkDataImmutableAccessTypes 0
233 void IONetworkData::setAccessTypes(UInt32 types
)
236 _access
= (_access
& kIONetworkDataImmutableAccessTypes
) |
237 (types
& ~kIONetworkDataImmutableAccessTypes
);
241 //---------------------------------------------------------------------------
242 // Register a target/action to handle access notification.
244 void IONetworkData::setNotificationTarget(void * target
,
255 //---------------------------------------------------------------------------
256 // Return the supported access types.
258 UInt32
IONetworkData::getAccessTypes() const
263 //---------------------------------------------------------------------------
264 // Return the notification target.
266 void * IONetworkData::getNotificationTarget() const
271 //---------------------------------------------------------------------------
272 // Return the notification action.
274 IONetworkData::Action
IONetworkData::getNotificationAction() const
279 //---------------------------------------------------------------------------
280 // Return the notification parameter.
282 void * IONetworkData::getNotificationParameter() const
287 //---------------------------------------------------------------------------
288 // Get an OSSymbol key associated with this instance.
289 // During initialization, IONetworkData will create an OSSymbol
290 // key based on its assigned name.
292 // Return an OSSymbol key generated from the assigned name.
294 const OSSymbol
* IONetworkData::getKey() const
299 //---------------------------------------------------------------------------
300 // Return the size of the data managed by this instance in bytes.
302 UInt32
IONetworkData::getSize() const
307 //---------------------------------------------------------------------------
308 // Write to the data buffer with data from a source buffer provided
311 bool IONetworkData::writeBytes(const void * srcBuffer
,
312 UInt32 srcBufferSize
,
315 if ( _buffer
== 0 ) return false;
317 if ( srcBufferSize
&&
318 (writeOffset
< _size
) &&
319 ((writeOffset
+ srcBufferSize
) <= _size
) )
321 bcopy(srcBuffer
, (char *) _buffer
+ writeOffset
, srcBufferSize
);
328 //---------------------------------------------------------------------------
329 // Return a pointer to the data buffer.
331 const void * IONetworkData::getBuffer() const
333 return (_buffer
) ? _buffer
: 0;
336 //---------------------------------------------------------------------------
337 // Copy the data buffer to a destination buffer provided by the caller.
339 bool IONetworkData::readBytes(void * dstBuffer
,
340 UInt32
* dstBufferSize
,
341 UInt32 readOffset
) const
343 if ( _buffer
== 0 ) return false;
345 if ( *dstBufferSize
&& (readOffset
< _size
) )
347 UInt32 bytesCopied
= min((_size
- readOffset
), *dstBufferSize
);
349 bcopy((char *) _buffer
+ readOffset
, dstBuffer
, bytesCopied
);
351 *dstBufferSize
= bytesCopied
;
359 //---------------------------------------------------------------------------
360 // Clear the entire data buffer by filling it with zeroes.
362 bool IONetworkData::clearBuffer()
366 bzero((void *) _buffer
, _size
);
372 //---------------------------------------------------------------------------
373 // Handle a user space request to reset the data buffer.
375 IOReturn
IONetworkData::reset()
377 IOReturn ret
= kIOReturnUnsupported
;
384 if ( (_access
& kIONetworkDataAccessTypeReset
) == 0 )
386 ret
= kIOReturnNotWritable
;
390 // Default action is to bzero the entire buffer.
394 ret
= kIOReturnSuccess
;
397 // Notify our target.
401 ret
= (*_tapAction
)(_tapTarget
, _tapParam
,
403 (UInt32
) kIONetworkDataAccessTypeReset
,
414 //---------------------------------------------------------------------------
415 // Handle an external request to read from the data buffer
416 // and copy it to the destination buffer provided by the accessor.
418 IOReturn
IONetworkData::read(void * dstBuffer
,
419 UInt32
* dstBufferSize
,
422 IOReturn ret
= kIOReturnUnsupported
;
427 // Check the arguments.
429 if ( !dstBuffer
|| !dstBufferSize
)
431 ret
= kIOReturnBadArgument
;
437 if ( (_access
& kIONetworkDataAccessTypeRead
) == 0 )
439 ret
= kIOReturnNotReadable
;
443 // Notify the target before the read operation.
444 // The target can take this opportunity to update the
445 // data buffer. If the target returns an error,
446 // abort and return the error.
450 ret
= (*_tapAction
)(_tapTarget
, _tapParam
,
452 (UInt32
) kIONetworkDataAccessTypeRead
,
456 if (ret
!= kIOReturnSuccess
)
462 ret
= readBytes(dstBuffer
, dstBufferSize
, readOffset
) ?
463 kIOReturnSuccess
: kIOReturnBadArgument
;
473 //---------------------------------------------------------------------------
474 // Handle an external request to write to the data buffer
475 // from a source buffer provided by the accessor.
477 IOReturn
IONetworkData::write(void * srcBuffer
,
478 UInt32 srcBufferSize
,
481 IOReturn ret
= kIOReturnUnsupported
;
486 // Check the arguments.
488 if ( srcBuffer
== 0 )
490 ret
= kIOReturnBadArgument
;
496 if ( (_access
& kIONetworkDataAccessTypeWrite
) == 0 )
498 ret
= kIOReturnNotWritable
;
502 // Update the data buffer.
505 (writeBytes(srcBuffer
, srcBufferSize
, writeOffset
) == false) )
507 ret
= kIOReturnBadArgument
;
511 // Notify the target after a successful write operation.
515 ret
= (*_tapAction
)(_tapTarget
, _tapParam
,
517 (UInt32
) kIONetworkDataAccessTypeWrite
,
530 //---------------------------------------------------------------------------
531 // Serialize the IONetworkData object. If notification is enabled,
532 // then the notification handler is called before the data buffer is
535 bool IONetworkData::serialize(OSSerialize
* s
) const
538 OSDictionary
* dictToSerialize
;
540 OSNumber
* numberEntry
;
542 dictToSerialize
= OSDictionary::withCapacity(3);
543 if (!dictToSerialize
)
546 numberEntry
= OSNumber::withNumber(_access
, sizeof(_access
) * 8);
548 dictToSerialize
->setObject(gIONDAccessKey
, numberEntry
);
549 numberEntry
->release();
552 numberEntry
= OSNumber::withNumber(_size
, sizeof(_size
) * 8);
554 dictToSerialize
->setObject(gIONDSizeKey
, numberEntry
);
555 numberEntry
->release();
563 if ((_access
& kIONetworkDataAccessTypeSerialize
) == 0)
569 // Notify the target before the read operation.
570 // The target can take this opportunity to update the
571 // data buffer. If the target returns an error,
572 // then the data buffer is not serialized.
575 ((*_tapAction
)(_tapTarget
, _tapParam
,
576 (IONetworkData
*) this,
577 kIONetworkDataAccessTypeSerialize
,
578 0, 0, 0) != kIOReturnSuccess
))
583 dataEntry
= OSData::withBytesNoCopy(_buffer
, _size
);
585 dictToSerialize
->setObject(gIONDDataKey
, dataEntry
);
586 dataEntry
->release();
591 ok
= dictToSerialize
->serialize(s
);
592 dictToSerialize
->release();