Annotation of XNU/iokit/Families/IONetworking/IONetworkMedium.cpp, revision 1.1.1.1

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:       &ethernetDescriptions[0],
                    275:       &ethernetOptionDescriptions[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()

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.