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

          Line data    Source code
       1             : /*      $OpenBSD: etphy.c,v 1.7 2015/03/14 03:38:48 jsg Exp $   */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
       5             :  * 
       6             :  * This code is derived from software contributed to The DragonFly Project
       7             :  * by Sepherosa Ziehau <sepherosa@gmail.com>
       8             :  * 
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  * 
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer.
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in
      17             :  *    the documentation and/or other materials provided with the
      18             :  *    distribution.
      19             :  * 3. Neither the name of The DragonFly Project nor the names of its
      20             :  *    contributors may be used to endorse or promote products derived
      21             :  *    from this software without specific, prior written permission.
      22             :  * 
      23             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      24             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      25             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      26             :  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
      27             :  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
      28             :  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
      29             :  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      30             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
      31             :  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
      32             :  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
      33             :  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34             :  * SUCH DAMAGE.
      35             :  * 
      36             :  * $DragonFly: src/sys/dev/netif/mii_layer/truephy.c,v 1.1 2007/10/12 14:12:42 sephe Exp $
      37             :  */
      38             : 
      39             : #include <sys/param.h>
      40             : #include <sys/systm.h>
      41             : #include <sys/device.h>
      42             : #include <sys/socket.h>
      43             : 
      44             : #include <net/if.h>
      45             : #include <net/if_var.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             : 
      52             : #define ETPHY_INDEX             0x10    /* XXX reserved in DS */
      53             : #define ETPHY_INDEX_MAGIC       0x402
      54             : #define ETPHY_DATA              0x11    /* XXX reserved in DS */
      55             : 
      56             : #define ETPHY_CTRL              0x12
      57             : #define ETPHY_CTRL_DIAG         0x0004
      58             : #define ETPHY_CTRL_RSV1         0x0002  /* XXX reserved */
      59             : #define ETPHY_CTRL_RSV0         0x0001  /* XXX reserved */
      60             : 
      61             : #define ETPHY_CONF              0x16
      62             : #define ETPHY_CONF_TXFIFO_MASK  0x3000
      63             : #define ETPHY_CONF_TXFIFO_8     0x0000
      64             : #define ETPHY_CONF_TXFIFO_16    0x1000
      65             : #define ETPHY_CONF_TXFIFO_24    0x2000
      66             : #define ETPHY_CONF_TXFIFO_32    0x3000
      67             : 
      68             : #define ETPHY_SR                0x1a
      69             : #define ETPHY_SR_SPD_MASK       0x0300
      70             : #define ETPHY_SR_SPD_1000T      0x0200
      71             : #define ETPHY_SR_SPD_100TX      0x0100
      72             : #define ETPHY_SR_SPD_10T        0x0000
      73             : #define ETPHY_SR_FDX            0x0080
      74             : 
      75             : 
      76             : int     etphy_service(struct mii_softc *, struct mii_data *, int);
      77             : void    etphy_attach(struct device *, struct device *, void *);
      78             : int     etphy_match(struct device *, void *, void *);
      79             : void    etphy_reset(struct mii_softc *);
      80             : void    etphy_status(struct mii_softc *);
      81             : 
      82             : const struct mii_phy_funcs etphy_funcs = {
      83             :         etphy_service, etphy_status, etphy_reset,
      84             : };
      85             : 
      86             : static const struct mii_phydesc etphys[] = {
      87             :         { MII_OUI_AGERE,        MII_MODEL_AGERE_ET1011,
      88             :           MII_STR_AGERE_ET1011 },
      89             :         { 0,                    0,
      90             :           NULL },
      91             : };
      92             : 
      93             : struct cfattach etphy_ca = {
      94             :         sizeof (struct mii_softc), etphy_match, etphy_attach,
      95             :         mii_phy_detach
      96             : };
      97             : 
      98             : struct cfdriver etphy_cd = {
      99             :         NULL, "etphy", DV_DULL
     100             : };
     101             : 
     102             : static const struct etphy_dsp {
     103             :         uint16_t        index;
     104             :         uint16_t        data;
     105             : } etphy_dspcode[] = {
     106             :         { 0x880b,       0x0926 },       /* AfeIfCreg4B1000Msbs */
     107             :         { 0x880c,       0x0926 },       /* AfeIfCreg4B100Msbs */
     108             :         { 0x880d,       0x0926 },       /* AfeIfCreg4B10Msbs */
     109             : 
     110             :         { 0x880e,       0xb4d3 },       /* AfeIfCreg4B1000Lsbs */
     111             :         { 0x880f,       0xb4d3 },       /* AfeIfCreg4B100Lsbs */
     112             :         { 0x8810,       0xb4d3 },       /* AfeIfCreg4B10Lsbs */
     113             : 
     114             :         { 0x8805,       0xb03e },       /* AfeIfCreg3B1000Msbs */
     115             :         { 0x8806,       0xb03e },       /* AfeIfCreg3B100Msbs */
     116             :         { 0x8807,       0xff00 },       /* AfeIfCreg3B10Msbs */
     117             : 
     118             :         { 0x8808,       0xe090 },       /* AfeIfCreg3B1000Lsbs */
     119             :         { 0x8809,       0xe110 },       /* AfeIfCreg3B100Lsbs */
     120             :         { 0x880a,       0x0000 },       /* AfeIfCreg3B10Lsbs */
     121             : 
     122             :         { 0x300d,       1      },       /* DisableNorm */
     123             : 
     124             :         { 0x280c,       0x0180 },       /* LinkHoldEnd */
     125             : 
     126             :         { 0x1c21,       0x0002 },       /* AlphaM */
     127             : 
     128             :         { 0x3821,       6      },       /* FfeLkgTx0 */
     129             :         { 0x381d,       1      },       /* FfeLkg1g4 */
     130             :         { 0x381e,       1      },       /* FfeLkg1g5 */
     131             :         { 0x381f,       1      },       /* FfeLkg1g6 */
     132             :         { 0x3820,       1      },       /* FfeLkg1g7 */
     133             : 
     134             :         { 0x8402,       0x01f0 },       /* Btinact */
     135             :         { 0x800e,       20     },       /* LftrainTime */
     136             :         { 0x800f,       24     },       /* DvguardTime */
     137             :         { 0x8010,       46     }        /* IdlguardTime */
     138             : };
     139             : 
     140             : int
     141           0 : etphy_match(struct device *parent, void *match, void *aux)
     142             : {
     143           0 :         struct mii_attach_args *ma = aux;
     144             : 
     145           0 :         if (mii_phy_match(ma, etphys) != NULL)
     146           0 :                 return (10);
     147             : 
     148           0 :         return (0);
     149           0 : }
     150             : 
     151             : void
     152           0 : etphy_attach(struct device *parent, struct device *self, void *aux)
     153             : {
     154           0 :         struct mii_softc *sc = (struct mii_softc *)self;
     155           0 :         struct mii_attach_args *ma = aux;
     156           0 :         struct mii_data *mii = ma->mii_data;
     157             :         const struct mii_phydesc *mpd;
     158             : 
     159           0 :         mpd = mii_phy_match(ma, etphys);
     160           0 :         printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
     161             : 
     162           0 :         sc->mii_inst = mii->mii_instance;
     163           0 :         sc->mii_phy = ma->mii_phyno;
     164           0 :         sc->mii_funcs = &etphy_funcs;
     165           0 :         sc->mii_model = MII_MODEL(ma->mii_id2);
     166           0 :         sc->mii_pdata = mii;
     167           0 :         sc->mii_flags = ma->mii_flags;
     168             : 
     169           0 :         sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
     170             : 
     171           0 :         PHY_RESET(sc);
     172             : 
     173           0 :         sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
     174           0 :         if (sc->mii_capabilities & BMSR_EXTSTAT) {
     175           0 :                 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
     176             :                 /* No 1000baseT half-duplex support */
     177           0 :                 sc->mii_extcapabilities &= ~EXTSR_1000THDX;
     178           0 :         }
     179             : 
     180           0 :         mii_phy_add_media(sc);
     181           0 : }
     182             : 
     183             : int
     184           0 : etphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
     185             : {
     186           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     187             :         int bmcr;
     188             : 
     189           0 :         switch (cmd) {
     190             :         case MII_POLLSTAT:
     191             :                 /*
     192             :                  * If we're not polling our PHY instance, just return.
     193             :                  */
     194           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
     195           0 :                         return 0;
     196             :                 break;
     197             : 
     198             :         case MII_MEDIACHG:
     199             :                 /*
     200             :                  * If the media indicates a different PHY instance,
     201             :                  * isolate ourselves.
     202             :                  */
     203           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
     204           0 :                         bmcr = PHY_READ(sc, MII_BMCR);
     205           0 :                         PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO);
     206           0 :                         return 0;
     207             :                 }
     208             : 
     209             :                 /*
     210             :                  * If the interface is not up, don't do anything.
     211             :                  */
     212           0 :                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
     213             :                         break;
     214             : 
     215           0 :                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
     216           0 :                         bmcr = PHY_READ(sc, MII_BMCR) & ~BMCR_AUTOEN;
     217           0 :                         PHY_WRITE(sc, MII_BMCR, bmcr);
     218           0 :                         PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_PDOWN);
     219           0 :                 }
     220             : 
     221           0 :                 mii_phy_setmedia(sc);
     222             : 
     223           0 :                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
     224           0 :                         bmcr = PHY_READ(sc, MII_BMCR) & ~BMCR_PDOWN;
     225           0 :                         PHY_WRITE(sc, MII_BMCR, bmcr);
     226             : 
     227           0 :                         if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
     228           0 :                                 PHY_WRITE(sc, MII_BMCR,
     229             :                                           bmcr | BMCR_AUTOEN | BMCR_STARTNEG);
     230           0 :                         }
     231             :                 }
     232             :                 break;
     233             : 
     234             :         case MII_TICK:
     235             :                 /*
     236             :                  * If we're not currently selected, just return.
     237             :                  */
     238           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
     239           0 :                         return 0;
     240             : 
     241           0 :                 if (mii_phy_tick(sc) == EJUSTRETURN)
     242           0 :                         return 0;
     243             :                 break;
     244             :         }
     245             : 
     246             :         /* Update the media status. */
     247           0 :         mii_phy_status(sc);
     248             : 
     249             :         /* Callback if something changed. */
     250           0 :         mii_phy_update(sc, cmd);
     251           0 :         return 0;
     252           0 : }
     253             : 
     254             : void
     255           0 : etphy_reset(struct mii_softc *sc)
     256             : {
     257             :         int i;
     258             : 
     259           0 :         for (i = 0; i < 2; ++i) {
     260           0 :                 PHY_READ(sc, MII_PHYIDR1);
     261           0 :                 PHY_READ(sc, MII_PHYIDR2);
     262             : 
     263           0 :                 PHY_READ(sc, ETPHY_CTRL);
     264           0 :                 PHY_WRITE(sc, ETPHY_CTRL,
     265             :                     ETPHY_CTRL_DIAG | ETPHY_CTRL_RSV1);
     266             : 
     267           0 :                 PHY_WRITE(sc, ETPHY_INDEX, ETPHY_INDEX_MAGIC);
     268           0 :                 PHY_READ(sc, ETPHY_DATA);
     269             : 
     270           0 :                 PHY_WRITE(sc, ETPHY_CTRL, ETPHY_CTRL_RSV1);
     271             :         }
     272             : 
     273           0 :         PHY_READ(sc, MII_BMCR);
     274           0 :         PHY_READ(sc, ETPHY_CTRL);
     275           0 :         PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_PDOWN | BMCR_S1000);
     276           0 :         PHY_WRITE(sc, ETPHY_CTRL,
     277             :             ETPHY_CTRL_DIAG | ETPHY_CTRL_RSV1 | ETPHY_CTRL_RSV0);
     278             : 
     279             : #define N(arr)  (int)(sizeof(arr) / sizeof(arr[0]))
     280             : 
     281           0 :         for (i = 0; i < N(etphy_dspcode); ++i) {
     282           0 :                 const struct etphy_dsp *dsp = &etphy_dspcode[i];
     283             : 
     284           0 :                 PHY_WRITE(sc, ETPHY_INDEX, dsp->index);
     285           0 :                 PHY_WRITE(sc, ETPHY_DATA, dsp->data);
     286             : 
     287           0 :                 PHY_WRITE(sc, ETPHY_INDEX, dsp->index);
     288           0 :                 PHY_READ(sc, ETPHY_DATA);
     289             :         }
     290             : 
     291             : #undef N
     292             : 
     293           0 :         PHY_READ(sc, MII_BMCR);
     294           0 :         PHY_READ(sc, ETPHY_CTRL);
     295           0 :         PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN |  BMCR_S1000);
     296           0 :         PHY_WRITE(sc, ETPHY_CTRL, ETPHY_CTRL_RSV1);
     297             : 
     298           0 :         mii_phy_reset(sc);
     299           0 : }
     300             : 
     301             : void
     302           0 : etphy_status(struct mii_softc *sc)
     303             : {
     304           0 :         struct mii_data *mii = sc->mii_pdata;
     305             :         int bmsr, bmcr, sr;
     306             : 
     307           0 :         mii->mii_media_status = IFM_AVALID;
     308           0 :         mii->mii_media_active = IFM_ETHER;
     309             : 
     310           0 :         sr = PHY_READ(sc, ETPHY_SR);
     311           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     312             : 
     313           0 :         bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
     314           0 :         if (bmsr & BMSR_LINK)
     315           0 :                 mii->mii_media_status |= IFM_ACTIVE;
     316             : 
     317           0 :         if (bmcr & BMCR_AUTOEN) {
     318           0 :                 if ((bmsr & BMSR_ACOMP) == 0) {
     319           0 :                         mii->mii_media_active |= IFM_NONE;
     320           0 :                         return;
     321             :                 }
     322             :         }
     323             : 
     324           0 :         switch (sr & ETPHY_SR_SPD_MASK) {
     325             :         case ETPHY_SR_SPD_1000T:
     326           0 :                 mii->mii_media_active |= IFM_1000_T;
     327           0 :                 break;
     328             :         case ETPHY_SR_SPD_100TX:
     329           0 :                 mii->mii_media_active |= IFM_100_TX;
     330           0 :                 break;
     331             :         case ETPHY_SR_SPD_10T:
     332           0 :                 mii->mii_media_active |= IFM_10_T;
     333           0 :                 break;
     334             :         default:
     335           0 :                 mii->mii_media_active |= IFM_NONE;
     336           0 :                 return;
     337             :         }
     338             : 
     339           0 :         if (sr & ETPHY_SR_FDX)
     340           0 :                 mii->mii_media_active |= IFM_FDX;
     341             :         else
     342           0 :                 mii->mii_media_active |= IFM_HDX;
     343           0 : }

Generated by: LCOV version 1.13