Blame SOURCES/mii-diag.c

612949
/* Mode: C;
612949
 * mii-diag.c: Examine and set the MII registers of a network interfaces.
612949
612949
	Usage:	mii-diag [-vw] interface.
612949
612949
	This program reads and writes the Media Independent Interface (MII)
612949
	management registers on network transceivers.  The registers control
612949
	and report network link settings and errors.  Examples are link speed,
612949
	duplex, capabilities advertised to the link partner, status LED
612949
	indications and link error counters.
612949
612949
	Notes:
612949
	The compile-command is at the end of this source file.
612949
	This program works with drivers that implement MII ioctl() calls.
612949
612949
	Written/copyright 1997-2003 by Donald Becker <becker@scyld.com>
612949
612949
	This program is free software; you can redistribute it
612949
	and/or modify it under the terms of the GNU General Public
612949
	License as published by the Free Software Foundation.
612949
612949
	The author may be reached as becker@scyld.com, or C/O
612949
	 Scyld Computing Corporation
612949
	 914 Bay Ridge Road, Suite 220
612949
	 Annapolis MD 21403
612949
612949
	References
612949
	http://scyld.com/expert/mii-status.html
612949
	http://scyld.com/expert/NWay.html
612949
	http://www.national.com/pf/DP/DP83840.html
612949
*/
612949
612949
static char version[] =
612949
"mii-diag.c:v2.11 3/21/2005 Donald Becker (becker@scyld.com)\n"
612949
" http://www.scyld.com/diag/index.html\n";
612949
612949
static const char usage_msg[] =
612949
"Usage: %s [--help] [-aDfrRvVw] [-AF <speed+duplex>] [--watch] <interface>\n";
612949
static const char long_usage_msg[] =
612949
"Usage: %s [-aDfrRvVw] [-AF <speed+duplex>] [--watch] <interface>\n\
612949
\n\
612949
  This program configures and monitors the transceiver management registers\n\
612949
  for network interfaces.  It uses the Media Independent Interface (MII)\n\
612949
  standard with additional Linux-specific controls to communicate with the\n\
612949
  underlying device driver.  The MII registers control and report network\n\
612949
  link settings and errors.  Examples are link speed, duplex, capabilities\n\
612949
  advertised to the link partner, status LED indications and link error\n\
612949
  counters.\n\
612949
\n\
612949
   The common usage is\n\
612949
      mii-diag eth0\n\
612949
\n\
612949
 Frequently used options are\n\
612949
   -A  --advertise <speed|setting>\n\
612949
   -F  --fixed-speed <speed>\n\
612949
	Speed is one of: 100baseT4, 100baseTx, 100baseTx-FD, 100baseTx-HD,\n\
612949
	                 10baseT, 10baseT-FD, 10baseT-HD\n\
612949
   -s  --status     Return exit status 2 if there is no link beat.\n\
612949
\n\
612949
 Less frequently used options are\n\
612949
   -a  --all-interfaces  Show the status all interfaces\n\
612949
              (Not recommended with options that change settings.)\n\
612949
   -D  --debug\n\
612949
   -g  --read-parameters 	Get driver-specific parameters.\n\
612949
   -G  --set-parameters PARMS	Set driver-specific parameters.\n\
612949
       Parameters are comma separated, missing parameters retain\n\
612949
       their previous values.\n\
612949
   -M  --msg-level LEVEL 	Set the driver message bit map.\n\
612949
   -p  --phy ADDR		Set the PHY (MII address) to report.\n\
612949
   -r  --restart	Restart the link autonegotiation.\n\
612949
   -R  --reset		Reset the transceiver.\n\
612949
   -v  --verbose	Report each action taken.\n\
612949
   -V  --version	Emit version information.\n\
612949
   -w  --watch		Continuously monitor the transceiver and report changes.\n\
612949
\n\
612949
   This command returns success (zero) if the interface information can be\n\
612949
   read.  If the --status option is passed, a zero return means that the\n\
612949
   interface has link beat.\n\
