mii.c

Go to the documentation of this file.
00001 /*
00002 
00003         mii.c: MII interface library
00004 
00005         Ported to gPXE by Daniel Verkamp <daniel@drv.nu>
00006         from Linux drivers/net/mii.c
00007 
00008         Maintained by Jeff Garzik <jgarzik@pobox.com>
00009         Copyright 2001,2002 Jeff Garzik
00010 
00011         Various code came from myson803.c and other files by
00012         Donald Becker.  Copyright:
00013 
00014                 Written 1998-2002 by Donald Becker.
00015 
00016                 This software may be used and distributed according
00017                 to the terms of the GNU General Public License (GPL),
00018                 incorporated herein by reference.  Drivers based on
00019                 or derived from this code fall under the GPL and must
00020                 retain the authorship, copyright and license notice.
00021                 This file is not a complete program and may only be
00022                 used when the entire operating system is licensed
00023                 under the GPL.
00024 
00025                 The author may be reached as becker@scyld.com, or C/O
00026                 Scyld Computing Corporation
00027                 410 Severn Ave., Suite 210
00028                 Annapolis MD 21403
00029 
00030 */
00031 
00032 #include <mii.h>
00033 
00034 /**
00035  * mii_link_ok - is link status up/ok
00036  * @mii: the MII interface
00037  *
00038  * Returns 1 if the MII reports link status up/ok, 0 otherwise.
00039  */
00040 int
00041 mii_link_ok ( struct mii_if_info *mii )
00042 {
00043         /* first, a dummy read, needed to latch some MII phys */
00044         mii->mdio_read ( mii->dev, mii->phy_id, MII_BMSR );
00045         if ( mii->mdio_read ( mii->dev, mii->phy_id, MII_BMSR ) & BMSR_LSTATUS )
00046                 return 1;
00047         return 0;
00048 }
00049 
00050 /**
00051  * mii_check_link - check MII link status
00052  * @mii: MII interface
00053  *
00054  * If the link status changed (previous != current), call
00055  * netif_carrier_on() if current link status is Up or call
00056  * netif_carrier_off() if current link status is Down.
00057  */
00058 void
00059 mii_check_link ( struct mii_if_info *mii )
00060 {
00061         int cur_link = mii_link_ok ( mii );
00062         int prev_link = netdev_link_ok ( mii->dev );
00063 
00064         if ( cur_link && !prev_link )
00065                 netdev_link_up ( mii->dev );
00066         else if (prev_link && !cur_link)
00067                 netdev_link_down ( mii->dev );
00068 }
00069 
00070 
00071 /**
00072  * mii_check_media - check the MII interface for a duplex change
00073  * @mii: the MII interface
00074  * @ok_to_print: OK to print link up/down messages
00075  * @init_media: OK to save duplex mode in @mii
00076  *
00077  * Returns 1 if the duplex mode changed, 0 if not.
00078  * If the media type is forced, always returns 0.
00079  */
00080 unsigned int
00081 mii_check_media ( struct mii_if_info *mii,
00082                   unsigned int ok_to_print,
00083                   unsigned int init_media )
00084 {
00085         unsigned int old_carrier, new_carrier;
00086         int advertise, lpa, media, duplex;
00087         int lpa2 = 0;
00088 
00089         /* if forced media, go no further */
00090         if (mii->force_media)
00091                 return 0; /* duplex did not change */
00092 
00093         /* check current and old link status */
00094         old_carrier = netdev_link_ok ( mii->dev ) ? 1 : 0;
00095         new_carrier = (unsigned int) mii_link_ok ( mii );
00096 
00097         /* if carrier state did not change, this is a "bounce",
00098          * just exit as everything is already set correctly
00099          */
00100         if ( ( ! init_media ) && ( old_carrier == new_carrier ) )
00101                 return 0; /* duplex did not change */
00102 
00103         /* no carrier, nothing much to do */
00104         if ( ! new_carrier ) {
00105                 netdev_link_down ( mii->dev );
00106                 if ( ok_to_print )
00107                         DBG ( "%s: link down\n", mii->dev->name);
00108                 return 0; /* duplex did not change */
00109         }
00110 
00111         /*
00112          * we have carrier, see who's on the other end
00113          */
00114         netdev_link_up ( mii->dev );
00115 
00116         /* get MII advertise and LPA values */
00117         if ( ( ! init_media ) && ( mii->advertising ) ) {
00118                 advertise = mii->advertising;
00119         } else {
00120                 advertise = mii->mdio_read ( mii->dev, mii->phy_id, MII_ADVERTISE );
00121                 mii->advertising = advertise;
00122         }
00123         lpa = mii->mdio_read ( mii->dev, mii->phy_id, MII_LPA );
00124         if ( mii->supports_gmii )
00125                 lpa2 = mii->mdio_read ( mii->dev, mii->phy_id, MII_STAT1000 );
00126 
00127         /* figure out media and duplex from advertise and LPA values */
00128         media = mii_nway_result ( lpa & advertise );
00129         duplex = ( media & ADVERTISE_FULL ) ? 1 : 0;
00130         if ( lpa2 & LPA_1000FULL )
00131                 duplex = 1;
00132 
00133         if ( ok_to_print )
00134                 DBG ( "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
00135                        mii->dev->name,
00136                        lpa2 & ( LPA_1000FULL | LPA_1000HALF ) ? "1000" :
00137                        media & ( ADVERTISE_100FULL | ADVERTISE_100HALF ) ? "100" : "10",
00138                        duplex ? "full" : "half",
00139                        lpa);
00140 
00141         if ( ( init_media ) || ( mii->full_duplex != duplex ) ) {
00142                 mii->full_duplex = duplex;
00143                 return 1; /* duplex changed */
00144         }
00145 
00146         return 0; /* duplex did not change */
00147 }

Generated on Tue Apr 6 20:01:10 2010 for gPXE by  doxygen 1.5.7.1