|
|
1.1 root 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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
24: *
25: * IONetworkMedium.cpp
26: *
27: * HISTORY
28: *
29: */
30:
31: #include <IOKit/assert.h>
32: #include <IOKit/IOLib.h>
33: #include <libkern/c++/OSObject.h>
34: #include <libkern/c++/OSData.h>
35: #include <libkern/c++/OSCollectionIterator.h>
36: #include <libkern/c++/OSDictionary.h>
37: #include <libkern/c++/OSSerialize.h>
38: #include <IOKit/network/IONetworkMedium.h>
39:
40: //---------------------------------------------------------------------------
41: // OSMetaClass macros.
42:
43: #define super OSObject
44: OSDefineMetaClassAndStructors( IONetworkMedium, OSObject )
45:
46: //---------------------------------------------------------------------------
47: // Initialize an IONetworkMedium instance.
48: //
49: // type: The medium type, the fields are encoded with bits defined in
50: // IONetworkMedium.h.
51: //
52: // speed: The maximum (or the only) link speed supported over this medium
53: // in units of bits per second.
54: //
55: // flags: An optional flag for the medium object.
56: // See IONetworkMedium.h for defined flags.
57: //
58: // index: An optional 32-bit index assigned by the caller. Drivers can use
59: // this to store an index or a pointer to a media table inside the
60: // driver, or it may map to a driver defined media type.
61: //
62: // name: An name to assign to this medium object. If 0, then a name
63: // will be created based on the medium type given using nameForType().
64: //
65: // Returns true on success, false otherwise.
66:
67: bool IONetworkMedium::init(IOMediumType type,
68: UInt64 speed,
69: UInt32 flags = 0,
70: UInt32 index = 0,
71: const char * name = 0)
72: {
73: if (!super::init())
74: return false;
75:
76: _desc = (IOMediumDescriptor *) IOMalloc(sizeof(*_desc));
77: if (!_desc)
78: return false;
79: bzero(_desc, sizeof(*_desc));
80:
81: _desc->type = type;
82: _desc->flags = flags;
83: _desc->speed = speed;
84: _desc->data = index;
85:
86: if (name)
87: _name = OSSymbol::withCString(name);
88: else
89: _name = IONetworkMedium::nameForType(type);
90:
91: if (!_name)
92: return false;
93:
94: return true;
95: }
96:
97: //---------------------------------------------------------------------------
98: // Factory method which performs allocation and initialization
99: // of an IONetworkMedium instance.
100: //
101: // Returns an IONetworkMedium instance on success, or 0 otherwise.
102:
103: IONetworkMedium * IONetworkMedium::medium(IOMediumType type,
104: UInt64 speed,
105: UInt32 flags = 0,
106: UInt32 index = 0,
107: const char * name = 0)
108: {
109: IONetworkMedium * medium = new IONetworkMedium;
110:
111: if (medium && !medium->init(type, speed, flags, index, name))
112: {
113: medium->release();
114: medium = 0;
115: }
116:
117: return medium;
118: }
119:
120: //---------------------------------------------------------------------------
121: // Free the IONetworkMedium instance.
122:
123: void IONetworkMedium::free()
124: {
125: if (_name)
126: _name->release();
127: if (_desc)
128: IOFree(_desc, sizeof(*_desc));
129:
130: super::free();
131: }
132:
133: //---------------------------------------------------------------------------
134: // Return the assigned medium type.
135:
136: IOMediumType IONetworkMedium::getType() const
137: {
138: return _desc->type;
139: }
140:
141: //---------------------------------------------------------------------------
142: // Return the medium flags.
143:
144: UInt32 IONetworkMedium::getFlags() const
145: {
146: return _desc->flags;
147: }
148:
149: //---------------------------------------------------------------------------
150: // Return the maximum medium speed.
151:
152: UInt64 IONetworkMedium::getSpeed() const
153: {
154: return _desc->speed;
155: }
156:
157: //---------------------------------------------------------------------------
158: // Return the assigned index.
159:
160: UInt32 IONetworkMedium::getIndex() const
161: {
162: return _desc->data;
163: }
164:
165: //---------------------------------------------------------------------------
166: // Return the name for this instance.
167:
168: const OSSymbol * IONetworkMedium::getName() const
169: {
170: return _name;
171: }
172:
173: //---------------------------------------------------------------------------
174: // descP: The IOMediumDescriptor structure associated with the
175: // instance is copied to a structure provided by the caller.
176:
177: void IONetworkMedium::getDescriptor(IOMediumDescriptor * descP) const
178: {
179: assert(descP);
180: bcopy(_desc, descP, sizeof(*descP));
181: }
182:
183: //===========================================================================
184: // The definitions and the routines were adapted from FreeBSD
185: // (net/if_media.c). Should try to reuse the similar function in BSD.
186: //===========================================================================
187: /*
188: * Copyright (c) 1997
189: * Jonathan Stone and Jason R. Thorpe. All rights reserved.
190: *
191: * This software is derived from information provided by Matt Thomas.
192: *
193: * Redistribution and use in source and binary forms, with or without
194: * modification, are permitted provided that the following conditions
195: * are met:
196: * 1. Redistributions of source code must retain the above copyright
197: * notice, this list of conditions and the following disclaimer.
198: * 2. Redistributions in binary form must reproduce the above copyright
199: * notice, this list of conditions and the following disclaimer in the
200: * documentation and/or other materials provided with the distribution.
201: * 3. All advertising materials mentioning features or use of this software
202: * must display the following acknowledgement:
203: * This product includes software developed by Jonathan Stone
204: * and Jason R. Thorpe for the NetBSD Project.
205: * 4. The names of the authors may not be used to endorse or promote products
206: * derived from this software without specific prior written permission.
207: *
208: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
209: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
210: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
211: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
212: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
213: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
214: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
215: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
216: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
217: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
218: * SUCH DAMAGE.
219: */
220:
221: /*
222: * Append a C string to a buffer. A counter is updated with the remaining
223: * size of the buffer.
224: */
225: static void append_string(char ** buf,
226: int * remain,
227: const char * str)
228: {
229: char * buffer = *buf;
230: int needed_length;
231:
232: if (!str)
233: return;
234:
235: // The remaining size must be big enough for 'str',
236: // and a terminating null character.
237:
238: needed_length = strlen(str) + 1;
239:
240: if (*remain >= needed_length) { // buffer is large enough
241: bcopy(str, buffer, strlen(str));
242: buffer += strlen(str);
243: *buffer = '\0';
244:
245: // decrement the remaining count, not counting the null char.
246: //
247: *remain -= (needed_length - 1);
248: *buf = buffer;
249: }
250: }
251:
252: struct IOMediumTypesAndOptions {
253: struct IOMediumDescription * types;
254: struct IOMediumDescription * options;
255: };
256:
257: static struct IOMediumDescription familyDescriptions[] =
258: kIOMediumFamilyDescriptions;
259:
260: static struct IOMediumDescription ethernetDescriptions[] =
261: kIOMediumEthernetDescriptions;
262:
263: static struct IOMediumDescription ethernetOptionDescriptions[] =
264: kIOMediumEthernetOptionDescriptions;
265:
266: static struct IOMediumDescription commonDescriptions[] =
267: kIOMediumCommonDescriptions;
268:
269: static struct IOMediumDescription commonOptionDescriptions[] =
270: kIOMediumCommonOptionDescriptions;
271:
272: static struct IOMediumTypesAndOptions typesAndOptionsTable[] = {
273: {
274: ðernetDescriptions[0],
275: ðernetOptionDescriptions[0]
276: },
277: };
278:
279: #define IO_IFM_APPEND_OPTION(str) { \
280: if (seen_option == 0) \
281: append_string(&buf, &maxlen, " ("); \
282: append_string(&buf, &maxlen, seen_option++ ? "," : ""); \
283: append_string(&buf, &maxlen, str); \
284: }
285:
286: /*
287: * print a media word.
288: */
289: static int
290: ifmedia_printword(int ifmw, char * buf, int maxlen)
291: {
292: struct IOMediumDescription * desc;
293: struct IOMediumTypesAndOptions * ttos;
294: int seen_option = 0;
295:
296: /* Find the media family first */
297: for (desc = familyDescriptions, ttos = typesAndOptionsTable;
298: desc->string != NULL;
299: desc++, ttos++)
300: if (IOMediumGetFamily(ifmw) == desc->word)
301: break;
302:
303: if (desc->string == NULL)
304: return 0; // unknown family type.
305:
306: #if 0 // disable family printing (e.g. Ethernet).
307: append_string(&buf, &maxlen, desc->string);
308: #endif
309:
310: /*
311: * Print the family specific type description. If the description
312: * is not found, then look at the common type descriptions.
313: */
314: for (desc = ttos->types; desc->string != NULL; desc++)
315: if (IOMediumGetType(ifmw) == desc->word)
316: goto got_subtype;
317:
318: for (desc = commonDescriptions; desc->string != NULL; desc++)
319: if (IOMediumGetIndex(ifmw) == desc->word)
320: break;
321:
322: if (desc->string == NULL)
323: return 0; // unknown family specific type.
324:
325: got_subtype:
326: #if 0 // by disabling type printing, we don't need the space padding.
327: append_string(&buf, &maxlen, " ");
328: #endif
329: append_string(&buf, &maxlen, desc->string);
330:
331: /*
332: * Look for common options.
333: */
334: for (desc = commonOptionDescriptions; desc->string != NULL; desc++) {
335: if (ifmw & desc->word)
336: IO_IFM_APPEND_OPTION(desc->string);
337: }
338:
339: /*
340: * Look for family specific options.
341: */
342: for (desc = ttos->options; desc->string != NULL; desc++) {
343: if (ifmw & desc->word)
344: IO_IFM_APPEND_OPTION(desc->string);
345: }
346:
347: /*
348: * Print the instance number.
349: */
350: if (IOMediumGetInstance(ifmw)) {
351: char instanceString[16];
352: sprintf(instanceString, "%d", IOMediumGetInstance(ifmw));
353: IO_IFM_APPEND_OPTION(instanceString);
354: }
355:
356: append_string(&buf, &maxlen, seen_option ? ")" : "");
357:
358: return 1;
359: }
360: //===========================================================================
361: // End of FreeBSD import.
362: //===========================================================================
363:
364: //---------------------------------------------------------------------------
365: // Given a 32-bit medium type, create an unique OSymbol name for the medium.
366: // The caller is responsible for releasing the OSSymbol object returned.
367: //
368: // type: A medium type. See IONetworkMedium.h for type encoding.
369: //
370: // Returns an OSSymbol created based on the type provided.
371:
372: const OSSymbol * IONetworkMedium::nameForType(IOMediumType type)
373: {
374: const UInt maxNameLen = 160;
375: char buffer[maxNameLen];
376:
377: if (ifmedia_printword(type, buffer, maxNameLen) == 0)
378: return 0; // error, cannot create name.
379:
380: // Caller must remember to free the OSSymbol!
381: //
382: return OSSymbol::withCString(buffer);
383: }
384:
385: //---------------------------------------------------------------------------
386: // Test for equality between two IONetworkMedium objects.
387: // Two IONetworkMedium objects are considered equal if
388: // they have similar properties assigned to them during initialization.
389: //
390: // medium: An IONetworkMedium to test against the IONetworkMedium
391: // object being called.
392: //
393: // Returns true if equal, false otherwise.
394:
395: bool IONetworkMedium::isEqualTo(const IONetworkMedium * medium) const
396: {
397: return ((bcmp(medium->_desc, _desc, sizeof(*_desc)) == 0) &&
398: (medium->_name == _name));
399: }
400:
401: //---------------------------------------------------------------------------
402: // Test for equality between a IONetworkMedium object and an OSObject.
403: // The OSObject is considered equal to the IONetworkMedium object if the
404: // OSObject is an IONetworkMedium, and they have similar properties assigned
405: // to them during initialization.
406: //
407: // obj: An OSObject to test against the IONetworkMedium object being called.
408: //
409: // Returns true if equal, false otherwise.
410:
411: bool IONetworkMedium::isEqualTo(const OSObject * obj) const
412: {
413: IONetworkMedium * medium;
414: if ((medium = OSDynamicCast(IONetworkMedium, (OSObject *) obj)))
415: return isEqualTo(medium);
416: else
417: return false;
418: }
419:
420: //---------------------------------------------------------------------------
421: // Create an OSData containing an IOMediumDescriptor structure (not copied),
422: // and ask the OSData to serialize.
423: //
424: // s: An OSSerialize object to handle the serialization.
425: //
426: // Returns true on success, false otherwise.
427:
428: bool IONetworkMedium::serialize(OSSerialize * s) const
429: {
430: bool ret = false;
431: OSData * descriptorData;
432:
433: // Create an OSData that encapsulates our IOMediumDescriptor structure.
434: // Then instruct the OSData to serialize itself.
435: //
436: descriptorData = OSData::withBytesNoCopy((void *) _desc, sizeof(*_desc));
437: if (descriptorData) {
438: ret = descriptorData->serialize(s);
439: descriptorData->release();
440: }
441:
442: return ret;
443: }
444:
445: //---------------------------------------------------------------------------
446: // A helper function to add an IONetworkMedium object to a given dictionary.
447: // The name of the medium is used as the key for the new dictionary entry.
448: //
449: // dict: An OSDictionary object where the medium object should be added to.
450: // medium: The IONetworkMedium object to add to the dictionary.
451: //
452: // Returns true on success, false otherwise.
453:
454: bool IONetworkMedium::addMedium(OSDictionary * dict,
455: const IONetworkMedium * medium)
456: {
457: // Arguments type checking.
458: //
459: if (!OSDynamicCast(OSDictionary, dict) ||
460: !OSDynamicCast(IONetworkMedium, medium))
461: return false;
462:
463: return dict->setObject(medium->getName(), (OSObject *) medium);
464: }
465:
466: //---------------------------------------------------------------------------
467: // A helper function to remove an entry in a dictionary with a key that
468: // matches the name of the IONetworkMedium object provided.
469: //
470: // dict: An OSDictionary object where the medium object should be removed
471: // from.
472: // medium: The name of this medium object is used as the removal key.
473:
474: void IONetworkMedium::removeMedium(OSDictionary * dict,
475: const IONetworkMedium * medium)
476: {
477: // Arguments type checking.
478: //
479: if (!OSDynamicCast(OSDictionary, dict) ||
480: !OSDynamicCast(IONetworkMedium, medium))
481: return;
482:
483: dict->removeObject(medium->getName());
484: }
485:
486: //---------------------------------------------------------------------------
487: // Iterate through a dictionary and return an IONetworkMedium entry that
488: // satisfies the matching criteria. Returns 0 if there is no match.
489: // Also see getMediumWithType() and getMediumWithIndex() that
490: // are specialized forms derived from this method.
491: //
492: // dict: The dictionary to look for a match.
493: // match: An IOMediumDescriptor structure containing the matching fields.
494: // mask: An IOMediumDescriptor structure containing the matching mask.
495: // Bits set are used for matching, while cleared bits are don't
496: // care bits.
497: //
498: // The first matching IONetworkMedium entry found, or 0 if no match was found.
499:
500: IONetworkMedium * IONetworkMedium::getMedium(const OSDictionary * dict,
501: IOMediumDescriptor * match,
502: IOMediumDescriptor * mask)
503: {
504: OSCollectionIterator * iter;
505: OSSymbol * keyObject;
506: IONetworkMedium * medium;
507: IONetworkMedium * retMedium = 0;
508: IOMediumDescriptor * desc;
509: UInt i;
510:
511: assert(match && mask);
512:
513: if (!dict) return 0;
514:
515: // Shouldn't withCollection take an (const OSDictionary *) argument?
516:
517: iter = OSCollectionIterator::withCollection((OSDictionary *) dict);
518: if (!iter)
519: return 0;
520:
521: while ( (keyObject = (OSSymbol *) iter->getNextObject()) )
522: {
523: medium = OSDynamicCast(IONetworkMedium, dict->getObject(keyObject));
524: if (!medium)
525: continue;
526:
527: desc = medium->_desc;
528:
529: // Perform bytewise matching.
530: //
531: for (i = 0; i < sizeof(IOMediumDescriptor); i++) {
532: if ( (((UInt8 *) desc)[i] ^ ((UInt8 *) match)[i]) &
533: ((UInt8 *) mask)[i] )
534: break;
535: }
536: if (i == sizeof(IOMediumDescriptor)) { // match found.
537: retMedium = medium;
538: break;
539: }
540: }
541:
542: iter->release();
543:
544: return retMedium;
545: }
546:
547: //---------------------------------------------------------------------------
548: // getMedium___ macro.
549: //
550: // Returns a IONetworkMedium entry that has a IOMediumDescriptor
551: // with a 'field' which matches the given 'value'.
552: //
553: // name - function name.
554: // vartype - data type of the IOMediumDescriptor field.
555: // field - field in IOMediumDescriptor to perform search.
556: // mask - don't care bits.
557:
558: #define GET_MEDIUM_FUNC(name, vartype, field) \
559: IONetworkMedium * \
560: IONetworkMedium::getMediumWith ## name(const OSDictionary * dict, \
561: vartype value, \
562: vartype mask = 0) \
563: { \
564: IOMediumDescriptor match[2]; \
565: \
566: bzero(&match[0], sizeof(match)); \
567: \
568: match[0]. ## field = value; \
569: match[1]. ## field = ~mask; \
570: \
571: return IONetworkMedium::getMedium(dict, &match[0], &match[1]); \
572: }
573:
574: GET_MEDIUM_FUNC(Type, IOMediumType, type) // getMediumWithType()
575: GET_MEDIUM_FUNC(Index, UInt32, data) // getMediumWithIndex()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.