612949
";
612949
612949
#include <unistd.h>
612949
#include <stdlib.h>
612949
#include <stdio.h>
612949
#include <ctype.h>
612949
#include <string.h>
612949
#include <errno.h>
612949
#include <fcntl.h>
612949
#include <getopt.h>
612949
#include <sys/types.h>
612949
#include <sys/socket.h>
612949
#include <sys/ioctl.h>
612949
#include <net/if.h>
612949
#ifdef use_linux_libc5
612949
#include <linux/if_arp.h>
612949
#include <linux/if_ether.h>
612949
#endif
612949
612949
typedef u_int32_t u32;
612949
typedef u_int16_t u16;
612949
typedef u_int8_t u8;
612949
612949
#if defined(SIOCGPARAMS)  && SIOCGPARAMS != SIOCDEVPRIVATE+3
612949
#error Changed definition for SIOCGPARAMS
612949
#else
612949
#define SIOCGPARAMS (SIOCDEVPRIVATE+3) 		/* Read operational parameters. */
612949
#define SIOCSPARAMS (SIOCDEVPRIVATE+4) 		/* Set operational parameters. */
612949
#endif
612949
612949
const char shortopts[] = "aA:C:DfF:gG:hmM:p:rRsvVw?";
612949
struct option longopts[] = {
612949
 /* { name  has_arg  *flag  val } */
612949
    {"all-interfaces", 0, 0, 'a'},	/* Show all interfaces. */
612949
	{"advertise",	1, 0, 'A'},		/* Change the capabilities advertised. */
612949
	{"BMCR",		1, 0, 'C'},		/* Set the control register. */
612949
    {"debug",       0, 0, 'D'},		/* Increase the debug level. */
612949
    {"force",       0, 0, 'f'},		/* Force the operation. */
612949
    {"fixed-speed", 1, 0, 'F'},		/* Fixed speed name. */
612949
    {"read-parameters", 0, 0, 'g'}, /* Show general settings values. */
612949
    {"set-parameters",  1, 0, 'G'},	/* Write general settings values. */
612949
    {"help", 		0, 0, 'h'},		/* Print a long usage message. */
612949
    {"monitor",		0, 0, 'm'},		/* Monitor status register. */
612949
    {"msg-level",	1, 0, 'M'},		/* Set the driver message level. */
612949
    {"phy",			1, 0, 'p'},		/* Set the PHY (MII address) to report. */
612949
    {"restart",		0, 0, 'r'},		/* Restart the link negotiation */
612949
    {"reset",		0, 0, 'R'},		/* Reset the transceiver. */
612949
    {"status",		0, 0, 's'},		/* Non-zero exit status w/ no link beat. */
612949
    {"verbose", 	0, 0, 'v'},		/* Report each action taken.  */
612949
    {"version", 	0, 0, 'V'},		/* Emit version information.  */
612949
    {"watch", 		0, 0, 'w'},		/* Constantly monitor the port.  */
612949
    {"error", 		0, 0, '?'},		/* Return the error message. */
612949
    { 0, 0, 0, 0 }
612949
};
612949
612949
/* Usually in libmii.c, but trivial substitions are below. */
612949
extern int  show_mii_details(long ioaddr, int phy_id);
612949
extern void monitor_mii(long ioaddr, int phy_id);
612949
int  show_mii_details(long ioaddr, int phy_id) __attribute__((weak));
612949
void monitor_mii(long ioaddr, int phy_id) __attribute__((weak));
612949
612949
612949
/* Command-line flags. */
612949
unsigned int opt_a = 0,					/* Show-all-interfaces flag. */
612949
	opt_f = 0,					/* Force the operation. */
612949
	opt_g = 0,
612949
	opt_G = 0,
612949
	verbose = 0,				/* Verbose flag. */
612949
	debug = 0,
612949
	opt_version = 0,
612949
	opt_restart = 0,
612949
	opt_reset = 0,
612949
	opt_status = 0,
612949
	opt_watch = 0;
