The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mii/urlphy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: urlphy.c,v 1.9 2003/09/04 15:17:38 tsutsui Exp $       */
    2 /*
    3  * Copyright (c) 2001, 2002
    4  *     Shingo WATANABE <nabe@nabechan.org>.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. Neither the name of the author nor the names of any co-contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  */
   31 
   32 /*
   33  * driver for Realtek RL8150L internal phy
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: urlphy.c,v 1.9 2003/09/04 15:17:38 tsutsui Exp $");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/device.h>
   43 #include <sys/socket.h>
   44 
   45 #include <net/if.h>
   46 #include <net/if_media.h>
   47 
   48 #include <dev/mii/mii.h>
   49 #include <dev/mii/miivar.h>
   50 #include <dev/mii/miidevs.h>
   51 #include <dev/mii/urlphyreg.h>
   52 
   53 #ifdef URLPHY_DEBUG
   54 #define DPRINTF(x)      if (urlphydebug) printf x
   55 #define DPRINTFN(n,x)   if (urlphydebug>(n)) printf x
   56 int urlphydebug = URLPHY_DEBUG;
   57 #else
   58 #define DPRINTF(x)
   59 #define DPRINTFN(n,x)
   60 #endif
   61 
   62 int urlphy_match(struct device *, struct cfdata *, void *);
   63 void urlphy_attach(struct device *, struct device *, void *);
   64 
   65 CFATTACH_DECL(urlphy, sizeof(struct mii_softc),
   66     urlphy_match, urlphy_attach, mii_phy_detach, mii_phy_activate);
   67 
   68 int urlphy_service(struct mii_softc *, struct mii_data *, int);
   69 void urlphy_status(struct mii_softc *);
   70 
   71 const struct mii_phy_funcs urlphy_funcs = {
   72         urlphy_service, urlphy_status, mii_phy_reset,
   73 };
   74 
   75 int
   76 urlphy_match(struct device *parent, struct cfdata *match, void *aux)
   77 {
   78         struct mii_attach_args *ma = aux;
   79 
   80         /*
   81          * RTL8150 reports OUT == 0, MODEL == 0
   82          */
   83         if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 &&
   84             MII_MODEL(ma->mii_id2) != 0)
   85                 return (0);
   86 
   87         /*
   88          * Make sure the parent is an 'url' device.
   89          */
   90         if (strcmp(parent->dv_cfdata->cf_name, "url") != 0)
   91                 return(0);
   92 
   93         return (10);
   94 }
   95 
   96 void
   97 urlphy_attach(struct device *parent, struct device *self, void *aux)
   98 {
   99         struct mii_softc *sc = (struct mii_softc *)self;
  100         struct mii_attach_args *ma = aux;
  101         struct mii_data *mii = ma->mii_data;
  102 
  103         aprint_naive(": Media interface\n");
  104         aprint_normal(": Realtek RTL8150L internal media interface\n");
  105 
  106         DPRINTF(("%s: %s: enter\n", sc->mii_dev.dv_xname, __FUNCTION__));
  107 
  108         sc->mii_inst = mii->mii_instance;
  109         sc->mii_phy = ma->mii_phyno;
  110         sc->mii_funcs = &urlphy_funcs;
  111         sc->mii_pdata = mii;
  112         sc->mii_flags = mii->mii_flags;
  113         sc->mii_anegticks = 10;
  114 
  115         /* Don't do loopback on this PHY. */
  116         sc->mii_flags |= MIIF_NOLOOP;
  117         /* Don't do isolate on this PHY. */
  118         sc->mii_flags |= MIIF_NOISOLATE;
  119 
  120         if (mii->mii_instance != 0) {
  121                 aprint_error("%s: ignoring this PHY, non-zero instance\n",
  122                        sc->mii_dev.dv_xname);
  123                 return;
  124         }
  125         PHY_RESET(sc);
  126 
  127         sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
  128         aprint_normal("%s: ", sc->mii_dev.dv_xname);
  129         if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
  130                 aprint_error("no media present");
  131         else
  132                 mii_phy_add_media(sc);
  133         aprint_normal("\n");
  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, __FUNCTION__));
  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 N seconds.
  197                  */
  198                 KASSERT(sc->mii_anegticks != 0);
  199                 if (++sc->mii_ticks != sc->mii_anegticks)
  200                         return (0);
  201 
  202                 sc->mii_ticks = 0;
  203                 PHY_RESET(sc);
  204 
  205                 if (mii_phy_auto(sc, 0) == EJUSTRETURN)
  206                         return (0);
  207 
  208                 break;
  209 
  210         case MII_DOWN:
  211                 mii_phy_down(sc);
  212                 return (0);
  213         }
  214 
  215         /* Update the media status. */
  216         mii_phy_status(sc);
  217 
  218         /* Callback if something changed. */
  219         mii_phy_update(sc, cmd);
  220 
  221         return (0);
  222 }
  223 
  224 void
  225 urlphy_status(struct mii_softc *sc)
  226 {
  227         struct mii_data *mii = sc->mii_pdata;
  228         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  229         int msr, bmsr, bmcr;
  230 
  231         DPRINTF(("%s: %s: enter\n", sc->mii_dev.dv_xname, __FUNCTION__));
  232 
  233         mii->mii_media_status = IFM_AVALID;
  234         mii->mii_media_active = IFM_ETHER;
  235 
  236         /*
  237          * The link status bit is not exist in the BMSR register,
  238          * so we need to read the MSR register to get link status.
  239          */
  240         msr = PHY_READ(sc, URLPHY_MSR) | PHY_READ(sc, URLPHY_MSR);
  241         if (msr & URLPHY_MSR_LINK)
  242                 mii->mii_media_status |= IFM_ACTIVE;
  243 
  244         DPRINTF(("%s: %s: link %s\n", sc->mii_dev.dv_xname, __FUNCTION__,
  245                  mii->mii_media_status & IFM_ACTIVE ? "up" : "down"));
  246 
  247         bmcr = PHY_READ(sc, MII_BMCR);
  248         if (bmcr & BMCR_AUTOEN) {
  249                 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
  250                 if ((bmsr & BMSR_ACOMP) == 0) {
  251                         /* Erg, still trying, I guess... */
  252                         mii->mii_media_active |= IFM_NONE;
  253                         return;
  254                 }
  255 
  256                 if (msr & URLPHY_MSR_SPEED_100)
  257                         mii->mii_media_active |= IFM_100_TX;
  258                 else
  259                         mii->mii_media_active |= IFM_10_T;
  260                 if (msr & URLPHY_MSR_DUPLEX)
  261                         mii->mii_media_active |= IFM_FDX;
  262         } else
  263                 mii->mii_media_active = ife->ifm_media;
  264 }

Cache object: 8c21e26e10321805c489cbda199c9541


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.