The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mii/mii.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: mii.c,v 1.12 1999/08/03 19:41:49 drochner Exp $        */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
    5  *
    6  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   11  * NASA Ames Research Center.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32  * POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 /*
   39  * MII bus layer, glues MII-capable network interface drivers to sharable
   40  * PHY drivers.  This exports an interface compatible with BSD/OS 3.0's,
   41  * plus some NetBSD extensions.
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/socket.h>
   47 #include <sys/malloc.h>
   48 #include <sys/module.h>
   49 #include <sys/bus.h>
   50 #include <sys/sbuf.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_var.h>
   54 #include <net/if_media.h>
   55 
   56 #include <dev/mii/mii.h>
   57 #include <dev/mii/miivar.h>
   58 
   59 MODULE_VERSION(miibus, 1);
   60 
   61 #include "miibus_if.h"
   62 
   63 static bus_child_detached_t miibus_child_detached;
   64 static bus_child_location_t miibus_child_location;
   65 static bus_child_pnpinfo_t miibus_child_pnpinfo;
   66 static device_detach_t miibus_detach;
   67 static bus_hinted_child_t miibus_hinted_child;
   68 static bus_print_child_t miibus_print_child;
   69 static device_probe_t miibus_probe;
   70 static bus_read_ivar_t miibus_read_ivar;
   71 static miibus_readreg_t miibus_readreg;
   72 static miibus_statchg_t miibus_statchg;
   73 static miibus_writereg_t miibus_writereg;
   74 static miibus_linkchg_t miibus_linkchg;
   75 static miibus_mediainit_t miibus_mediainit;
   76 
   77 static unsigned char mii_bitreverse(unsigned char x);
   78 
   79 static device_method_t miibus_methods[] = {
   80         /* device interface */
   81         DEVMETHOD(device_probe,         miibus_probe),
   82         DEVMETHOD(device_attach,        miibus_attach),
   83         DEVMETHOD(device_detach,        miibus_detach),
   84         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
   85 
   86         /* bus interface */
   87         DEVMETHOD(bus_print_child,      miibus_print_child),
   88         DEVMETHOD(bus_read_ivar,        miibus_read_ivar),
   89         DEVMETHOD(bus_child_detached,   miibus_child_detached),
   90         DEVMETHOD(bus_child_pnpinfo,    miibus_child_pnpinfo),
   91         DEVMETHOD(bus_child_location,   miibus_child_location),
   92         DEVMETHOD(bus_hinted_child,     miibus_hinted_child),
   93 
   94         /* MII interface */
   95         DEVMETHOD(miibus_readreg,       miibus_readreg),
   96         DEVMETHOD(miibus_writereg,      miibus_writereg),
   97         DEVMETHOD(miibus_statchg,       miibus_statchg),
   98         DEVMETHOD(miibus_linkchg,       miibus_linkchg),
   99         DEVMETHOD(miibus_mediainit,     miibus_mediainit),
  100 
  101         DEVMETHOD_END
  102 };
  103 
  104 DEFINE_CLASS_0(miibus, miibus_driver, miibus_methods, sizeof(struct mii_data));
  105 
  106 struct miibus_ivars {
  107         if_t            ifp;
  108         ifm_change_cb_t ifmedia_upd;
  109         ifm_stat_cb_t   ifmedia_sts;
  110         u_int           mii_flags;
  111         u_int           mii_offset;
  112 };
  113 
  114 static int
  115 miibus_probe(device_t dev)
  116 {
  117 
  118         device_set_desc(dev, "MII bus");
  119 
  120         return (BUS_PROBE_SPECIFIC);
  121 }
  122 
  123 int
  124 miibus_attach(device_t dev)
  125 {
  126         struct miibus_ivars     *ivars;
  127         struct mii_attach_args  *ma;
  128         struct mii_data         *mii;
  129         device_t                *children;
  130         int                     i, nchildren;
  131 
  132         mii = device_get_softc(dev);
  133         if (device_get_children(dev, &children, &nchildren) == 0) {
  134                 for (i = 0; i < nchildren; i++) {
  135                         ma = device_get_ivars(children[i]);
  136                         ma->mii_data = mii;
  137                 }
  138                 free(children, M_TEMP);
  139         }
  140         if (nchildren == 0) {
  141                 device_printf(dev, "cannot get children\n");
  142                 return (ENXIO);
  143         }
  144         ivars = device_get_ivars(dev);
  145         ifmedia_init(&mii->mii_media, IFM_IMASK, ivars->ifmedia_upd,
  146             ivars->ifmedia_sts);
  147         mii->mii_ifp = ivars->ifp;
  148         if_setcapabilitiesbit(mii->mii_ifp, IFCAP_LINKSTATE, 0);
  149         if_setcapenablebit(mii->mii_ifp, IFCAP_LINKSTATE, 0);
  150         LIST_INIT(&mii->mii_phys);
  151 
  152         return (bus_generic_attach(dev));
  153 }
  154 
  155 static int
  156 miibus_detach(device_t dev)
  157 {
  158         struct mii_data         *mii;
  159         struct miibus_ivars     *ivars;
  160 
  161         ivars = device_get_ivars(dev);
  162         bus_generic_detach(dev);
  163         mii = device_get_softc(dev);
  164         ifmedia_removeall(&mii->mii_media);
  165         free(ivars, M_DEVBUF);
  166         mii->mii_ifp = NULL;
  167 
  168         return (0);
  169 }
  170 
  171 static void
  172 miibus_child_detached(device_t dev, device_t child)
  173 {
  174         struct mii_attach_args *args;
  175 
  176         args = device_get_ivars(child);
  177         free(args, M_DEVBUF);
  178 }
  179 
  180 static int
  181 miibus_print_child(device_t dev, device_t child)
  182 {
  183         struct mii_attach_args *ma;
  184         int retval;
  185 
  186         ma = device_get_ivars(child);
  187         retval = bus_print_child_header(dev, child);
  188         retval += printf(" PHY %d", ma->mii_phyno);
  189         retval += bus_print_child_footer(dev, child);
  190 
  191         return (retval);
  192 }
  193 
  194 static int
  195 miibus_read_ivar(device_t dev, device_t child __unused, int which,
  196     uintptr_t *result)
  197 {
  198         struct miibus_ivars *ivars;
  199 
  200         /*
  201          * NB: this uses the instance variables of the miibus rather than
  202          * its PHY children.
  203          */
  204         ivars = device_get_ivars(dev);
  205         switch (which) {
  206         case MIIBUS_IVAR_FLAGS:
  207                 *result = ivars->mii_flags;
  208                 break;
  209         default:
  210                 return (ENOENT);
  211         }
  212         return (0);
  213 }
  214 
  215 static int
  216 miibus_child_pnpinfo(device_t dev __unused, device_t child, struct sbuf *sb)
  217 {
  218         struct mii_attach_args *ma;
  219 
  220         ma = device_get_ivars(child);
  221         sbuf_printf(sb, "oui=0x%x model=0x%x rev=0x%x",
  222             MII_OUI(ma->mii_id1, ma->mii_id2),
  223             MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2));
  224         return (0);
  225 }
  226 
  227 static int
  228 miibus_child_location(device_t dev __unused, device_t child, struct sbuf *sb)
  229 {
  230         struct mii_attach_args *ma;
  231 
  232         ma = device_get_ivars(child);
  233         sbuf_printf(sb, "phyno=%d", ma->mii_phyno);
  234         return (0);
  235 }
  236 
  237 static void
  238 miibus_hinted_child(device_t dev, const char *name, int unit)
  239 {
  240         struct miibus_ivars *ivars;
  241         struct mii_attach_args *args, *ma;
  242         device_t *children, phy;
  243         int i, nchildren;
  244         u_int val;
  245 
  246         if (resource_int_value(name, unit, "phyno", &val) != 0)
  247                 return;
  248         if (device_get_children(dev, &children, &nchildren) != 0)
  249                 return;
  250         ma = NULL;
  251         for (i = 0; i < nchildren; i++) {
  252                 args = device_get_ivars(children[i]);
  253                 if (args->mii_phyno == val) {
  254                         ma = args;
  255                         break;
  256                 }
  257         }
  258         free(children, M_TEMP);
  259 
  260         /*
  261          * Don't add a PHY that was automatically identified by having media
  262          * in its BMSR twice, only allow to alter its attach arguments.
  263          */
  264         if (ma == NULL) {
  265                 ma = malloc(sizeof(struct mii_attach_args), M_DEVBUF,
  266                     M_NOWAIT);
  267                 if (ma == NULL)
  268                         return;
  269                 phy = device_add_child(dev, name, unit);
  270                 if (phy == NULL) {
  271                         free(ma, M_DEVBUF);
  272                         return;
  273                 }
  274                 ivars = device_get_ivars(dev);
  275                 ma->mii_phyno = val;
  276                 ma->mii_offset = ivars->mii_offset++;
  277                 ma->mii_id1 = 0;
  278                 ma->mii_id2 = 0;
  279                 ma->mii_capmask = BMSR_DEFCAPMASK;
  280                 device_set_ivars(phy, ma);
  281         }
  282 
  283         if (resource_int_value(name, unit, "id1", &val) == 0)
  284                 ma->mii_id1 = val;
  285         if (resource_int_value(name, unit, "id2", &val) == 0)
  286                 ma->mii_id2 = val;
  287         if (resource_int_value(name, unit, "capmask", &val) == 0)
  288                 ma->mii_capmask = val;
  289 }
  290 
  291 static int
  292 miibus_readreg(device_t dev, int phy, int reg)
  293 {
  294         device_t                parent;
  295 
  296         parent = device_get_parent(dev);
  297         return (MIIBUS_READREG(parent, phy, reg));
  298 }
  299 
  300 static int
  301 miibus_writereg(device_t dev, int phy, int reg, int data)
  302 {
  303         device_t                parent;
  304 
  305         parent = device_get_parent(dev);
  306         return (MIIBUS_WRITEREG(parent, phy, reg, data));
  307 }
  308 
  309 static void
  310 miibus_statchg(device_t dev)
  311 {
  312         device_t                parent;
  313         struct mii_data         *mii;
  314 
  315         parent = device_get_parent(dev);
  316         MIIBUS_STATCHG(parent);
  317 
  318         mii = device_get_softc(dev);
  319         if_setbaudrate(mii->mii_ifp, ifmedia_baudrate(mii->mii_media_active));
  320 }
  321 
  322 static void
  323 miibus_linkchg(device_t dev)
  324 {
  325         struct mii_data         *mii;
  326         device_t                parent;
  327         int                     link_state;
  328 
  329         parent = device_get_parent(dev);
  330         MIIBUS_LINKCHG(parent);
  331 
  332         mii = device_get_softc(dev);
  333 
  334         if (mii->mii_media_status & IFM_AVALID) {
  335                 if (mii->mii_media_status & IFM_ACTIVE)
  336                         link_state = LINK_STATE_UP;
  337                 else
  338                         link_state = LINK_STATE_DOWN;
  339         } else
  340                 link_state = LINK_STATE_UNKNOWN;
  341         if_link_state_change(mii->mii_ifp, link_state);
  342 }
  343 
  344 static void
  345 miibus_mediainit(device_t dev)
  346 {
  347         struct mii_data         *mii;
  348         struct ifmedia_entry    *m;
  349         int                     media = 0;
  350 
  351         /* Poke the parent in case it has any media of its own to add. */
  352         MIIBUS_MEDIAINIT(device_get_parent(dev));
  353 
  354         mii = device_get_softc(dev);
  355         LIST_FOREACH(m, &mii->mii_media.ifm_list, ifm_list) {
  356                 media = m->ifm_media;
  357                 if (media == (IFM_ETHER | IFM_AUTO))
  358                         break;
  359         }
  360 
  361         ifmedia_set(&mii->mii_media, media);
  362 }
  363 
  364 /*
  365  * Helper function used by network interface drivers, attaches the miibus and
  366  * the PHYs to the network interface driver parent.
  367  */
  368 int
  369 mii_attach(device_t dev, device_t *miibus, if_t ifp,
  370     ifm_change_cb_t ifmedia_upd, ifm_stat_cb_t ifmedia_sts, int capmask,
  371     int phyloc, int offloc, int flags)
  372 {
  373         struct miibus_ivars *ivars;
  374         struct mii_attach_args *args, ma;
  375         device_t *children, phy;
  376         int bmsr, first, i, nchildren, phymax, phymin, rv;
  377         uint32_t phymask;
  378 
  379         bus_topo_assert();
  380 
  381         if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY) {
  382                 printf("%s: phyloc and offloc specified\n", __func__);
  383                 return (EINVAL);
  384         }
  385 
  386         if (offloc != MII_OFFSET_ANY && (offloc < 0 || offloc >= MII_NPHY)) {
  387                 printf("%s: invalid offloc %d\n", __func__, offloc);
  388                 return (EINVAL);
  389         }
  390 
  391         if (phyloc == MII_PHY_ANY) {
  392                 phymin = 0;
  393                 phymax = MII_NPHY - 1;
  394         } else {
  395                 if (phyloc < 0 || phyloc >= MII_NPHY) {
  396                         printf("%s: invalid phyloc %d\n", __func__, phyloc);
  397                         return (EINVAL);
  398                 }
  399                 phymin = phymax = phyloc;
  400         }
  401 
  402         first = 0;
  403         if (*miibus == NULL) {
  404                 first = 1;
  405                 ivars = malloc(sizeof(*ivars), M_DEVBUF, M_NOWAIT);
  406                 if (ivars == NULL)
  407                         return (ENOMEM);
  408                 ivars->ifp = ifp;
  409                 ivars->ifmedia_upd = ifmedia_upd;
  410                 ivars->ifmedia_sts = ifmedia_sts;
  411                 ivars->mii_flags = flags;
  412                 *miibus = device_add_child(dev, "miibus", -1);
  413                 if (*miibus == NULL) {
  414                         rv = ENXIO;
  415                         goto fail;
  416                 }
  417                 device_set_ivars(*miibus, ivars);
  418         } else {
  419                 ivars = device_get_ivars(*miibus);
  420                 if (ivars->ifp != ifp || ivars->ifmedia_upd != ifmedia_upd ||
  421                     ivars->ifmedia_sts != ifmedia_sts ||
  422                     ivars->mii_flags != flags) {
  423                         printf("%s: non-matching invariant\n", __func__);
  424                         return (EINVAL);
  425                 }
  426                 /*
  427                  * Assignment of the attach arguments mii_data for the first
  428                  * pass is done in miibus_attach(), i.e. once the miibus softc
  429                  * has been allocated.
  430                  */
  431                 ma.mii_data = device_get_softc(*miibus);
  432         }
  433 
  434         ma.mii_capmask = capmask;
  435 
  436         if (resource_int_value(device_get_name(*miibus),
  437             device_get_unit(*miibus), "phymask", &phymask) != 0)
  438                 phymask = 0xffffffff;
  439 
  440         if (device_get_children(*miibus, &children, &nchildren) != 0) {
  441                 children = NULL;
  442                 nchildren = 0;
  443         }
  444         ivars->mii_offset = 0;
  445         for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) {
  446                 /*
  447                  * Make sure we haven't already configured a PHY at this
  448                  * address.  This allows mii_attach() to be called
  449                  * multiple times.
  450                  */
  451                 for (i = 0; i < nchildren; i++) {
  452                         args = device_get_ivars(children[i]);
  453                         if (args->mii_phyno == ma.mii_phyno) {
  454                                 /*
  455                                  * Yes, there is already something
  456                                  * configured at this address.
  457                                  */
  458                                 goto skip;
  459                         }
  460                 }
  461 
  462                 /*
  463                  * Check to see if there is a PHY at this address.  Note,
  464                  * many braindead PHYs report 0/0 in their ID registers,
  465                  * so we test for media in the BMSR.
  466                  */
  467                 bmsr = MIIBUS_READREG(dev, ma.mii_phyno, MII_BMSR);
  468                 if (bmsr == 0 || bmsr == 0xffff ||
  469                     (bmsr & (BMSR_EXTSTAT | BMSR_MEDIAMASK)) == 0) {
  470                         /* Assume no PHY at this address. */
  471                         continue;
  472                 }
  473 
  474                 /*
  475                  * There is a PHY at this address.  If we were given an
  476                  * `offset' locator, skip this PHY if it doesn't match.
  477                  */
  478                 if (offloc != MII_OFFSET_ANY && offloc != ivars->mii_offset)
  479                         goto skip;
  480 
  481                 /*
  482                  * Skip this PHY if it's not included in the phymask hint.
  483                  */
  484                 if ((phymask & (1 << ma.mii_phyno)) == 0)
  485                         goto skip;
  486 
  487                 /*
  488                  * Extract the IDs.  Braindead PHYs will be handled by
  489                  * the `ukphy' driver, as we have no ID information to
  490                  * match on.
  491                  */
  492                 ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1);
  493                 ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2);
  494 
  495                 ma.mii_offset = ivars->mii_offset;
  496                 args = malloc(sizeof(struct mii_attach_args), M_DEVBUF,
  497                     M_NOWAIT);
  498                 if (args == NULL)
  499                         goto skip;
  500                 bcopy((char *)&ma, (char *)args, sizeof(ma));
  501                 phy = device_add_child(*miibus, NULL, -1);
  502                 if (phy == NULL) {
  503                         free(args, M_DEVBUF);
  504                         goto skip;
  505                 }
  506                 device_set_ivars(phy, args);
  507  skip:
  508                 ivars->mii_offset++;
  509         }
  510         free(children, M_TEMP);
  511 
  512         if (first != 0) {
  513                 rv = device_set_driver(*miibus, &miibus_driver);
  514                 if (rv != 0)
  515                         goto fail;
  516                 bus_enumerate_hinted_children(*miibus);
  517                 rv = device_get_children(*miibus, &children, &nchildren);
  518                 if (rv != 0)
  519                         goto fail;
  520                 free(children, M_TEMP);
  521                 if (nchildren == 0) {
  522                         rv = ENXIO;
  523                         goto fail;
  524                 }
  525                 rv = bus_generic_attach(dev);
  526                 if (rv != 0)
  527                         goto fail;
  528 
  529                 /* Attaching of the PHY drivers is done in miibus_attach(). */
  530                 return (0);
  531         }
  532         rv = bus_generic_attach(*miibus);
  533         if (rv != 0)
  534                 goto fail;
  535 
  536         return (0);
  537 
  538  fail:
  539         if (*miibus != NULL)
  540                 device_delete_child(dev, *miibus);
  541         free(ivars, M_DEVBUF);
  542         if (first != 0)
  543                 *miibus = NULL;
  544         return (rv);
  545 }
  546 
  547 /*
  548  * Media changed; notify all PHYs.
  549  */
  550 int
  551 mii_mediachg(struct mii_data *mii)
  552 {
  553         struct mii_softc *child;
  554         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  555         int rv;
  556 
  557         mii->mii_media_status = 0;
  558         mii->mii_media_active = IFM_NONE;
  559 
  560         LIST_FOREACH(child, &mii->mii_phys, mii_list) {
  561                 /*
  562                  * If the media indicates a different PHY instance,
  563                  * isolate this one.
  564                  */
  565                 if (IFM_INST(ife->ifm_media) != child->mii_inst) {
  566                         if ((child->mii_flags & MIIF_NOISOLATE) != 0) {
  567                                 device_printf(child->mii_dev, "%s: "
  568                                     "can't handle non-zero PHY instance %d\n",
  569                                     __func__, child->mii_inst);
  570                                 continue;
  571                         }
  572                         PHY_WRITE(child, MII_BMCR, PHY_READ(child, MII_BMCR) |
  573                             BMCR_ISO);
  574                         continue;
  575                 }
  576                 rv = PHY_SERVICE(child, mii, MII_MEDIACHG);
  577                 if (rv)
  578                         return (rv);
  579         }
  580         return (0);
  581 }
  582 
  583 /*
  584  * Call the PHY tick routines, used during autonegotiation.
  585  */
  586 void
  587 mii_tick(struct mii_data *mii)
  588 {
  589         struct mii_softc *child;
  590         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  591 
  592         LIST_FOREACH(child, &mii->mii_phys, mii_list) {
  593                 /*
  594                  * If this PHY instance isn't currently selected, just skip
  595                  * it.
  596                  */
  597                 if (IFM_INST(ife->ifm_media) != child->mii_inst)
  598                         continue;
  599                 (void)PHY_SERVICE(child, mii, MII_TICK);
  600         }
  601 }
  602 
  603 /*
  604  * Get media status from PHYs.
  605  */
  606 void
  607 mii_pollstat(struct mii_data *mii)
  608 {
  609         struct mii_softc *child;
  610         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  611 
  612         mii->mii_media_status = 0;
  613         mii->mii_media_active = IFM_NONE;
  614 
  615         LIST_FOREACH(child, &mii->mii_phys, mii_list) {
  616                 /*
  617                  * If we're not polling this PHY instance, just skip it.
  618                  */
  619                 if (IFM_INST(ife->ifm_media) != child->mii_inst)
  620                         continue;
  621                 (void)PHY_SERVICE(child, mii, MII_POLLSTAT);
  622         }
  623 }
  624 
  625 static unsigned char
  626 mii_bitreverse(unsigned char x)
  627 {
  628         static unsigned const char nibbletab[16] = {
  629                 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
  630         };
  631 
  632         return ((nibbletab[x & 15] << 4) | nibbletab[x >> 4]);
  633 }
  634 
  635 u_int
  636 mii_oui(u_int id1, u_int id2)
  637 {
  638         u_int h;
  639 
  640         h = (id1 << 6) | (id2 >> 10);
  641 
  642         return ((mii_bitreverse(h >> 16) << 16) |
  643             (mii_bitreverse((h >> 8) & 0xff) << 8) |
  644             mii_bitreverse(h & 0xff));
  645 }
  646 
  647 int
  648 mii_phy_mac_match(struct mii_softc *mii, const char *name)
  649 {
  650 
  651         return (strcmp(device_get_name(device_get_parent(mii->mii_dev)),
  652             name) == 0);
  653 }
  654 
  655 int
  656 mii_dev_mac_match(device_t parent, const char *name)
  657 {
  658 
  659         return (strcmp(device_get_name(device_get_parent(
  660             device_get_parent(parent))), name) == 0);
  661 }
  662 
  663 void *
  664 mii_phy_mac_softc(struct mii_softc *mii)
  665 {
  666 
  667         return (device_get_softc(device_get_parent(mii->mii_dev)));
  668 }
  669 
  670 void *
  671 mii_dev_mac_softc(device_t parent)
  672 {
  673 
  674         return (device_get_softc(device_get_parent(device_get_parent(parent))));
  675 }

Cache object: a207bc1e642485e3bdeef38ba6a0fded


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.