From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-lb0-f177.google.com ([209.85.217.177]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TKxIF-0000XS-Dg for barebox@lists.infradead.org; Sun, 07 Oct 2012 20:17:44 +0000 Received: by mail-lb0-f177.google.com with SMTP id gi11so2400703lbb.36 for ; Sun, 07 Oct 2012 13:17:40 -0700 (PDT) From: Antony Pavlov Date: Mon, 8 Oct 2012 00:17:33 +0400 Message-Id: <1349641053-18685-1-git-send-email-antonynpavlov@gmail.com> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: barebox-bounces@lists.infradead.org Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [RFC] add 'miitool' command to view media-independent interface status To: barebox@lists.infradead.org This command is based on "mii-diag" and "mii-tool" programs. TODO: * drop MII_ANER_ and MII_AN_, use linux/mii.h macros; * add routines to manipulate media-independent interface state. EXAMPLES: barebox:/ mii_tool -v /dev/phy0 negotiated 100baseTx-FD, link ok barebox:/ mii_tool -v /dev/phy0 negotiated 100baseTx-FD, link ok product info: Level One LXT971A rev 2 basic mode: autonegotiation enabled basic status: autonegotiation complete, link ok capabilities: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD advertising: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD link partner: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control barebox:/ mii_tool -vv /dev/phy0 negotiated 100baseTx-FD, link ok registers for MII PHY: 3100 782d 0013 78e2 01e1 45e1 0007 2001 0000 ffff ffff ffff ffff ffff ffff ffff 0084 4780 0000 0000 0422 0000 0000 0000 0000 0000 0080 0000 ffff 0000 0000 3660 product info: Level One LXT971A rev 2 basic mode: autonegotiation enabled basic status: autonegotiation complete, link ok capabilities: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD advertising: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD link partner: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control Signed-off-by: Antony Pavlov --- commands/Kconfig | 8 ++ commands/Makefile | 1 + commands/miitool.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mii.h | 25 +++++ 4 files changed, 300 insertions(+) create mode 100644 commands/miitool.c diff --git a/commands/Kconfig b/commands/Kconfig index e934f29..7da722f 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -620,6 +620,14 @@ config CMD_USB help The usb command allows to rescan for USB devices. +config CMD_MIITOOL + bool + prompt "miitool command" + depends on NET + default y + help + The miitool command allows to view media-independent interface status. + config CMD_CLK tristate depends on COMMON_CLK diff --git a/commands/Makefile b/commands/Makefile index 610be55..c6416ca 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -76,3 +76,4 @@ obj-$(CONFIG_CMD_READLINK) += readlink.o obj-$(CONFIG_CMD_LN) += ln.o obj-$(CONFIG_CMD_CLK) += clk.o obj-$(CONFIG_CMD_TFTP) += tftp.o +obj-$(CONFIG_CMD_MIITOOL) += miitool.o diff --git a/commands/miitool.c b/commands/miitool.c new file mode 100644 index 0000000..5303531 --- /dev/null +++ b/commands/miitool.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2012 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is based on Donald Becker's "mii-diag" and + * David A. Hinds's "mii-tool". + * + * mii-tool is written/copyright 2000 by David A. Hinds + * + * + * mii-diag is written/copyright 1997-2000 by Donald Becker + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CMD_MII_TOOL_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +static u16 mdio_read(int fd, int offset) +{ + int ret; + u16 buf; + + ret = lseek(fd, offset << 1, SEEK_SET); + if (ret < 0) { + return 0; + } + + ret = read(fd, &buf, sizeof(u16)); + if (ret < 0) { + return 0; + } + + return buf; +} + +/* Table of known MII's */ +static struct { + u_short id1, id2; + u_short mask1, mask2; + char *name; +} mii_id[] = { + { 0x7810, 0x0003, 0xffff, 0xffff, "Level One LXT970A" }, + { 0x7810, 0x0000, 0xffff, 0xfff0, "Level One LXT970/LXT971" }, + { 0x0013, 0x78e0, 0xffff, 0xfff0, "Level One LXT971A" }, +}; +#define NMII (sizeof(mii_id)/sizeof(mii_id[0])) + +const struct { + char *name; + u_short value; +} media[] = { + /* The order through 100baseT4 matches bits in the BMSR */ + { "10baseT-HD", MII_AN_10BASET_HD }, + { "10baseT-FD", MII_AN_10BASET_FD }, + { "100baseTx-HD", ADVERTISE_100HALF }, + { "100baseTx-FD", ADVERTISE_100FULL }, + { "100baseT4", LPA_100BASE4 }, + { "100baseTx", ADVERTISE_100FULL | ADVERTISE_100HALF }, + { "10baseT", MII_AN_10BASET_FD | MII_AN_10BASET_HD }, +}; +#define NMEDIA (sizeof(media)/sizeof(media[0])) + +static char *media_list(int mask, int best) +{ + static char buf[100]; + int i; + *buf = '\0'; + mask >>= 5; + for (i = 4; i >= 0; i--) { + if (mask & (1 << i)) { + strcat(buf, " "); + strcat(buf, media[i].name); + if (best) break; + } + } + if (mask & (1 << 5)) + strcat(buf, " flow-control"); + + return buf; +} + +static int verbose = 0; + +static int show_basic_mii(int fd) +{ + char buf[100]; + int i, mii_val[32]; + int bmcr, bmsr, advert, lkpar; + + /* 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(fd, MII_BMSR); + for (i = 0; i < ((verbose > 1) ? 32 : 8); i++) + mii_val[i] = mdio_read(fd, i); + + if (mii_val[MII_BMCR] == 0xffff) { + fprintf(stderr, " No MII transceiver present!.\n"); + return -1; + } + + /* Descriptive rename. */ + bmcr = mii_val[MII_BMCR]; bmsr = mii_val[MII_BMSR]; + advert = mii_val[MII_ADVERTISE]; lkpar = mii_val[MII_LPA]; + + buf[0] = 0; + if (bmcr & BMCR_ANENABLE) { + if (bmsr & BMSR_ANEGCOMPLETE) { + if (advert & lkpar) { + strcat(buf, (lkpar & LPA_LPACK) ? + "negotiated" : "no autonegotiation,"); + strcat(buf, media_list(advert & lkpar, 1)); + strcat(buf, ", "); + } else { + strcat(buf, "autonegotiation failed, "); + } + } else if (bmcr & BMCR_ANRESTART) { + strcat(buf, "autonegotiation restarted, "); + } + } else { + sprintf(buf+strlen(buf), "%s Mbit, %s duplex, ", + (bmcr & BMCR_SPEED100) ? "100" : "10", + (bmcr & BMCR_FULLDPLX) ? "full" : "half"); + } + strcat(buf, (bmsr & BMSR_LSTATUS) ? "link ok" : "no link"); + + printf("%s\n", buf); + + if (verbose > 1) { + printf(" registers for MII PHY: "); + for (i = 0; i < 32; i++) + printf("%s %4.4x", ((i % 8) ? "" : "\n "), mii_val[i]); + + printf("\n"); + } + + if (verbose) { + printf(" product info: "); + for (i = 0; i < NMII; i++) + if ((mii_id[i].id1 == (mii_val[2] & mii_id[i].mask1)) && + (mii_id[i].id2 == (mii_val[3] & mii_id[i].mask2))) + break; + + if (i < NMII) + printf("%s rev %d\n", mii_id[i].name, mii_val[3]&0x0f); + else + printf("vendor %02x:%02x:%02x, model %d rev %d\n", + mii_val[2]>>10, (mii_val[2]>>2)&0xff, + ((mii_val[2]<<6)|(mii_val[3]>>10))&0xff, + (mii_val[3]>>4)&0x3f, mii_val[3]&0x0f); + + printf(" basic mode: "); + if (bmcr & BMCR_RESET) + printf("software reset, "); + if (bmcr & BMCR_LOOPBACK) + printf("loopback, "); + if (bmcr & BMCR_ISOLATE) + printf("isolate, "); + if (bmcr & BMCR_CTST) + printf("collision test, "); + if (bmcr & BMCR_ANENABLE) { + printf("autonegotiation enabled\n"); + } else { + printf("%s Mbit, %s duplex\n", + (bmcr & BMCR_SPEED100) ? "100" : "10", + (bmcr & BMCR_FULLDPLX) ? "full" : "half"); + } + printf(" basic status: "); + if (bmsr & BMSR_ANEGCOMPLETE) + printf("autonegotiation complete, "); + else if (bmcr & BMCR_ANRESTART) + printf("autonegotiation restarted, "); + 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)); + + if (lkpar & MII_AN_ABILITY_MASK) + printf("\n link partner:%s", media_list(lkpar, 0)); + printf("\n"); + } + + return 0; +} + +static int do_miitool(int argc, char *argv[]) +{ + char *filename; + int opt; + int argc_min; + int fd; + + verbose = 0; + while ((opt = getopt(argc, argv, "v")) > 0) { + switch (opt) { + case 'v': + verbose++; + break; + } + } + + argc_min = optind + 1; + + if (argc < argc_min) + return COMMAND_ERROR_USAGE; + + filename = argv[optind]; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("unable to read %s\n", filename); + return COMMAND_ERROR; + } + + show_basic_mii(fd); + + close(fd); + + return COMMAND_SUCCESS; +} + +BAREBOX_CMD_HELP_START(miitool) +BAREBOX_CMD_HELP_USAGE("miitool [[[-v] -v] -v] \n") +BAREBOX_CMD_HELP_SHORT("view status for MII .\n") +BAREBOX_CMD_HELP_END + +/** + * @page miitool_command +This utility checks or sets the status of a network interface's +Media Independent Interface (MII) unit. Most fast ethernet +adapters use an MII to autonegotiate link speed and duplex setting. + */ +BAREBOX_CMD_START(miitool) + .cmd = do_miitool, + .usage = "view media-independent interface status", + BAREBOX_CMD_HELP(cmd_miitool_help) +BAREBOX_CMD_END diff --git a/include/linux/mii.h b/include/linux/mii.h index 5bac6c2..e685b6c 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -90,6 +90,31 @@ #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ ADVERTISE_100HALF | ADVERTISE_100FULL) +/* 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 + /* Link partner ability register. */ #define LPA_SLCT 0x001f /* Same as advertise selector */ #define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox