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

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

1.1       nbrk        1: /*     $OpenBSD: urlphy.c,v 1.12 2006/12/27 19:11:09 kettenis Exp $ */
                      2: /*     $NetBSD: urlphy.c,v 1.1 2002/03/28 21:07:53 ichiro Exp $        */
                      3: /*
                      4:  * Copyright (c) 2001, 2002
                      5:  *     Shingo WATANABE <nabe@nabechan.org>.  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. Neither the name of the author nor the names of any co-contributors
                     16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  *
                     31:  */
                     32:
                     33: /*
                     34:  * driver for Realtek RL8150L internal phy
                     35:  */
                     36:
                     37: #include <sys/param.h>
                     38: #include <sys/systm.h>
                     39: #include <sys/kernel.h>
                     40: #include <sys/device.h>
                     41: #include <sys/socket.h>
                     42:
                     43: #include <net/if.h>
                     44: #include <net/if_media.h>
                     45:
                     46: #include <dev/mii/mii.h>
                     47: #include <dev/mii/miivar.h>
                     48: #include <dev/mii/miidevs.h>
                     49: #include <dev/mii/urlphyreg.h>
                     50:
                     51: #define        URLPHY_DEBUG    0
                     52: #ifdef URLPHY_DEBUG
                     53: #define DPRINTF(x)     if (urlphydebug) printf x
                     54: #define DPRINTFN(n,x)  if (urlphydebug>(n)) printf x
                     55: int urlphydebug = URLPHY_DEBUG;
                     56: #else
                     57: #define DPRINTF(x)
                     58: #define DPRINTFN(n,x)
                     59: #endif
                     60:
                     61: int urlphy_match(struct device *, void *, void *);
                     62: void urlphy_attach(struct device *, struct device *, void *);
                     63:
                     64: struct cfattach urlphy_ca = {
                     65:        sizeof(struct mii_softc), urlphy_match, urlphy_attach, mii_phy_detach,
                     66:        mii_phy_activate
                     67: };
                     68:
                     69: struct cfdriver urlphy_cd = {
                     70:        NULL, "urlphy", DV_DULL
                     71: };
                     72:
                     73: int urlphy_service(struct mii_softc *, struct mii_data *, int);
                     74: void urlphy_status(struct mii_softc *);
                     75:
                     76: const struct mii_phy_funcs urlphy_funcs = {
                     77:        urlphy_service, urlphy_status, mii_phy_reset,
                     78: };
                     79:
                     80: int
                     81: urlphy_match(struct device *parent, void *match, void *aux)
                     82: {
                     83:        struct mii_attach_args *ma = aux;
                     84:
                     85:        /*
                     86:         * RTL8150 reports OUT == 0, MODEL == 0
                     87:         */
                     88:        if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 &&
                     89:            MII_MODEL(ma->mii_id2) != 0)
                     90:                return (0);
                     91:
                     92:        /*
                     93:         * Make sure the parent is an 'url' device.
                     94:         */
                     95:        if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "url") != 0)
                     96:                return (0);
                     97:
                     98:        return (10);
                     99: }
                    100:
                    101: void
                    102: urlphy_attach(struct device *parent, struct device *self, void *aux)
                    103: {
                    104:        struct mii_softc *sc = (struct mii_softc *)self;
                    105:        struct mii_attach_args *ma = aux;
                    106:        struct mii_data *mii = ma->mii_data;
                    107:
                    108:        printf(": RTL internal phy\n");
                    109:
                    110:        DPRINTF(("%s: %s: enter\n", sc->mii_dev.dv_xname, __func__));
                    111:
                    112:        sc->mii_inst = mii->mii_instance;
                    113:        sc->mii_phy = ma->mii_phyno;
                    114:        sc->mii_funcs = &urlphy_funcs;
                    115:        sc->mii_pdata = mii;
                    116:        sc->mii_flags = ma->mii_flags;
                    117:        sc->mii_anegticks = MII_ANEGTICKS_GIGE;
                    118:
                    119:        /* Don't do loopback on this PHY. */
                    120:        sc->mii_flags |= MIIF_NOLOOP;
                    121:        /* Don't do isolate on this PHY. */
                    122:        sc->mii_flags |= MIIF_NOISOLATE;
                    123:
                    124:        if (mii->mii_instance != 0) {
                    125:                printf("%s: ignoring this PHY, non-zero instance\n",
                    126:                       sc->mii_dev.dv_xname);
                    127:                return;
                    128:        }
                    129:        PHY_RESET(sc);
                    130:
                    131:        sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
                    132:        if (sc->mii_capabilities & BMSR_MEDIAMASK)
                    133:                mii_phy_add_media(sc);
                    134: }
                    135:
                    136: int
                    137: urlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
                    138: {
                    139:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
                    140:        int reg;
                    141:
                    142:        DPRINTF(("%s: %s: enter\n", sc->mii_dev.dv_xname, __func__));
                    143:
                    144:        if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
                    145:                return (ENXIO);
                    146:
                    147:        switch (cmd) {
                    148:        case MII_POLLSTAT:
                    149:                /*
                    150:                 * If we're not polling our PHY instance, just return.
                    151:                 */
                    152:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
                    153:                        return (0);
                    154:                break;
                    155:
                    156:        case MII_MEDIACHG:
                    157:                /*
                    158:                 * If we're not currently selected, just return.
                    159:                 */
                    160:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
                    161:                        return (0);
                    162:
                    163:                /* If the interface is not up, don't do anything. */
                    164:                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
                    165:                        break;
                    166:
                    167:                mii_phy_setmedia(sc);
                    168:                break;
                    169:
                    170:        case MII_TICK:
                    171:                /*
                    172:                 * If we're not currently selected, just return.
                    173:                 */
                    174:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
                    175:                        return (0);
                    176:
                    177:                /* Just bail now if the interface is down. */
                    178:                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
                    179:                        return (0);
                    180:
                    181:                /*
                    182:                 * If we're not doing autonegotiation, we don't need to do
                    183:                 * any extra work here.  However, we need to check the link
                    184:                 * status so we can generate an announcement if the status
                    185:                 * changes.
                    186:                 */
                    187:                if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
                    188:                        return (0);
                    189:
                    190:                /* Read the status register twice; MSR_LINK is latch-low. */
                    191:                reg = PHY_READ(sc, URLPHY_MSR) | PHY_READ(sc, URLPHY_MSR);
                    192:                if (reg & URLPHY_MSR_LINK)
                    193:                        return (0);
                    194:
                    195:                /*
                    196:                 * Only retry autonegotiation every mii_anegticks seconds.
                    197:                 */
                    198:                if (++sc->mii_ticks <= sc->mii_anegticks)
                    199:                        return (0);
                    200:
                    201:                sc->mii_ticks = 0;
                    202:                PHY_RESET(sc);
                    203:
                    204:                if (mii_phy_auto(sc, 0) == EJUSTRETURN)
                    205:                        return (0);
                    206:
                    207:                break;
                    208:
                    209:        case MII_DOWN:
                    210:                mii_phy_down(sc);
                    211:                return (0);
                    212:        }
                    213:
                    214:        /* Update the media status. */
                    215:        mii_phy_status(sc);
                    216:
                    217:        /* Callback if something changed. */
                    218:        mii_phy_update(sc, cmd);
                    219:
                    220:        return (0);
                    221: }
                    222:
                    223: void
                    224: urlphy_status(struct mii_softc *sc)
                    225: {
                    226:        struct mii_data *mii = sc->mii_pdata;
                    227:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
                    228:        int msr, bmsr, bmcr;
                    229:
                    230:        DPRINTF(("%s: %s: enter\n", sc->mii_dev.dv_xname, __func__));
                    231:
                    232:        mii->mii_media_status = IFM_AVALID;
                    233:        mii->mii_media_active = IFM_ETHER;
                    234:
                    235:        /*
                    236:         * The link status bit is not exist in the BMSR register,
                    237:         * so we need to read the MSR register to get link status.
                    238:         */
                    239:        msr = PHY_READ(sc, URLPHY_MSR) | PHY_READ(sc, URLPHY_MSR);
                    240:        if (msr & URLPHY_MSR_LINK)
                    241:                mii->mii_media_status |= IFM_ACTIVE;
                    242:
                    243:        DPRINTF(("%s: %s: link %s\n", sc->mii_dev.dv_xname, __func__,
                    244:                 mii->mii_media_status & IFM_ACTIVE ? "up" : "down"));
                    245:
                    246:        bmcr = PHY_READ(sc, MII_BMCR);
                    247:        if (bmcr & BMCR_AUTOEN) {
                    248:                bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
                    249:                if ((bmsr & BMSR_ACOMP) == 0) {
                    250:                        /* Erg, still trying, I guess... */
                    251:                        mii->mii_media_active |= IFM_NONE;
                    252:                        return;
                    253:                }
                    254:
                    255:                if (msr & URLPHY_MSR_SPEED_100)
                    256:                        mii->mii_media_active |= IFM_100_TX;
                    257:                else
                    258:                        mii->mii_media_active |= IFM_10_T;
                    259:
                    260:                if (msr & URLPHY_MSR_DUPLEX)
                    261:                        mii->mii_media_active |= IFM_FDX;
                    262:                else
                    263:                        mii->mii_media_active |= IFM_HDX;
                    264:        } else
                    265:                mii->mii_media_active = ife->ifm_media;
                    266: }

CVSweb