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

          Line data    Source code
       1             : /*      $OpenBSD: mii.c,v 1.23 2015/12/29 18:35:39 mmcc Exp $   */
       2             : /*      $NetBSD: mii.c,v 1.19 2000/02/02 17:09:44 thorpej Exp $ */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 1998, 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             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      22             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      23             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      24             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      25             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      26             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      27             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      29             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      30             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      31             :  * POSSIBILITY OF SUCH DAMAGE.
      32             :  */
      33             : 
      34             : /*
      35             :  * MII bus layer, glues MII-capable network interface drivers to sharable
      36             :  * PHY drivers.  This exports an interface compatible with BSD/OS 3.0's,
      37             :  * plus some NetBSD extensions.
      38             :  */
      39             : 
      40             : #include <sys/param.h>
      41             : #include <sys/device.h>
      42             : #include <sys/systm.h>
      43             : #include <sys/socket.h>
      44             : 
      45             : #include <net/if.h>
      46             : #include <net/if_media.h>
      47             : 
      48             : #include <dev/mii/mii.h>
      49             : #include <dev/mii/miivar.h>
      50             : 
      51             : int     mii_print(void *, const char *);
      52             : int     mii_submatch(struct device *, void *, void *);
      53             : 
      54             : #define MIICF_PHY               0       /* cf_loc index */
      55             : #define MIICF_PHY_DEFAULT       (-1)    /* default phy device */
      56             : 
      57             : /*
      58             :  * Helper function used by network interface drivers, attaches PHYs
      59             :  * to the network interface driver parent.
      60             :  */
      61             : void
      62           0 : mii_attach(struct device *parent, struct mii_data *mii, int capmask,
      63             :     int phyloc, int offloc, int flags)
      64             : {
      65           0 :         struct mii_attach_args ma;
      66             :         struct mii_softc *child;
      67             :         int bmsr, offset = 0;
      68             :         int phymin, phymax;
      69             : 
      70           0 :         if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY)
      71           0 :                 panic("mii_attach: phyloc and offloc specified");
      72             : 
      73           0 :         if (phyloc == MII_PHY_ANY) {
      74             :                 phymin = 0;
      75             :                 phymax = MII_NPHY - 1;
      76           0 :         } else
      77             :                 phymin = phymax = phyloc;
      78             : 
      79           0 :         if ((mii->mii_flags & MIIF_INITDONE) == 0) {
      80           0 :                 LIST_INIT(&mii->mii_phys);
      81           0 :                 mii->mii_flags |= MIIF_INITDONE;
      82           0 :         }
      83             : 
      84           0 :         for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) {
      85             :                 /*
      86             :                  * Make sure we haven't already configured a PHY at this
      87             :                  * address.  This allows mii_attach() to be called
      88             :                  * multiple times.
      89             :                  */
      90           0 :                 for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
      91           0 :                      child = LIST_NEXT(child, mii_list)) {
      92           0 :                         if (child->mii_phy == ma.mii_phyno) {
      93             :                                 /*
      94             :                                  * Yes, there is already something
      95             :                                  * configured at this address.
      96             :                                  */
      97           0 :                                 offset++;
      98           0 :                                 goto loop_end;
      99             :                         }
     100             :                 }
     101             : 
     102             :                 /*
     103             :                  * Check to see if there is a PHY at this address.  Note,
     104             :                  * many braindead PHYs report 0/0 in their ID registers,
     105             :                  * so we test for media in the BMSR.
     106             :                  */
     107           0 :                 bmsr = (*mii->mii_readreg)(parent, ma.mii_phyno, MII_BMSR);
     108           0 :                 if (bmsr == 0 || bmsr == 0xffff ||
     109           0 :                     (bmsr & (BMSR_MEDIAMASK|BMSR_EXTSTAT)) == 0) {
     110             :                         /* Assume no PHY at this address. */
     111             :                         goto loop_end;
     112             :                 }
     113             : 
     114             :                 /*
     115             :                  * There is a PHY at this address.  If we were given an
     116             :                  * `offset' locator, skip this PHY if it doesn't match.
     117             :                  */
     118           0 :                 if (offloc != MII_OFFSET_ANY && offloc != offset) {
     119           0 :                         offset++;
     120           0 :                         goto loop_end;
     121             :                 }
     122             : 
     123             :                 /*
     124             :                  * Extract the IDs.  Braindead PHYs will be handled by
     125             :                  * the `ukphy' driver, as we have no ID information to
     126             :                  * match on.
     127             :                  */
     128           0 :                 ma.mii_id1 = (*mii->mii_readreg)(parent, ma.mii_phyno,
     129             :                     MII_PHYIDR1);
     130           0 :                 ma.mii_id2 = (*mii->mii_readreg)(parent, ma.mii_phyno,
     131             :                     MII_PHYIDR2);
     132             : 
     133           0 :                 ma.mii_data = mii;
     134           0 :                 ma.mii_capmask = capmask;
     135           0 :                 ma.mii_flags = flags | (mii->mii_flags & MIIF_INHERIT_MASK);
     136             : 
     137           0 :                 if ((child = (struct mii_softc *)config_found_sm(parent, &ma,
     138           0 :                     mii_print, mii_submatch)) != NULL) {
     139             :                         /*
     140             :                          * Link it up in the parent's MII data.
     141             :                          */
     142           0 :                         LIST_INSERT_HEAD(&mii->mii_phys, child, mii_list);
     143           0 :                         child->mii_offset = offset;
     144           0 :                         mii->mii_instance++;
     145           0 :                 }
     146           0 :                 offset++;
     147             : 
     148             : loop_end:       ;
     149             :         }
     150           0 : }
     151             : 
     152             : void
     153           0 : mii_detach(struct mii_data *mii, int phyloc, int offloc)
     154             : {
     155             :         struct mii_softc *child, *nchild;
     156             : 
     157           0 :         if (phyloc != MII_PHY_ANY && offloc != MII_PHY_ANY)
     158           0 :                 panic("mii_detach: phyloc and offloc specified");
     159             : 
     160           0 :         if ((mii->mii_flags & MIIF_INITDONE) == 0)
     161           0 :                 return;
     162             : 
     163           0 :         for (child = LIST_FIRST(&mii->mii_phys);
     164           0 :              child != NULL; child = nchild) {
     165           0 :                 nchild = LIST_NEXT(child, mii_list);
     166           0 :                 if (phyloc != MII_PHY_ANY || offloc != MII_OFFSET_ANY) {
     167           0 :                         if (phyloc != MII_PHY_ANY &&
     168           0 :                             phyloc != child->mii_phy)
     169             :                                 continue;
     170           0 :                         if (offloc != MII_OFFSET_ANY &&
     171           0 :                             offloc != child->mii_offset)
     172             :                                 continue;
     173             :                 }
     174           0 :                 LIST_REMOVE(child, mii_list);
     175           0 :                 (void) config_detach(&child->mii_dev, DETACH_FORCE);
     176           0 :         }
     177           0 : }
     178             : 
     179             : int
     180           0 : mii_print(void *aux, const char *pnp)
     181             : {
     182           0 :         struct mii_attach_args *ma = aux;
     183             : 
     184           0 :         if (pnp != NULL)
     185           0 :                 printf("OUI 0x%06x model 0x%04x rev %d at %s",
     186           0 :                     MII_OUI(ma->mii_id1, ma->mii_id2), MII_MODEL(ma->mii_id2),
     187           0 :                     MII_REV(ma->mii_id2), pnp);
     188             : 
     189           0 :         printf(" phy %d", ma->mii_phyno);
     190           0 :         return (UNCONF);
     191             : }
     192             : 
     193             : int
     194           0 : mii_submatch(struct device *parent, void *match, void *aux)
     195             : {
     196           0 :         struct cfdata *cf = match;
     197           0 :         struct mii_attach_args *ma = aux;
     198             : 
     199           0 :         if (ma->mii_phyno != cf->cf_loc[MIICF_PHY] &&
     200           0 :             cf->cf_loc[MIICF_PHY] != MIICF_PHY_DEFAULT)
     201           0 :                 return (0);
     202             : 
     203           0 :         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
     204           0 : }
     205             : 
     206             : /*
     207             :  * Media changed; notify all PHYs.
     208             :  */
     209             : int
     210           0 : mii_mediachg(struct mii_data *mii)
     211             : {
     212             :         struct mii_softc *child;
     213             :         int rv;
     214             : 
     215           0 :         mii->mii_media_status = 0;
     216           0 :         mii->mii_media_active = IFM_NONE;
     217             : 
     218           0 :         for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
     219           0 :              child = LIST_NEXT(child, mii_list)) {
     220           0 :                 rv = PHY_SERVICE(child, mii, MII_MEDIACHG);
     221           0 :                 if (rv)
     222           0 :                         return (rv);
     223             :         }
     224           0 :         return (0);
     225           0 : }
     226             : 
     227             : /*
     228             :  * Call the PHY tick routines, used during autonegotiation.
     229             :  */
     230             : void
     231           0 : mii_tick(struct mii_data *mii)
     232             : {
     233             :         struct mii_softc *child;
     234             : 
     235           0 :         for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
     236           0 :              child = LIST_NEXT(child, mii_list))
     237           0 :                 (void) PHY_SERVICE(child, mii, MII_TICK);
     238           0 : }
     239             : 
     240             : /*
     241             :  * Get media status from PHYs.
     242             :  */
     243             : void
     244           0 : mii_pollstat(struct mii_data *mii)
     245             : {
     246             :         struct mii_softc *child;
     247             : 
     248           0 :         mii->mii_media_status = 0;
     249           0 :         mii->mii_media_active = IFM_NONE;
     250             : 
     251           0 :         for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
     252           0 :              child = LIST_NEXT(child, mii_list))
     253           0 :                 (void) PHY_SERVICE(child, mii, MII_POLLSTAT);
     254           0 : }
     255             : 
     256             : /*
     257             :  * Inform the PHYs that the interface is down.
     258             :  */
     259             : void
     260           0 : mii_down(struct mii_data *mii)
     261             : {
     262             :         struct mii_softc *child;
     263             : 
     264           0 :         for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
     265           0 :              child = LIST_NEXT(child, mii_list))
     266           0 :                 (void) PHY_SERVICE(child, mii, MII_DOWN);
     267           0 : }

Generated by: LCOV version 1.13