Annotation of XNU/bsd/net/if_media.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 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: /*     $NetBSD: if_media.c,v 1.1 1997/03/17 02:55:15 thorpej Exp $     */
                     23: 
                     24: /*
                     25:  * Copyright (c) 1997
                     26:  *     Jonathan Stone and Jason R. Thorpe.  All rights reserved.
                     27:  *
                     28:  * This software is derived from information provided by Matt Thomas.
                     29:  *
                     30:  * Redistribution and use in source and binary forms, with or without
                     31:  * modification, are permitted provided that the following conditions
                     32:  * are met:
                     33:  * 1. Redistributions of source code must retain the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer.
                     35:  * 2. Redistributions in binary form must reproduce the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer in the
                     37:  *    documentation and/or other materials provided with the distribution.
                     38:  * 3. All advertising materials mentioning features or use of this software
                     39:  *    must display the following acknowledgement:
                     40:  *      This product includes software developed by Jonathan Stone
                     41:  *     and Jason R. Thorpe for the NetBSD Project.
                     42:  * 4. The names of the authors may not be used to endorse or promote products
                     43:  *    derived from this software without specific prior written permission.
                     44:  *
                     45:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
                     46:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     47:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     48:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     49:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     50:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     51:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     52:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     53:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     54:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     55:  * SUCH DAMAGE.
                     56:  */
                     57: 
                     58: /*
                     59:  * BSD/OS-compatible network interface media selection.
                     60:  *
                     61:  * Where it is safe to do so, this code strays slightly from the BSD/OS
                     62:  * design.  Software which uses the API (device drivers, basically)
                     63:  * shouldn't notice any difference.
                     64:  *
                     65:  * Many thanks to Matt Thomas for providing the information necessary
                     66:  * to implement this interface.
                     67:  */
                     68: 
                     69: #include <sys/param.h>
                     70: #include <sys/systm.h>
                     71: #include <sys/socket.h>
                     72: #include <sys/sockio.h>
                     73: #include <sys/malloc.h>
                     74: 
                     75: #include <net/if.h>
                     76: #include <net/if_media.h>
                     77: 
                     78: /*
                     79:  * Compile-time options:
                     80:  * IFMEDIA_DEBUG:
                     81:  *     turn on implementation-level debug printfs.
                     82:  *     Useful for debugging newly-ported  drivers.
                     83:  */
                     84: 
                     85: static struct ifmedia_entry *ifmedia_match __P((struct ifmedia *ifm,
                     86:     int flags, int mask));
                     87: 
                     88: #ifdef IFMEDIA_DEBUG
                     89: int    ifmedia_debug = 0;
                     90: static void ifmedia_printword __P((int));
                     91: #endif
                     92: 
                     93: /*
                     94:  * Initialize if_media struct for a specific interface instance.
                     95:  */
                     96: void
                     97: ifmedia_init(ifm, dontcare_mask, change_callback, status_callback)
                     98:        struct ifmedia *ifm;
                     99:        int dontcare_mask;
                    100:        ifm_change_cb_t change_callback;
                    101:        ifm_stat_cb_t status_callback;
                    102: {
                    103: 
                    104:        LIST_INIT(&ifm->ifm_list);
                    105:        ifm->ifm_cur = NULL;
                    106:        ifm->ifm_media = 0;
                    107:        ifm->ifm_mask = dontcare_mask;          /* IF don't-care bits */
                    108:        ifm->ifm_change = change_callback;
                    109:        ifm->ifm_status = status_callback;
                    110: }
                    111: 
                    112: /*
                    113:  * Add a media configuration to the list of supported media
                    114:  * for a specific interface instance.
                    115:  */
                    116: void
                    117: ifmedia_add(ifm, mword, data, aux)
                    118:        struct ifmedia *ifm;
                    119:        int mword;
                    120:        int data;
                    121:        void *aux;
                    122: {
                    123:        register struct ifmedia_entry *entry;
                    124: 
                    125: #ifdef IFMEDIA_DEBUG
                    126:        if (ifmedia_debug) {
                    127:                if (ifm == NULL) {
                    128:                        printf("ifmedia_add: null ifm\n");
                    129:                        return;
                    130:                }
                    131:                printf("Adding entry for ");
                    132:                ifmedia_printword(mword);
                    133:        }
                    134: #endif
                    135: 
                    136:        entry = _MALLOC(sizeof(*entry), M_IFADDR, M_NOWAIT);
                    137:        if (entry == NULL)
                    138:                panic("ifmedia_add: can't malloc entry");
                    139: 
                    140:        entry->ifm_media = mword;
                    141:        entry->ifm_data = data;
                    142:        entry->ifm_aux = aux;
                    143: 
                    144:        LIST_INSERT_HEAD(&ifm->ifm_list, entry, ifm_list);
                    145: }
                    146: 
                    147: /*
                    148:  * Add an array of media configurations to the list of
                    149:  * supported media for a specific interface instance.
                    150:  */
                    151: void
                    152: ifmedia_list_add(ifm, lp, count)
                    153:        struct ifmedia *ifm;
                    154:        struct ifmedia_entry *lp;
                    155:        int count;
                    156: {
                    157:        int i;
                    158: 
                    159:        for (i = 0; i < count; i++)
                    160:                ifmedia_add(ifm, lp[i].ifm_media, lp[i].ifm_data,
                    161:                    lp[i].ifm_aux);
                    162: }
                    163: 
                    164: /*
                    165:  * Set the default active media. 
                    166:  *
                    167:  * Called by device-specific code which is assumed to have already
                    168:  * selected the default media in hardware.  We do _not_ call the
                    169:  * media-change callback.
                    170:  */
                    171: void
                    172: ifmedia_set(ifm, target)
                    173:        struct ifmedia *ifm; 
                    174:        int target;
                    175: 
                    176: {
                    177:        struct ifmedia_entry *match;
                    178: 
                    179:        match = ifmedia_match(ifm, target, ifm->ifm_mask);
                    180: 
                    181:        if (match == NULL) {
                    182:                printf("ifmedia_set: no match for 0x%x/0x%x\n",
                    183:                    target, ~ifm->ifm_mask);
                    184:                panic("ifmedia_set");
                    185:        }
                    186:        ifm->ifm_cur = match;
                    187: 
                    188: #ifdef IFMEDIA_DEBUG
                    189:        if (ifmedia_debug) {
                    190:                printf("ifmedia_set: target ");
                    191:                ifmedia_printword(target);
                    192:                printf("ifmedia_set: setting to ");
                    193:                ifmedia_printword(ifm->ifm_cur->ifm_media);
                    194:        }
                    195: #endif
                    196: }
                    197: 
                    198: /*
                    199:  * Device-independent media ioctl support function.
                    200:  */
                    201: int
                    202: ifmedia_ioctl(ifp, ifr, ifm, cmd)
                    203:        struct ifnet *ifp;
                    204:        struct ifreq *ifr;
                    205:        struct ifmedia *ifm;
                    206:        u_long cmd;
                    207: {
                    208:        struct ifmedia_entry *match;
                    209:        struct ifmediareq *ifmr = (struct ifmediareq *) ifr;
                    210:        int error = 0, sticky;
                    211: 
                    212:        if (ifp == NULL || ifr == NULL || ifm == NULL)
                    213:                return(EINVAL);
                    214: 
                    215:        switch (cmd) {
                    216: 
                    217:        /*
                    218:         * Set the current media.
                    219:         */
                    220:        case  SIOCSIFMEDIA:
                    221:        {
                    222:                struct ifmedia_entry *oldentry;
                    223:                int oldmedia;
                    224:                int newmedia = ifr->ifr_media;
                    225: 
                    226:                match = ifmedia_match(ifm, newmedia, ifm->ifm_mask);
                    227:                if (match == NULL) {
                    228: #ifdef IFMEDIA_DEBUG
                    229:                        if (ifmedia_debug) {
                    230:                                printf(
                    231:                                    "ifmedia_ioctl: no media found for 0x%x\n", 
                    232:                                    newmedia);
                    233:                        }
                    234: #endif
                    235:                        return (ENXIO);
                    236:                }
                    237: 
                    238:                /*
                    239:                 * If no change, we're done.
                    240:                 * XXX Automedia may invole software intervention.
                    241:                 *     Keep going in case the the connected media changed.
                    242:                 *     Similarly, if best match changed (kernel debugger?).
                    243:                 */
                    244:                if ((IFM_SUBTYPE(newmedia) != IFM_AUTO) &&
                    245:                    (newmedia == ifm->ifm_media) &&
                    246:                    (match == ifm->ifm_cur))
                    247:                        return 0;
                    248: 
                    249:                /*
                    250:                 * We found a match, now make the driver switch to it.
                    251:                 * Make sure to preserve our old media type in case the
                    252:                 * driver can't switch.
                    253:                 */
                    254: #ifdef IFMEDIA_DEBUG
                    255:                if (ifmedia_debug) {
                    256:                        printf("ifmedia_ioctl: switching %s to ",
                    257:                            ifp->if_xname);
                    258:                        ifmedia_printword(match->ifm_media);
                    259:                }
                    260: #endif
                    261:                oldentry = ifm->ifm_cur;
                    262:                oldmedia = ifm->ifm_media;
                    263:                ifm->ifm_cur = match;
                    264:                ifm->ifm_media = newmedia;
                    265:                error = (*ifm->ifm_change)(ifp);
                    266:                if (error) {
                    267:                        ifm->ifm_cur = oldentry;
                    268:                        ifm->ifm_media = oldmedia;
                    269:                }
                    270:                break;
                    271:        }
                    272: 
                    273:        /*
                    274:         * Get list of available media and current media on interface.
                    275:         */
                    276:        case  SIOCGIFMEDIA: 
                    277:        {
                    278:                struct ifmedia_entry *ep;
                    279:                int *kptr, count;
                    280: 
                    281:                kptr = NULL;            /* XXX gcc */
                    282: 
                    283:                ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
                    284:                    ifm->ifm_cur->ifm_media : IFM_NONE;
                    285:                ifmr->ifm_mask = ifm->ifm_mask;
                    286:                ifmr->ifm_status = 0;
                    287:                (*ifm->ifm_status)(ifp, ifmr);
                    288: 
                    289:                count = 0;
                    290:                ep = ifm->ifm_list.lh_first;
                    291: 
                    292:                if (ifmr->ifm_count != 0) {
                    293:                        kptr = (int *) _MALLOC(ifmr->ifm_count * sizeof(int),
                    294:                            M_TEMP, M_WAITOK);
                    295: 
                    296:                        /*
                    297:                         * Get the media words from the interface's list.
                    298:                         */
                    299:                        for (; ep != NULL && count < ifmr->ifm_count;
                    300:                            ep = ep->ifm_list.le_next, count++)
                    301:                                kptr[count] = ep->ifm_media;
                    302: 
                    303:                        if (ep != NULL)
                    304:                                error = E2BIG;  /* oops! */
                    305:                }
                    306: 
                    307:                /*
                    308:                 * If there are more interfaces on the list, count
                    309:                 * them.  This allows the caller to set ifmr->ifm_count
                    310:                 * to 0 on the first call to know how much space to
                    311:                 * callocate.
                    312:                 */
                    313:                for (; ep != NULL; ep = ep->ifm_list.le_next)
                    314:                        count++;
                    315: 
                    316:                /*
                    317:                 * We do the copyout on E2BIG, because that's
                    318:                 * just our way of telling userland that there
                    319:                 * are more.  This is the behavior I've observed
                    320:                 * under BSD/OS 3.0
                    321:                 */
                    322:                sticky = error;
                    323:                if ((error == 0 || error == E2BIG) && ifmr->ifm_count != 0) {
                    324:                        error = copyout((caddr_t)kptr,
                    325:                            (caddr_t)ifmr->ifm_ulist,
                    326:                            ifmr->ifm_count * sizeof(int));
                    327:                }
                    328: 
                    329:                if (error == 0)
                    330:                        error = sticky;
                    331: 
                    332:                if (ifmr->ifm_count != 0)
                    333:                        FREE(kptr, M_TEMP);
                    334: 
                    335:                ifmr->ifm_count = count;
                    336:                break;
                    337:        }
                    338: 
                    339:        default:
                    340:                return (EINVAL);
                    341:        }
                    342: 
                    343:        return (error);
                    344: }
                    345: 
                    346: /*
                    347:  * Find media entry matching a given ifm word.
                    348:  *
                    349:  */
                    350: static struct ifmedia_entry *
                    351: ifmedia_match(ifm, target, mask)
                    352:        struct ifmedia *ifm; 
                    353:        int target;
                    354:        int mask;
                    355: {
                    356:        struct ifmedia_entry *match, *next;
                    357: 
                    358:        match = NULL;
                    359:        mask = ~mask;
                    360: 
                    361:        for (next = ifm->ifm_list.lh_first; next != NULL;
                    362:            next = next->ifm_list.le_next) {
                    363:                if ((next->ifm_media & mask) == (target & mask)) {
                    364: #if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)
                    365:                        if (match) {
                    366:                                printf("ifmedia_match: multiple match for "
                    367:                                    "0x%x/0x%x\n", target, mask);
                    368:                        }
                    369: #endif
                    370:                        match = next;
                    371:                }
                    372:        }
                    373: 
                    374:        return match;
                    375: }
                    376: 
                    377: #ifdef IFMEDIA_DEBUG
                    378: struct ifmedia_description ifm_type_descriptions[] =
                    379:     IFM_TYPE_DESCRIPTIONS;
                    380: 
                    381: struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
                    382:     IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
                    383: 
                    384: struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
                    385:     IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
                    386: 
                    387: struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
                    388:     IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
                    389: 
                    390: struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
                    391:     IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
                    392: 
                    393: struct ifmedia_description ifm_subtype_fddi_descriptions[] =
                    394:     IFM_SUBTYPE_FDDI_DESCRIPTIONS;
                    395: 
                    396: struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
                    397:     IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
                    398: 
                    399: struct ifmedia_description ifm_subtype_shared_descriptions[] =
                    400:     IFM_SUBTYPE_SHARED_DESCRIPTIONS;
                    401: 
                    402: struct ifmedia_description ifm_shared_option_descriptions[] =
                    403:     IFM_SHARED_OPTION_DESCRIPTIONS;
                    404: 
                    405: struct ifmedia_type_to_subtype {
                    406:        struct ifmedia_description *subtypes;
                    407:        struct ifmedia_description *options;
                    408: };
                    409: 
                    410: /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
                    411: struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
                    412:        {
                    413:          &ifm_subtype_ethernet_descriptions[0],
                    414:          &ifm_subtype_ethernet_option_descriptions[0]
                    415:        },
                    416:        {
                    417:          &ifm_subtype_tokenring_descriptions[0],
                    418:          &ifm_subtype_tokenring_option_descriptions[0]
                    419:        },
                    420:        {
                    421:          &ifm_subtype_fddi_descriptions[0],
                    422:          &ifm_subtype_fddi_option_descriptions[0]
                    423:        },
                    424: };
                    425: 
                    426: /*
                    427:  * print a media word.
                    428:  */
                    429: static void
                    430: ifmedia_printword(ifmw)
                    431:        int ifmw;
                    432: {
                    433:        struct ifmedia_description *desc;
                    434:        struct ifmedia_type_to_subtype *ttos;
                    435:        int seen_option = 0;
                    436: 
                    437:        /* Find the top-level interface type. */
                    438:        for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
                    439:            desc->ifmt_string != NULL; desc++, ttos++)
                    440:                if (IFM_TYPE(ifmw) == desc->ifmt_word)
                    441:                        break;
                    442:        if (desc->ifmt_string == NULL) {
                    443:                printf("<unknown type>\n");
                    444:                return;
                    445:        }
                    446:        printf(desc->ifmt_string);
                    447: 
                    448:        /*
                    449:         * Check for the shared subtype descriptions first, then the
                    450:         * type-specific ones.
                    451:         */
                    452:        for (desc = ifm_subtype_shared_descriptions;
                    453:            desc->ifmt_string != NULL; desc++)
                    454:                if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
                    455:                        goto got_subtype;
                    456: 
                    457:        for (desc = ttos->subtypes; desc->ifmt_string != NULL; desc++)
                    458:                if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
                    459:                        break;
                    460:        if (desc->ifmt_string == NULL) {
                    461:                printf(" <unknown subtype>\n");
                    462:                return;
                    463:        }
                    464: 
                    465:  got_subtype:
                    466:        printf(" %s", desc->ifmt_string);
                    467: 
                    468:        /*
                    469:         * Look for shared options.
                    470:         */
                    471:        for (desc = ifm_shared_option_descriptions;
                    472:            desc->ifmt_string != NULL; desc++) {
                    473:                if (ifmw & desc->ifmt_word) {
                    474:                        if (seen_option == 0)
                    475:                                printf(" <");
                    476:                        printf("%s%s", seen_option++ ? "," : "",
                    477:                            desc->ifmt_string);
                    478:                }
                    479:        }
                    480: 
                    481:        /*
                    482:         * Look for subtype-specific options.
                    483:         */
                    484:        for (desc = ttos->options; desc->ifmt_string != NULL; desc++) {
                    485:                if (ifmw & desc->ifmt_word) {
                    486:                        if (seen_option == 0)
                    487:                                printf(" <");
                    488:                        printf("%s%s", seen_option++ ? "," : "",
                    489:                            desc->ifmt_string); 
                    490:                }
                    491:        }
                    492:        printf("%s\n", seen_option ? ">" : "");
                    493: }
                    494: #endif /* IFMEDIA_DEBUG */

unix.superglobalmegacorp.com

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