diff -up net-tools-1.60/mii-tool.c.mii-gigabit net-tools-1.60/mii-tool.c --- net-tools-1.60/mii-tool.c.mii-gigabit 2010-06-14 15:51:23.000000000 +0200 +++ net-tools-1.60/mii-tool.c 2010-06-14 16:10:34.000000000 +0200 @@ -57,7 +57,7 @@ static char version[] = #define LPA_ABILITY_MASK 0x07e0 /* Table of known MII's */ -static struct { +static const struct { u_short id1, id2; char *name; } mii_id[] = { @@ -76,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])) @@ -139,40 +142,47 @@ 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", LPA_10HALF }, - { "10baseT-FD", LPA_10FULL }, - { "100baseTx-HD", LPA_100HALF }, - { "100baseTx-FD", LPA_100FULL }, - { "100baseT4", LPA_100BASE4 }, - { "100baseTx", LPA_100FULL | LPA_100HALF }, - { "10baseT", LPA_10FULL | LPA_10HALF }, + { "10baseT-HD", {LPA_10HALF} }, + { "10baseT-FD", {LPA_10FULL} }, + { "100baseTx-HD", {LPA_100HALF} }, + { "100baseTx-FD", {LPA_100FULL} }, + { "100baseT4", {LPA_100BASE4} }, + { "100baseTx", {LPA_100FULL | LPA_100HALF} }, + { "10baseT", {LPA_10FULL | LPA_10HALF} }, + { "1000baseT-HD", {0, ADVERTISE_1000HALF} }, + { "1000baseT-FD", {0, ADVERTISE_1000FULL} }, + { "1000baseT", {0, ADVERTISE_1000HALF|ADVERTISE_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 & LPA_ABILITY_MASK) && - !(mask & ~LPA_ABILITY_MASK)) - return mask; - goto failed; - } else { - mask = 0; - s = strtok(arg, ", "); - do { - for (i = 0; i < NMEDIA; i++) - if (strcasecmp(media[i].name, s) == 0) break; - if (i == NMEDIA) goto failed; - mask |= media[i].value; - } while ((s = strtok(NULL, ", ")) != NULL); - } + if ((mask & LPA_ABILITY_MASK) && + !(mask & ~LPA_ABILITY_MASK)) { + *bmcr2 = 0; + return mask; + } + goto failed; + } + 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[0]; + *bmcr2 |= media[i].value[1]; + } while ((s = strtok(NULL, ", ")) != NULL); + return mask; failed: fprintf(stderr, "Invalid media specification '%s'.\n", arg); @@ -181,11 +191,25 @@ 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 & BMCR_SPEED1000) { + if (mask2 & ADVERTISE_1000HALF) { + strcat(buf, " "); + strcat(buf, "1000baseT-HD"); + if (best) goto out; + } + if (mask2 & ADVERTISE_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_STAT1000+1)); i++) { if ((i == MII_BMCR) || (i == MII_BMSR) || (i == MII_PHYSID1) || (i == MII_PHYSID2) || (i == MII_ADVERTISE) || (i == MII_LPA) || (i == MII_EXPANSION) || (i == MII_CTRL1000) || (i == MII_STAT1000) || @@ -220,7 +245,7 @@ int show_basic_mii(int sock, int phy_id) else mii_val[i] = 0; } - 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; } @@ -228,6 +253,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_ADVERTISE]; lkpar = mii_val[MII_LPA]; + bmcr2 = mii_val[MII_CTRL1000]; lpa2 = mii_val[MII_STAT1000]; sprintf(buf, "%s: ", ifr.ifr_name); if (bmcr & BMCR_ANENABLE) { @@ -235,7 +261,7 @@ int show_basic_mii(int sock, int phy_id) if (advert & lkpar) { strcat(buf, (lkpar & LPA_LPACK) ? "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, "); @@ -245,8 +271,10 @@ int show_basic_mii(int sock, int phy_id) } } else { sprintf(buf+strlen(buf), "%s Mbit, %s duplex, ", - (bmcr & BMCR_SPEED100) ? "100" : "10", - (bmcr & BMCR_FULLDPLX) ? "full" : "half"); + ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) & lpa2 >> 2) + ? "1000" + : (bmcr & BMCR_SPEED100) ? "100" : "10", + (bmcr & BMCR_FULLDPLX) ? "full" : "half"); } strcat(buf, (bmsr & BMSR_LSTATUS) ? "link ok" : "no link"); @@ -307,10 +335,10 @@ int show_basic_mii(int sock, int phy_id) if (bmsr & BMSR_RFAULT) printf("remote fault, "); printf((bmsr & BMSR_LSTATUS) ? "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 & LPA_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); @@ -341,7 +369,7 @@ static int do_one_xcvr(int skfd, char *i printf("resetting the transceiver...\n"); mdio_write(skfd, MII_BMCR, BMCR_RESET); } - if (nway_advertise) { + if (nway_advertise > 0) { mdio_write(skfd, MII_ADVERTISE, nway_advertise | 1); opt_restart = 1; } @@ -400,18 +428,20 @@ usage: %s [-VvRrwl] [-A media,... | -F m -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\ +media: 1000baseTx-HD, 1000baseTx-FD,\n\ + 100baseT4, 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD,\n\ (to advertise both HD and FD) 100baseTx, 10baseT\n"; 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; @@ -423,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]);