diff options
author | Jiri Popelka <jpopelka@redhat.com> | 2012-01-05 14:53:49 +0100 |
---|---|---|
committer | Jiri Popelka <jpopelka@redhat.com> | 2012-01-05 14:53:49 +0100 |
commit | faf31f80deba7c27040f925a4ad194d76197cd1c (patch) | |
tree | 9b9276851a1bd6624bf2e5dfd7e4a7e4b4d87110 | |
parent | 6ccabd574062869c3b1101e64b4e85c86a85ec15 (diff) | |
download | net-tools-faf31f80deba7c27040f925a4ad194d76197cd1c.tar.gz net-tools-faf31f80deba7c27040f925a4ad194d76197cd1c.tar.bz2 net-tools-faf31f80deba7c27040f925a4ad194d76197cd1c.zip |
mii-tool: use <linux/mii.h> instead of "mii.h" and fix RHBZ #491358
Using mii-tool with e1000e driver results in:
SIOCGMIIREG on eth0 failed: Input/output error
Problem is in show_basic_mii() where the loop
for (i = 0; i < ((verbose > 1) ? 32 : MII_BASIC_MAX); i++)
mii_val[i] = mdio_read(sock, i);
checks all MII registers from 0x00 to 0x07 (or to 0x1F in verbose mode).
But there's no register with 0x07 value.
For more details see:
https://bugzilla.redhat.com/show_bug.cgi?id=491358#c1
Solution is to check only defined MII registers.
Also the "mii.h" is actually a duplicate of <linux/mii.h>.
-rw-r--r-- | include/mii.h | 103 | ||||
-rw-r--r-- | mii-tool.c | 132 |
2 files changed, 81 insertions, 154 deletions
diff --git a/include/mii.h b/include/mii.h deleted file mode 100644 index 8a26226..0000000 --- a/include/mii.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * mii.h 1.4 2000/04/25 22:06:15 - * - * Media Independent Interface support: register layout and ioctl's - * - * Copyright (C) 2000 David A. Hinds -- dhinds@pcmcia.sourceforge.org - */ - -#ifndef _NETTOOL_MII_H -#define _NETTOOLS_MII_H - -#include <linux/sockios.h> - -/* network interface ioctl's for MII commands */ -#ifndef SIOCGMIIPHY -#warning "SIOCGMIIPHY is not defined by your kernel source" -#define SIOCGMIIPHY (SIOCDEVPRIVATE) /* Read from current PHY */ -#define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read any PHY register */ -#define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write any PHY register */ -#define SIOCGPARAMS (SIOCDEVPRIVATE+3) /* Read operational parameters */ -#define SIOCSPARAMS (SIOCDEVPRIVATE+4) /* Set operational parameters */ -#endif - -#include <linux/types.h> - -/* This data structure is used for all the MII ioctl's */ -struct mii_data { - __u16 phy_id; - __u16 reg_num; - __u16 val_in; - __u16 val_out; -}; - -/* Basic Mode Control Register */ -#define MII_BMCR 0x00 -#define MII_BMCR_RESET 0x8000 -#define MII_BMCR_LOOPBACK 0x4000 -#define MII_BMCR_100MBIT 0x2000 -#define MII_BMCR_AN_ENA 0x1000 -#define MII_BMCR_ISOLATE 0x0400 -#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 -#define MII_BMSR_CAP_MASK 0xf800 -#define MII_BMSR_100BASET4 0x8000 -#define MII_BMSR_100BASETX_FD 0x4000 -#define MII_BMSR_100BASETX_HD 0x2000 -#define MII_BMSR_10BASET_FD 0x1000 -#define MII_BMSR_10BASET_HD 0x0800 -#define MII_BMSR_NO_PREAMBLE 0x0040 -#define MII_BMSR_AN_COMPLETE 0x0020 -#define MII_BMSR_REMOTE_FAULT 0x0010 -#define MII_BMSR_AN_ABLE 0x0008 -#define MII_BMSR_LINK_VALID 0x0004 -#define MII_BMSR_JABBER 0x0002 -#define MII_BMSR_EXT_CAP 0x0001 - -#define MII_PHY_ID1 0x02 -#define MII_PHY_ID2 0x03 - -/* Auto-Negotiation Advertisement Register */ -#define MII_ANAR 0x04 -/* Auto-Negotiation Link Partner Ability Register */ -#define MII_ANLPAR 0x05 -#define MII_AN_NEXT_PAGE 0x8000 -#define MII_AN_ACK 0x4000 -#define MII_AN_REMOTE_FAULT 0x2000 -#define MII_AN_ABILITY_MASK 0x07e0 -#define MII_AN_FLOW_CONTROL 0x0400 -#define MII_AN_100BASET4 0x0200 -#define MII_AN_100BASETX_FD 0x0100 -#define MII_AN_100BASETX_HD 0x0080 -#define MII_AN_10BASET_FD 0x0040 -#define MII_AN_10BASET_HD 0x0020 -#define MII_AN_PROT_MASK 0x001f -#define MII_AN_PROT_802_3 0x0001 - -/* Auto-Negotiation Expansion Register */ -#define MII_ANER 0x06 -#define MII_ANER_MULT_FAULT 0x0010 -#define MII_ANER_LP_NP_ABLE 0x0008 -#define MII_ANER_NP_ABLE 0x0004 -#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 */ @@ -51,10 +51,12 @@ static char Version[] = "$Id: mii-tool.c,v 1.9 2006/09/27 20:59:18 ecki Exp $\n( #include <linux/if_arp.h> #include <linux/if_ether.h> #endif -#include "mii.h" +#include <linux/mii.h> +#include <linux/sockios.h> #include "version.h" #define MAX_ETH 8 /* Maximum # of interfaces */ +#define LPA_ABILITY_MASK 0x07e0 /* Table of known MII's */ static const struct { @@ -117,7 +119,7 @@ static struct ifreq ifr; static int mdio_read(int skfd, int location) { - struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data; mii->reg_num = location; if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) { fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, @@ -129,7 +131,7 @@ static int mdio_read(int skfd, int location) static void mdio_write(int skfd, int location, int value) { - struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data; mii->reg_num = location; mii->val_in = value; if (ioctl(skfd, SIOCSMIIREG, &ifr) < 0) { @@ -145,17 +147,17 @@ const struct { 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} }, - - { "1000baseT-HD", {0, MII_BMCR2_1000HALF} }, - { "1000baseT-FD", {0, MII_BMCR2_1000FULL} }, - { "1000baseT", {0, MII_BMCR2_1000HALF|MII_BMCR2_1000FULL} }, + { "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])) @@ -166,8 +168,8 @@ static int parse_media(char *arg, unsigned *bmcr2) char *s; mask = strtoul(arg, &s, 16); if ((*arg != '\0') && (*s == '\0')) { - if ((mask & MII_AN_ABILITY_MASK) && - !(mask & ~MII_AN_ABILITY_MASK)) { + if ((mask & LPA_ABILITY_MASK) && + !(mask & ~LPA_ABILITY_MASK)) { *bmcr2 = 0; return mask; } @@ -198,18 +200,19 @@ static const char *media_list(unsigned mask, unsigned mask2, int best) int i; *buf = '\0'; - if (mask & MII_BMCR_SPEED1000) { - if (mask2 & MII_BMCR2_1000HALF) { + if (mask & BMCR_SPEED1000) { + if (mask2 & ADVERTISE_1000HALF) { strcat(buf, " "); strcat(buf, "1000baseT-HD"); if (best) goto out; } - if (mask2 & MII_BMCR2_1000FULL) { + 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<<i)) { @@ -233,8 +236,35 @@ int show_basic_mii(int sock, int phy_id) /* 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 : MII_BASIC_MAX); i++) - mii_val[i] = mdio_read(sock, i); + for (i = 0; i < ((verbose > 1) ? 32 : (MII_STAT1000+1)); i++) + switch (i & 0x1F) { + case MII_BMCR: + case MII_BMSR: + case MII_PHYSID1: + case MII_PHYSID2: + case MII_ADVERTISE: + case MII_LPA: + case MII_EXPANSION: + case MII_CTRL1000: + case MII_STAT1000: + case MII_ESTATUS: + case MII_DCOUNTER: + case MII_FCSCOUNTER: + case MII_NWAYTEST: + case MII_RERRCOUNTER: + case MII_SREVISION: + case MII_RESV1: + case MII_LBRERROR: + case MII_PHYADDR: + case MII_RESV2: + case MII_TPISTATUS: + case MII_NCONFIG: + mii_val[i] = mdio_read(sock, i); + break; + default: + mii_val[i] = 0; + break; + } if (mii_val[MII_BMCR] == 0xffff || mii_val[MII_BMSR] == 0x0000) { fprintf(stderr, " No MII transceiver present!.\n"); @@ -243,31 +273,31 @@ 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]; + 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 & MII_BMCR_AN_ENA) { - if (bmsr & MII_BMSR_AN_COMPLETE) { + if (bmcr & BMCR_ANENABLE) { + if (bmsr & BMSR_ANEGCOMPLETE) { if (advert & lkpar) { - strcat(buf, (lkpar & MII_AN_ACK) ? + strcat(buf, (lkpar & LPA_LPACK) ? "negotiated" : "no autonegotiation,"); strcat(buf, media_list(advert & lkpar, bmcr2 & lpa2>>2, 1)); strcat(buf, ", "); } else { strcat(buf, "autonegotiation failed, "); } - } else if (bmcr & MII_BMCR_RESTART) { + } else if (bmcr & BMCR_ANRESTART) { strcat(buf, "autonegotiation restarted, "); } } else { sprintf(buf+strlen(buf), "%s Mbit, %s duplex, ", - ((bmcr2 & (MII_BMCR2_1000HALF | MII_BMCR2_1000FULL)) & lpa2 >> 2) + ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) & lpa2 >> 2) ? "1000" - : (bmcr & MII_BMCR_100MBIT) ? "100" : "10", - (bmcr & MII_BMCR_DUPLEX) ? "full" : "half"); + : (bmcr & BMCR_SPEED100) ? "100" : "10", + (bmcr & BMCR_FULLDPLX) ? "full" : "half"); } - strcat(buf, (bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link"); + strcat(buf, (bmsr & BMSR_LSTATUS) ? "link ok" : "no link"); if (opt_watch) { if (opt_log) { @@ -303,32 +333,32 @@ int show_basic_mii(int sock, int phy_id) ((mii_val[2]<<6)|(mii_val[3]>>10))&0xff, (mii_val[3]>>4)&0x3f, mii_val[3]&0x0f); printf(" basic mode: "); - if (bmcr & MII_BMCR_RESET) + if (bmcr & BMCR_RESET) printf("software reset, "); - if (bmcr & MII_BMCR_LOOPBACK) + if (bmcr & BMCR_LOOPBACK) printf("loopback, "); - if (bmcr & MII_BMCR_ISOLATE) + if (bmcr & BMCR_ISOLATE) printf("isolate, "); - if (bmcr & MII_BMCR_COLTEST) + if (bmcr & BMCR_CTST) printf("collision test, "); - if (bmcr & MII_BMCR_AN_ENA) { + if (bmcr & BMCR_ANENABLE) { printf("autonegotiation enabled\n"); } else { printf("%s Mbit, %s duplex\n", - (bmcr & MII_BMCR_100MBIT) ? "100" : "10", - (bmcr & MII_BMCR_DUPLEX) ? "full" : "half"); + (bmcr & BMCR_SPEED100) ? "100" : "10", + (bmcr & BMCR_FULLDPLX) ? "full" : "half"); } printf(" basic status: "); - if (bmsr & MII_BMSR_AN_COMPLETE) + if (bmsr & BMSR_ANEGCOMPLETE) printf("autonegotiation complete, "); - else if (bmcr & MII_BMCR_RESTART) + else if (bmcr & BMCR_ANRESTART) printf("autonegotiation restarted, "); - if (bmsr & MII_BMSR_REMOTE_FAULT) + if (bmsr & BMSR_RFAULT) printf("remote fault, "); - printf((bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link"); + printf((bmsr & BMSR_LSTATUS) ? "link ok" : "no link"); printf("\n capabilities:%s", media_list(bmsr >> 6, bmcr2, 0)); printf("\n advertising: %s", media_list(advert, bmcr2, 0)); - if (lkpar & MII_AN_ABILITY_MASK) + if (lkpar & LPA_ABILITY_MASK) printf("\n link partner:%s", media_list(lkpar, lpa2 >> 2, 0)); printf("\n"); } @@ -340,7 +370,7 @@ int show_basic_mii(int sock, int phy_id) static int do_one_xcvr(int skfd, char *ifname, int maybe) { - struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data; /* Get the vitals from the interface. */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); @@ -358,23 +388,23 @@ static int do_one_xcvr(int skfd, char *ifname, int maybe) if (opt_reset) { printf("resetting the transceiver...\n"); - mdio_write(skfd, MII_BMCR, MII_BMCR_RESET); + mdio_write(skfd, MII_BMCR, BMCR_RESET); } if (nway_advertise > 0) { - mdio_write(skfd, MII_ANAR, nway_advertise | 1); + mdio_write(skfd, MII_ADVERTISE, nway_advertise | 1); opt_restart = 1; } if (opt_restart) { printf("restarting autonegotiation...\n"); mdio_write(skfd, MII_BMCR, 0x0000); - mdio_write(skfd, MII_BMCR, MII_BMCR_AN_ENA|MII_BMCR_RESTART); + mdio_write(skfd, MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART); } if (fixed_speed) { int bmcr = 0; - if (fixed_speed & (MII_AN_100BASETX_FD|MII_AN_100BASETX_HD)) - bmcr |= MII_BMCR_100MBIT; - if (fixed_speed & (MII_AN_100BASETX_FD|MII_AN_10BASET_FD)) - bmcr |= MII_BMCR_DUPLEX; + if (fixed_speed & (LPA_100FULL|LPA_100HALF)) + bmcr |= BMCR_SPEED100; + if (fixed_speed & (LPA_100FULL|LPA_10FULL)) + bmcr |= BMCR_FULLDPLX; mdio_write(skfd, MII_BMCR, bmcr); } @@ -388,7 +418,7 @@ static int do_one_xcvr(int skfd, char *ifname, int maybe) static void watch_one_xcvr(int skfd, char *ifname, int index) { - struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data; static int status[MAX_ETH] = { 0, /* ... */ }; int now; |