Sync with upstream CVS, complete log:

Revision 1.9 - Wed Sep 27 20:59:18 2006 UTC by ecki

GigE Support by Stephen Hemminger from
http://developer.osdl.org/shemminger/prototypes/mii-tool.tar.bz2
with verbose register patch from Dean Gaudet

Revision 1.8 - Thu Jun 3 22:18:26 2004 UTC by ecki

added linebreak to  version signature

Revision 1.7 - Mon Oct 20 22:22:22 2003 UTC by ecki
make sure version string is helpful

Revision 1.6 - Mon Oct 20 22:01:13 2003 UTC by ecki
patch to recognize more hardware without MII support (from Redhat Bug#77882,
notified by Tilmann Bubeck).

Revision 1.5 - Sat Jun 28 03:19:04 2003 UTC by ecki
Use new style MII ioctls only. This will give you a warning, if compiled
with old kernel source tree. It will also not work if compiled with
new source on old kernels. The new ioctls also require root for reading, the
old didnt. This fixes Debian bug #133648. No fallback compatibility
is included for reasons of cleaner source.

Revision 1.4 - Wed May 28 19:41:16 2003 UTC by ecki
make it compile on stricter gcc3.3

Revision 1.3 - Sun Sep 15 00:25:14 2002 UTC by ecki
Implemented the Sean Reifenschneider suggested fflush() to the --watch
function of mii-tool.

Revision 1.2 - Fri Jun 14 01:08:20 2002 UTC by ecki
this fixes segfault on -A "" and -F "" in mii-tool reported in debian
bug #139027

Index: net-tools/mii-tool.c
===================================================================
--- net-tools.orig/mii-tool.c
+++ net-tools/mii-tool.c
@@ -29,8 +29,7 @@
 	http://www.national.com/pf/DP/DP83840.html
 */
 
-static char version[] =
-"mii-tool.c 1.9 2000/04/28 00:56:08 (David Hinds)\n";
+static char Version[] = "$Id: mii-tool.c,v 1.9 2006/09/27 20:59:18 ecki Exp $\n(Author: David Hinds based on Donald Becker's mii-diag)";
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -46,16 +45,19 @@ static char version[] =
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
+#include <linux/sockios.h>
+
 #ifndef __GLIBC__
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #endif
 #include "mii.h"
+#include "version.h"
 
 #define MAX_ETH		8		/* Maximum # of interfaces */
 
 /* Table of known MII's */
