apps/mii-diag/mii-diag.c

Go to the documentation of this file.
00001 /* Mode: C;
00002  * mii-diag.c: Examine and set the MII registers of a network interfaces.
00003 
00004         Usage:  mii-diag [-vw] interface.
00005 
00006         This program reads and writes the Media Independent Interface (MII)
00007         management registers on network transceivers.  The registers control
00008         and report network link settings and errors.  Examples are link speed,
00009         duplex, capabilities advertised to the link partner, status LED
00010         indications and link error counters.
00011 
00012         Notes:
00013         The compile-command is at the end of this source file.
00014         This program works with drivers that implement MII ioctl() calls.
00015 
00016         Written/copyright 1997-2003 by Donald Becker <becker@scyld.com>
00017 
00018         This program is free software; you can redistribute it
00019         and/or modify it under the terms of the GNU General Public
00020         License as published by the Free Software Foundation.
00021 
00022         The author may be reached as becker@scyld.com, or C/O
00023          Scyld Computing Corporation
00024          914 Bay Ridge Road, Suite 220
00025          Annapolis MD 21403
00026 
00027         References
00028         http://scyld.com/expert/mii-status.html
00029         http://scyld.com/expert/NWay.html
00030         http://www.national.com/pf/DP/DP83840.html
00031 */
00032 
00033 static char version[] =
00034 "mii-diag.c:v2.11 3/21/2005 Donald Becker (becker@scyld.com)\n"
00035 " http://www.scyld.com/diag/index.html\n";
00036 
00037 static const char usage_msg[] =
00038 "Usage: %s [--help] [-aDfrRvVw] [-AF <speed+duplex>] [--watch] <interface>.\n";
00039 static const char long_usage_msg[] =
00040 "Usage: %s [-aDfrRvVw] [-AF <speed+duplex>] [--watch] <interface>.\n"
00041 "\n"
00042 "  This program configures and monitors the transceiver management registers\n"
00043 "  for network interfaces.  It uses the Media Independent Interface (MII)\n"
00044 "  standard with additional Linux-specific controls to communicate with the\n"
00045 "  underlying device driver.  The MII registers control and report network\n"
00046 "  link settings and errors.  Examples are link speed, duplex, capabilities\n"
00047 "  advertised to the link partner, status LED indications and link error\n"
00048 "  counters.\n"
00049 "\n"
00050 "   The common usage is\n"
00051 "      mii-diag eth0\n"
00052 "\n"
00053 "   The default interface is \"eth0\".\n"
00054 " Frequently used options are\n"
00055 "   -A  --advertise <speed|setting>\n"
00056 "   -F  --fixed-speed <speed>\n"
00057 "       Speed is one of: 100baseT4, 100baseTx, 100baseTx-FD, 100baseTx-HD,\n"
00058 "                        10baseT, 10baseT-FD, 10baseT-HD\n"
00059 "   -s  --status     Return exit status 2 if there is no link beat.\n"
00060 "\n"
00061 " Less frequently used options are\n"
00062 "   -a  --all-interfaces  Show the status all interfaces\n"
00063 "              (Not recommended with options that change settings.)\n"
00064 "   -D  --debug\n"
00065 "   -g  --read-parameters       Get driver-specific parameters.\n"
00066 "   -G  --set-parameters PARMS  Set driver-specific parameters.\n"
00067 "       Parameters are comma separated, missing elements retain existing value.\n"
00068 "   -M  --msg-level LEVEL       Set the driver message bit map.\n"
00069 "   -p  --phy ADDR              Set the PHY (MII address) to report.\n"
00070 "   -r  --restart       Restart the link autonegotiation.\n"
00071 "   -R  --reset         Reset the transceiver.\n"
00072 "   -v  --verbose       Report each action taken.\n"
00073 "   -V  --version       Emit version information.\n"
00074 "   -w  --watch         Continuously monitor the transceiver and report changes.\n"
00075 " MII register manipulation options are\n"
00076 "   -x  --mii-addr ADDR         MII register decimal address (to read, if VALUE not present). Must be in the range from '0' to '31' .\n"
00077 "   -y  --mii-value VALUE       write new value to MII register, hex format. Must be used together with ADDR option.\n"
00078 "\n"
00079 "   This command returns success (zero) if the interface information can be\n"
00080 "   read.  If the --status option is passed, a zero return means that the\n"
00081 "   interface has link beat.\n";
00082 
00083 #include <unistd.h>
00084 #include <stdlib.h>
00085 #include <stdio.h>
00086 #include <ctype.h>
00087 #include <string.h>
00088 #include <errno.h>
00089 #include <fcntl.h>
00090 #include <getopt.h>
00091 #include <sys/types.h>
00092 #include <sys/socket.h>
00093 #include <sys/ioctl.h>
00094 #include <net/if.h>
00095 #ifdef use_linux_libc5
00096 #include <linux/if_arp.h>
00097 #include <linux/if_ether.h>
00098 #endif
00099 
00100 typedef u_int32_t u32;
00101 typedef u_int16_t u16;
00102 typedef u_int8_t u8;
00103 
00104 #if defined(SIOCGPARAMS)  && SIOCGPARAMS != SIOCDEVPRIVATE+3
00105 #error Changed definition for SIOCGPARAMS
00106 #else
00107 #define SIOCGPARAMS (SIOCDEVPRIVATE+3)          /* Read operational parameters. */
00108 #define SIOCSPARAMS (SIOCDEVPRIVATE+4)          /* Set operational parameters. */
00109 #endif
00110 
00111 const char shortopts[] = "aA:C:x:y:DfF:gG:hmM:p:rRsvVw?";
00112 struct option longopts[] = {
00113  /* { name  has_arg  *flag  val } */
00114     {"all-interfaces", 0, 0, 'a'},      /* Show all interfaces. */
00115         {"advertise",   1, 0, 'A'},             /* Change the capabilities advertised. */
00116         {"BMCR",                1, 0, 'C'},             /* Set the control register. */
00117     {"debug",       0, 0, 'D'},         /* Increase the debug level. */
00118     {"force",       0, 0, 'f'},         /* Force the operation. */
00119     {"fixed-speed", 1, 0, 'F'},         /* Fixed speed name. */
00120     {"read-parameters", 0, 0, 'g'}, /* Show general settings values. */
00121     {"set-parameters",  1, 0, 'G'},     /* Write general settings values. */
00122     {"mii-addr", 1, 0, 'x'},    /* Addr of MII register */
00123     {"mii-value", 1, 0, 'y'},   /* value to write at MII register */
00124     {"help",            0, 0, 'h'},             /* Print a long usage message. */
00125     {"monitor",         0, 0, 'm'},             /* Monitor status register. */
00126     {"msg-level",       1, 0, 'M'},             /* Set the driver message level. */
00127     {"phy",                     1, 0, 'p'},             /* Set the PHY (MII address) to report. */
00128     {"restart",         0, 0, 'r'},             /* Restart the link negotiation */
00129     {"reset",           0, 0, 'R'},             /* Reset the transceiver. */
00130     {"status",          0, 0, 's'},             /* Non-zero exit status w/ no link beat. */
00131     {"verbose",         0, 0, 'v'},             /* Report each action taken.  */
00132     {"version",         0, 0, 'V'},             /* Emit version information.  */
00133     {"watch",           0, 0, 'w'},             /* Constantly monitor the port.  */
00134     {"error",           0, 0, '?'},             /* Return the error message. */
00135     { 0, 0, 0, 0 }
00136 };
00137 
00138 /* Usually in libmii.c, but trivial substitions are below. */
00139 extern int  show_mii_details(long ioaddr, int phy_id);
00140 extern void monitor_mii(long ioaddr, int phy_id);
00141 int  show_mii_details(long ioaddr, int phy_id) __attribute__((weak));
00142 void monitor_mii(long ioaddr, int phy_id) __attribute__((weak));
00143 
00144 
00145 /* Command-line flags. */
00146 unsigned int opt_a = 0,                                 /* Show-all-interfaces flag. */
00147         opt_f = 0,                                      /* Force the operation. */
00148         opt_g = 0,
00149         opt_G = 0,
00150         verbose = 0,                            /* Verbose flag. */
00151         debug = 0,
00152         opt_version = 0,
00153         opt_restart = 0,
00154         opt_reset = 0,
00155         opt_status = 0,
00156         opt_watch = 0;
00157 static int msg_level = -1;
00158 static int set_BMCR = -1;
00159 static int nway_advertise = 0;
00160 static int fixed_speed = -1;
00161 static int override_phy = -1;
00162 char *opt_G_string = NULL;
00163 
00164 #define MII_ACTION_NONE         0
00165 #define MII_ACTION_READ         1
00166 #define MII_ACTION_WRITE        2
00167 static int mii_action = MII_ACTION_NONE;
00168 unsigned mii_addr = 0xFFFF;
00169 unsigned mii_value = 0;
00170 int silent = 0;
00171 
00172 /* Internal values. */
00173 int new_ioctl_nums;
00174 int skfd = -1;                                  /* AF_INET socket for ioctl() calls.    */
00175 struct ifreq ifr;
00176 
00177 int do_one_xcvr(int skfd);
00178 int show_basic_mii(long ioaddr, int phy_id);
00179 int mdio_read(int skfd, int phy_id, int location);
00180 void mdio_write(int skfd, int phy_id, int location, int value);
00181 static int parse_advertise(const char *capabilities);
00182 static void monitor_status(long ioaddr, int phy_id);
00183 
00184 
00185 int
00186 main(int argc, char **argv)
00187 {
00188         int c, errflag = 0;
00189         char **spp, *ifname;
00190     char *progname = rindex(argv[0], '/') ? rindex(argv[0], '/')+1 : argv[0];
00191 
00192         while ((c = getopt_long(argc, argv, shortopts, longopts, 0)) != EOF)
00193                 switch (c) {
00194                 case 'a': opt_a++; break;
00195                 case 'A': nway_advertise |= parse_advertise(optarg);
00196                         if (nway_advertise == -1) errflag++;
00197                         break;
00198                 case 'C': set_BMCR = strtoul(optarg, NULL, 16); break;
00199                 case 'x': {
00200                         mii_addr = strtoul(optarg, NULL, 10);
00201                         if(mii_action == MII_ACTION_NONE)
00202                                 mii_action = MII_ACTION_READ;
00203                         break;
00204                 }
00205                 case 'y': {
00206 printf("y\n");
00207                         mii_value = strtoul(optarg, NULL, 16);
00208                         mii_action = MII_ACTION_WRITE;
00209                         break;
00210                 }
00211                 case 'D': debug++;                      break;
00212                 case 'f': opt_f++; break;
00213                 case 'F': fixed_speed = parse_advertise(optarg);
00214                         if (fixed_speed == -1) errflag++;
00215                         break;
00216                 case 'g': opt_g++; break;
00217                 case 'G': opt_G++; opt_G_string = strdup(optarg); break;
00218                 case 'm': opt_watch++; opt_status++; break;
00219                 case 'M': msg_level = strtoul(optarg, NULL, 0); break;
00220                 case 'h': fprintf(stderr, long_usage_msg, progname); return 0;
00221                 case 'p': override_phy = atoi(optarg); break;
00222                 case 'r': opt_restart++;        break;
00223                 case 'R': opt_reset++;          break;
00224                 case 's': opt_status++;         break;
00225                 case 'v': verbose++;            break;
00226                 case 'V': opt_version++;        break;
00227                 case 'w': opt_watch++;          break;
00228                 case '?': errflag++;            break;
00229                 }
00230         if (errflag) {
00231                 fprintf(stderr, usage_msg, progname);
00232                 return 2;
00233         }
00234 
00235         if (verbose || opt_version)
00236                 printf(version);
00237 
00238         /* Open a basic socket. */
00239         if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
00240                 perror("socket");
00241                 return 1;
00242         }
00243 
00244         if (debug)
00245                 fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n",
00246                                 argc, optind, argv[optind]);
00247 
00248         /* No remaining args means show all interfaces. */
00249         if (optind == argc) {
00250                 ifname = "eth0";
00251                 fprintf(stderr, "Using the default interface 'eth0'.\n");
00252         } else {
00253                 /* Copy the interface name. */
00254                 spp = argv + optind;
00255                 ifname = *spp++;
00256         }
00257 
00258         if (ifname == NULL) {
00259                 ifname = "eth0";
00260                 fprintf(stderr, "Using the default interface 'eth0'.\n");
00261         }
00262 
00263         /* Verify that the interface supports the ioctl(), and if
00264            it is using the new or old SIOCGMIIPHY value (grrr...).
00265          */
00266         {
00267                 u16 *data = (u16 *)(&ifr.ifr_data);
00268 
00269                 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
00270                 data[0] = 0;
00271 
00272                 if (ioctl(skfd, 0x8947, &ifr) >= 0) {
00273                         new_ioctl_nums = 1;
00274                 } else if (ioctl(skfd, SIOCDEVPRIVATE, &ifr) >= 0) {
00275                         new_ioctl_nums = 0;
00276                 } else {
00277                         fprintf(stderr, "SIOCGMIIPHY on %s failed: %s\n", ifname,
00278                                         strerror(errno));
00279                         (void) close(skfd);
00280                         return 1;
00281                 }
00282                 if (verbose)
00283                         printf("  Using the %s SIOCGMIIPHY value on PHY %d "
00284                                    "(BMCR 0x%4.4x).\n",
00285                                    new_ioctl_nums ? "new" : "old", data[0], data[3]);
00286         }
00287 
00288         do_one_xcvr(skfd);
00289 
00290         (void) close(skfd);
00291         return 0;
00292 }
00293 
00294 int do_one_xcvr(int skfd)
00295 {
00296         u16 *data = (u16 *)(&ifr.ifr_data);
00297         u32 *data32 = (u32 *)(&ifr.ifr_data);
00298         unsigned phy_id = data[0];
00299 
00300         if (override_phy >= 0) {
00301                 printf("Using the specified MII PHY index %d.\n", override_phy);
00302                 phy_id = override_phy;
00303         }
00304 
00305         if (opt_g || opt_G || msg_level >= 0) {
00306                 if (ioctl(skfd, SIOCGPARAMS, &ifr) < 0) {
00307                         fprintf(stderr, "SIOCGPARAMS on %s failed: %s\n", ifr.ifr_name,
00308                                         strerror(errno));
00309                         return -1;
00310                 }
00311         }
00312         if (opt_g) {
00313                 int i;
00314                 printf("Driver general parameter settings:");
00315                 for (i = 0; i*sizeof(u32) < sizeof(ifr.ifr_ifru); i++) {
00316                         printf(" %d", data32[i]);
00317                 }
00318                 printf(".\n");
00319         }
00320         if (opt_G) {
00321                 /* Set up to four arbitrary driver parameters from the -G parameter.
00322                    The format is comma separated integers, with a missing element
00323                    retaining the previous value.
00324                 */
00325                 char *str = opt_G_string;
00326                 int i;
00327                 for (i = 0; str && i < 4; i++) {
00328                         char *endstr;
00329                         u32 newval = strtol(str, &endstr, 0);
00330                         if (debug)
00331                                 printf(" parse string '%s'  value %d end '%s'.\n",
00332                                            str, newval, endstr);
00333                         if (str == endstr) {
00334                                 if (endstr[0] == ',') /* No parameter */
00335                                         str = endstr+1;
00336                                 else {
00337                                         fprintf(stderr, "Invalid driver parameter '%s'.\n", str);
00338                                         str = index(str, ',');
00339                                 }
00340                         } else if (endstr[0] == ',') {
00341                                 data32[i] = newval;
00342                                 str = endstr + 1;
00343                         } else if (endstr[0] == 0) {
00344                                 data32[i] = newval;
00345                                 break;
00346                         }
00347                 }
00348                 printf("Setting new driver general parameters:");
00349                 for (i = 0; i*sizeof(u32) < sizeof(ifr.ifr_ifru); i++) {
00350                         printf(" %d", data32[i]);
00351                 }
00352                 printf(".\n");
00353                 if (ioctl(skfd, SIOCSPARAMS, &ifr) < 0) {
00354                         fprintf(stderr, "SIOCSPARAMS on %s failed: %s\n", ifr.ifr_name,
00355                                         strerror(errno));
00356                         return -1;
00357                 }
00358         }
00359         if (msg_level >= 0) {
00360                 data32[0] = msg_level;
00361                 if (ioctl(skfd, SIOCSPARAMS, &ifr) < 0) {
00362                         fprintf(stderr, "SIOCSPARAMS on %s failed: %s\n", ifr.ifr_name,
00363                                         strerror(errno));
00364                         return -1;
00365                 }
00366         }
00367 
00368         if (opt_reset) {
00369                 printf("Resetting the transceiver...\n");
00370                 mdio_write(skfd, phy_id, 0, 0x8000);
00371         }
00372         /* Note: PHY addresses > 32 are pseudo-MII devices, usually built-in. */
00373         if (phy_id < 64  &&  nway_advertise > 0) {
00374                 printf(" Setting the media capability advertisement register of "
00375                            "PHY #%d to 0x%4.4x.\n", phy_id, nway_advertise | 1);
00376                 mdio_write(skfd, phy_id, 4, nway_advertise | 1);
00377                 mdio_write(skfd, phy_id, 0, 0x1000);
00378         }
00379 
00380         if (opt_restart) {
00381                 printf("Restarting negotiation...\n");
00382                 mdio_write(skfd, phy_id, 0, 0x0000);
00383                 mdio_write(skfd, phy_id, 0, 0x1200);
00384         }
00385         /* To force 100baseTx-HD do  mdio_write(skfd, phy_id, 0, 0x2000); */
00386         if (fixed_speed >= 0) {
00387                 int reg0_val = 0;
00388                 if (fixed_speed & 0x0180)               /* 100mpbs */
00389                         reg0_val |=  0x2000;
00390                 if ((fixed_speed & 0x0140) &&           /* A full duplex type and */
00391                         ! (fixed_speed & 0x0820))               /* no half duplex types. */
00392                         reg0_val |= 0x0100;
00393                 printf("Setting the speed to \"fixed\", Control register %4.4x.\n",
00394                            reg0_val);
00395                 mdio_write(skfd, phy_id, 0, reg0_val);
00396         }
00397         if (mii_action != MII_ACTION_NONE) {
00398                 if (mii_addr > 31) {
00399                         fprintf(stderr, "MII register address must be in 0-31 diapason\n");
00400                 } else {
00401                         silent = 1;
00402                         if (mii_action == MII_ACTION_WRITE) {
00403                                 mdio_write(skfd, phy_id, mii_addr, mii_value);
00404                                 fprintf(stderr, "write to register MR%d value 0x%04X\n", mii_addr, mii_value);
00405                         }
00406                         if (mii_action == MII_ACTION_READ) {
00407                                 unsigned long v = mdio_read(skfd, phy_id, mii_addr);
00408                                 printf("0x%04X\n", v);
00409                                 fprintf(stderr, "read from register MR%d value 0x%04X\n", mii_addr, v);
00410                         }
00411                 }
00412         }
00413         if (set_BMCR >= 0) {
00414                 printf("Setting the Basic Mode Control Register to 0x%4.4x.\n",
00415                            set_BMCR);
00416                 mdio_write(skfd, phy_id, 0, set_BMCR);
00417         }
00418 
00419         if (opt_watch && opt_status)
00420                 monitor_status(skfd, phy_id);
00421 
00422         show_basic_mii(skfd, phy_id);
00423 #ifdef LIBMII
00424         if (verbose)
00425                 show_mii_details(skfd, phy_id);
00426 #else
00427         if (verbose || debug) {
00428                 int mii_reg, mii_val;
00429                 printf(" MII PHY #%d transceiver registers:", phy_id);
00430                 for (mii_reg = 0; mii_reg < 32; mii_reg++) {
00431                         mii_val = mdio_read(skfd, phy_id, mii_reg);
00432                         printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n  " : "",
00433                                    mii_val);
00434                 }
00435                 printf("\n");
00436         }
00437 #endif
00438 
00439         if (opt_watch)
00440                 monitor_mii(skfd, phy_id);
00441         if (opt_status &&
00442                 (mdio_read(skfd, phy_id, 1) & 0x0004) == 0)
00443                 exit(2);
00444         return 0;
00445 }
00446 
00447 int mdio_read(int skfd, int phy_id, int location)
00448 {
00449         u16 *data = (u16 *)(&ifr.ifr_data);
00450 
00451         data[0] = phy_id;
00452         data[1] = location;
00453 
00454         if (ioctl(skfd, new_ioctl_nums ? 0x8948 : SIOCDEVPRIVATE+1, &ifr) < 0) {
00455                 fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
00456                                 strerror(errno));
00457                 return -1;
00458         }
00459         return data[3];
00460 }
00461 
00462 void mdio_write(int skfd, int phy_id, int location, int value)
00463 {
00464         u16 *data = (u16 *)(&ifr.ifr_data);
00465 
00466         data[0] = phy_id;
00467         data[1] = location;
00468         data[2] = value;
00469 
00470         if (ioctl(skfd, new_ioctl_nums ? 0x8949 : SIOCDEVPRIVATE+2, &ifr) < 0) {
00471                 fprintf(stderr, "SIOCSMIIREG on %s failed: %s\n", ifr.ifr_name,
00472                                 strerror(errno));
00473         }
00474 }
00475 
00476 /* Parse the command line argument for advertised capabilities. */
00477 static int parse_advertise(const char *capabilities)
00478 {
00479         const char *mtypes[] = {
00480                 "100baseT4", "100baseTx", "100baseTx-FD", "100baseTx-HD",
00481                 "10baseT", "10baseT-FD", "10baseT-HD", 0,
00482         };
00483         char *endptr;
00484         int cap_map[] = { 0x0200, 0x0180, 0x0100, 0x0080, 0x0060, 0x0040, 0x0020,};
00485         int i;
00486         if ( ! capabilities) {
00487                 fprintf(stderr, "You passed -A 'NULL'.  You must provide a media"
00488                                 " list to advertise!\n");
00489                 return -1;
00490         }
00491         if (debug)
00492                 fprintf(stderr, "Advertise string is '%s'.\n", capabilities);
00493         for (i = 0; mtypes[i]; i++)
00494                 if (strcasecmp(mtypes[i], capabilities) == 0)
00495                         return cap_map[i];
00496         if ((i = strtol(capabilities, &endptr, 16)) <= 0xffff  &&  endptr[0] == 0)
00497                 return i;
00498         fprintf(stderr, "Invalid media advertisement value '%s'.\n"
00499                         "  Either pass a numeric value or one of the following names:\n",
00500                         capabilities);
00501         for (i = 0; mtypes[i]; i++)
00502                 fprintf(stderr, "   %-14s %3.3x\n", mtypes[i], cap_map[i]);
00503         return -1;
00504 }
00505 
00506 /* Trivial versions if we don't link against libmii.c */
00507 static const char *media_names[] = {
00508         "10baseT", "10baseT-FD", "100baseTx", "100baseTx-FD", "100baseT4",
00509         "Flow-control", 0,
00510 };
00511 /* Various non-good bits in the command register. */
00512 static const char *bmcr_bits[] = {
00513         "  Internal Collision-Test enabled!\n", "",             /* 0x0080,0x0100 */
00514         "  Restarted auto-negotiation in progress!\n",
00515         "  Transceiver isolated from the MII!\n",
00516         "  Transceiver powered down!\n", "", "",
00517         "  Transceiver in loopback mode!\n",
00518         "  Transceiver currently being reset!\n",
00519 };
00520 
00521 int show_basic_mii(long ioaddr, int phy_id)
00522 {
00523         int mii_reg, i;
00524         u16 mii_val[32];
00525         u16 bmcr, bmsr, new_bmsr, nway_advert, lkpar;
00526 
00527         if(silent)
00528                 return 0;
00529         for (mii_reg = 0; mii_reg < 8; mii_reg++)
00530                 mii_val[mii_reg] = mdio_read(ioaddr, phy_id, mii_reg);
00531         if ( ! verbose) {
00532                 printf("Basic registers of MII PHY #%d: ", phy_id);
00533                 for (mii_reg = 0; mii_reg < 8; mii_reg++)
00534                         printf(" %4.4x", mii_val[mii_reg]);
00535                 printf(".\n");
00536         }
00537 
00538         if (mii_val[0] == 0xffff  ||  mii_val[1] == 0x0000) {
00539                 printf("  No MII transceiver present!.\n");
00540                 if (! opt_f) {
00541                         printf("  Use '--force' to view the information anyway.\n");
00542                         return -1;
00543                 }
00544         }
00545         /* Descriptive rename. */
00546         bmcr = mii_val[0];
00547         bmsr = mii_val[1];
00548         nway_advert = mii_val[4];
00549         lkpar = mii_val[5];
00550 
00551         if (lkpar & 0x4000) {
00552                 int negotiated = nway_advert & lkpar & 0x3e0;
00553                 int max_capability = 0;
00554                 /* Scan for the highest negotiated capability, highest priority
00555                    (100baseTx-FDX) to lowest (10baseT-HDX). */
00556                 int media_priority[] = {8, 9, 7, 6, 5};         /* media_names[i-5] */
00557                 printf(" The autonegotiated capability is %4.4x.\n", negotiated);
00558                 for (i = 0; media_priority[i]; i++)
00559                         if (negotiated & (1 << media_priority[i])) {
00560                                 max_capability = media_priority[i];
00561                                 break;
00562                         }
00563                 if (max_capability)
00564                         printf("The autonegotiated media type is %s.\n",
00565                                    media_names[max_capability - 5]);
00566                 else
00567                         printf("No common media type was autonegotiated!\n"
00568                                    "This is extremely unusual and typically indicates a "
00569                                    "configuration error.\n" "Perhaps the advertised "
00570                                    "capability set was intentionally limited.\n");
00571         }
00572         printf(" Basic mode control register 0x%4.4x:", bmcr);
00573         if (bmcr & 0x1000)
00574                 printf(" Auto-negotiation enabled.\n");
00575         else
00576                 printf(" Auto-negotiation disabled, with\n"
00577                            " Speed fixed at 10%s mbps, %s-duplex.\n",
00578                            bmcr & 0x2000 ? "0" : "",
00579                            bmcr & 0x0100 ? "full":"half");
00580         for (i = 0; i < 9; i++)
00581                 if (bmcr & (0x0080<<i))
00582                         printf(bmcr_bits[i]);
00583 
00584         new_bmsr = mdio_read(ioaddr, phy_id, 1);
00585         if ((bmsr & 0x0016) == 0x0004)
00586                 printf( " You have link beat, and everything is working OK.\n");
00587         else
00588                 printf(" Basic mode status register 0x%4.4x ... %4.4x.\n"
00589                            "   Link status: %sestablished.\n",
00590                            bmsr, new_bmsr,
00591                            bmsr & 0x0004 ? "" :
00592                            (new_bmsr & 0x0004) ? "previously broken, but now re" : "not ");
00593         if (verbose) {
00594                 printf("   This transceiver is capable of ");
00595                 if (bmsr & 0xF800) {
00596                         for (i = 15; i >= 11; i--)
00597                                 if (bmsr & (1<<i))
00598                                         printf(" %s", media_names[i-11]);
00599                 } else
00600                         printf("<Warning! No media capabilities>");
00601                 printf(".\n");
00602                 printf("   %s to perform Auto-negotiation, negotiation %scomplete.\n",
00603                            bmsr & 0x0008 ? "Able" : "Unable",
00604                            bmsr & 0x0020 ? "" : "not ");
00605         }
00606 
00607         if (bmsr & 0x0010)
00608                 printf(" Remote fault detected!\n");
00609         if (bmsr & 0x0002)
00610                 printf("   *** Link Jabber! ***\n");
00611 
00612         if (lkpar & 0x4000) {
00613                 printf(" Your link partner advertised %4.4x:",
00614                            lkpar);
00615                 for (i = 5; i >= 0; i--)
00616                         if (lkpar & (0x20<<i))
00617                                 printf(" %s", media_names[i]);
00618                 printf("%s.\n", lkpar & 0x0400 ? ", w/ 802.3X flow control" : "");
00619         } else if (lkpar & 0x00A0)
00620                 printf(" Your link partner is generating %s link beat  (no"
00621                            " autonegotiation).\n",
00622                            lkpar & 0x0080 ? "100baseTx" : "10baseT");
00623         else if ( ! (bmcr & 0x1000))
00624                 printf(" Link partner information is not exchanged when in"
00625                            " fixed speed mode.\n");
00626         else if ( ! (new_bmsr & 0x004))
00627                                                         ;       /* If no partner, do not report status. */
00628         else if (lkpar == 0x0001  ||  lkpar == 0x0000) {
00629                 printf(" Your link partner does not do autonegotiation, and this "
00630                            "transceiver type\n  does not report the sensed link "
00631                            "speed.\n");
00632         } else
00633                 printf(" Your link partner is strange, status %4.4x.\n", lkpar);
00634 
00635         printf("   End of basic transceiver information.\n\n");
00636         return 0;
00637 }
00638 
00639 static void monitor_status(long ioaddr, int phy_id)
00640 {
00641         unsigned int baseline_1 = 0x55555555;   /* Always show initial status. */
00642 
00643         while (1) {
00644                 unsigned int new_1 = mdio_read(ioaddr, phy_id, 1);
00645                 if (new_1 != baseline_1) {
00646                         printf("%-12s 0x%4.4x 0x%4.4x\n",
00647                                    new_1 & 0x04 ? (new_1==0xffff ? "unknown" : "up") :
00648                                    new_1 & 0x20 ? "negotiating" : "down",
00649                                    new_1, mdio_read(ioaddr, phy_id, 5));
00650                         fflush(stdout);
00651                         baseline_1 = new_1;
00652                 }
00653                 sleep(1);
00654         }
00655 }
00656 
00657 int  show_mii_details(long ioaddr, int phy_id)
00658 {
00659         int mii_reg, mii_val;
00660         printf(" MII PHY #%d transceiver registers:", phy_id);
00661         for (mii_reg = 0; mii_reg < 32; mii_reg++) {
00662                 mii_val = mdio_read(skfd, phy_id, mii_reg);
00663                 printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n  " : "",
00664                            mii_val);
00665         }
00666         printf("\nThis version of 'mii-diag' has not been linked with "
00667                         "the libmii.c library.\n"
00668                         "  That library provides extended transceiver status reports.\n");
00669         return 0;
00670 }
00671 
00672 void monitor_mii(long ioaddr, int phy_id)
00673 {
00674         fprintf(stderr, "\nThis version of 'mii-diag' has not been linked with "
00675                         "the libmii.c library \n"
00676                         "  required for the media monitor option.\n");
00677 }
00678 
00679 
00680 
00681 /*
00682  * Local variables:
00683  *  version-control: t
00684  *  kept-new-versions: 5
00685  *  c-indent-level: 4
00686  *  c-basic-offset: 4
00687  *  tab-width: 4
00688  *  compile-command: "gcc -Wall -Wstrict-prototypes -O mii-diag.c -DLIBMII libmii.c -o mii-diag"
00689  *  simple-compile-command: "gcc mii-diag.c -o mii-diag"
00690  * End:
00691  */

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1