LCOV - code coverage report
Current view: top level - dev/mii - jmphy.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 126 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: jmphy.c,v 1.6 2015/03/14 03:38:48 jsg 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             : 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           0 : jmphy_match(struct device *parent, void *match, void *aux)
      82             : {
      83           0 :         struct mii_attach_args *ma = aux;
      84             : 
      85           0 :         if (mii_phy_match(ma, jmphys) != NULL)
      86           0 :                 return (10);
      87             : 
      88           0 :         return (0);
      89           0 : }
      90             : 
      91             : void
      92           0 : jmphy_attach(struct device *parent, struct device *self, void *aux)
      93             : {
      94           0 :         struct mii_softc *sc = (struct mii_softc *)self;
      95           0 :         struct mii_attach_args *ma = aux;
      96           0 :         struct mii_data *mii = ma->mii_data;
      97             :         const struct mii_phydesc *mpd;
      98             : 
      99           0 :         mpd = mii_phy_match(ma, jmphys);
     100           0 :         printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
     101             : 
     102           0 :         sc->mii_inst = mii->mii_instance;
     103           0 :         sc->mii_phy = ma->mii_phyno;
     104           0 :         sc->mii_funcs = &jmphy_funcs;
     105           0 :         sc->mii_model = MII_MODEL(ma->mii_id2);
     106           0 :         sc->mii_pdata = mii;
     107           0 :         sc->mii_flags = ma->mii_flags;
     108             : 
     109           0 :         sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
     110             : 
     111           0 :         PHY_RESET(sc);
     112             : 
     113           0 :         sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
     114           0 :         if (sc->mii_capabilities & BMSR_EXTSTAT)
     115           0 :                 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
     116             : 
     117           0 :         if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
     118           0 :             (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
     119             :                 ;
     120             :         else
     121           0 :                 mii_phy_add_media(sc);
     122           0 : }
     123             : 
     124             : int
     125           0 : jmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
     126             : {
     127           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     128             :         uint16_t bmcr;
     129             : 
     130           0 :         switch (cmd) {
     131             :         case MII_POLLSTAT:
     132             :                 /*
     133             :                  * If we're not polling our PHY instance, just return.
     134             :                  */
     135           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
     136           0 :                         return (0);
     137             :                 break;
     138             : 
     139             :         case MII_MEDIACHG:
     140             :                 /*
     141             :                  * If the media indicates a different PHY instance,
     142             :                  * isolate ourselves.
     143             :                  */
     144           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
     145           0 :                         bmcr = PHY_READ(sc, MII_BMCR);
     146           0 :                         PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO);
     147           0 :                         return (0);
     148             :                 }
     149             : 
     150             :                 /*
     151             :                  * If the interface is not up, don't do anything.
     152             :                  */
     153           0 :                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
     154             :                         break;
     155             : 
     156           0 :                 if (jmphy_auto(sc, ife) != EJUSTRETURN)
     157           0 :                         return (EINVAL);
     158             :                 break;
     159             : 
     160             :         case MII_TICK:
     161             :                 /*
     162             :                  * If we're not currently selected, just return.
     163             :                  */
     164           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
     165           0 :                         return (0);
     166             : 
     167             :                 /*
     168             :                  * Is the interface even up?
     169             :                  */
     170           0 :                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
     171           0 :                         return (0);
     172             : 
     173             :                 /*
     174             :                  * Only used for autonegotiation.
     175             :                  */
     176           0 :                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
     177             :                         break;
     178             : 
     179             :                 /* Check for link. */
     180           0 :                 if (PHY_READ(sc, JMPHY_SSR) & JMPHY_SSR_LINK_UP) {
     181           0 :                         sc->mii_ticks = 0;
     182           0 :                         break;
     183             :                 }
     184             : 
     185             :                 /* Announce link loss right after it happens. */
     186           0 :                 if (sc->mii_ticks++ == 0)
     187             :                         break;
     188           0 :                 if (sc->mii_ticks <= sc->mii_anegticks)
     189           0 :                         return (0);
     190             : 
     191           0 :                 sc->mii_ticks = 0;
     192           0 :                 jmphy_auto(sc, ife);
     193           0 :                 break;
     194             :         }
     195             : 
     196             :         /* Update the media status. */
     197           0 :         jmphy_status(sc);
     198             : 
     199             :         /* Callback if something changed. */
     200           0 :         mii_phy_update(sc, cmd);
     201           0 :         return (0);
     202           0 : }
     203             : 
     204             : void
     205           0 : jmphy_status(struct mii_softc *sc)
     206             : {
     207           0 :         struct mii_data *mii = sc->mii_pdata;
     208             :         int bmcr, ssr;
     209             : 
     210           0 :         mii->mii_media_status = IFM_AVALID;
     211           0 :         mii->mii_media_active = IFM_ETHER;
     212             : 
     213           0 :         ssr = PHY_READ(sc, JMPHY_SSR);
     214           0 :         if ((ssr & JMPHY_SSR_LINK_UP) != 0)
     215           0 :                 mii->mii_media_status |= IFM_ACTIVE;
     216             : 
     217           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     218           0 :         if ((bmcr & BMCR_ISO) != 0) {
     219           0 :                 mii->mii_media_active |= IFM_NONE;
     220           0 :                 mii->mii_media_status = 0;
     221           0 :                 return;
     222             :         }
     223             : 
     224           0 :         if ((bmcr & BMCR_LOOP) != 0)
     225           0 :                 mii->mii_media_active |= IFM_LOOP;
     226             : 
     227           0 :         if ((ssr & JMPHY_SSR_SPD_DPLX_RESOLVED) == 0) {
     228             :                 /* Erg, still trying, I guess... */
     229           0 :                 mii->mii_media_active |= IFM_NONE;
     230           0 :                 return;
     231             :         }
     232             : 
     233           0 :         switch ((ssr & JMPHY_SSR_SPEED_MASK)) {
     234             :         case JMPHY_SSR_SPEED_1000:
     235           0 :                 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           0 :                 sc->mii_ticks = 0;
     242           0 :                 break;
     243             :         case JMPHY_SSR_SPEED_100:
     244           0 :                 mii->mii_media_active |= IFM_100_TX;
     245           0 :                 sc->mii_ticks = 0;
     246           0 :                 break;
     247             :         case JMPHY_SSR_SPEED_10:
     248           0 :                 mii->mii_media_active |= IFM_10_T;
     249           0 :                 sc->mii_ticks = 0;
     250           0 :                 break;
     251             :         default:
     252           0 :                 mii->mii_media_active |= IFM_NONE;
     253           0 :                 return;
     254             :         }
     255             : 
     256           0 :         if ((ssr & JMPHY_SSR_DUPLEX) != 0)
     257           0 :                 mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
     258             :         else
     259           0 :                 mii->mii_media_active |= IFM_HDX;
     260             : 
     261           0 :         if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
     262           0 :                 if ((PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0)
     263           0 :                         mii->mii_media_active |= IFM_ETH_MASTER;
     264             :         }
     265           0 : }
     266             : 
     267             : void
     268           0 : jmphy_reset(struct mii_softc *sc)
     269             : {
     270             :         int i;
     271             : 
     272             :         /* Disable sleep mode. */
     273           0 :         PHY_WRITE(sc, JMPHY_TMCTL,
     274             :             PHY_READ(sc, JMPHY_TMCTL) & ~JMPHY_TMCTL_SLEEP_ENB);
     275           0 :         PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN);
     276             : 
     277           0 :         for (i = 0; i < 1000; i++) {
     278           0 :                 DELAY(1);
     279           0 :                 if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0)
     280             :                         break;
     281             :         }
     282           0 : }
     283             : 
     284             : uint16_t
     285           0 : jmphy_anar(struct ifmedia_entry *ife)
     286             : {
     287             :         uint16_t anar;
     288             : 
     289             :         anar = 0;
     290           0 :         switch (IFM_SUBTYPE(ife->ifm_media)) {
     291             :         case IFM_AUTO:
     292             :                 anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
     293           0 :                 break;
     294             :         case IFM_1000_T:
     295             :                 break;
     296             :         case IFM_100_TX:
     297             :                 anar |= ANAR_TX | ANAR_TX_FD;
     298           0 :                 break;
     299             :         case IFM_10_T:
     300             :                 anar |= ANAR_10 | ANAR_10_FD;
     301           0 :                 break;
     302             :         default:
     303             :                 break;
     304             :         }
     305             : 
     306           0 :         return (anar);
     307             : }
     308             : 
     309             : int
     310           0 : jmphy_auto(struct mii_softc *sc, struct ifmedia_entry *ife)
     311             : {
     312             :         uint16_t anar, bmcr, gig;
     313             : 
     314             :         gig = 0;
     315           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     316           0 :         switch (IFM_SUBTYPE(ife->ifm_media)) {
     317             :         case IFM_AUTO:
     318             :                 gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
     319           0 :                 break;
     320             :         case IFM_1000_T:
     321             :                 gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
     322           0 :                 break;
     323             :         case IFM_100_TX:
     324             :         case IFM_10_T:
     325             :                 break;
     326             :         case IFM_NONE:
     327           0 :                 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO | BMCR_PDOWN);
     328           0 :                 return (EJUSTRETURN);
     329             :         default:
     330           0 :                 return (EINVAL);
     331             :         }
     332             : 
     333           0 :         if ((ife->ifm_media & IFM_LOOP) != 0)
     334           0 :                 bmcr |= BMCR_LOOP;
     335             : 
     336           0 :         anar = jmphy_anar(ife);
     337           0 :         if (sc->mii_flags & MIIF_DOPAUSE)
     338           0 :                 anar |= ANAR_PAUSE_TOWARDS;
     339             : 
     340           0 :         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           0 :                 PHY_WRITE(sc, MII_100T2CR, gig);
     349           0 :         }
     350           0 :         PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA);
     351           0 :         PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_AUTOEN | BMCR_STARTNEG);
     352             : 
     353           0 :         return (EJUSTRETURN);
     354           0 : }

Generated by: LCOV version 1.13