-static struct {
+static const struct {
     u_short	id1, id2;
     char	*name;
 } mii_id[] = {
@@ -74,6 +76,9 @@ static struct {
     { 0x0181, 0x4410, "Quality QS6612" },
     { 0x0282, 0x1c50, "SMSC 83C180" },
     { 0x0300, 0xe540, "TDK 78Q2120" },
+    { 0x0141, 0x0c20, "Yukon 88E1011" },
+    { 0x0141, 0x0cc0, "Yukon-EC 88E1111" },
+    { 0x0141, 0x0c90, "Yukon-2 88E1112" },
 };
 #define NMII (sizeof(mii_id)/sizeof(mii_id[0]))
 
@@ -137,40 +142,48 @@ static void mdio_write(int skfd, int loc
 
 const struct {
     char	*name;
-    u_short	value;
+    u_short	value[2];
 } media[] = {
     /* The order through 100baseT4 matches bits in the BMSR */
-    { "10baseT-HD",	MII_AN_10BASET_HD },
-    { "10baseT-FD",	MII_AN_10BASET_FD },
-    { "100baseTx-HD",	MII_AN_100BASETX_HD },
-    { "100baseTx-FD",	MII_AN_100BASETX_FD },
-    { "100baseT4",	MII_AN_100BASET4 },
-    { "100baseTx",	MII_AN_100BASETX_FD | MII_AN_100BASETX_HD },
-    { "10baseT",	MII_AN_10BASET_FD | MII_AN_10BASET_HD },
+    { "10baseT-HD",	{MII_AN_10BASET_HD} },
+    { "10baseT-FD",	{MII_AN_10BASET_FD} },
+    { "100baseTx-HD",	{MII_AN_100BASETX_HD} },
+    { "100baseTx-FD",	{MII_AN_100BASETX_FD} },
+    { "100baseT4",	{MII_AN_100BASET4} },
+    { "100baseTx",	{MII_AN_100BASETX_FD | MII_AN_100BASETX_HD} },
+    { "10baseT",	{MII_AN_10BASET_FD | MII_AN_10BASET_HD} },
+
+    { "1000baseT-HD",	{0, MII_BMCR2_1000HALF} },
+    { "1000baseT-FD",	{0, MII_BMCR2_1000FULL} },
+    { "1000baseT",	{0, MII_BMCR2_1000HALF|MII_BMCR2_1000FULL} },
 };
 #define NMEDIA (sizeof(media)/sizeof(media[0]))
 	
 /* Parse an argument list of media types */
-static int parse_media(char *arg)
+static int parse_media(char *arg, unsigned *bmcr2)
 {
     int mask, i;
     char *s;
     mask = strtoul(arg, &s, 16);
     if ((*arg != '\0') && (*s == '\0')) {
 	if ((mask & MII_AN_ABILITY_MASK) &&
-	    !(mask & ~MII_AN_ABILITY_MASK))
-	    return mask;
+	    !(mask & ~MII_AN_ABILITY_MASK)) {
+		*bmcr2 = 0;
+		return mask;
+	}
 	goto failed;
-    } else {
-	mask = 0;
-	s = strtok(arg, ", ");
-	do {
+    }
+    mask = 0;
+    *bmcr2 = 0;
+    s = strtok(arg, ", ");
+    do {
 	    for (i = 0; i < NMEDIA; i++)
-		if (strcasecmp(media[i].name, s) == 0) break;
+		if (s && strcasecmp(media[i].name, s) == 0) break;
 	    if (i == NMEDIA) goto failed;
-	    mask |= media[i].value;
-	} while ((s = strtok(NULL, ", ")) != NULL);
-    }
+	    mask |= media[i].value[0];
+	    *bmcr2 |= media[i].value[1];
+    } while ((s = strtok(NULL, ", ")) != NULL);
+
     return mask;
 failed:
     fprintf(stderr, "Invalid media specification '%s'.\n", arg);
@@ -179,11 +192,24 @@ failed:
 
 /*--------------------------------------------------------------------*/
 
-static char *media_list(int mask, int best)
+static const char *media_list(unsigned mask, unsigned mask2, int best)
 {
     static char buf[100];
     int i;
     *buf = '\0';
+
+    if (mask & MII_BMCR_SPEED1000) {
+	if (mask2 & MII_BMCR2_1000HALF) {
+	    strcat(buf, " ");
+	    strcat(buf, "1000baseT-HD");
+	    if (best) goto out;
+	}
+	if (mask2 & MII_BMCR2_1000FULL) {
+	    strcat(buf, " ");
+	    strcat(buf, "1000baseT-FD");
+	    if (best) goto out;
+	}
+    }
     mask >>= 5;
     for (i = 4; i >= 0; i--) {
 	if (mask & (1<<i)) {
@@ -192,6 +218,7 @@ static char *media_list(int mask, int be
 	    if (best) break;
 	}
     }
+ out:
     if (mask & (1<<5))
 	strcat(buf, " flow-control");
     return buf;
@@ -201,15 +228,15 @@ int show_basic_mii(int sock, int phy_id)
 {
     char buf[100];
     int i, mii_val[32];
-    int bmcr, bmsr, advert, lkpar;
+    unsigned bmcr, bmsr, advert, lkpar, bmcr2, lpa2;
 
     /* Some bits in the BMSR are latched, but we can't rely on being
        the only reader, so only the current values are meaningful */
     mdio_read(sock, MII_BMSR);
-    for (i = 0; i < ((verbose > 1) ? 32 : 8); i++)
+    for (i = 0; i < ((verbose > 1) ? 32 : MII_BASIC_MAX); i++)
 	mii_val[i] = mdio_read(sock, i);
 
-    if (mii_val[MII_BMCR] == 0xffff) {
+    if (mii_val[MII_BMCR] == 0xffff  || mii_val[MII_BMSR] == 0x0000) {
 	fprintf(stderr, "  No MII transceiver present!.\n");
 	return -1;
     }
@@ -217,6 +244,7 @@ int show_basic_mii(int sock, int phy_id)
     /* Descriptive rename. */
     bmcr = mii_val[MII_BMCR]; bmsr = mii_val[MII_BMSR];
     advert = mii_val[MII_ANAR]; lkpar = mii_val[MII_ANLPAR];
+    bmcr2 = mii_val[MII_CTRL1000]; lpa2 = mii_val[MII_STAT1000];
 
     sprintf(buf, "%s: ", ifr.ifr_name);
     if (bmcr & MII_BMCR_AN_ENA) {
@@ -224,7 +252,7 @@ int show_basic_mii(int sock, int phy_id)
 	    if (advert & lkpar) {
 		strcat(buf, (lkpar & MII_AN_ACK) ?
 		       "negotiated" : "no autonegotiation,");
-		strcat(buf, media_list(advert & lkpar, 1));
+		strcat(buf, media_list(advert & lkpar, bmcr2 & lpa2>>2, 1));
 		strcat(buf, ", ");
 	    } else {
 		strcat(buf, "autonegotiation failed, ");
@@ -234,8 +262,10 @@ int show_basic_mii(int sock, int phy_id)
 	}
     } else {
 	sprintf(buf+strlen(buf), "%s Mbit, %s duplex, ",
-	       (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
-	       (bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
+		((bmcr2 & (MII_BMCR2_1000HALF | MII_BMCR2_1000FULL)) & lpa2 >> 2)
+		? "1000"
+		: (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
+		(bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
     }
     strcat(buf, (bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link");
 
@@ -296,12 +326,13 @@ int show_basic_mii(int sock, int phy_id)
 	if (bmsr & MII_BMSR_REMOTE_FAULT)
 	    printf("remote fault, ");
 	printf((bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link");
-	printf("\n  capabilities:%s", media_list(bmsr >> 6, 0));
-	printf("\n  advertising: %s", media_list(advert, 0));
+	printf("\n  capabilities:%s", media_list(bmsr >> 6, bmcr2, 0));
+	printf("\n  advertising: %s", media_list(advert, lpa2 >> 2, 0));
 	if (lkpar & MII_AN_ABILITY_MASK)
-	    printf("\n  link partner:%s", media_list(lkpar, 0));
+	    printf("\n  link partner:%s", media_list(lkpar, bmcr2, 0));
 	printf("\n");
     }
+    fflush(stdout);
     return 0;
 }
 
@@ -329,7 +360,7 @@ static int do_one_xcvr(int skfd, char *i
 	printf("resetting the transceiver...\n");
 	mdio_write(skfd, MII_BMCR, MII_BMCR_RESET);
     }
-    if (nway_advertise) {
+    if (nway_advertise > 0) {
 	mdio_write(skfd, MII_ANAR, nway_advertise | 1);
 	opt_restart = 1;
     }
@@ -379,27 +410,38 @@ static void watch_one_xcvr(int skfd, cha
 /*--------------------------------------------------------------------*/
 
 const char *usage =
-"usage: %s [-VvRrwl] [-A media,... | -F media] [interface ...]
-       -V, --version               display version information
-       -v, --verbose               more verbose output
-       -R, --reset                 reset MII to poweron state
-       -r, --restart               restart autonegotiation
-       -w, --watch                 monitor for link status changes
-       -l, --log                   with -w, write events to syslog
-       -A, --advertise=media,...   advertise only specified media
-       -F, --force=media           force specified media technology
-media: 100baseT4, 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD,
-       (to advertise both HD and FD) 100baseTx, 10baseT\n";
+"usage: %s [-VvRrwl] [-A media,... | -F media] [interface ...]\n"
+"       -V, --version               display version information\n"
+"       -v, --verbose               more verbose output\n"
+"       -R, --reset                 reset MII to poweron state\n"
+"       -r, --restart               restart autonegotiation\n"
+"       -w, --watch                 monitor for link status changes\n"
+"       -l, --log                   with -w, write events to syslog\n"
+"       -A, --advertise=media,...   advertise only specified media\n"
+"       -F, --force=media           force specified media technology\n"
+"media: 1000baseTx-HD, 1000baseTx-FD,\n"
+"       100baseT4, 100baseTx-FD, 100baseTx-HD,\n"
+"       10baseT-FD, 10baseT-HD,\n"
+"       (to advertise both HD and FD) 1000baseTx, 100baseTx, 10baseT\n";
+
+
+static void version(void)
+{
+    fprintf(stderr, "%s\n%s\n", Version, RELEASE);
+    exit(5); /* E_VERSION */
+}
+
 
 int main(int argc, char **argv)
 {
     int i, c, ret, errflag = 0;
     char s[6];
+    unsigned ctrl1000 = 0;
     
     while ((c = getopt_long(argc, argv, "A:F:p:lrRvVw?", longopts, 0)) != EOF)
 	switch (c) {
-	case 'A': nway_advertise = parse_media(optarg); break;
-	case 'F': fixed_speed = parse_media(optarg); break;
+	case 'A': nway_advertise = parse_media(optarg, &ctrl1000); break;
+	case 'F': fixed_speed = parse_media(optarg, &ctrl1000); break;
 	case 'p': override_phy = atoi(optarg); break;
 	case 'r': opt_restart++;	break;
 	case 'R': opt_reset++;		break;
@@ -411,6 +453,10 @@ int main(int argc, char **argv)
 	}
     /* Check for a few inappropriate option combinations */
     if (opt_watch) verbose = 0;
+
+    if ((nway_advertise < 0) || (fixed_speed < 0))
+    	return 2;
+
     if (errflag || (fixed_speed & (fixed_speed-1)) ||
 	(fixed_speed && (opt_restart || nway_advertise))) {
 	fprintf(stderr, usage, argv[0]);
@@ -418,7 +464,7 @@ int main(int argc, char **argv)
     }
 
     if (opt_version)
-	printf(version);
+	version();
 
     /* Open a basic socket. */
     if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
@@ -426,6 +472,9 @@ int main(int argc, char **argv)
 	exit(-1);
     }
 
+    if (verbose > 1)
+    	printf("Using SIOCGMIIPHY=0x%x\n", SIOCGMIIPHY);	
+
     /* No remaining args means show all interfaces. */
     if (optind == argc) {
 	ret = 1;