612949
static int msg_level = -1;
612949
static int set_BMCR = -1;
612949
static int nway_advertise = 0;
612949
static int fixed_speed = -1;
612949
static int override_phy = -1;
612949
char *opt_G_string = NULL;
612949
612949
/* Internal values. */
612949
int new_ioctl_nums;
612949
int skfd = -1;					/* AF_INET socket for ioctl() calls.	*/
612949
struct ifreq ifr;
612949
612949
int do_one_xcvr(int skfd);
612949
int show_basic_mii(long ioaddr, int phy_id);
612949
int mdio_read(int skfd, int phy_id, int location);
612949
void mdio_write(int skfd, int phy_id, int location, int value);
612949
static int parse_advertise(const char *capabilities);
612949
static void monitor_status(long ioaddr, int phy_id);
612949
612949
612949
int
612949
main(int argc, char **argv)
612949
{
612949
	int c, errflag = 0;
612949
	char **spp, *ifname;
612949
    char *progname = rindex(argv[0], '/') ? rindex(argv[0], '/')+1 : argv[0];
612949
612949
	while ((c = getopt_long(argc, argv, shortopts, longopts, 0)) != EOF)
612949
		switch (c) {
612949
		case 'a': opt_a++; break;
612949
		case 'A': nway_advertise |= parse_advertise(optarg);
612949
			if (nway_advertise == -1) errflag++;
612949
			break;
612949
		case 'C': set_BMCR = strtoul(optarg, NULL, 16); break;
612949
		case 'D': debug++;			break;
612949
		case 'f': opt_f++; break;
612949
		case 'F': fixed_speed = parse_advertise(optarg);
612949
			if (fixed_speed == -1) errflag++;
612949
			break;
612949
		case 'g': opt_g++; break;
612949
		case 'G': opt_G++; opt_G_string = strdup(optarg); break;
612949
		case 'm': opt_watch++; opt_status++; break;
612949
		case 'M': msg_level = strtoul(optarg, NULL, 0); break;
612949
		case 'h': fprintf(stderr, long_usage_msg, progname); return 0;
612949
		case 'p': override_phy = atoi(optarg); break;
612949
		case 'r': opt_restart++;	break;
612949
		case 'R': opt_reset++;		break;
612949
		case 's': opt_status++;		break;
612949
		case 'v': verbose++;		break;
612949
		case 'V': opt_version++;	break;
612949
		case 'w': opt_watch++;		break;
612949
		case '?': errflag++;		break;
612949
		}
612949
	if (errflag) {
612949
		fprintf(stderr, usage_msg, progname);
612949
		return 2;
612949
	}
612949
612949
	if (verbose || opt_version)
612949
		printf(version);
612949
612949
	/* Open a basic socket. */
612949
	if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
612949
		perror("socket");
612949
		return 1;
612949
	}
612949
612949
	if (debug)
612949
		fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n",
612949
				argc, optind, argv[optind]);
612949
612949
	/* No remaining args means interface wasn't specified. */
612949
	if (optind == argc) {
612949
		fprintf(stderr, "No interface specified.\n");
612949
		fprintf(stderr, usage_msg, progname);
612949
		(void) close(skfd);
612949
		return 2;
612949
	} else {
612949
		/* Copy the interface name. */
612949
		spp = argv + optind;
612949
		ifname = *spp++;
612949
	}
612949
612949
	if (ifname == NULL) {
612949
		fprintf(stderr, "No ifname.\n");
612949
		(void) close(skfd);
612949
		return -1;
612949
	}
612949
612949
	/* Verify that the interface supports the ioctl(), and if
612949
	   it is using the new or old SIOCGMIIPHY value (grrr...).
612949
	 */
612949
	{
612949
		u16 *data = (u16 *)(&ifr.ifr_data);
612949
612949
		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
612949
		ifr.ifr_name[IFNAMSIZ-1] = '\0';
612949
		data[0] = 0;
612949
612949
		if (ioctl(skfd, 0x8947, &ifr) >= 0) {
612949
			new_ioctl_nums = 1;
612949
		} else if (ioctl(skfd, SIOCDEVPRIVATE, &ifr) >= 0) {
612949
			new_ioctl_nums = 0;
612949
		} else {
612949
			fprintf(stderr, "SIOCGMIIPHY on %s failed: %s\n", ifname,
612949
					strerror(errno));
612949
			(void) close(skfd);
612949
			return 1;
612949
		}
612949
		if (verbose)
612949
			printf("  Using the %s SIOCGMIIPHY value on PHY %d "
612949
				   "(BMCR 0x%4.4x).\n",
612949
				   new_ioctl_nums ? "new" : "old", data[0], data[3]);
612949
	}
612949
612949
	do_one_xcvr(skfd);
612949
612949
	(void) close(skfd);
612949
	return 0;
