GigE Support by Stephen Hemminger from
authorBernd Eckenfels <net-tools@lina.inka.de>
Wed, 27 Sep 2006 20:59:18 +0000 (20:59 +0000)
committerBernd Eckenfels <net-tools@lina.inka.de>
Wed, 27 Sep 2006 20:59:18 +0000 (20:59 +0000)
http://developer.osdl.org/shemminger/prototypes/mii-tool.tar.bz2
with verbose register patch from Dean Gaudet

include/mii.h
mii-tool.c

index 71e0f9d..8a26226 100644 (file)
@@ -41,6 +41,7 @@ struct mii_data {
 #define  MII_BMCR_RESTART      0x0200
 #define  MII_BMCR_DUPLEX       0x0100
 #define  MII_BMCR_COLTEST      0x0080
+#define  MII_BMCR_SPEED1000    0x0040
 
 /* Basic Mode Status Register */
 #define MII_BMSR               0x01
@@ -86,4 +87,17 @@ struct mii_data {
 #define  MII_ANER_PAGE_RX      0x0002
 #define  MII_ANER_LP_AN_ABLE   0x0001
 
+#define MII_CTRL1000           0x09
+#define   MII_BMCR2_1000FULL   0x0200
+#define   MII_BMCR2_1000HALF   0x0100
+
+#define MII_STAT1000           0x0a
+#define   MII_LPA2_1000LOCALOK  0x2000
+#define   MII_LPA2_1000REMRXOK 0x1000
+#define   MII_LPA2_1000FULL    0x0800
+#define   MII_LPA2_1000HALF    0x0400
+
+/* Last register we need for show_basic_mii() */
+#define MII_BASIC_MAX          (MII_STAT1000+1)
+
 #endif /* _NETTOOLS_MII_H */
index 1d18fff..d812e8a 100644 (file)
@@ -29,7 +29,7 @@
        http://www.national.com/pf/DP/DP83840.html
 */
 
-static char version[] = "$Id: mii-tool.c,v 1.8 2004/06/03 22:18:26 ecki Exp $\n(Author: David Hinds based on Donald Becker's mii-diag)";
+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>
@@ -45,6 +45,8 @@ static char version[] = "$Id: mii-tool.c,v 1.8 2004/06/03 22:18:26 ecki Exp $\n(
 #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>
@@ -55,7 +57,7 @@ static char version[] = "$Id: mii-tool.c,v 1.8 2004/06/03 22:18:26 ecki Exp $\n(
 #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 location, int value)
 
 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 (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 best)
            if (best) break;
        }
     }
+ out:
     if (mask & (1<<5))
        strcat(buf, " flow-control");
     return buf;
@@ -201,14 +228,14 @@ 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  || 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,10 +326,10 @@ 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);
@@ -379,7 +409,8 @@ static void watch_one_xcvr(int skfd, char *ifname, int index)
 
 /*--------------------------------------------------------------------*/
 
-const char *usage = "usage: %s [-VvRrwl] [-A media,... | -F media] [interface ...]\n"
+const char *usage =
+"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"
@@ -388,18 +419,29 @@ const char *usage = "usage: %s [-VvRrwl] [-A media,... | -F media] [interface ..
 "       -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: 100baseT4, 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD,\n"
-"       (to advertise both HD and FD) 100baseTx, 10baseT\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;
@@ -422,14 +464,14 @@ int main(int argc, char **argv)
     }
 
     if (opt_version)
-       printf("%s\n%s\n", version, RELEASE);
+       version();
 
     /* Open a basic socket. */
     if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
        perror("socket");
        exit(-1);
     }
-    
+
     if (verbose > 1)
        printf("Using SIOCGMIIPHY=0x%x\n", SIOCGMIIPHY);