[BACK]Return to mii.c CVS log [TXT][DIR] Up to [local] / sys / dev / mii

Annotation of sys/dev/mii/mii.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: mii.c,v 1.18 2005/07/23 01:42:16 brad Exp $   */
        !             2: /*     $NetBSD: mii.c,v 1.19 2000/02/02 17:09:44 thorpej Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
        !            10:  * NASA Ames Research Center.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: /*
        !            42:  * MII bus layer, glues MII-capable network interface drivers to sharable
        !            43:  * PHY drivers.  This exports an interface compatible with BSD/OS 3.0's,
        !            44:  * plus some NetBSD extensions.
        !            45:  */
        !            46:
        !            47: #include <sys/param.h>
        !            48: #include <sys/device.h>
        !            49: #include <sys/systm.h>
        !            50: #include <sys/socket.h>
        !            51:
        !            52: #include <net/if.h>
        !            53: #include <net/if_media.h>
        !            54:
        !            55: #include <dev/mii/mii.h>
        !            56: #include <dev/mii/miivar.h>
        !            57:
        !            58: int    mii_print(void *, const char *);
        !            59: int    mii_submatch(struct device *, void *, void *);
        !            60:
        !            61: #define MIICF_PHY              0       /* cf_loc index */
        !            62: #define MIICF_PHY_DEFAULT      (-1)    /* default phy device */
        !            63:
        !            64: /*
        !            65:  * Helper function used by network interface drivers, attaches PHYs
        !            66:  * to the network interface driver parent.
        !            67:  */
        !            68: void
        !            69: mii_attach(struct device *parent, struct mii_data *mii, int capmask,
        !            70:     int phyloc, int offloc, int flags)
        !            71: {
        !            72:        struct mii_attach_args ma;
        !            73:        struct mii_softc *child;
        !            74:        int bmsr, offset = 0;
        !            75:        int phymin, phymax;
        !            76:
        !            77:        if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY)
        !            78:                panic("mii_attach: phyloc and offloc specified");
        !            79:
        !            80:        if (phyloc == MII_PHY_ANY) {
        !            81:                phymin = 0;
        !            82:                phymax = MII_NPHY - 1;
        !            83:        } else
        !            84:                phymin = phymax = phyloc;
        !            85:
        !            86:        if ((mii->mii_flags & MIIF_INITDONE) == 0) {
        !            87:                LIST_INIT(&mii->mii_phys);
        !            88:                mii->mii_flags |= MIIF_INITDONE;
        !            89:        }
        !            90:
        !            91:        for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) {
        !            92:                /*
        !            93:                 * Make sure we haven't already configured a PHY at this
        !            94:                 * address.  This allows mii_attach() to be called
        !            95:                 * multiple times.
        !            96:                 */
        !            97:                for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
        !            98:                     child = LIST_NEXT(child, mii_list)) {
        !            99:                        if (child->mii_phy == ma.mii_phyno) {
        !           100:                                /*
        !           101:                                 * Yes, there is already something
        !           102:                                 * configured at this address.
        !           103:                                 */
        !           104:                                offset++;
        !           105:                                continue;
        !           106:                        }
        !           107:                }
        !           108:
        !           109:                /*
        !           110:                 * Check to see if there is a PHY at this address.  Note,
        !           111:                 * many braindead PHYs report 0/0 in their ID registers,
        !           112:                 * so we test for media in the BMSR.
        !           113:                 */
        !           114:                bmsr = (*mii->mii_readreg)(parent, ma.mii_phyno, MII_BMSR);
        !           115:                if (bmsr == 0 || bmsr == 0xffff ||
        !           116:                    (bmsr & (BMSR_MEDIAMASK|BMSR_EXTSTAT)) == 0) {
        !           117:                        /* Assume no PHY at this address. */
        !           118:                        continue;
        !           119:                }
        !           120:
        !           121:                /*
        !           122:                 * There is a PHY at this address.  If we were given an
        !           123:                 * `offset' locator, skip this PHY if it doesn't match.
        !           124:                 */
        !           125:                if (offloc != MII_OFFSET_ANY && offloc != offset) {
        !           126:                        offset++;
        !           127:                        continue;
        !           128:                }
        !           129:
        !           130:                /*
        !           131:                 * Extract the IDs.  Braindead PHYs will be handled by
        !           132:                 * the `ukphy' driver, as we have no ID information to
        !           133:                 * match on.
        !           134:                 */
        !           135:                ma.mii_id1 = (*mii->mii_readreg)(parent, ma.mii_phyno,
        !           136:                    MII_PHYIDR1);
        !           137:                ma.mii_id2 = (*mii->mii_readreg)(parent, ma.mii_phyno,
        !           138:                    MII_PHYIDR2);
        !           139:
        !           140:                ma.mii_data = mii;
        !           141:                ma.mii_capmask = capmask;
        !           142:                ma.mii_flags = flags | (mii->mii_flags & MIIF_INHERIT_MASK);
        !           143:
        !           144:                if ((child = (struct mii_softc *)config_found_sm(parent, &ma,
        !           145:                    mii_print, mii_submatch)) != NULL) {
        !           146:                        /*
        !           147:                         * Link it up in the parent's MII data.
        !           148:                         */
        !           149:                        LIST_INSERT_HEAD(&mii->mii_phys, child, mii_list);
        !           150:                        child->mii_offset = offset;
        !           151:                        mii->mii_instance++;
        !           152:                }
        !           153:                offset++;
        !           154:        }
        !           155: }
        !           156:
        !           157: void
        !           158: mii_activate(struct mii_data *mii, enum devact act, int phyloc, int offloc)
        !           159: {
        !           160:        struct mii_softc *child;
        !           161:
        !           162:        if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY)
        !           163:                panic("mii_activate: phyloc and offloc specified");
        !           164:
        !           165:        if ((mii->mii_flags & MIIF_INITDONE) == 0)
        !           166:                return;
        !           167:
        !           168:        for (child = LIST_FIRST(&mii->mii_phys);
        !           169:             child != NULL; child = LIST_NEXT(child, mii_list)) {
        !           170:                if (phyloc != MII_PHY_ANY || offloc != MII_OFFSET_ANY) {
        !           171:                        if (phyloc != MII_PHY_ANY &&
        !           172:                            phyloc != child->mii_phy)
        !           173:                                continue;
        !           174:                        if (offloc != MII_OFFSET_ANY &&
        !           175:                            offloc != child->mii_offset)
        !           176:                                continue;
        !           177:                }
        !           178:                switch (act) {
        !           179:                case DVACT_ACTIVATE:
        !           180:                        panic("mii_activate: DVACT_ACTIVATE");
        !           181:                        break;
        !           182:
        !           183:                case DVACT_DEACTIVATE:
        !           184:                        if (config_deactivate(&child->mii_dev) != 0)
        !           185:                                panic("%s: config_activate(%d) failed",
        !           186:                                    child->mii_dev.dv_xname, act);
        !           187:                }
        !           188:        }
        !           189: }
        !           190:
        !           191: void
        !           192: mii_detach(struct mii_data *mii, int phyloc, int offloc)
        !           193: {
        !           194:        struct mii_softc *child, *nchild;
        !           195:
        !           196:        if (phyloc != MII_PHY_ANY && offloc != MII_PHY_ANY)
        !           197:                panic("mii_detach: phyloc and offloc specified");
        !           198:
        !           199:        if ((mii->mii_flags & MIIF_INITDONE) == 0)
        !           200:                return;
        !           201:
        !           202:        for (child = LIST_FIRST(&mii->mii_phys);
        !           203:             child != NULL; child = nchild) {
        !           204:                nchild = LIST_NEXT(child, mii_list);
        !           205:                if (phyloc != MII_PHY_ANY || offloc != MII_OFFSET_ANY) {
        !           206:                        if (phyloc != MII_PHY_ANY &&
        !           207:                            phyloc != child->mii_phy)
        !           208:                                continue;
        !           209:                        if (offloc != MII_OFFSET_ANY &&
        !           210:                            offloc != child->mii_offset)
        !           211:                                continue;
        !           212:                }
        !           213:                LIST_REMOVE(child, mii_list);
        !           214:                (void) config_detach(&child->mii_dev, DETACH_FORCE);
        !           215:        }
        !           216: }
        !           217:
        !           218: int
        !           219: mii_print(void *aux, const char *pnp)
        !           220: {
        !           221:        struct mii_attach_args *ma = aux;
        !           222:
        !           223:        if (pnp != NULL)
        !           224:                printf("OUI 0x%06x model 0x%04x rev %d at %s",
        !           225:                    MII_OUI(ma->mii_id1, ma->mii_id2), MII_MODEL(ma->mii_id2),
        !           226:                    MII_REV(ma->mii_id2), pnp);
        !           227:
        !           228:        printf(" phy %d", ma->mii_phyno);
        !           229:        return (UNCONF);
        !           230: }
        !           231:
        !           232: int
        !           233: mii_submatch(struct device *parent, void *match, void *aux)
        !           234: {
        !           235:        struct cfdata *cf = match;
        !           236:        struct mii_attach_args *ma = aux;
        !           237:
        !           238:        if (ma->mii_phyno != cf->cf_loc[MIICF_PHY] &&
        !           239:            cf->cf_loc[MIICF_PHY] != MIICF_PHY_DEFAULT)
        !           240:                return (0);
        !           241:
        !           242:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
        !           243: }
        !           244:
        !           245: /*
        !           246:  * Media changed; notify all PHYs.
        !           247:  */
        !           248: int
        !           249: mii_mediachg(struct mii_data *mii)
        !           250: {
        !           251:        struct mii_softc *child;
        !           252:        int rv;
        !           253:
        !           254:        mii->mii_media_status = 0;
        !           255:        mii->mii_media_active = IFM_NONE;
        !           256:
        !           257:        for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
        !           258:             child = LIST_NEXT(child, mii_list)) {
        !           259:                rv = PHY_SERVICE(child, mii, MII_MEDIACHG);
        !           260:                if (rv)
        !           261:                        return (rv);
        !           262:        }
        !           263:        return (0);
        !           264: }
        !           265:
        !           266: /*
        !           267:  * Call the PHY tick routines, used during autonegotiation.
        !           268:  */
        !           269: void
        !           270: mii_tick(struct mii_data *mii)
        !           271: {
        !           272:        struct mii_softc *child;
        !           273:
        !           274:        for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
        !           275:             child = LIST_NEXT(child, mii_list))
        !           276:                (void) PHY_SERVICE(child, mii, MII_TICK);
        !           277: }
        !           278:
        !           279: /*
        !           280:  * Get media status from PHYs.
        !           281:  */
        !           282: void
        !           283: mii_pollstat(struct mii_data *mii)
        !           284: {
        !           285:        struct mii_softc *child;
        !           286:
        !           287:        mii->mii_media_status = 0;
        !           288:        mii->mii_media_active = IFM_NONE;
        !           289:
        !           290:        for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
        !           291:             child = LIST_NEXT(child, mii_list))
        !           292:                (void) PHY_SERVICE(child, mii, MII_POLLSTAT);
        !           293: }
        !           294:
        !           295: /*
        !           296:  * Inform the PHYs that the interface is down.
        !           297:  */
        !           298: void
        !           299: mii_down(struct mii_data *mii)
        !           300: {
        !           301:        struct mii_softc *child;
        !           302:
        !           303:        for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
        !           304:             child = LIST_NEXT(child, mii_list))
        !           305:                (void) PHY_SERVICE(child, mii, MII_DOWN);
        !           306: }

CVSweb