612949
}
612949
612949
int do_one_xcvr(int skfd)
612949
{
612949
	u16 *data = (u16 *)(&ifr.ifr_data);
612949
	u32 *data32 = (u32 *)(&ifr.ifr_data);
612949
	unsigned phy_id = data[0];
612949
612949
	if (override_phy >= 0) {
612949
		printf("Using the specified MII PHY index %d.\n", override_phy);
612949
		phy_id = override_phy;
612949
	}
612949
612949
	if (opt_g || opt_G || msg_level >= 0) {
612949
		if (ioctl(skfd, SIOCGPARAMS, &ifr) < 0) {
612949
			fprintf(stderr, "SIOCGPARAMS on %s failed: %s\n", ifr.ifr_name,
612949
					strerror(errno));
612949
			return -1;
612949
		}
612949
	}
612949
	if (opt_g) {
612949
		int i;
612949
		printf("Driver general parameter settings:");
612949
		for (i = 0; i*sizeof(u32) < sizeof(ifr.ifr_ifru); i++) {
612949
			printf(" %d", data32[i]);
612949
		}
612949
		printf(".\n");
612949
	}
612949
	if (opt_G) {
612949
		/* Set up to four arbitrary driver parameters from the -G parameter.
612949
		   The format is comma separated integers, with a missing element
612949
		   retaining the previous value.
612949
		*/
612949
		char *str = opt_G_string;
612949
		int i;
612949
		for (i = 0; str && i < 4; i++) {
612949
			char *endstr;
612949
			u32 newval = strtol(str, &endstr, 0);
612949
			if (debug)
612949
				printf(" parse string '%s'  value %d end '%s'.\n",
612949
					   str, newval, endstr);
612949
			if (str == endstr) {
612949
				if (endstr[0] == ',') /* No parameter */
612949
					str = endstr+1;
612949
				else {
612949
					fprintf(stderr, "Invalid driver parameter '%s'.\n", str);
612949
					str = index(str, ',');
612949
				}
612949
			} else if (endstr[0] == ',') {
612949
				data32[i] = newval;
612949
				str = endstr + 1;
612949
			} else if (endstr[0] == 0) {
612949
				data32[i] = newval;
612949
				break;
612949
			}
612949
		}
612949
		printf("Setting new driver general parameters:");
612949
		for (i = 0; i*sizeof(u32) < sizeof(ifr.ifr_ifru); i++) {
612949
			printf(" %d", data32[i]);
612949
		}
612949
		printf(".\n");
612949
		if (ioctl(skfd, SIOCSPARAMS, &ifr) < 0) {
612949
			fprintf(stderr, "SIOCSPARAMS on %s failed: %s\n", ifr.ifr_name,
612949
					strerror(errno));
612949
			return -1;
612949
		}
612949
	}
612949
	if (msg_level >= 0) {
612949
		data32[0] = msg_level;
612949
		if (ioctl(skfd, SIOCSPARAMS, &ifr) < 0) {
612949
			fprintf(stderr, "SIOCSPARAMS on %s failed: %s\n", ifr.ifr_name,
612949
					strerror(errno));
612949
			return -1;
612949
		}
612949
	}
612949
612949
	if (opt_reset) {
612949
		printf("Resetting the transceiver...\n");
612949
		mdio_write(skfd, phy_id, 0, 0x8000);
612949
	}
612949
	/* Note: PHY addresses > 32 are pseudo-MII devices, usually built-in. */
612949
	if (phy_id < 64  &&  nway_advertise > 0) {
612949
		printf(" Setting the media capability advertisement register of "
612949
			   "PHY #%d to 0x%4.4x.\n", phy_id, nway_advertise | 1);
612949
		mdio_write(skfd, phy_id, 4, nway_advertise | 1);
612949
		mdio_write(skfd, phy_id, 0, 0x1000);
612949
	}
612949
612949
	if (opt_restart) {
612949
		printf("Restarting negotiation...\n");
612949
		mdio_write(skfd, phy_id, 0, 0x0000);
612949
		mdio_write(skfd, phy_id, 0, 0x1200);
612949
	}
612949
	/* To force 100baseTx-HD do  mdio_write(skfd, phy_id, 0, 0x2000); */
612949
	if (fixed_speed >= 0) {
612949
		int reg0_val = 0;
612949
		if (fixed_speed & 0x0180) 		/* 100mpbs */
612949
			reg0_val |=  0x2000;
612949
		if ((fixed_speed & 0x0140) &&		/* A full duplex type and */
612949
			! (fixed_speed & 0x0820)) 		/* no half duplex types. */
612949
			reg0_val |= 0x0100;
612949
		printf("Setting the speed to \"fixed\", Control register %4.4x.\n",
612949
			   reg0_val);
612949
		mdio_write(skfd, phy_id, 0, reg0_val);
612949
	}
612949
	if (set_BMCR >= 0) {
612949
		printf("Setting the Basic Mode Control Register to 0x%4.4x.\n",
612949
			   set_BMCR);
612949
		mdio_write(skfd, phy_id, 0, set_BMCR);
612949
	}
612949
612949
	if (opt_watch && opt_status)
612949
		monitor_status(skfd, phy_id);
612949
612949
	show_basic_mii(skfd, phy_id);
612949
#ifdef LIBMII
612949
	if (verbose)
612949
		show_mii_details(skfd, phy_id);
612949
#else
612949
	if (verbose || debug) {
612949
		int mii_reg, mii_val;
612949
		printf(" MII PHY #%d transceiver registers:", phy_id);
612949
		for (mii_reg = 0; mii_reg < 32; mii_reg++) {
612949
			mii_val = mdio_read(skfd, phy_id, mii_reg);
612949
			printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n  " : "",
612949
				   mii_val);
612949
		}
612949
		printf("\n");
612949
	}
