root/dev/mii/mii_physubr.c

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

DEFINITIONS

This source file includes following definitions.
  1. mii_phy_setmedia
  2. mii_phy_auto
  3. mii_phy_auto_timeout
  4. mii_phy_tick
  5. mii_phy_reset
  6. mii_phy_down
  7. mii_phy_status
  8. mii_phy_update
  9. mii_phy_statusmsg
  10. mii_phy_add_media
  11. mii_phy_delete_media
  12. mii_phy_activate
  13. mii_phy_detach
  14. mii_phy_match
  15. mii_phy_flowstatus
  16. mii_anar

    1 /*      $OpenBSD: mii_physubr.c,v 1.32 2007/02/10 22:36:18 kettenis Exp $       */
    2 /*      $NetBSD: mii_physubr.c,v 1.20 2001/04/13 23:30:09 thorpej Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1998, 1999, 2000 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  * Subroutines common to all PHYs.
   43  */
   44 
   45 #include <sys/param.h>
   46 #include <sys/device.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/socket.h>
   50 #include <sys/errno.h>
   51 #include <sys/proc.h>
   52 
   53 #include <net/if.h>
   54 #include <net/if_media.h>
   55 
   56 #include <dev/mii/mii.h>
   57 #include <dev/mii/miivar.h>
   58 
   59 /*
   60  * Media to register setting conversion table.  Order matters.
   61  * XXX 802.3 doesn't specify ANAR or ANLPAR bits for 1000base.
   62  */
   63 const struct mii_media mii_media_table[] = {
   64         /* None */
   65         { BMCR_ISO,             ANAR_CSMA,              0 },
   66         /* 10baseT */
   67         { BMCR_S10,             ANAR_CSMA|ANAR_10,      0 },
   68         /* 10baseT-FDX */
   69         { BMCR_S10|BMCR_FDX,    ANAR_CSMA|ANAR_10_FD,   0 },
   70         /* 100baseT4 */
   71         { BMCR_S100,            ANAR_CSMA|ANAR_T4,      0 },
   72         /* 100baseTX */
   73         { BMCR_S100,            ANAR_CSMA|ANAR_TX,      0 },
   74         /* 100baseTX-FDX */
   75         { BMCR_S100|BMCR_FDX,   ANAR_CSMA|ANAR_TX_FD,   0 },
   76         /* 1000baseX */
   77         { BMCR_S1000,           ANAR_CSMA,              0 },
   78         /* 1000baseX-FDX */
   79         { BMCR_S1000|BMCR_FDX,  ANAR_CSMA,              0 },
   80         /* 1000baseT */
   81         { BMCR_S1000,           ANAR_CSMA,              GTCR_ADV_1000THDX },
   82         /* 1000baseT-FDX */
   83         { BMCR_S1000|BMCR_FDX,  ANAR_CSMA,              GTCR_ADV_1000TFDX },
   84 };
   85 
   86 void
   87 mii_phy_setmedia(struct mii_softc *sc)
   88 {
   89         struct mii_data *mii = sc->mii_pdata;
   90         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
   91         int bmcr, anar, gtcr;
   92 
   93         if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
   94                 if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
   95                     (sc->mii_flags & MIIF_FORCEANEG))
   96                         (void) mii_phy_auto(sc, 1);
   97                 return;
   98         }
   99 
  100         /*
  101          * Table index is stored in the media entry.
  102          */
  103 #ifdef DIAGNOSTIC
  104         if (ife->ifm_data < 0 || ife->ifm_data >= MII_NMEDIA)
  105                 panic("mii_phy_setmedia");
  106 #endif
  107 
  108         anar = mii_media_table[ife->ifm_data].mm_anar;
  109         bmcr = mii_media_table[ife->ifm_data].mm_bmcr;
  110         gtcr = mii_media_table[ife->ifm_data].mm_gtcr;
  111 
  112         if (mii->mii_media.ifm_media & IFM_ETH_MASTER) {
  113                 switch (IFM_SUBTYPE(ife->ifm_media)) {
  114                 case IFM_1000_T:
  115                         gtcr |= GTCR_MAN_MS|GTCR_ADV_MS;
  116                         break;
  117 
  118                 default:
  119                         panic("mii_phy_setmedia: MASTER on wrong media");
  120                 }
  121         }
  122 
  123         if (ife->ifm_media & IFM_LOOP)
  124                 bmcr |= BMCR_LOOP;
  125 
  126         PHY_WRITE(sc, MII_ANAR, anar);
  127         PHY_WRITE(sc, MII_BMCR, bmcr);
  128         if (sc->mii_flags & MIIF_HAVE_GTCR)
  129                 PHY_WRITE(sc, MII_100T2CR, gtcr);
  130 }
  131 
  132 int
  133 mii_phy_auto(struct mii_softc *sc, int waitfor)
  134 {
  135         int bmsr, i;
  136 
  137         if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
  138                 /*
  139                  * Check for 1000BASE-X.  Autonegotiation is a bit
  140                  * different on such devices.
  141                  */
  142                 if (sc->mii_flags & MIIF_IS_1000X) {
  143                         uint16_t anar = 0;
  144 
  145                         if (sc->mii_extcapabilities & EXTSR_1000XFDX)
  146                                 anar |= ANAR_X_FD;
  147                         if (sc->mii_extcapabilities & EXTSR_1000XHDX)
  148                                 anar |= ANAR_X_HD;
  149 
  150                         if (sc->mii_flags & MIIF_DOPAUSE &&
  151                             sc->mii_extcapabilities & EXTSR_1000XFDX)
  152                                 anar |= ANAR_X_PAUSE_TOWARDS;
  153 
  154                         PHY_WRITE(sc, MII_ANAR, anar);
  155                 } else {
  156                         uint16_t anar;
  157 
  158                         anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
  159                             ANAR_CSMA;
  160                         /* 
  161                          * Most 100baseTX PHY's only support symmetric
  162                          * PAUSE, so we don't advertise asymmetric
  163                          * PAUSE unless we also have 1000baseT capability.
  164                          */
  165                         if (sc->mii_flags & MIIF_DOPAUSE) {
  166                                 if (sc->mii_capabilities & BMSR_100TXFDX)
  167                                         anar |= ANAR_FC;
  168                                 if (sc->mii_extcapabilities & EXTSR_1000TFDX)
  169                                         anar |= ANAR_PAUSE_TOWARDS;
  170                         }
  171                         PHY_WRITE(sc, MII_ANAR, anar);
  172                         if (sc->mii_flags & MIIF_HAVE_GTCR) {
  173                                 uint16_t gtcr = 0;
  174 
  175                                 if (sc->mii_extcapabilities & EXTSR_1000TFDX)
  176                                         gtcr |= GTCR_ADV_1000TFDX;
  177                                 if (sc->mii_extcapabilities & EXTSR_1000THDX)
  178                                         gtcr |= GTCR_ADV_1000THDX;
  179 
  180                                 PHY_WRITE(sc, MII_100T2CR, gtcr);
  181                         }
  182                 }
  183                 PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
  184         }
  185 
  186         if (waitfor) {
  187                 /* Wait 500ms for it to complete. */
  188                 for (i = 0; i < 500; i++) {
  189                         if ((bmsr = PHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
  190                                 return (0);
  191                         delay(1000);
  192                 }
  193 
  194                 /*
  195                  * Don't need to worry about clearing MIIF_DOINGAUTO.
  196                  * If that's set, a timeout is pending, and it will
  197                  * clear the flag.
  198                  */
  199                 return (EIO);
  200         }
  201 
  202         /*
  203          * Just let it finish asynchronously.  This is for the benefit of
  204          * the tick handler driving autonegotiation.  Don't want 500ms
  205          * delays all the time while the system is running!
  206          */
  207         if (sc->mii_flags & MIIF_AUTOTSLEEP) {
  208                 sc->mii_flags |= MIIF_DOINGAUTO;
  209                 tsleep(&sc->mii_flags, PZERO, "miiaut", hz >> 1);
  210                 mii_phy_auto_timeout(sc);
  211         } else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
  212                 sc->mii_flags |= MIIF_DOINGAUTO;
  213                 timeout_set(&sc->mii_phy_timo, mii_phy_auto_timeout, sc);
  214                 timeout_add(&sc->mii_phy_timo, hz / 2);
  215         }
  216         return (EJUSTRETURN);
  217 }
  218 
  219 void
  220 mii_phy_auto_timeout(void *arg)
  221 {
  222         struct mii_softc *sc = arg;
  223         int s, bmsr;
  224 
  225         if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
  226                 return;
  227 
  228         s = splnet();
  229         sc->mii_flags &= ~MIIF_DOINGAUTO;
  230         bmsr = PHY_READ(sc, MII_BMSR);
  231 
  232         /* Update the media status. */
  233         (void) PHY_SERVICE(sc, sc->mii_pdata, MII_POLLSTAT);
  234         splx(s);
  235 }
  236 
  237 int
  238 mii_phy_tick(struct mii_softc *sc)
  239 {
  240         struct mii_data *mii = sc->mii_pdata;
  241         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  242         int reg;
  243 
  244         /* Just bail now if the interface is down. */
  245         if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  246                 return (EJUSTRETURN);
  247 
  248         /*
  249          * If we're not doing autonegotiation, we don't need to do
  250          * any extra work here.  However, we need to check the link
  251          * status so we can generate an announcement if the status
  252          * changes.
  253          */
  254         if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
  255                 return (0);
  256 
  257         /* Read the status register twice; BMSR_LINK is latch-low. */
  258         reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
  259         if (reg & BMSR_LINK) {
  260                 /*
  261                  * See above.
  262                  */
  263                 return (0);
  264         }
  265 
  266         /*
  267          * Only retry autonegotiation every mii_anegticks seconds.
  268          */
  269         if (!sc->mii_anegticks)
  270                 sc->mii_anegticks = MII_ANEGTICKS;
  271 
  272         if (++sc->mii_ticks <= sc->mii_anegticks)
  273                 return (EJUSTRETURN);
  274 
  275         sc->mii_ticks = 0;
  276         PHY_RESET(sc);
  277 
  278         if (mii_phy_auto(sc, 0) == EJUSTRETURN)
  279                 return (EJUSTRETURN);
  280 
  281         /*
  282          * Might need to generate a status message if autonegotiation
  283          * failed.
  284          */
  285         return (0);
  286 }
  287 
  288 void
  289 mii_phy_reset(struct mii_softc *sc)
  290 {
  291         int reg, i;
  292 
  293         if (sc->mii_flags & MIIF_NOISOLATE)
  294                 reg = BMCR_RESET;
  295         else
  296                 reg = BMCR_RESET | BMCR_ISO;
  297         PHY_WRITE(sc, MII_BMCR, reg);
  298 
  299         /*
  300          * It is best to allow a little time for the reset to settle
  301          * in before we start polling the BMCR again.  Notably, the
  302          * DP83840A manual states that there should be a 500us delay
  303          * between asserting software reset and attempting MII serial
  304          * operations.  Also, a DP83815 can get into a bad state on
  305          * cable removal and reinsertion if we do not delay here.
  306          */
  307         delay(500);
  308 
  309         /* Wait another 100ms for it to complete. */
  310         for (i = 0; i < 100; i++) {
  311                 reg = PHY_READ(sc, MII_BMCR);
  312                 if ((reg & BMCR_RESET) == 0)
  313                         break;
  314                 delay(1000);
  315         }
  316 
  317         if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0))
  318                 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
  319 }
  320 
  321 void
  322 mii_phy_down(struct mii_softc *sc)
  323 {
  324         if (sc->mii_flags & MIIF_DOINGAUTO) {
  325                 sc->mii_flags &= ~MIIF_DOINGAUTO;
  326                 timeout_del(&sc->mii_phy_timo);
  327         }
  328 }
  329 
  330 
  331 void
  332 mii_phy_status(struct mii_softc *sc)
  333 {
  334         PHY_STATUS(sc);
  335 }
  336 
  337 void
  338 mii_phy_update(struct mii_softc *sc, int cmd)
  339 {
  340         struct mii_data *mii = sc->mii_pdata;
  341         struct ifnet *ifp = mii->mii_ifp;
  342         int announce, s;
  343 
  344         if (sc->mii_media_active != mii->mii_media_active ||
  345             sc->mii_media_status != mii->mii_media_status ||
  346             cmd == MII_MEDIACHG) {
  347                 announce = mii_phy_statusmsg(sc);
  348                 (*mii->mii_statchg)(sc->mii_dev.dv_parent);
  349                 sc->mii_media_active = mii->mii_media_active;
  350                 sc->mii_media_status = mii->mii_media_status;
  351 
  352                 if (announce) {
  353                         s = splnet();
  354                         if_link_state_change(ifp);
  355                         splx(s);
  356                 }
  357         }
  358 }
  359 
  360 int
  361 mii_phy_statusmsg(struct mii_softc *sc)
  362 {
  363         struct mii_data *mii = sc->mii_pdata;
  364         struct ifnet *ifp = mii->mii_ifp;
  365         int baudrate, link_state, announce = 0;
  366 
  367         if (mii->mii_media_status & IFM_AVALID) {
  368                 if (mii->mii_media_status & IFM_ACTIVE) {
  369                         if (mii->mii_media_active & IFM_FDX)
  370                                 link_state = LINK_STATE_FULL_DUPLEX;
  371                         else if (mii->mii_media_active & IFM_HDX)
  372                                 link_state = LINK_STATE_HALF_DUPLEX;
  373                         else
  374                                 link_state = LINK_STATE_UP;
  375                 } else
  376                         link_state = LINK_STATE_DOWN;
  377         } else
  378                 link_state = LINK_STATE_UNKNOWN;
  379 
  380         baudrate = ifmedia_baudrate(mii->mii_media_active);
  381 
  382         if (link_state != ifp->if_link_state) {
  383                 ifp->if_link_state = link_state;
  384                 /*
  385                  * XXX Right here we'd like to notify protocols
  386                  * XXX that the link status has changed, so that
  387                  * XXX e.g. Duplicate Address Detection can restart.
  388                  */
  389                 announce = 1;
  390         }
  391 
  392         if (baudrate != ifp->if_baudrate) {
  393                 ifp->if_baudrate = baudrate;
  394                 announce = 1;
  395         }
  396 
  397         return (announce);
  398 }
  399 
  400 /*
  401  * Initialize generic PHY media based on BMSR, called when a PHY is
  402  * attached.  We expect to be set up to print a comma-separated list
  403  * of media names.  Does not print a newline.
  404  */
  405 void
  406 mii_phy_add_media(struct mii_softc *sc)
  407 {
  408         struct mii_data *mii = sc->mii_pdata;
  409 
  410 #define ADD(m, c)       ifmedia_add(&mii->mii_media, (m), (c), NULL)
  411 
  412         if ((sc->mii_flags & MIIF_NOISOLATE) == 0)
  413                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
  414                     MII_MEDIA_NONE);
  415 
  416         if (sc->mii_capabilities & BMSR_10THDX) {
  417                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
  418                     MII_MEDIA_10_T);
  419         }
  420         if (sc->mii_capabilities & BMSR_10TFDX) {
  421                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
  422                     MII_MEDIA_10_T_FDX);
  423         }
  424         if (sc->mii_capabilities & BMSR_100TXHDX) {
  425                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
  426                     MII_MEDIA_100_TX);
  427         }
  428         if (sc->mii_capabilities & BMSR_100TXFDX) {
  429                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
  430                     MII_MEDIA_100_TX_FDX);
  431         }
  432         if (sc->mii_capabilities & BMSR_100T4) {
  433                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
  434                     MII_MEDIA_100_T4);
  435         }
  436         if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) {
  437                 /*
  438                  * XXX Right now only handle 1000SX and 1000TX.  Need
  439                  * XXX to handle 1000LX and 1000CX some how.
  440                  */
  441                 if (sc->mii_extcapabilities & EXTSR_1000XHDX) {
  442                         sc->mii_anegticks = MII_ANEGTICKS_GIGE;
  443                         sc->mii_flags |= MIIF_IS_1000X;
  444                         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0,
  445                             sc->mii_inst), MII_MEDIA_1000_X);
  446                 }
  447                 if (sc->mii_extcapabilities & EXTSR_1000XFDX) {
  448                         sc->mii_anegticks = MII_ANEGTICKS_GIGE;
  449                         sc->mii_flags |= MIIF_IS_1000X;
  450                         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
  451                             sc->mii_inst), MII_MEDIA_1000_X_FDX);
  452                 }
  453 
  454                 /*
  455                  * 1000baseT media needs to be able to manipulate
  456                  * master/slave mode.  We set IFM_ETH_MASTER in
  457                  * the "don't care mask" and filter it out when
  458                  * the media is set.
  459                  *
  460                  * All 1000baseT PHYs have a 1000baseT control register.
  461                  */
  462                 if (sc->mii_extcapabilities & EXTSR_1000THDX) {
  463                         sc->mii_anegticks = MII_ANEGTICKS_GIGE;
  464                         sc->mii_flags |= MIIF_HAVE_GTCR;
  465                         mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
  466                         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
  467                             sc->mii_inst), MII_MEDIA_1000_T);
  468                 }
  469                 if (sc->mii_extcapabilities & EXTSR_1000TFDX) {
  470                         sc->mii_anegticks = MII_ANEGTICKS_GIGE;
  471                         sc->mii_flags |= MIIF_HAVE_GTCR;
  472                         mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
  473                         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
  474                             sc->mii_inst), MII_MEDIA_1000_T_FDX);
  475                 }
  476         }
  477 
  478         if (sc->mii_capabilities & BMSR_ANEG) {
  479                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
  480                     MII_NMEDIA);        /* intentionally invalid index */
  481         }
  482 #undef ADD
  483 }
  484 
  485 void
  486 mii_phy_delete_media(struct mii_softc *sc)
  487 {
  488         struct mii_data *mii = sc->mii_pdata;
  489 
  490         ifmedia_delete_instance(&mii->mii_media, sc->mii_inst);
  491 }
  492 
  493 int
  494 mii_phy_activate(struct device *self, enum devact act)
  495 {
  496         int rv = 0;
  497 
  498         switch (act) {
  499         case DVACT_ACTIVATE:
  500                 rv = EOPNOTSUPP;
  501                 break;
  502 
  503         case DVACT_DEACTIVATE:
  504                 /* Nothing special to do. */
  505                 break;
  506         }
  507 
  508         return (rv);
  509 }
  510 
  511 int
  512 mii_phy_detach(struct device *self, int flags)
  513 {
  514         struct mii_softc *sc = (void *) self;
  515 
  516         if (sc->mii_flags & MIIF_DOINGAUTO)
  517                 timeout_del(&sc->mii_phy_timo);
  518 
  519         mii_phy_delete_media(sc);
  520 
  521         return (0);
  522 }
  523 
  524 const struct mii_phydesc *
  525 mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd)
  526 {
  527 
  528         for (; mpd->mpd_name != NULL; mpd++) {
  529                 if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui &&
  530                     MII_MODEL(ma->mii_id2) == mpd->mpd_model)
  531                         return (mpd);
  532         }
  533         return (NULL);
  534 }
  535 
  536 /*
  537  * Return the flow control status flag from MII_ANAR & MII_ANLPAR.
  538  */
  539 int
  540 mii_phy_flowstatus(struct mii_softc *sc)
  541 {
  542         int anar, anlpar;
  543 
  544         if ((sc->mii_flags & MIIF_DOPAUSE) == 0)
  545                 return (0);
  546 
  547         anar = PHY_READ(sc, MII_ANAR);
  548         anlpar = PHY_READ(sc, MII_ANLPAR);
  549 
  550         /* For 1000baseX, the bits are in a different location. */
  551         if (sc->mii_flags & MIIF_IS_1000X) {
  552                 anar <<= 3;
  553                 anlpar <<= 3;
  554         }
  555 
  556         if ((anar & ANAR_PAUSE_SYM) & (anlpar & ANLPAR_PAUSE_SYM))
  557                 return (IFM_FLOW|IFM_ETH_TXPAUSE|IFM_ETH_RXPAUSE);
  558 
  559         if ((anar & ANAR_PAUSE_SYM) == 0) {
  560                 if ((anar & ANAR_PAUSE_ASYM) &&
  561                     ((anlpar & ANLPAR_PAUSE_TOWARDS) == ANLPAR_PAUSE_TOWARDS))
  562                         return (IFM_FLOW|IFM_ETH_TXPAUSE);
  563                 else
  564                         return (0);
  565         }
  566 
  567         if ((anar & ANAR_PAUSE_ASYM) == 0) {
  568                 if (anlpar & ANLPAR_PAUSE_SYM)
  569                         return (IFM_FLOW|IFM_ETH_TXPAUSE|IFM_ETH_RXPAUSE);
  570                 else
  571                         return (0);
  572         }
  573 
  574         switch ((anlpar & ANLPAR_PAUSE_TOWARDS)) {
  575         case ANLPAR_PAUSE_NONE:
  576                 return (0);
  577 
  578         case ANLPAR_PAUSE_ASYM:
  579                 return (IFM_FLOW|IFM_ETH_RXPAUSE);
  580 
  581         default:
  582                 return (IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE);
  583         }
  584         /* NOTREACHED */
  585 }
  586 
  587 /*
  588  * Given an ifmedia word, return the corresponding ANAR value.
  589  */
  590 int
  591 mii_anar(int media)
  592 {
  593         int rv;
  594 
  595         switch (media & (IFM_TMASK|IFM_NMASK|IFM_FDX)) {
  596         case IFM_ETHER|IFM_10_T:
  597                 rv = ANAR_10|ANAR_CSMA;
  598                 break;
  599         case IFM_ETHER|IFM_10_T|IFM_FDX:
  600                 rv = ANAR_10_FD|ANAR_CSMA;
  601                 break;
  602         case IFM_ETHER|IFM_100_TX:
  603                 rv = ANAR_TX|ANAR_CSMA;
  604                 break;
  605         case IFM_ETHER|IFM_100_TX|IFM_FDX:
  606                 rv = ANAR_TX_FD|ANAR_CSMA;
  607                 break;
  608         case IFM_ETHER|IFM_100_T4:
  609                 rv = ANAR_T4|ANAR_CSMA;
  610                 break;
  611         default:
  612                 rv = 0;
  613                 break;
  614         }
  615 
  616         return (rv);
  617 }

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