root/dev/mii/tqphy.c

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

DEFINITIONS

This source file includes following definitions.
  1. tqphymatch
  2. tqphyattach
  3. tqphy_service
  4. tqphy_status

    1 /*      $OpenBSD: tqphy.c,v 1.11 2006/12/27 19:11:09 kettenis Exp $     */
    2 /*      $NetBSD: tqphy.c,v 1.9 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  * TDK TSC78Q2120 PHY driver
   72  *
   73  * Documentation available at http://www.tsc.tdk.com/lan/78Q2120.pdf .
   74  */
   75 
   76 #include <sys/param.h>
   77 #include <sys/systm.h>
   78 #include <sys/kernel.h>
   79 #include <sys/device.h>
   80 #include <sys/socket.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/tqphyreg.h>
   90 
   91 int     tqphymatch(struct device *, void *, void *);
   92 void    tqphyattach(struct device *, struct device *, void *);
   93 int     tqphydetach(struct device *, int);
   94 
   95 struct cfattach tqphy_ca = {
   96         sizeof(struct mii_softc), tqphymatch, tqphyattach, mii_phy_detach,
   97             mii_phy_activate
   98 };
   99 
  100 struct cfdriver tqphy_cd = {
  101         NULL, "tqphy", DV_DULL
  102 };
  103 
  104 int     tqphy_service(struct mii_softc *, struct mii_data *, int);
  105 void    tqphy_status(struct mii_softc *);
  106 
  107 const struct mii_phy_funcs tqphy_funcs = {
  108         tqphy_service, tqphy_status, mii_phy_reset,
  109 };
  110 
  111 static const struct mii_phydesc tqphys[] = {
  112         { MII_OUI_TSC,          MII_MODEL_TSC_78Q2120,
  113           MII_STR_TSC_78Q2120 },
  114 
  115         { 0,                    0,
  116           NULL },
  117 };
  118 
  119 int
  120 tqphymatch(struct device *parent, void *match, void *aux)
  121 {
  122         struct mii_attach_args *ma = aux;
  123 
  124         if (mii_phy_match(ma, tqphys) != NULL)
  125                 return (10);
  126 
  127         return (0);
  128 }
  129 
  130 void
  131 tqphyattach(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, tqphys);
  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 = &tqphy_funcs;
  144         sc->mii_pdata = mii;
  145         sc->mii_flags = ma->mii_flags;
  146 
  147         /*
  148          * Apparently, we can't do loopback on this PHY.
  149          */
  150         sc->mii_flags |= MIIF_NOLOOP;
  151 
  152         PHY_RESET(sc);
  153 
  154         sc->mii_capabilities =
  155             PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
  156         if (sc->mii_capabilities & BMSR_MEDIAMASK)
  157                 mii_phy_add_media(sc);
  158 }
  159 
  160 int
  161 tqphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
  162 {
  163         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  164         int reg;
  165 
  166         if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
  167                 return (ENXIO);
  168 
  169         switch (cmd) {
  170         case MII_POLLSTAT:
  171                 /*
  172                  * If we're not polling our PHY instance, just return.
  173                  */
  174                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  175                         return (0);
  176                 break;
  177 
  178         case MII_MEDIACHG:
  179                 /*
  180                  * If the media indicates a different PHY instance,
  181                  * isolate ourselves.
  182                  */
  183                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
  184                         reg = PHY_READ(sc, MII_BMCR);
  185                         PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
  186                         return (0);
  187                 }
  188 
  189                 /*
  190                  * If the interface is not up, don't do anything.
  191                  */
  192                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  193                         break;
  194 
  195                 mii_phy_setmedia(sc);
  196                 break;
  197 
  198         case MII_TICK:
  199                 /*
  200                  * If we're not currently selected, just return.
  201                  */
  202                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  203                         return (0);
  204 
  205                 if (mii_phy_tick(sc) == EJUSTRETURN)
  206                         return (0);
  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         return (0);
  220 }
  221 
  222 void
  223 tqphy_status(struct mii_softc *sc)
  224 {
  225         struct mii_data *mii = sc->mii_pdata;
  226         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  227         int bmsr, bmcr, diag;
  228 
  229         mii->mii_media_status = IFM_AVALID;
  230         mii->mii_media_active = IFM_ETHER;
  231 
  232         bmsr = PHY_READ(sc, MII_BMSR) |
  233             PHY_READ(sc, MII_BMSR);
  234         if (bmsr & BMSR_LINK)
  235                 mii->mii_media_status |= IFM_ACTIVE;
  236 
  237         bmcr = PHY_READ(sc, MII_BMCR);
  238         if (bmcr & BMCR_ISO) {
  239                 mii->mii_media_active |= IFM_NONE;
  240                 mii->mii_media_status = 0;
  241                 return;
  242         }
  243 
  244         if (bmcr & BMCR_LOOP)
  245                 mii->mii_media_active |= IFM_LOOP;
  246 
  247         if (bmcr & BMCR_AUTOEN) {
  248                 if ((bmsr & BMSR_ACOMP) == 0) {
  249                         /* Erg, still trying, I guess... */
  250                         mii->mii_media_active |= IFM_NONE;
  251                         return;
  252                 }
  253                 diag = PHY_READ(sc, MII_TQPHY_DIAG);
  254                 if (diag & DIAG_RATE)
  255                         mii->mii_media_active |= IFM_100_TX;
  256                 else
  257                         mii->mii_media_active |= IFM_10_T;
  258 
  259                 if (diag & DIAG_DPLX)
  260                         mii->mii_media_active |= IFM_FDX;
  261                 else
  262                         mii->mii_media_active |= IFM_HDX;
  263         } else
  264                 mii->mii_media_active = ife->ifm_media;
  265 }

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