612949
#endif
612949
612949
	if (opt_watch)
612949
		monitor_mii(skfd, phy_id);
612949
	if (opt_status &&
612949
		(mdio_read(skfd, phy_id, 1) & 0x0004) == 0)
612949
		exit(2);
612949
	return 0;
612949
}
612949
612949
int mdio_read(int skfd, int phy_id, int location)
612949
{
612949
	u16 *data = (u16 *)(&ifr.ifr_data);
612949
612949
	data[0] = phy_id;
612949
	data[1] = location;
612949
612949
	if (ioctl(skfd, new_ioctl_nums ? 0x8948 : SIOCDEVPRIVATE+1, &ifr) < 0) {
612949
		fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
612949
				strerror(errno));
612949
		return -1;
612949
	}
612949
	return data[3];
612949
}
612949
612949
void mdio_write(int skfd, int phy_id, int location, int value)
612949
{
612949
	u16 *data = (u16 *)(&ifr.ifr_data);
612949
612949
	data[0] = phy_id;
612949
	data[1] = location;
612949
	data[2] = value;
612949
612949
	if (ioctl(skfd, new_ioctl_nums ? 0x8949 : SIOCDEVPRIVATE+2, &ifr) < 0) {
612949
		fprintf(stderr, "SIOCSMIIREG on %s failed: %s\n", ifr.ifr_name,
612949
				strerror(errno));
612949
	}
612949
}
612949
612949
/* Parse the command line argument for advertised capabilities. */
612949
static int parse_advertise(const char *capabilities)
612949
{
612949
	const char *mtypes[] = {
612949
		"100baseT4", "100baseTx", "100baseTx-FD", "100baseTx-HD",
612949
		"10baseT", "10baseT-FD", "10baseT-HD", 0,
612949
	};
612949
	char *endptr;
612949
	int cap_map[] = { 0x0200, 0x0180, 0x0100, 0x0080, 0x0060, 0x0040, 0x0020,};
612949
	int i;
612949
	if ( ! capabilities) {
612949
		fprintf(stderr, "You passed -A 'NULL'.  You must provide a media"
612949
				" list to advertise!\n");
612949
		return -1;
612949
	}
612949
	if (debug)
612949
		fprintf(stderr, "Advertise string is '%s'.\n", capabilities);
612949
	for (i = 0; mtypes[i]; i++)
612949
		if (strcasecmp(mtypes[i], capabilities) == 0)
612949
			return cap_map[i];
612949
	if ((i = strtol(capabilities, &endptr, 16)) <= 0xffff  &&  endptr[0] == 0)
612949
		return i;
612949
	fprintf(stderr, "Invalid media advertisement value '%s'.\n"
612949
			"  Either pass a numeric value or one of the following names:\n",
612949
			capabilities);
612949
	for (i = 0; mtypes[i]; i++)
612949
		fprintf(stderr, "   %-14s %3.3x\n", mtypes[i], cap_map[i]);
612949
	return -1;
612949
}
612949
612949
/* Trivial versions if we don't link against libmii.c */
612949
static const char *media_names[] = {
612949
	"10baseT", "10baseT-FD", "100baseTx", "100baseTx-FD", "100baseT4",
612949
	"Flow-control", 0,
612949
};
612949
/* Various non-good bits in the command register. */
612949
static const char *bmcr_bits[] = {
612949
	"  Internal Collision-Test enabled!\n", "",		/* 0x0080,0x0100 */
612949
	"  Restarted auto-negotiation in progress!\n",
612949
	"  Transceiver isolated from the MII!\n",
612949
	"  Transceiver powered down!\n", "", "",
612949
	"  Transceiver in loopback mode!\n",
612949
	"  Transceiver currently being reset!\n",
612949
};
612949
612949
int show_basic_mii(long ioaddr, int phy_id)
612949
{
612949
	int mii_reg, i;
612949
	u16 mii_val[32];
612949
	u16 bmcr, bmsr, new_bmsr, nway_advert, lkpar;
612949
612949
	for (mii_reg = 0; mii_reg < 8; mii_reg++)
612949
		mii_val[mii_reg] = mdio_read(ioaddr, phy_id, mii_reg);
612949
	if ( ! verbose) {
612949
		printf("Basic registers of MII PHY #%d: ", phy_id);
612949
		for (mii_reg = 0; mii_reg < 8; mii_reg++)
612949
			printf(" %4.4x", mii_val[mii_reg]);
612949
		printf(".\n");
612949
	}
612949
612949
	if (mii_val[0] == 0xffff  ||  mii_val[1] == 0x0000) {
612949
		printf("  No MII transceiver present!.\n");
612949
		if (! opt_f) {
612949
			printf("  Use '--force' to view the information anyway.\n");
612949
			return -1;
612949
		}
612949
	}
612949
	/* Descriptive rename. */
612949
	bmcr = mii_val[0];
612949
	bmsr = mii_val[1];
612949
	nway_advert = mii_val[4];
612949
	lkpar = mii_val[5];
612949
612949
	if (lkpar & 0x4000) {
612949
		int negotiated = nway_advert & lkpar & 0x3e0;
612949
		int max_capability = 0;
612949
		/* Scan for the highest negotiated capability, highest priority
612949
		   (100baseTx-FDX) to lowest (10baseT-HDX). */
612949
		int media_priority[] = {8, 9, 7, 6, 5}; 	/* media_names[i-5] */
612949
		printf(" The autonegotiated capability is %4.4x.\n", negotiated);
612949
		for (i = 0; media_priority[i]; i++)
612949
			if (negotiated & (1 << media_priority[i])) {
612949
				max_capability = media_priority[i];
612949
				break;
612949
			}
612949
		if (max_capability)
612949
			printf("The autonegotiated media type is %s.\n",
612949
				   media_names[max_capability - 5]);
612949
		else
612949
			printf("No common media type was autonegotiated!\n"
612949
				   "This is extremely unusual and typically indicates a "
612949
				   "configuration error.\n" "Perhaps the advertised "
612949
				   "capability set was intentionally limited.\n");
612949
	}
612949
	printf(" Basic mode control register 0x%4.4x:", bmcr);
612949
	if (bmcr & 0x1000)
612949
		printf(" Auto-negotiation enabled.\n");
612949
	else
612949
		printf(" Auto-negotiation disabled, with\n"
612949
			   " Speed fixed at 10%s mbps, %s-duplex.\n",
612949
			   bmcr & 0x2000 ? "0" : "",
612949
			   bmcr & 0x0100 ? "full":"half");
612949
	for (i = 0; i < 9; i++)
612949
		if (bmcr & (0x0080<
612949
			printf(bmcr_bits[i]);
612949
612949
	new_bmsr = mdio_read(ioaddr, phy_id, 1);
612949
	if ((bmsr & 0x0016) == 0x0004)
612949
		printf( " You have link beat, and everything is working OK.\n");
612949
	else
612949
		printf(" Basic mode status register 0x%4.4x ... %4.4x.\n"
612949
			   "   Link status: %sestablished.\n",
612949
			   bmsr, new_bmsr,
612949
			   bmsr & 0x0004 ? "" :
612949
			   (new_bmsr & 0x0004) ? "previously broken, but now re" : "not ");
612949
	if (verbose) {
612949
		printf("   This transceiver is capable of ");
612949
		if (bmsr & 0xF800) {
612949
			for (i = 15; i >= 11; i--)
612949
				if (bmsr & (1<
612949
					printf(" %s", media_names[i-11]);
612949
		} else
612949
			printf("<Warning! No media capabilities>");
612949
		printf(".\n");
612949
		printf("   %s to perform Auto-negotiation, negotiation %scomplete.\n",
612949
			   bmsr & 0x0008 ? "Able" : "Unable",
612949
			   bmsr & 0x0020 ? "" : "not ");
612949
	}
612949
612949
	if (bmsr & 0x0010)
612949
		printf(" Remote fault detected!\n");
612949
	if (bmsr & 0x0002)
612949
		printf("   *** Link Jabber! ***\n");
612949
612949
	if (lkpar & 0x4000) {
612949
		printf(" Your link partner advertised %4.4x:",
612949
			   lkpar);
612949
		for (i = 5; i >= 0; i--)
612949
			if (lkpar & (0x20<
612949
				printf(" %s", media_names[i]);
612949
		printf("%s.\n", lkpar & 0x0400 ? ", w/ 802.3X flow control" : "");
612949
	} else if (lkpar & 0x00A0)
612949
		printf(" Your link partner is generating %s link beat  (no"
612949
			   " autonegotiation).\n",
612949
			   lkpar & 0x0080 ? "100baseTx" : "10baseT");
612949
	else if ( ! (bmcr & 0x1000))
612949
		printf(" Link partner information is not exchanged when in"
612949
			   " fixed speed mode.\n");
612949
	else if ( ! (new_bmsr & 0x004))
612949
							;	/* If no partner, do not report status. */
612949
	else if (lkpar == 0x0001  ||  lkpar == 0x0000) {
612949
		printf(" Your link partner does not do autonegotiation, and this "
612949
			   "transceiver type\n  does not report the sensed link "
612949
			   "speed.\n");
612949
	} else
612949
		printf(" Your link partner is strange, status %4.4x.\n", lkpar);
612949
612949
	printf("   End of basic transceiver information.\n\n");
612949
	return 0;
612949
}
612949
612949
static void monitor_status(long ioaddr, int phy_id)
612949
{
612949
	unsigned int baseline_1 = 0x55555555; 	/* Always show initial status. */
612949
612949
	while (1) {
612949
		unsigned int new_1 = mdio_read(ioaddr, phy_id, 1);
612949
		if (new_1 != baseline_1) {
612949
			printf("%-12s 0x%4.4x 0x%4.4x\n",
612949
				   new_1 & 0x04 ? (new_1==0xffff ? "unknown" : "up") :
612949
				   new_1 & 0x20 ? "negotiating" : "down",
612949
				   new_1, mdio_read(ioaddr, phy_id, 5));
612949
			fflush(stdout);
612949
			baseline_1 = new_1;
612949
		}
612949
		sleep(1);
612949
	}
612949
}
612949
612949
int  show_mii_details(long ioaddr, int phy_id)
612949
{
612949
	int mii_reg, mii_val;
612949
	printf(" MII PHY #%d transceiver registers:", phy_id);
612949
	for (mii_reg = 0; mii_reg < 32; mii_reg++) {
612949
		mii_val = mdio_read(skfd, phy_id, mii_reg);
612949
		printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n  " : "",
612949
			   mii_val);
612949
	}
612949
	printf("\nThis version of 'mii-diag' has not been linked with "
612949
			"the libmii.c library.\n"
612949
			"  That library provides extended transceiver status reports.\n");
612949
	return 0;
612949
}
612949
612949
void monitor_mii(long ioaddr, int phy_id)
612949
{
612949
	fprintf(stderr, "\nThis version of 'mii-diag' has not been linked with "
612949
			"the libmii.c library \n"
612949
			"  required for the media monitor option.\n");
612949
}
612949
612949
612949

612949
/*
612949
 * Local variables:
612949
 *  version-control: t
612949
 *  kept-new-versions: 5
612949
 *  c-indent-level: 4
612949
 *  c-basic-offset: 4
612949
 *  tab-width: 4
612949
 *  compile-command: "gcc -Wall -Wstrict-prototypes -O mii-diag.c -DLIBMII libmii.c -o mii-diag"
612949
 *  simple-compile-command: "gcc mii-diag.c -o mii-diag"
612949
 * End:
612949
 */