From 2c5906a576d4c24efce18742049bd6eb85e0c46d Mon Sep 17 00:00:00 2001 From: Bernd Eckenfels Date: Wed, 27 Sep 2006 20:59:18 +0000 Subject: [PATCH] GigE Support by Stephen Hemminger from http://developer.osdl.org/shemminger/prototypes/mii-tool.tar.bz2 with verbose register patch from Dean Gaudet --- include/mii.h | 14 +++++++ mii-tool.c | 116 +++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 93 insertions(+), 37 deletions(-) diff --git a/include/mii.h b/include/mii.h index 71e0f9d..8a26226 100644 --- a/include/mii.h +++ b/include/mii.h @@ -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 */ diff --git a/mii-tool.c b/mii-tool.c index 1d18fff..d812e8a 100644 --- a/mii-tool.c +++ b/mii-tool.c @@ -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 #include @@ -45,6 +45,8 @@ static char version[] = "$Id: mii-tool.c,v 1.8 2004/06/03 22:18:26 ecki Exp $\n( #include #include #include +#include + #ifndef __GLIBC__ #include #include @@ -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< 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); -- 2.7.4