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

Annotation of sys/dev/mii/amphy.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: amphy.c,v 1.15 2006/12/31 15:04:33 krw Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 1997, 1998, 1999
                      5:  *     Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by Bill Paul.
                     18:  * 4. Neither the name of the author nor the names of any co-contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
                     26:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     27:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     28:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     29:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     30:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     31:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     32:  * THE POSSIBILITY OF SUCH DAMAGE.
                     33:  *
                     34:  * $FreeBSD: src/sys/dev/mii/amphy.c,v 1.3 2000/04/19 14:57:29 phk Exp $
                     35:  */
                     36:
                     37: /*
                     38:  * driver for AMD AM79c873 PHYs
                     39:  * This driver also works for the Davicom DM9101 PHY, which appears to
                     40:  * be an AM79c873 workalike.
                     41:  */
                     42:
                     43: #include <sys/param.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/device.h>
                     47: #include <sys/socket.h>
                     48:
                     49: #include <net/if.h>
                     50: #include <net/if_media.h>
                     51:
                     52: #include <dev/mii/mii.h>
                     53: #include <dev/mii/miivar.h>
                     54: #include <dev/mii/miidevs.h>
                     55:
                     56: #include <dev/mii/amphyreg.h>
                     57:
                     58: int    amphymatch(struct device *, void *, void *);
                     59: void   amphyattach(struct device *, struct device *, void *);
                     60:
                     61: struct cfattach amphy_ca = {
                     62:        sizeof(struct mii_softc), amphymatch, amphyattach, mii_phy_detach,
                     63:            mii_phy_activate
                     64: };
                     65:
                     66: struct cfdriver amphy_cd = {
                     67:        NULL, "amphy", DV_DULL
                     68: };
                     69:
                     70: int    amphy_service(struct mii_softc *, struct mii_data *, int);
                     71: void   amphy_status(struct mii_softc *);
                     72:
                     73: const struct mii_phy_funcs amphy_funcs = {
                     74:        amphy_service, amphy_status, mii_phy_reset,
                     75: };
                     76:
                     77: static const struct mii_phydesc amphys[] = {
                     78:        { MII_OUI_xxAMD,                MII_MODEL_xxAMD_79C873,
                     79:          MII_STR_xxAMD_79C873 },
                     80:        { MII_OUI_xxDAVICOM,            MII_MODEL_xxDAVICOM_DM9101,
                     81:          MII_STR_xxDAVICOM_DM9101 },
                     82:        { MII_OUI_DAVICOM,              MII_MODEL_DAVICOM_DM9102,
                     83:          MII_STR_DAVICOM_DM9102 },
                     84:        { MII_OUI_DAVICOM,              MII_MODEL_DAVICOM_DM9601,
                     85:          MII_STR_DAVICOM_DM9601 },
                     86:        { MII_OUI_xxALTIMA,             MII_MODEL_AMD_79C875phy,
                     87:          MII_STR_AMD_79C875phy },
                     88:
                     89:        { 0,                            0,
                     90:          NULL },
                     91: };
                     92:
                     93: int
                     94: amphymatch(struct device *parent, void *match, void *aux)
                     95: {
                     96:        struct mii_attach_args *ma = aux;
                     97:
                     98:        if (mii_phy_match(ma, amphys) != NULL)
                     99:                return (10);
                    100:
                    101:        return (0);
                    102: }
                    103:
                    104: void
                    105: amphyattach(struct device *parent, struct device *self, void *aux)
                    106: {
                    107:        struct mii_softc *sc = (struct mii_softc *)self;
                    108:        struct mii_attach_args *ma = aux;
                    109:        struct mii_data *mii = ma->mii_data;
                    110:        const struct mii_phydesc *mpd;
                    111:
                    112:        mpd = mii_phy_match(ma, amphys);
                    113:        printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
                    114:
                    115:        sc->mii_inst = mii->mii_instance;
                    116:        sc->mii_phy = ma->mii_phyno;
                    117:        sc->mii_funcs = &amphy_funcs;
                    118:        sc->mii_pdata = mii;
                    119:        sc->mii_flags = ma->mii_flags;
                    120:
                    121:        sc->mii_flags |= MIIF_NOISOLATE;
                    122:
                    123:        PHY_RESET(sc);
                    124:
                    125:        sc->mii_capabilities =
                    126:            PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
                    127:        if (sc->mii_capabilities & BMSR_MEDIAMASK)
                    128:                mii_phy_add_media(sc);
                    129: }
                    130:
                    131: int
                    132: amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
                    133: {
                    134:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
                    135:        int reg;
                    136:
                    137:        switch (cmd) {
                    138:        case MII_POLLSTAT:
                    139:                /*
                    140:                 * If we're not polling our PHY instance, just return.
                    141:                 */
                    142:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
                    143:                        return (0);
                    144:                break;
                    145:
                    146:        case MII_MEDIACHG:
                    147:                /*
                    148:                 * If the media indicates a different PHY instance,
                    149:                 * isolate ourselves.
                    150:                 */
                    151:                if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
                    152:                        reg = PHY_READ(sc, MII_BMCR);
                    153:                        PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
                    154:                        return (0);
                    155:                }
                    156:
                    157:                /*
                    158:                 * If the interface is not up, don't do anything.
                    159:                 */
                    160:                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
                    161:                        break;
                    162:
                    163:                mii_phy_setmedia(sc);
                    164:                break;
                    165:
                    166:        case MII_TICK:
                    167:                /*
                    168:                 * If we're not currently selected, just return.
                    169:                 */
                    170:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
                    171:                        return (0);
                    172:
                    173:                if (mii_phy_tick(sc) == EJUSTRETURN)
                    174:                        return (0);
                    175:                break;
                    176:        case MII_DOWN:
                    177:                mii_phy_down(sc);
                    178:                return (0);
                    179:        }
                    180:
                    181:        /* Update the media status. */
                    182:        mii_phy_status(sc);
                    183:
                    184:        /* Callback if something changed. */
                    185:        mii_phy_update(sc, cmd);
                    186:        return (0);
                    187: }
                    188:
                    189: void
                    190: amphy_status(struct mii_softc *sc)
                    191: {
                    192:        struct mii_data *mii = sc->mii_pdata;
                    193:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
                    194:        int bmsr, bmcr, par, anlpar;
                    195:
                    196:        mii->mii_media_status = IFM_AVALID;
                    197:        mii->mii_media_active = IFM_ETHER;
                    198:
                    199:        bmsr = PHY_READ(sc, MII_BMSR) |
                    200:            PHY_READ(sc, MII_BMSR);
                    201:        if (bmsr & BMSR_LINK)
                    202:                mii->mii_media_status |= IFM_ACTIVE;
                    203:
                    204:        bmcr = PHY_READ(sc, MII_BMCR);
                    205:        if (bmcr & BMCR_ISO) {
                    206:                mii->mii_media_active |= IFM_NONE;
                    207:                mii->mii_media_status = 0;
                    208:                return;
                    209:        }
                    210:
                    211:        if (bmcr & BMCR_LOOP)
                    212:                mii->mii_media_active |= IFM_LOOP;
                    213:
                    214:        if (bmcr & BMCR_AUTOEN) {
                    215:                /*
                    216:                 * The PAR status bits are only valid of autonegotiation
                    217:                 * has completed (or it's disabled).
                    218:                 */
                    219:                if ((bmsr & BMSR_ACOMP) == 0) {
                    220:                        /* Erg, still trying, I guess... */
                    221:                        mii->mii_media_active |= IFM_NONE;
                    222:                        return;
                    223:                }
                    224:
                    225:                if (PHY_READ(sc, MII_ANER) & ANER_LPAN) {
                    226:                        anlpar = PHY_READ(sc, MII_ANAR) &
                    227:                            PHY_READ(sc, MII_ANLPAR);
                    228:                        if (anlpar & ANLPAR_T4)
                    229:                                mii->mii_media_active |= IFM_100_T4|IFM_HDX;
                    230:                        else if (anlpar & ANLPAR_TX_FD)
                    231:                                mii->mii_media_active |= IFM_100_TX|IFM_FDX;
                    232:                        else if (anlpar & ANLPAR_TX)
                    233:                                mii->mii_media_active |= IFM_100_TX|IFM_HDX;
                    234:                        else if (anlpar & ANLPAR_10_FD)
                    235:                                mii->mii_media_active |= IFM_10_T|IFM_FDX;
                    236:                        else if (anlpar & ANLPAR_10)
                    237:                                mii->mii_media_active |= IFM_10_T|IFM_HDX;
                    238:                        else
                    239:                                mii->mii_media_active |= IFM_NONE;
                    240:                        return;
                    241:                }
                    242:
                    243:                /*
                    244:                 * Link partner is not capable of autonegotiation.
                    245:                 */
                    246:                par = PHY_READ(sc, MII_AMPHY_DSCSR);
                    247:                if (par & DSCSR_100FDX)
                    248:                        mii->mii_media_active |= IFM_100_TX|IFM_FDX;
                    249:                else if (par & DSCSR_100HDX)
                    250:                        mii->mii_media_active |= IFM_100_TX|IFM_HDX;
                    251:                else if (par & DSCSR_10FDX)
                    252:                        mii->mii_media_active |= IFM_10_T|IFM_HDX;
                    253:                else if (par & DSCSR_10HDX)
                    254:                        mii->mii_media_active |= IFM_10_T|IFM_HDX;
                    255:        } else
                    256:                mii->mii_media_active = ife->ifm_media;
                    257: }

CVSweb