root/dev/mii/nsphy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nsphymatch
  2. nsphyattach
  3. nsphy_service
  4. nsphy_status
  5. nsphy_reset

    1 /*      $OpenBSD: nsphy.c,v 1.20 2006/12/27 19:11:09 kettenis Exp $     */
    2 /*      $NetBSD: nsphy.c,v 1.25 2000/02/02 23:34:57 thorpej Exp $       */
    3 
    4 /*-
    5  * Copyright (c) 1998, 1999 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  * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
   43  *
   44  * Redistribution and use in source and binary forms, with or without
   45  * modification, are permitted provided that the following conditions
   46  * are met:
   47  * 1. Redistributions of source code must retain the above copyright
   48  *    notice, this list of conditions and the following disclaimer.
   49  * 2. Redistributions in binary form must reproduce the above copyright
   50  *    notice, this list of conditions and the following disclaimer in the
   51  *    documentation and/or other materials provided with the distribution.
   52  * 3. All advertising materials mentioning features or use of this software
   53  *    must display the following acknowledgement:
   54  *      This product includes software developed by Manuel Bouyer.
   55  * 4. The name of the author may not be used to endorse or promote products
   56  *    derived from this software without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   59  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   60  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   61  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   62  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   63  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   64  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   65  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   66  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   67  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   68  */
   69 
   70 /*
   71  * driver for National Semiconductor's DP83840A ethernet 10/100 PHY
   72  * Data Sheet available from www.national.com
   73  */
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/kernel.h>
   78 #include <sys/device.h>
   79 #include <sys/socket.h>
   80 #include <sys/errno.h>
   81 
   82 #include <net/if.h>
   83 #include <net/if_media.h>
   84 
   85 #include <dev/mii/mii.h>
   86 #include <dev/mii/miivar.h>
   87 #include <dev/mii/miidevs.h>
   88 
   89 #include <dev/mii/nsphyreg.h>
   90 
   91 int     nsphymatch(struct device *, void *, void *);
   92 void    nsphyattach(struct device *, struct device *, void *);
   93 
   94 struct cfattach nsphy_ca = {
   95         sizeof(struct mii_softc), nsphymatch, nsphyattach, mii_phy_detach,
   96             mii_phy_activate
   97 };
   98 
   99 struct cfdriver nsphy_cd = {
  100         NULL, "nsphy", DV_DULL
  101 };
  102 
  103 int     nsphy_service(struct mii_softc *, struct mii_data *, int);
  104 void    nsphy_status(struct mii_softc *);
  105 void    nsphy_reset(struct mii_softc *);
  106 
  107 const struct mii_phy_funcs nsphy_funcs = {
  108         nsphy_service, nsphy_status, nsphy_reset,
  109 };
  110 
  111 static const struct mii_phydesc nsphys[] = {
  112         { MII_OUI_NATSEMI,              MII_MODEL_NATSEMI_DP83840,
  113           MII_STR_NATSEMI_DP83840 },
  114 
  115         { 0,                    0,
  116           NULL },
  117 };
  118 
  119 int
  120 nsphymatch(struct device *parent, void *match, void *aux)
  121 {
  122         struct mii_attach_args *ma = aux;
  123 
  124         if (mii_phy_match(ma, nsphys) != NULL)
  125                 return (10);
  126 
  127         return (0);
  128 }
  129 
  130 void
  131 nsphyattach(struct device *parent, struct device *self, void *aux)
  132 {
  133         struct mii_softc *sc = (struct mii_softc *)self;
  134         struct mii_attach_args *ma = aux;
  135         struct mii_data *mii = ma->mii_data;
  136         const struct mii_phydesc *mpd;
  137 
  138         mpd = mii_phy_match(ma, nsphys);
  139         printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
  140 
  141         sc->mii_inst = mii->mii_instance;
  142         sc->mii_phy = ma->mii_phyno;
  143         sc->mii_funcs = &nsphy_funcs;
  144         sc->mii_pdata = mii;
  145         sc->mii_flags = ma->mii_flags;
  146         sc->mii_anegticks = MII_ANEGTICKS;
  147 
  148         PHY_RESET(sc);
  149 
  150         sc->mii_capabilities =
  151             PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
  152         if (sc->mii_capabilities & BMSR_MEDIAMASK)
  153                 mii_phy_add_media(sc);
  154 }
  155 
  156 int
  157 nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
  158 {
  159         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  160         int reg;
  161 
  162         if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
  163                 return (ENXIO);
  164 
  165         switch (cmd) {
  166         case MII_POLLSTAT:
  167                 /*
  168                  * If we're not polling our PHY instance, just return.
  169                  */
  170                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  171                         return (0);
  172                 break;
  173 
  174         case MII_MEDIACHG:
  175                 /*
  176                  * If the media indicates a different PHY instance,
  177                  * isolate ourselves.
  178                  */
  179                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
  180                         reg = PHY_READ(sc, MII_BMCR);
  181                         PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
  182                         return (0);
  183                 }
  184 
  185                 /*
  186                  * If the interface is not up, don't do anything.
  187                  */
  188                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  189                         break;
  190 
  191                 reg = PHY_READ(sc, MII_NSPHY_PCR);
  192 
  193                 /*
  194                  * Set up the PCR to use LED4 to indicate full-duplex
  195                  * in both 10baseT and 100baseTX modes.
  196                  */
  197                 reg |= PCR_LED4MODE;
  198 
  199                 /*
  200                  * Make sure Carrier Integrity Monitor function is
  201                  * disabled (normal for Node operation, but sometimes
  202                  * it's not set?!)
  203                  */
  204                 reg |= PCR_CIMDIS;
  205 
  206                 /*
  207                  * Make sure "force link good" is set to normal mode.
  208                  * It's only intended for debugging.
  209                  */
  210                 reg |= PCR_FLINK100;
  211 
  212                 /*
  213                  * Mystery bits which are supposedly `reserved',
  214                  * but we seem to need to set them when the PHY
  215                  * is connected to some interfaces!
  216                  */
  217                 reg |= PCR_CONGCTRL | PCR_TXREADYSEL;
  218 
  219                 PHY_WRITE(sc, MII_NSPHY_PCR, reg);
  220 
  221                 mii_phy_setmedia(sc);
  222                 break;
  223 
  224         case MII_TICK:
  225                 /*
  226                  * If we're not currently selected, just return.
  227                  */
  228                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  229                         return (0);
  230 
  231                 if (mii_phy_tick(sc) == EJUSTRETURN)
  232                         return (0);
  233                 break;
  234 
  235         case MII_DOWN:
  236                 mii_phy_down(sc);
  237                 return (0);
  238         }
  239 
  240         /* Update the media status. */
  241         mii_phy_status(sc);
  242 
  243         /* Callback if something changed. */
  244         mii_phy_update(sc, cmd);
  245         return (0);
  246 }
  247 
  248 void
  249 nsphy_status(struct mii_softc *sc)
  250 {
  251         struct mii_data *mii = sc->mii_pdata;
  252         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  253         int bmsr, bmcr, par, anlpar;
  254 
  255         mii->mii_media_status = IFM_AVALID;
  256         mii->mii_media_active = IFM_ETHER;
  257 
  258         bmsr = PHY_READ(sc, MII_BMSR) |
  259             PHY_READ(sc, MII_BMSR);
  260         if (bmsr & BMSR_LINK)
  261                 mii->mii_media_status |= IFM_ACTIVE;
  262 
  263         bmcr = PHY_READ(sc, MII_BMCR);
  264         if (bmcr & BMCR_ISO) {
  265                 mii->mii_media_active |= IFM_NONE;
  266                 mii->mii_media_status = 0;
  267                 return;
  268         }
  269 
  270         if (bmcr & BMCR_LOOP)
  271                 mii->mii_media_active |= IFM_LOOP;
  272 
  273         if (bmcr & BMCR_AUTOEN) {
  274                 /*
  275                  * The PAR status bits are only valid of autonegotiation
  276                  * has completed (or it's disabled).
  277                  */
  278                 if ((bmsr & BMSR_ACOMP) == 0) {
  279                         /* Erg, still trying, I guess... */
  280                         mii->mii_media_active |= IFM_NONE;
  281                         return;
  282                 }
  283 
  284                 /*
  285                  * Argh.  The PAR doesn't seem to indicate duplex mode
  286                  * properly!  Determine media based on link partner's
  287                  * advertised capabilities.
  288                  */
  289                 if (PHY_READ(sc, MII_ANER) & ANER_LPAN) {
  290                         anlpar = PHY_READ(sc, MII_ANAR) &
  291                             PHY_READ(sc, MII_ANLPAR);
  292                         if (anlpar & ANLPAR_T4)
  293                                 mii->mii_media_active |= IFM_100_T4;
  294                         else if (anlpar & ANLPAR_TX_FD)
  295                                 mii->mii_media_active |= IFM_100_TX|IFM_FDX;
  296                         else if (anlpar & ANLPAR_TX)
  297                                 mii->mii_media_active |= IFM_100_TX|IFM_HDX;
  298                         else if (anlpar & ANLPAR_10_FD)
  299                                 mii->mii_media_active |= IFM_10_T|IFM_FDX;
  300                         else if (anlpar & ANLPAR_10)
  301                                 mii->mii_media_active |= IFM_10_T|IFM_HDX;
  302                         else
  303                                 mii->mii_media_active |= IFM_NONE;
  304                         return;
  305                 }
  306 
  307                 /*
  308                  * Link partner is not capable of autonegotiation.
  309                  * We will never be in full-duplex mode if this is
  310                  * the case, so reading the PAR is OK.
  311                  */
  312                 par = PHY_READ(sc, MII_NSPHY_PAR);
  313                 if (par & PAR_10)
  314                         mii->mii_media_active |= IFM_10_T;
  315                 else
  316                         mii->mii_media_active |= IFM_100_TX;
  317                 mii->mii_media_active |= IFM_HDX;
  318         } else
  319                 mii->mii_media_active = ife->ifm_media;
  320 }
  321 
  322 void
  323 nsphy_reset(struct mii_softc *sc)
  324 {
  325         int anar;
  326 
  327         mii_phy_reset(sc);
  328         anar = PHY_READ(sc, MII_ANAR);
  329         anar |= BMSR_MEDIA_TO_ANAR(PHY_READ(sc, MII_BMSR));
  330         PHY_WRITE(sc, MII_ANAR, anar);
  331 }

/* [<][>][^][v][top][bottom][index][help] */