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/jmphy.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 /*      $OpenBSD: jmphy.c,v 1.7 2022/04/06 18:59:29 naddy Exp $ */
    2 /*-
    3  * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
    4  * 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 unmodified, this list of conditions, and the following
   11  *    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  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD: src/sys/dev/mii/jmphy.c,v 1.1 2008/05/27 01:16:40 yongari Exp $
   29  * $DragonFly: src/sys/dev/netif/mii_layer/jmphy.c,v 1.1 2008/07/22 11:28:49 sephe Exp $
   30  */
   31 
   32 /*
   33  * Driver for the JMicron JMP211 10/100/1000, JMP202 10/100 PHY.
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/device.h>
   39 #include <sys/socket.h>
   40 
   41 #include <net/if.h>
   42 #include <net/if_var.h>
   43 #include <net/if_media.h>
   44 
   45 #include <dev/mii/mii.h>
   46 #include <dev/mii/miivar.h>
   47 #include <dev/mii/miidevs.h>
   48 #include <dev/mii/jmphyreg.h>
   49 
   50 int     jmphy_service(struct mii_softc *, struct mii_data *, int);
   51 void    jmphy_status(struct mii_softc *);
   52 int     jmphy_match(struct device *, void *, void *);
   53 void    jmphy_attach(struct device *, struct device *, void *);
   54 void    jmphy_reset(struct mii_softc *);
   55 uint16_t        jmphy_anar(struct ifmedia_entry *);
   56 int     jmphy_auto(struct mii_softc *, struct ifmedia_entry *);
   57 
   58 const struct mii_phy_funcs jmphy_funcs = {
   59         jmphy_service, jmphy_status, jmphy_reset,
   60 };
   61 
   62 const struct cfattach jmphy_ca = {
   63         sizeof (struct mii_softc), jmphy_match, jmphy_attach,
   64         mii_phy_detach
   65 };
   66 
   67 struct cfdriver jmphy_cd = {
   68         NULL, "jmphy", DV_DULL
   69 };
   70 
   71 static const struct mii_phydesc jmphys[] = {
   72         { MII_OUI_JMICRON,      MII_MODEL_JMICRON_JMP202,
   73           MII_STR_JMICRON_JMP202 },
   74         { MII_OUI_JMICRON,      MII_MODEL_JMICRON_JMP211,
   75           MII_STR_JMICRON_JMP211 },
   76         { 0,                    0,
   77           NULL },
   78 };
   79 
   80 int
   81 jmphy_match(struct device *parent, void *match, void *aux)
   82 {
   83         struct mii_attach_args *ma = aux;
   84 
   85         if (mii_phy_match(ma, jmphys) != NULL)
   86                 return (10);
   87 
   88         return (0);
   89 }
   90 
   91 void
   92 jmphy_attach(struct device *parent, struct device *self, void *aux)
   93 {
   94         struct mii_softc *sc = (struct mii_softc *)self;
   95         struct mii_attach_args *ma = aux;
   96         struct mii_data *mii = ma->mii_data;
   97         const struct mii_phydesc *mpd;
   98 
   99         mpd = mii_phy_match(ma, jmphys);
  100         printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
  101 
  102         sc->mii_inst = mii->mii_instance;
  103         sc->mii_phy = ma->mii_phyno;
  104         sc->mii_funcs = &jmphy_funcs;
  105         sc->mii_model = MII_MODEL(ma->mii_id2);
  106         sc->mii_pdata = mii;
  107         sc->mii_flags = ma->mii_flags;
  108 
  109         sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
  110 
  111         PHY_RESET(sc);
  112 
  113         sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
  114         if (sc->mii_capabilities & BMSR_EXTSTAT)
  115                 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
  116 
  117         if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
  118             (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
  119                 ;
  120         else
  121                 mii_phy_add_media(sc);
  122 }
  123 
  124 int
  125 jmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
  126 {
  127         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  128         uint16_t bmcr;
  129 
  130         switch (cmd) {
  131         case MII_POLLSTAT:
  132                 /*
  133                  * If we're not polling our PHY instance, just return.
  134                  */
  135                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  136                         return (0);
  137                 break;
  138 
  139         case MII_MEDIACHG:
  140                 /*
  141                  * If the media indicates a different PHY instance,
  142                  * isolate ourselves.
  143                  */
  144                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
  145                         bmcr = PHY_READ(sc, MII_BMCR);
  146                         PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO);
  147                         return (0);
  148                 }
  149 
  150                 /*
  151                  * If the interface is not up, don't do anything.
  152                  */
  153                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  154                         break;
  155 
  156                 if (jmphy_auto(sc, ife) != EJUSTRETURN)
  157                         return (EINVAL);
  158                 break;
  159 
  160         case MII_TICK:
  161                 /*
  162                  * If we're not currently selected, just return.
  163                  */
  164                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  165                         return (0);
  166 
  167                 /*
  168                  * Is the interface even up?
  169                  */
  170                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  171                         return (0);
  172 
  173                 /*
  174                  * Only used for autonegotiation.
  175                  */
  176                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
  177                         break;
  178 
  179                 /* Check for link. */
  180                 if (PHY_READ(sc, JMPHY_SSR) & JMPHY_SSR_LINK_UP) {
  181                         sc->mii_ticks = 0;
  182                         break;
  183                 }
  184 
  185                 /* Announce link loss right after it happens. */
  186                 if (sc->mii_ticks++ == 0)
  187                         break;
  188                 if (sc->mii_ticks <= sc->mii_anegticks)
  189                         return (0);
  190 
  191                 sc->mii_ticks = 0;
  192                 jmphy_auto(sc, ife);
  193                 break;
  194         }
  195 
  196         /* Update the media status. */
  197         jmphy_status(sc);
  198 
  199         /* Callback if something changed. */
  200         mii_phy_update(sc, cmd);
  201         return (0);
  202 }
  203 
  204 void
  205 jmphy_status(struct mii_softc *sc)
  206 {
  207         struct mii_data *mii = sc->mii_pdata;
  208         int bmcr, ssr;
  209 
  210         mii->mii_media_status = IFM_AVALID;
  211         mii->mii_media_active = IFM_ETHER;
  212 
  213         ssr = PHY_READ(sc, JMPHY_SSR);
  214         if ((ssr & JMPHY_SSR_LINK_UP) != 0)
  215                 mii->mii_media_status |= IFM_ACTIVE;
  216 
  217         bmcr = PHY_READ(sc, MII_BMCR);
  218         if ((bmcr & BMCR_ISO) != 0) {
  219                 mii->mii_media_active |= IFM_NONE;
  220                 mii->mii_media_status = 0;
  221                 return;
  222         }
  223 
  224         if ((bmcr & BMCR_LOOP) != 0)
  225                 mii->mii_media_active |= IFM_LOOP;
  226 
  227         if ((ssr & JMPHY_SSR_SPD_DPLX_RESOLVED) == 0) {
  228                 /* Erg, still trying, I guess... */
  229                 mii->mii_media_active |= IFM_NONE;
  230                 return;
  231         }
  232 
  233         switch ((ssr & JMPHY_SSR_SPEED_MASK)) {
  234         case JMPHY_SSR_SPEED_1000:
  235                 mii->mii_media_active |= IFM_1000_T;
  236                 /*
  237                  * jmphy(4) got a valid link so reset mii_ticks.
  238                  * Resetting mii_ticks is needed in order to
  239                  * detect link loss after auto-negotiation.
  240                  */
  241                 sc->mii_ticks = 0;
  242                 break;
  243         case JMPHY_SSR_SPEED_100:
  244                 mii->mii_media_active |= IFM_100_TX;
  245                 sc->mii_ticks = 0;
  246                 break;
  247         case JMPHY_SSR_SPEED_10:
  248                 mii->mii_media_active |= IFM_10_T;
  249                 sc->mii_ticks = 0;
  250                 break;
  251         default:
  252                 mii->mii_media_active |= IFM_NONE;
  253                 return;
  254         }
  255 
  256         if ((ssr & JMPHY_SSR_DUPLEX) != 0)
  257                 mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
  258         else
  259                 mii->mii_media_active |= IFM_HDX;
  260 
  261         if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
  262                 if ((PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0)
  263                         mii->mii_media_active |= IFM_ETH_MASTER;
  264         }
  265 }
  266 
  267 void
  268 jmphy_reset(struct mii_softc *sc)
  269 {
  270         int i;
  271 
  272         /* Disable sleep mode. */
  273         PHY_WRITE(sc, JMPHY_TMCTL,
  274             PHY_READ(sc, JMPHY_TMCTL) & ~JMPHY_TMCTL_SLEEP_ENB);
  275         PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN);
  276 
  277         for (i = 0; i < 1000; i++) {
  278                 DELAY(1);
  279                 if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0)
  280                         break;
  281         }
  282 }
  283 
  284 uint16_t
  285 jmphy_anar(struct ifmedia_entry *ife)
  286 {
  287         uint16_t anar;
  288 
  289         anar = 0;
  290         switch (IFM_SUBTYPE(ife->ifm_media)) {
  291         case IFM_AUTO:
  292                 anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
  293                 break;
  294         case IFM_1000_T:
  295                 break;
  296         case IFM_100_TX:
  297                 anar |= ANAR_TX | ANAR_TX_FD;
  298                 break;
  299         case IFM_10_T:
  300                 anar |= ANAR_10 | ANAR_10_FD;
  301                 break;
  302         default:
  303                 break;
  304         }
  305 
  306         return (anar);
  307 }
  308 
  309 int
  310 jmphy_auto(struct mii_softc *sc, struct ifmedia_entry *ife)
  311 {
  312         uint16_t anar, bmcr, gig;
  313 
  314         gig = 0;
  315         bmcr = PHY_READ(sc, MII_BMCR);
  316         switch (IFM_SUBTYPE(ife->ifm_media)) {
  317         case IFM_AUTO:
  318                 gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
  319                 break;
  320         case IFM_1000_T:
  321                 gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
  322                 break;
  323         case IFM_100_TX:
  324         case IFM_10_T:
  325                 break;
  326         case IFM_NONE:
  327                 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO | BMCR_PDOWN);
  328                 return (EJUSTRETURN);
  329         default:
  330                 return (EINVAL);
  331         }
  332 
  333         if ((ife->ifm_media & IFM_LOOP) != 0)
  334                 bmcr |= BMCR_LOOP;
  335 
  336         anar = jmphy_anar(ife);
  337         if (sc->mii_flags & MIIF_DOPAUSE)
  338                 anar |= ANAR_PAUSE_TOWARDS;
  339 
  340         if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) {
  341 #ifdef notyet
  342                 struct mii_data *mii;
  343 
  344                 mii = sc->mii_pdata;
  345                 if ((mii->mii_media.ifm_media & IFM_ETH_MASTER) != 0)
  346                         gig |= GTCR_MAN_MS | GTCR_MAN_ADV;
  347 #endif
  348                 PHY_WRITE(sc, MII_100T2CR, gig);
  349         }
  350         PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA);
  351         PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_AUTOEN | BMCR_STARTNEG);
  352 
  353         return (EJUSTRETURN);
  354 }

Cache object: 74ac53a90002708be2636f95b17e2b02


[ 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.