From 32c8037055f5fdaba9c9f401fd532c02571b66d7 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 25 Oct 2005 01:56:48 -0400 Subject: Initial import of ethtool version 3 + a few patches. --- AUTHORS | 7 + ChangeLog | 351 ++++++++++ Makefile.am | 13 + NEWS | 78 +++ README | 2 + amd8111e.c | 305 +++++++++ autogen.sh | 11 + configure.ac | 26 + de2104x.c | 783 ++++++++++++++++++++++ e100.c | 238 +++++++ e1000.c | 438 ++++++++++++ ethtool-copy.h | 366 ++++++++++ ethtool-util.h | 42 ++ ethtool.8 | 384 +++++++++++ ethtool.c | 2003 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ethtool.spec.in | 42 ++ fec_8xx.c | 81 +++ natsemi.c | 985 +++++++++++++++++++++++++++ pcnet32.c | 222 ++++++ realtek.c | 517 ++++++++++++++ tg3.c | 23 + 21 files changed, 6917 insertions(+) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 amd8111e.c create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 de2104x.c create mode 100644 e100.c create mode 100644 e1000.c create mode 100644 ethtool-copy.h create mode 100644 ethtool-util.h create mode 100644 ethtool.8 create mode 100644 ethtool.c create mode 100644 ethtool.spec.in create mode 100644 fec_8xx.c create mode 100644 natsemi.c create mode 100644 pcnet32.c create mode 100644 realtek.c create mode 100644 tg3.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b2b9043 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +David Miller +Jakub Jelinek +Jeff Garzik +Tim Hockin +Eli Kupermann +Chris Leech +Scott Feldman diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..379c0bb --- /dev/null +++ b/ChangeLog @@ -0,0 +1,351 @@ + + +NOTE: For further changelog entries, see BitKeeper repository. + + +Tue Aug 17 2004 Jeff Garzik + + * NEWS, configure.ac: Release version 2 + +Fri Jul 2 2004 Jeff Garzik + + Merged + * fec_8xx.c, ethtool-util.h, Makefile.am: Add fec_8xx register dump. + Contributed by Pantelis Antoniou + + * Update ethtool.c to iterate through a list of drivers + * Fixed fec_8xx.c warnings on 64-bit + +Fri Jul 2 2004 Jim Lewis + + * pcnet32.c, ethtool-util.h, Makefile.am: Add pcnet32 register dump. + +Fri Apr 9 2004 Jason Lunz + + * ethtool.c: Remove incorrect restriction on ethernet interface + names. + +Fri Apr 9 2004 OGAWA Hirofumi + + * ethtool.c: This fixes the bogus tail backslash that I did. + +Fri Apr 9 2004 Jim Lewis + + * ethtool.c: Return results of self-test back to OS, + via exit(2). + +Fri Apr 9 2004 Jeb Cramer + + * e1000.c: Update device id list and add printout of phy type in + register dump. Set default mac_type to 82543 since register offsets + haven't changed. + +Fri Apr 9 2004 Jeff Garzik + + * configure.ac, Makefile.am, ethtool.c, etc.: + convert to more recent autoconf. + +Sat Aug 30 2003 OGAWA Hirofumi + + * ethtool.8, ethtool.c: ethtool register dump raw mode + +Sat Jul 19 2003 Scott Feldman + + * ethtool.8, ethtool.c, ethtool-copy.h: + Add support for TSO get/set. Corresponds to NETIF_F_TSO. + Extended -k|K option to included tso, and changed meaning from + just "checksum/sg" to more general "offload". Now covers Rx/Tx + csum, SG, and TSO. + +Thu May 28 2003 Ganesh Venkatesan + + * ethtool-copy.h: new definitions for 10GbE + +Thu May 28 2003 Scott Feldman + + * ethtool.c: Add ethtool -E to write EEPROM byte. + * e100.c: Added MDI/MDI-X status to register dump. + +Thu May 28 2003 Reeja John + + * amd8111e.c: new file, support for AMD-8111e NICs + * ethtool.c: properly set ecmd.advertising + +Sat Mar 29 2003 OGAWA Hirofumi + + * realtek.c: clean up chip enumeration, support additional chips + +Fri Mar 28 2003 Jeb Cramer + + * e1000.c: Update supported devices (82541 & 82547). Add bus type, + speed and width to register dump printout. + * ethtool.c (show_usage): Add -S to printout of supported commands. + +Tue Jan 22 2003 Jeff Garzik + + * natsemi.c (PRINT_INTR, __print_intr): Decompose PRINT_INTR + macro into macro abuse and function call portions. Move the + actual function body to new static functoin __print_intr. + + This eliminates the annoying build warning :) + +Thu Jan 16 2003 Jeb Cramer + + * ethtool.c (do_regs, dump_eeprom): Fix memory leaks on failed + operations. Add error handling of dump_regs(). Modify printout of + eeprom dump to accomodate larger eeproms. + * e1000.c: Update supported devices. Add error conditions for + unsupported devices. + +Mon Oct 21 2002 Ben Collins + + * ethtool.c: Add new parameters to -e, for raw EEPROM output, and + offset and length options. + * natsemi.c (natsemi_dump_eeprom): Show correct offset using new + offset feature above. + * tg3.c: New file, implements tg3_dump_eeprom. + * Makefile.am: Add it to the build sources. + * ethtool-util.h: Prototype tg3_dump_eeprom. + * ethtool.8: Document new -e options. + +Thu Oct 17 2002 Tim Hockin + + * ethtool.c: make calls to strtol() use base 0 + +Wed Sep 18 2002 Scott Feldman + + * ethtool.c (dump_regs): call e100_dump_regs if e100 + * e100.c: new file + * ethtool-util.h: prototype e100_dump_regs + +Thu Jun 20 2002 Jeff Garzik + + * ethtool.8: document new -S stats dump argument + * configure.in, NEWS: release version 1.6 + +Fri Jun 14 2002 Jeff Garzik + + * realtek.c (realtek_dump_regs): dump legacy 8139 registers + * ethtool.c (do_gstats, doit, parse_cmdline): + support dumping of NIC-specific statistics + +Fri Jun 14 2002 Jeff Garzik + + * realtek.c (realtek_dump_regs): dump RTL8139C+ registers + +Fri Jun 14 2002 Jeff Garzik + + * realtek.c: new file, dumps RealTek RTL8169 PCI NIC's registers + * Makefile.am, ethtool.c, ethtool-util.h: use it + +Tue Jun 11 2002 Jeff Garzik + + * NEWS: list new commands added recently + * ethtool.c (do_gcoalesce, do_scoalesce, dump_coalesce): new + (parse_cmdline, doit): handle get/set coalesce parameters (-c,-C) + (do_[gs]*): convert to use table-driven cmd line parsing + * ethtool.8: document -c and -C + +Tue Jun 11 2002 Jeff Garzik + + * ethtool.c (do_gring, do_sring, dump_ring, + parse_ring_cmdline): new functions + (parse_cmdline, doit): handle get/set ring parameters (-g,-G) + (do_spause): fix off-by-one bugs + * ethtool.8: document -g and -G + +Tue Jun 11 2002 Jeff Garzik + + * ethtool.c (do_gpause, do_spause, dump_pause, + parse_pause_cmdline): new functions + (parse_cmdline, doit): handle get/set pause parameters (-a,-A) + * ethtool.8: document -a, -A, -e, and -p + +Wed May 22 2002 Chris Leech + Scott Feldman + + * ethtool-copy.h: add support for ETHTOOL_PHYS_ID function. + * ethtool.c: add support for ETHTOOL_PHYS_ID function, add + support for e1000 reg dump. + * Makefile.am: add e1000.c + * e1000.c: reg dump support for Intel(R) PRO/1000 adapters. + * ethtool-util.h: add e1000 reg dump support. + +Sat May 11 2002 Eli Kupermann + + * ethtool.c (do_test): add support for online/offline test modes + Elsewhere: document "-t" arg usage, and handle usage + +Sat May 11 2002 Jes Sorensen + + * ethtool.c (dump_ecmd): If unknown value is + encountered in speed, duplex, or port ETHTOOL_GSET + return data, print the numeric value returned. + +Wed May 1 2002 Eli Kupermann + + * ethtool.8: document new -t test option + +Wed May 1 2002 Christoph Hellwig + + * Makefile.am (dist-hook): Use $(top-srcdir) for refering to sources. + +Mon Apr 29 2002 Christoph Hellwig + + * Makefile.am (SUBDIRS): Remove. + (RPMSRCS): Likewise. + (TMPDIR): Likewise. + (rpm): Likewise. + (EXTRA_DIST): Add ethtool.spec.in. + (dist-hook): New rule. Create rpm specfile. + * configure.in (AC_OUTPUT): Add ethtool.spec. + * ethtool.spec.in: New file. Rpm specfile template. + * redhat/ethtool.spec.in: Removed. + * redhat/Makefile.am: Removed. + +Wed Mar 20 2002 Jeff Garzik + + * ethtool-copy.h: Merge coalescing param, ring + param, and pause param ioctl structs from kernel 2.5.7. + Merge ethtool_test changes fromkernel 2.5.7. + * ethtool: Update for ethtool_test cleanups. + +Wed Mar 20 2002 Eli Kupermann + + * ethtool.c: (do_test): new function + Elsewhere: add support for 'perform test' function, + via a new "-t" arg, by calling do_test. + +Sun Mar 3 2002 Brad Hards + + * ethtool.c (parse_cmdline): Support "usb" + as well as "eth" network interfaces. USB networking + uses a different prefix. + +Fri Feb 8 2002 "Noam, Amir" , + "Kupermann, Eli" + + * ethtool.c (dump_advertised): new function. + (dump_ecmd): Call it. + Elsewhere: reformat code. + +Wed Nov 28 2001 Jeff Garzik + + * configure.in, Makefile.am, redhat/Makefile.am: + make sure redhat spec is included in dist tarball. + +Tue Nov 27 2001 Tim Hockin + + * natsemi.c: strings changes + * ethtool.c: print messagelevel as hex (netif_msg_* shows better :) + +Sun Nov 18 2001 Jeff Garzik + + * NEWS: update with recent changes + * ethtool.8: phy address can be used if implemented in the + driver, so remove "Not used yet" remark. + +Sun Nov 18 2001 Jeff Garzik + + * Makefile.am, de2104x.c, ethtool-util.h, ethtool.c: + Support register dumps for de2104x driver. + +Tue Nov 13 2001 Tim Hockin + + * natsemi.c, ethtool.c: use u8 data for ethtool_regs + * ethtool-copy.h: latest from kernel + * natsemi.c, ethtool.c: support ETHTOOL_GEEPROM via -e param + +Mon Nov 12 2001 Tim Hockin + + * natsemi.c: check version, conditionally print RFCR-indexed data + +Wed Nov 07 2001 Tim Hockin + + * ethtool.c: print less errors for unsupported ioctl()s + * ethtool.c: warn if all ioctl()s are unsupported or failed + * ethtool.c: change autoneg-restart mechanism to -r (as per jgarzik) + * ethtool.c: check for "eth" in devicename (per jg) + * ethtool.c: remove 'extraneous' braces + +Wed Nov 07 2001 Jeff Garzik + + * ethtool.c, ethtool.8: support bnc port/media + +Tue Nov 06 2001 Tim Hockin + + * ethtool.c: clean up output for unhandled register dumps + * natsemi.c: finish pretty-printing register dumps + * ethtool.8: document -d option + * various: add copyright info, where applicable + * ethtool.c: be nicer about unsupported ioctl()s where possible + and be more verbose where nice is not an option. + +Mon Nov 05 2001 Tim Hockin + + * natsemi.c: first cut at 'pretty-printing' register dumps + +Fri Nov 02 2001 Tim Hockin + + * ethtool.c: add support for ETHTOOL_GREGS via -d (dump) flag + * ethtool.c: add support for device-specific dumps for known devices + * ethtool.c: make mode-specific handling allocate ifr_data + * Makefile.am: import ChangeLog to rpm specfile + * natsemi.c: added + * ethtool-util.h: added + +Thu Nov 01 2001 Tim Hockin + + * ethtool.c: add support for ETHTOOL_GLINK in output + * ethtool.c: add support for ETHTOOL_NWAY_RST via 'autoneg restart' + * ethtool.c: add support for ETHTOOL_[GS]MSGLVL via 'msglvl' param + * ethtool.8: add documentation for above + * ethtool-copy.h: updated to sync with kernel + +Fri Oct 26 2001 Jeff Garzik + + * ethtool.8: Update contributors list, home page URL. + * ethtool.8: Much cleanup, no content change. + Contributed by Andre Majorel. + * ethtool.c: Clean up '-h' usage message. + Contributed by Andre Majorel. + +Fri Oct 26 2001 Jeff Garzik + + * Configure.in: bump version to 1.4cvs + * Makefile.am: include ethtool-copy.h in list of sources + * ethtool-copy.h: + Import ethtool.h from kernel 2.4.13. + * ethtool.c: + Define SIOCETHTOOL if it is missing, + trim trailing whitespace. + * NEWS: update for these changes + +Wed Sep 19 2001 Jeff Garzik + + * ethtool.c, ethtool-copy.h: + Import copy of kernel 2.4.10-pre12's ethtool.h. + +Wed Sep 19 2001 Tim Hockin + + * Makefile.am, redhat/ethtool.spec.in: + Basic "make rpm" support. + +Wed Sep 19 2001 Tim Hockin + + * AUTHORS, NEWS, ethtool.8, ethtool.c: + Wake-on-LAN support. + +Thu May 17 2001 Jeff Garzik + + * configure.in, NEWS, README: Version 1.2 release + + * ethtool.c: Support ETHTOOL_GDRVINFO. + * ethtool.8: Document it. + +Fri Mar 20 2001 Jeff Garzik + + * Makefile.am, configure.in, autogen.sh, NEWS, + ChangeLog, AUTHORS, README: + Add autoconf/automake support. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e6b83cd --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +AM_CFLAGS = -Wall + +man_MANS = ethtool.8 +EXTRA_DIST = ethtool.8 ethtool.spec.in aclocal.m4 ChangeLog autogen.sh + +sbin_PROGRAMS = ethtool +ethtool_SOURCES = de2104x.c ethtool.c ethtool-copy.h ethtool-util.h natsemi.c \ + e1000.c realtek.c e100.c tg3.c amd8111e.c pcnet32.c \ + fec_8xx.c + +dist-hook: + cp $(top_srcdir)/ethtool.spec $(distdir) + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..3e0086f --- /dev/null +++ b/NEWS @@ -0,0 +1,78 @@ + +Version 3 - January 27, 2005 + + * Feature: r8159 register dump support + * Feature / bug fix: Support advertising gigabit ethernet + * Bug fix: make sure to advertise 10baseT-HD + * Other minor bug fixes. + +Version 2 - August 17, 2004 + + * Feature: ethtool register dump raw mode + * Feature: return results of self-test back to OS via exit(2) + * Feature: add verbose register dump for pcnet32, fec_8xx + * Maintenance: update to more recent autoconf + * Maintenance: minor updates to e1000-specific module + * Bug fix: Remove silly restriction on ethernet interface naming + +Version 1.8 - July 19, 2003 + + * Feature: Support amd8111e register dumps + * Feature: Support TSO enable/disable + * Feature: Support 10 gigabit ethernet + * Feature: Support writing EEPROM data + * Feature: Output e100 MDI/MDI-x status in register dump + * Feature: Clean up RealTek (RTL) chip output, support new chips. + * Feature: More supported e1000 devices. + * Bug fix: Properly set ecmd.advertising + * Bug fix: Fix leaks, handle some error conditions better. + +Version 1.7 - October 21, 2002 + + * Feature: Support e100 register dumps + * Feature: Support tg3 eeprom dumps + * Feature: Support partial eeprom dumps (with non-zero offsets) + * Feature: Support decimal/octal/hex numbers transparently, + at the user's discretion. + +Version 1.6 - June 20, 2002 + + * Feature: Support e1000 register dumps + * Feature: Support RealTek RTL-8139C+ and RTL-8169 register dumps + * Feature: Support coalescing config (ETHTOOL_[GS]COALESCE) + * Feature: Support ring param config (ETHTOOL_[GS]RINGPARAM) + * Feature: Support pause param config (ETHTOOL_[GS]PAUSEPARAM) + * Feature: Support physical NIC identification (ETHTOOL_PHYS_ID) + * Feature: Support NIC self-testing (ETHTOOL_TEST) + * Feature: Support NIC checksum/scatter-gather configuration + (ETHTOOL_[GS]RXCSUM, ETHTOOL_[GS]TXCSUM, ETHTOOL_[GS]SG) + +Version 1.5 - Mar 4, 2002 + + * Fix: support usb network interfaces + * Fix: include redhat spec file in autoconf build system + * Fix: minor fixes to natsemi register dump + * Feature: report advertised as well as supported media, + when printing device settings. + +Version 1.4 - Nov 19, 2001 + + * Support builds on configurations missing SIOCETHTOOL constant. + * Import ethtool.h from kernel 2.4.15-pre6. + * Support retrieval/setting of per-driver debug levels + (ETHTOOL G/SMSGLVL) + * Support pretty-printing register dumps on natsemi, de2104x + (ETHTOOL GREGS) + * Support restarting autonegotiation (ETHTOOL NWAY_RST) + * Support obtaining link status (ETHTOOL GLINK) + +Version 1.3 - Aug 02, 2001 + + * Support Wake-on-LAN (ETHTOOL GWOL and ETHTOOL SWOL ioctl). + +Version 1.2 - May 17, 2001 + + * Support ETHTOOL_GDRVINFO ioctl, which obtains + information from the ethernet driver associated + with the specified interface. + diff --git a/README b/README new file mode 100644 index 0000000..9e03205 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +ethtool is a small utility for examining and tuning your ethernet-based +network interface. See the man page for more details. diff --git a/amd8111e.c b/amd8111e.c new file mode 100644 index 0000000..b4cd65d --- /dev/null +++ b/amd8111e.c @@ -0,0 +1,305 @@ + +/* Copyright (C) 2003 Advanced Micro Devices Inc. */ +#include +#include "ethtool-util.h" + +typedef enum { + /* VAL2 */ + RDMD0 = (1 << 16), + /* VAL1 */ + TDMD3 = (1 << 11), + TDMD2 = (1 << 10), + TDMD1 = (1 << 9), + TDMD0 = (1 << 8), + /* VAL0 */ + UINTCMD = (1 << 6), + RX_FAST_SPND = (1 << 5), + TX_FAST_SPND = (1 << 4), + RX_SPND = (1 << 3), + TX_SPND = (1 << 2), + INTREN = (1 << 1), + RUN = (1 << 0), + + CMD0_CLEAR = 0x000F0F7F, /* Command style register */ + +}CMD0_BITS; +typedef enum { + + /* VAL3 */ + CONDUIT_MODE = (1 << 29), + /* VAL2 */ + RPA = (1 << 19), + DRCVPA = (1 << 18), + DRCVBC = (1 << 17), + PROM = (1 << 16), + /* VAL1 */ + ASTRP_RCV = (1 << 13), + RCV_DROP0 = (1 << 12), + EMBA = (1 << 11), + DXMT2PD = (1 << 10), + LTINTEN = (1 << 9), + DXMTFCS = (1 << 8), + /* VAL0 */ + APAD_XMT = (1 << 6), + DRTY = (1 << 5), + INLOOP = (1 << 4), + EXLOOP = (1 << 3), + REX_RTRY = (1 << 2), + REX_UFLO = (1 << 1), + REX_LCOL = (1 << 0), + + CMD2_CLEAR = 0x3F7F3F7F, /* Command style register */ + +}CMD2_BITS; +typedef enum { + + /* VAL3 */ + ASF_INIT_DONE_ALIAS = (1 << 29), + /* VAL2 */ + JUMBO = (1 << 21), + VSIZE = (1 << 20), + VLONLY = (1 << 19), + VL_TAG_DEL = (1 << 18), + /* VAL1 */ + EN_PMGR = (1 << 14), + INTLEVEL = (1 << 13), + FORCE_FULL_DUPLEX = (1 << 12), + FORCE_LINK_STATUS = (1 << 11), + APEP = (1 << 10), + MPPLBA = (1 << 9), + /* VAL0 */ + RESET_PHY_PULSE = (1 << 2), + RESET_PHY = (1 << 1), + PHY_RST_POL = (1 << 0), + +}CMD3_BITS; +typedef enum { + + INTR = (1 << 31), + PCSINT = (1 << 28), + LCINT = (1 << 27), + APINT5 = (1 << 26), + APINT4 = (1 << 25), + APINT3 = (1 << 24), + TINT_SUM = (1 << 23), + APINT2 = (1 << 22), + APINT1 = (1 << 21), + APINT0 = (1 << 20), + MIIPDTINT = (1 << 19), + MCCINT = (1 << 17), + MREINT = (1 << 16), + RINT_SUM = (1 << 15), + SPNDINT = (1 << 14), + MPINT = (1 << 13), + SINT = (1 << 12), + TINT3 = (1 << 11), + TINT2 = (1 << 10), + TINT1 = (1 << 9), + TINT0 = (1 << 8), + UINT = (1 << 7), + STINT = (1 << 4), + RINT0 = (1 << 0), + +}INT0_BITS; +typedef enum { + + /* VAL3 */ + LCINTEN = (1 << 27), + APINT5EN = (1 << 26), + APINT4EN = (1 << 25), + APINT3EN = (1 << 24), + /* VAL2 */ + APINT2EN = (1 << 22), + APINT1EN = (1 << 21), + APINT0EN = (1 << 20), + MIIPDTINTEN = (1 << 19), + MCCIINTEN = (1 << 18), + MCCINTEN = (1 << 17), + MREINTEN = (1 << 16), + /* VAL1 */ + SPNDINTEN = (1 << 14), + MPINTEN = (1 << 13), + TINTEN3 = (1 << 11), + SINTEN = (1 << 12), + TINTEN2 = (1 << 10), + TINTEN1 = (1 << 9), + TINTEN0 = (1 << 8), + /* VAL0 */ + STINTEN = (1 << 4), + RINTEN0 = (1 << 0), + + INTEN0_CLEAR = 0x1F7F7F1F, /* Command style register */ + +}INTEN0_BITS; + +typedef enum { + + PMAT_DET = (1 << 12), + MP_DET = (1 << 11), + LC_DET = (1 << 10), + SPEED_MASK = (1 << 9)|(1 << 8)|(1 << 7), + FULL_DPLX = (1 << 6), + LINK_STATS = (1 << 5), + AUTONEG_COMPLETE = (1 << 4), + MIIPD = (1 << 3), + RX_SUSPENDED = (1 << 2), + TX_SUSPENDED = (1 << 1), + RUNNING = (1 << 0), + +}STAT0_BITS; + +#define PHY_SPEED_10 0x2 +#define PHY_SPEED_100 0x3 + + +int amd8111e_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + + u32 *reg_buff = (u32 *)regs->data; + u32 reg; + + fprintf(stdout, "Descriptor Registers\n"); + fprintf(stdout, "---------------------\n"); + + /* Transmit descriptor base address register */ + reg = reg_buff[0]; + fprintf(stdout, + "0x00100: Transmit descriptor base address register %08X\n",reg); + + /* Transmit descriptor length register */ + reg = reg_buff[1]; + fprintf(stdout, + "0x00140: Transmit descriptor length register 0x%08X\n",reg); + + /* Receive descriptor base address register */ + reg = reg_buff[2]; + fprintf(stdout, + "0x00120: Receive descriptor base address register %08X\n",reg); + + /* Receive descriptor length register */ + reg = reg_buff[3]; + fprintf(stdout, + "0x00150: Receive descriptor length register 0x%08X\n",reg); + + fprintf(stdout, "\n"); + + + fprintf(stdout, "Command Registers\n"); + fprintf(stdout, "-------------------\n"); + + /* Command 0 Register */ + reg = reg_buff[4]; + fprintf(stdout, + "0x00048: Command 0 register 0x%08X\n" + " Interrupts: %s\n" + " Device: %s\n", + reg, + reg & INTREN ? "Enabled" : "Disabled", + reg & RUN ? "Running" : "Stopped"); + + /* Command 2 Register */ + reg = reg_buff[5]; + fprintf(stdout, + "0x00050: Command 2 register 0x%08X\n" + " Promiscuous mode: %s\n" + " Retransmit on underflow: %s\n", + reg, + reg & PROM ? "Enabled" : "Disabled", + reg & REX_UFLO ? "Enabled" : "Disabled"); + /* Command 3 Register */ + reg = reg_buff[6]; + fprintf(stdout, + "0x00054: Command 3 register 0x%08X\n" + " Jumbo frame: %s\n" + " Admit only VLAN frame: %s\n" + " Delete VLAN tag: %s\n", + reg, + reg & JUMBO ? "Enabled" : "Disabled", + reg & VLONLY ? "Yes" : "No", + reg & VL_TAG_DEL ? "Yes" : "No"); + + /* Command 7 Register */ + reg = reg_buff[7]; + fprintf(stdout, + "0x00064: Command 7 register 0x%08X\n", + reg); + + fprintf(stdout, "\n"); + fprintf(stdout, "Interrupt Registers\n"); + fprintf(stdout, "-------------------\n"); + + /* Interrupt 0 Register */ + reg = reg_buff[8]; + fprintf(stdout, + "0x00038: Interrupt register 0x%08X\n" + " Any interrupt is set: %s\n" + " Link change interrupt: %s\n" + " Register 0 auto-poll interrupt: %s\n" + " Transmit interrupt: %s\n" + " Software timer interrupt: %s\n" + " Receive interrupt: %s\n", + reg, + reg & INTR ? "Yes" : "No", + reg & LCINT ? "Yes" : "No", + reg & APINT0 ? "Yes" : "No", + reg & TINT0 ? "Yes" : "No", + reg & STINT ? "Yes" : "No", + reg & RINT0 ? "Yes" : "No" + ); + /* Interrupt 0 enable Register */ + reg = reg_buff[9]; + fprintf(stdout, + "0x00040: Interrupt enable register 0x%08X\n" + " Link change interrupt: %s\n" + " Register 0 auto-poll interrupt: %s\n" + " Transmit interrupt: %s\n" + " Software timer interrupt: %s\n" + " Receive interrupt: %s\n", + reg, + reg & LCINTEN ? "Enabled" : "Disabled", + reg & APINT0EN ? "Enabled" : "Disabled", + reg & TINTEN0 ? "Enabled" : "Disabled", + reg & STINTEN ? "Enabled" : "Disabled", + reg & RINTEN0 ? "Enabled" : "Disabled" + ); + + fprintf(stdout, "\n"); + fprintf(stdout, "Logical Address Filter Register\n"); + fprintf(stdout, "-------------------\n"); + + /* Logical Address Filter Register */ + fprintf(stdout, + "0x00168: Logical address filter register 0x%08X%08X\n", + reg_buff[11],reg_buff[10]); + + fprintf(stdout, "\n"); + fprintf(stdout, "Link status Register\n"); + fprintf(stdout, "-------------------\n"); + + /* Status 0 Register */ + reg = reg_buff[12]; + if(reg & LINK_STATS){ + fprintf(stdout, + "0x00030: Link status register 0x%08X\n" + " Link status: %s\n" + " Auto negotiation complete %s\n" + " Duplex %s\n" + " Speed %s\n", + reg, + reg & LINK_STATS ? "Valid" : "Invalid", + reg & AUTONEG_COMPLETE ? "Yes" : "No", + reg & FULL_DPLX ? "Full" : "Half", + ((reg & SPEED_MASK) >> 7 == PHY_SPEED_10) ? "10Mbits/ Sec": + "100Mbits/Sec"); + + } + else{ + fprintf(stdout, + "0x00030: Link status register 0x%08X\n" + " Link status: %s\n", + reg, + reg & LINK_STATS ? "Valid" : "Invalid"); + } + return 0; + +} diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..9f98ef8 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# You need autoconf 2.5x, preferably 2.57 or later +# You need automake 1.7 or later. 1.6 might work. + +set -e + +aclocal +autoheader +automake --gnu --add-missing --copy +autoconf diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..40fd39c --- /dev/null +++ b/configure.ac @@ -0,0 +1,26 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(ethtool, 3, [Jeff Garzik ]) +AC_PREREQ(2.52) +AC_CONFIG_SRCDIR([ethtool.c]) +AM_INIT_AUTOMAKE([gnu]) +AC_CONFIG_HEADERS([ethtool-config.h]) + +AM_MAINTAINER_MODE + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_GCC_TRADITIONAL + +dnl Checks for libraries. + +dnl Checks for header files. +AC_CHECK_HEADERS(sys/ioctl.h) + +dnl Checks for typedefs, structures, and compiler characteristics. + +dnl Checks for library functions. +AC_HEADER_STDC +AC_CHECK_FUNCS(socket strtol) + +AC_CONFIG_FILES([Makefile ethtool.spec]) +AC_OUTPUT diff --git a/de2104x.c b/de2104x.c new file mode 100644 index 0000000..f64e1b2 --- /dev/null +++ b/de2104x.c @@ -0,0 +1,783 @@ +/* Copyright 2001 Sun Microsystems (thockin@sun.com) */ +#include +#include "ethtool-util.h" + +static const char * const csr0_tap[4] = { + "No transmit automatic polling", + "Transmit automatic polling every 200 seconds", + "Transmit automatic polling every 800 seconds", + "Transmit automatic polling every 1.6 milliseconds", +}; + +static const char * const csr0_cache_al[4] = { + "not used", + "8-longword boundary alignment", + "16-longword boundary alignment", + "32-longword boundary alignment", +}; + +static const char * const csr5_buserr[8] = { + " Bus error: parity", + " Bus error: master abort", + " Bus error: target abort", + " Bus error: (unknown code, reserved)", + " Bus error: (unknown code, reserved)", + " Bus error: (unknown code, reserved)", + " Bus error: (unknown code, reserved)", + " Bus error: (unknown code, reserved)", +}; + +static const int csr6_tx_thresh[4] = { + 72, + 96, + 128, + 160, +}; + +static const char * const csr6_om[4] = { + "normal", + "internal loopback", + "external loopback", + "unknown (not used)", +}; + +static const char * const csr5_tx_state[8] = { + "stopped", + "running: fetch desc", + "running: wait xmit end", + "running: read buf", + "unknown (reserved)", + "running: setup packet", + "suspended", + "running: close desc", +}; + +static const char * const csr5_rx_state[8] = { + "stopped", + "running: fetch desc", + "running: chk pkt end", + "running: wait for pkt", + "suspended", + "running: close", + "running: flush", + "running: queue", +}; + +static const char * const csr12_nway_state[8] = { + "Autonegotiation disable", + "Transmit disable", + "Ability detect", + "Acknowledge detect", + "Complete acknowledge", + "FLP link good, nway complete", + "Link check", + "unknown (reserved)", +}; + +static const char * const csr14_tp_comp[4] = { + "Compensation Disabled Mode", + "Compensation Disabled Mode", + "High Power Mode", + "Normal Compensation Mode", +}; + +static void +print_ring_addresses(u32 csr3, u32 csr4) +{ + fprintf(stdout, + "0x18: CSR3 (Rx Ring Base Address) 0x%08x\n" + "0x20: CSR4 (Tx Ring Base Address) 0x%08x\n" + , + csr3, + csr4); +} + +static void +print_rx_missed(u32 csr8) +{ + fprintf(stdout, + "0x40: CSR8 (Missed Frames Counter) 0x%08x\n", csr8); + if (csr8 & (1 << 16)) + fprintf(stdout, + " Counter overflow\n"); + else { + unsigned int rx_missed = csr8 & 0xffff; + if (!rx_missed) + fprintf(stdout, + " No missed frames\n"); + else + fprintf(stdout, + " %u missed frames\n", rx_missed); + } +} + +static void +de21040_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + u32 tmp, v, *data = (u32 *)regs->data; + + fprintf(stdout, "21040 Registers\n"); + fprintf(stdout, "---------------\n"); + + /* + * CSR0 + */ + v = data[0]; + fprintf(stdout, + "0x00: CSR0 (Bus Mode) 0x%08x\n" + " %s\n" + " %s address space\n" + " Cache alignment: %s\n" + , + v, + csr0_tap[(v >> 17) & 3], + v & (1 << 16) ? "Diagnostic" : "Standard", + csr0_cache_al[(v >> 14) & 3]); + tmp = (v >> 8) & 0x3f; + if (tmp == 0) + fprintf(stdout, " Programmable burst length unlimited\n"); + else + fprintf(stdout, + " Programmable burst length %d longwords\n", + tmp); + fprintf(stdout, + " %s endian data buffers\n" + " Descriptor skip length %d longwords\n" + " %s bus arbitration scheme\n" + , + v & (1 << 7) ? "Big" : "Little", + (v >> 2) & 0x1f, + v & (1 << 1) ? "Round-robin" : "RX-has-priority"); + if (v & (1 << 0)) + fprintf(stdout, " Software reset asserted\n"); + + /* + * CSR3, 4 + */ + print_ring_addresses(data[3], data[4]); + + /* + * CSR5 + */ + v = data[5]; + fprintf(stdout, + "0x28: CSR5 (Status) 0x%08x\n" + "%s" + " Transmit process %s\n" + " Receive process %s\n" + " Link %s\n" + , + v, + v & (1 << 13) ? csr5_buserr[(v >> 23) & 0x7] : "", + csr5_tx_state[(v >> 20) & 0x7], + csr5_rx_state[(v >> 17) & 0x7], + v & (1 << 12) ? "fail" : "OK"); + if (v & (1 << 16)) + fprintf(stdout, + " Normal interrupts: %s%s%s\n" + , + v & (1 << 0) ? "TxOK " : "", + v & (1 << 2) ? "TxNoBufs " : "", + v & (1 << 6) ? "RxOK" : ""); + if (v & (1 << 15)) + fprintf(stdout, + " Abnormal intr: %s%s%s%s%s%s%s%s\n" + , + v & (1 << 1) ? "TxStop " : "", + v & (1 << 3) ? "TxJabber " : "", + v & (1 << 5) ? "TxUnder " : "", + v & (1 << 7) ? "RxNoBufs " : "", + v & (1 << 8) ? "RxStopped " : "", + v & (1 << 9) ? "RxTimeout " : "", + v & (1 << 10) ? "AUI_TP " : "", + v & (1 << 11) ? "FD_Short " : ""); + + /* + * CSR6 + */ + v = data[6]; + fprintf(stdout, + "0x30: CSR6 (Operating Mode) 0x%08x\n" + "%s" + "%s" + " Transmit threshold %d bytes\n" + " Transmit DMA %sabled\n" + "%s" + " Operating mode: %s\n" + " %s duplex\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + " Receive DMA %sabled\n" + " %s filtering mode\n" + , + v, + v & (1<<17) ? " Capture effect enabled\n" : "", + v & (1<<16) ? " Back pressure enabled\n" : "", + csr6_tx_thresh[(v >> 14) & 3], + v & (1<<13) ? "en" : "dis", + v & (1<<12) ? " Forcing collisions\n" : "", + csr6_om[(v >> 10) & 3], + v & (1<<9) ? "Full" : "Half", + v & (1<<8) ? " Flaky oscillator disable\n" : "", + v & (1<<7) ? " Pass All Multicast\n" : "", + v & (1<<6) ? " Promisc Mode\n" : "", + v & (1<<5) ? " Start/Stop Backoff Counter\n" : "", + v & (1<<4) ? " Inverse Filtering\n" : "", + v & (1<<3) ? " Pass Bad Frames\n" : "", + v & (1<<2) ? " Hash-only Filtering\n" : "", + v & (1<<1) ? "en" : "dis", + v & (1<<0) ? "Hash" : "Perfect"); + + /* + * CSR7 + */ + v = data[7]; + fprintf(stdout, + "0x38: CSR7 (Interrupt Mask) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + , + v, + v & (1<<16) ? " Normal interrupt summary\n" : "", + v & (1<<15) ? " Abnormal interrupt summary\n" : "", + v & (1<<13) ? " System error\n" : "", + v & (1<<12) ? " Link fail\n" : "", + v & (1<<11) ? " Full duplex\n" : "", + v & (1<<10) ? " AUI_TP pin\n" : "", + v & (1<<9) ? " Receive watchdog timeout\n" : "", + v & (1<<8) ? " Receive stopped\n" : "", + v & (1<<7) ? " Receive buffer unavailable\n" : "", + v & (1<<6) ? " Receive interrupt\n" : "", + v & (1<<5) ? " Transmit underflow\n" : "", + v & (1<<3) ? " Transmit jabber timeout\n" : "", + v & (1<<2) ? " Transmit buffer unavailable\n" : "", + v & (1<<1) ? " Transmit stopped\n" : "", + v & (1<<0) ? " Transmit interrupt\n" : ""); + + /* + * CSR8 + */ + print_rx_missed(data[8]); + + /* + * CSR9 + */ + v = data[9]; + fprintf(stdout, + "0x48: CSR9 (Ethernet Address ROM) 0x%08x\n", v); + + /* + * CSR11 + */ + v = data[11]; + fprintf(stdout, + "0x58: CSR11 (Full Duplex Autoconfig) 0x%08x\n", v); + + /* + * CSR12 + */ + v = data[12]; + fprintf(stdout, + "0x60: CSR12 (SIA Status) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + " AUI_TP pin: %s\n" + , + v, + v & (1<<7) ? " PLL sampler high\n" : "", + v & (1<<6) ? " PLL sampler low\n" : "", + v & (1<<5) ? " PLL self-test pass\n" : "", + v & (1<<4) ? " PLL self-test done\n" : "", + v & (1<<3) ? " Autopolarity state\n" : "", + v & (1<<2) ? " Link fail\n" : "", + v & (1<<1) ? " Network connection error\n" : "", + v & (1<<0) ? "AUI" : "TP"); + + /* + * CSR13 + */ + v = data[13]; + fprintf(stdout, + "0x68: CSR13 (SIA Connectivity) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + " External port output multiplexer select: %u%u%u%u\n" + "%s" + "%s" + "%s" + "%s" + " %s interface selected\n" + "%s" + "%s" + "%s" + , + v, + v & (1<<15) ? " Enable pins 5, 6, 7\n" : "", + v & (1<<14) ? " Enable pins 2, 4\n" : "", + v & (1<<13) ? " Enable pins 1, 3\n" : "", + v & (1<<12) ? " Input enable\n" : "", + v & (1<<11) ? 1 : 0, + v & (1<<10) ? 1 : 0, + v & (1<<9) ? 1 : 0, + v & (1<<8) ? 1 : 0, + v & (1<<7) ? " APLL start\n" : "", + v & (1<<6) ? " Serial interface input multiplexer\n" : "", + v & (1<<5) ? " Encoder input multiplexer\n" : "", + v & (1<<4) ? " SIA PLL external input enable\n" : "", + v & (1<<3) ? "AUI" : "10base-T", + v & (1<<2) ? " CSR autoconfiguration\n" : "", + v & (1<<1) ? " AUI_TP pin autoconfiguration\n" : "", + v & (1<<0) ? " SIA reset\n" : ""); + + /* + * CSR14 + */ + v = data[14]; + fprintf(stdout, + "0x70: CSR14 (SIA Transmit and Receive) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + " %s\n" + "%s" + "%s" + "%s" + "%s" + , + v, + v & (1<<14) ? " Set polarity plus\n" : "", + v & (1<<13) ? " Autopolarity enable\n" : "", + v & (1<<12) ? " Link test enable\n" : "", + v & (1<<11) ? " Heartbeat enable\n" : "", + v & (1<<10) ? " Collision detect enable\n" : "", + v & (1<<9) ? " Collision squelch enable\n" : "", + v & (1<<8) ? " Receive squelch enable\n" : "", + csr14_tp_comp[(v >> 4) & 0x3], + v & (1<<3) ? " Link pulse send enable\n" : "", + v & (1<<2) ? " Driver enable\n" : "", + v & (1<<1) ? " Loopback enable\n" : "", + v & (1<<0) ? " Encoder enable\n" : ""); + + /* + * CSR15 + */ + v = data[15]; + fprintf(stdout, + "0x78: CSR15 (SIA General) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + , + v, + v & (1<<13) ? " Force receiver low\n" : "", + v & (1<<12) ? " PLL self-test start\n" : "", + v & (1<<11) ? " Force link fail\n" : "", + v & (1<<9) ? " Force unsquelch\n" : "", + v & (1<<8) ? " Test clock\n" : "", + v & (1<<5) ? " Receive watchdog release\n" : "", + v & (1<<4) ? " Receive watchdog disable\n" : "", + v & (1<<2) ? " Jabber clock\n" : "", + v & (1<<1) ? " Host unjab\n" : "", + v & (1<<0) ? " Jabber disable\n" : ""); +} + +static void +de21041_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + u32 tmp, v, *data = (u32 *)regs->data; + + fprintf(stdout, "21041 Registers\n"); + fprintf(stdout, "---------------\n"); + + /* + * CSR0 + */ + v = data[0]; + fprintf(stdout, + "0x00: CSR0 (Bus Mode) 0x%08x\n" + " %s endian descriptors\n" + " %s\n" + " %s address space\n" + " Cache alignment: %s\n" + , + v, + v & (1 << 20) ? "Big" : "Little", + csr0_tap[(v >> 17) & 3], + v & (1 << 16) ? "Diagnostic" : "Standard", + csr0_cache_al[(v >> 14) & 3]); + tmp = (v >> 8) & 0x3f; + if (tmp == 0) + fprintf(stdout, " Programmable burst length unlimited\n"); + else + fprintf(stdout, + " Programmable burst length %d longwords\n", + tmp); + fprintf(stdout, + " %s endian data buffers\n" + " Descriptor skip length %d longwords\n" + " %s bus arbitration scheme\n" + , + v & (1 << 7) ? "Big" : "Little", + (v >> 2) & 0x1f, + v & (1 << 1) ? "Round-robin" : "RX-has-priority"); + if (v & (1 << 0)) + fprintf(stdout, " Software reset asserted\n"); + + /* + * CSR3, 4 + */ + print_ring_addresses(data[3], data[4]); + + /* + * CSR5 + */ + v = data[5]; + fprintf(stdout, + "0x28: CSR5 (Status) 0x%08x\n" + "%s" + " Transmit process %s\n" + " Receive process %s\n" + " Link %s\n" + , + v, + v & (1 << 13) ? csr5_buserr[(v >> 23) & 0x7] : "", + csr5_tx_state[(v >> 20) & 0x7], + csr5_rx_state[(v >> 17) & 0x7], + v & (1 << 12) ? "fail" : "OK"); + if (v & (1 << 16)) + fprintf(stdout, + " Normal interrupts: %s%s%s%s%s\n" + , + v & (1 << 0) ? "TxOK " : "", + v & (1 << 2) ? "TxNoBufs " : "", + v & (1 << 6) ? "RxOK" : "", + v & (1 << 11) ? "TimerExp " : "", + v & (1 << 14) ? "EarlyRx " : ""); + if (v & (1 << 15)) + fprintf(stdout, + " Abnormal intr: %s%s%s%s%s%s%s\n" + , + v & (1 << 1) ? "TxStop " : "", + v & (1 << 3) ? "TxJabber " : "", + v & (1 << 4) ? "ANC " : "", + v & (1 << 5) ? "TxUnder " : "", + v & (1 << 7) ? "RxNoBufs " : "", + v & (1 << 8) ? "RxStopped " : "", + v & (1 << 9) ? "RxTimeout " : ""); + + /* + * CSR6 + */ + v = data[6]; + fprintf(stdout, + "0x30: CSR6 (Operating Mode) 0x%08x\n" + "%s" + "%s" + " Transmit threshold %d bytes\n" + " Transmit DMA %sabled\n" + "%s" + " Operating mode: %s\n" + " %s duplex\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + " Receive DMA %sabled\n" + " %s filtering mode\n" + , + v, + v & (1<<31) ? " Special capture effect enabled\n" : "", + v & (1<<17) ? " Capture effect enabled\n" : "", + csr6_tx_thresh[(v >> 14) & 3], + v & (1<<13) ? "en" : "dis", + v & (1<<12) ? " Forcing collisions\n" : "", + csr6_om[(v >> 10) & 3], + v & (1<<9) ? "Full" : "Half", + v & (1<<8) ? " Flaky oscillator disable\n" : "", + v & (1<<7) ? " Pass All Multicast\n" : "", + v & (1<<6) ? " Promisc Mode\n" : "", + v & (1<<5) ? " Start/Stop Backoff Counter\n" : "", + v & (1<<4) ? " Inverse Filtering\n" : "", + v & (1<<3) ? " Pass Bad Frames\n" : "", + v & (1<<2) ? " Hash-only Filtering\n" : "", + v & (1<<1) ? "en" : "dis", + v & (1<<0) ? "Hash" : "Perfect"); + + /* + * CSR7 + */ + v = data[7]; + fprintf(stdout, + "0x38: CSR7 (Interrupt Mask) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + , + v, + v & (1<<16) ? " Normal interrupt summary\n" : "", + v & (1<<15) ? " Abnormal interrupt summary\n" : "", + v & (1<<14) ? " Early receive interrupt\n" : "", + v & (1<<13) ? " System error\n" : "", + v & (1<<12) ? " Link fail\n" : "", + v & (1<<11) ? " Timer expired\n" : "", + v & (1<<9) ? " Receive watchdog timeout\n" : "", + v & (1<<8) ? " Receive stopped\n" : "", + v & (1<<7) ? " Receive buffer unavailable\n" : "", + v & (1<<6) ? " Receive interrupt\n" : "", + v & (1<<5) ? " Transmit underflow\n" : "", + v & (1<<4) ? " Link pass\n" : "", + v & (1<<3) ? " Transmit jabber timeout\n" : "", + v & (1<<2) ? " Transmit buffer unavailable\n" : "", + v & (1<<1) ? " Transmit stopped\n" : "", + v & (1<<0) ? " Transmit interrupt\n" : ""); + + /* + * CSR8 + */ + print_rx_missed(data[8]); + + /* + * CSR9 + */ + v = data[9]; + fprintf(stdout, + "0x48: CSR9 (Boot and Ethernet ROMs) 0x%08x\n" + " Select bits: %s%s%s%s%s%s\n" + " Data: %d%d%d%d%d%d%d%d\n" + , + v, + v & (1<<15) ? "Mode " : "", + v & (1<<14) ? "Read " : "", + v & (1<<13) ? "Write " : "", + v & (1<<12) ? "BootROM " : "", + v & (1<<11) ? "SROM " : "", + v & (1<<10) ? "ExtReg " : "", + v & (1<<7) ? 1 : 0, + v & (1<<6) ? 1 : 0, + v & (1<<5) ? 1 : 0, + v & (1<<4) ? 1 : 0, + v & (1<<3) ? 1 : 0, + v & (1<<2) ? 1 : 0, + v & (1<<1) ? 1 : 0, + v & (1<<0) ? 1 : 0); + + /* + * CSR10 + */ + v = data[10]; + fprintf(stdout, + "0x50: CSR10 (Boot ROM Address) 0x%08x\n", v); + + /* + * CSR11 + */ + v = data[11]; + fprintf(stdout, + "0x58: CSR11 (General Purpose Timer) 0x%08x\n" + "%s" + " Timer value: %u cycles\n" + , + v, + v & (1<<16) ? " Continuous mode\n" : "", + v & 0xffff); + + /* + * CSR12 + */ + v = data[12]; + fprintf(stdout, + "0x60: CSR12 (SIA Status) 0x%08x\n" + " Link partner code word 0x%04x\n" + "%s" + " NWay state: %s\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + , + v, + v >> 16, + v & (1<<15) ? " Link partner negotiable\n" : "", + csr12_nway_state[(v >> 12) & 0x7], + v & (1<<11) ? " Transmit remote fault\n" : "", + v & (1<<10) ? " Unstable NLP detected\n" : "", + v & (1<<9) ? " Non-selected port receive activity\n" : "", + v & (1<<8) ? " Selected port receive activity\n" : "", + v & (1<<7) ? " PLL sampler high\n" : "", + v & (1<<6) ? " PLL sampler low\n" : "", + v & (1<<5) ? " PLL self-test pass\n" : "", + v & (1<<4) ? " PLL self-test done\n" : "", + v & (1<<3) ? " Autopolarity state\n" : "", + v & (1<<2) ? " Link fail\n" : "", + v & (1<<1) ? " Network connection error\n" : ""); + + /* + * CSR13 + */ + v = data[13]; + fprintf(stdout, + "0x68: CSR13 (SIA Connectivity) 0x%08x\n" + " SIA Diagnostic Mode 0x%04x\n" + " %s\n" + "%s" + "%s" + , + v, + (v >> 4) & 0xfff, + v & (1<<3) ? "AUI/BNC port" : "10base-T port", + v & (1<<2) ? " CSR autoconfiguration enabled\n" : "", + v & (1<<0) ? " SIA register reset asserted\n" : ""); + + /* + * CSR14 + */ + v = data[14]; + fprintf(stdout, + "0x70: CSR14 (SIA Transmit and Receive) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + " %s\n" + "%s" + "%s" + "%s" + "%s" + , + v, + v & (1<<15) ? " 10base-T/AUI autosensing\n" : "", + v & (1<<14) ? " Set polarity plus\n" : "", + v & (1<<13) ? " Autopolarity enable\n" : "", + v & (1<<12) ? " Link test enable\n" : "", + v & (1<<11) ? " Heartbeat enable\n" : "", + v & (1<<10) ? " Collision detect enable\n" : "", + v & (1<<9) ? " Collision squelch enable\n" : "", + v & (1<<8) ? " Receive squelch enable\n" : "", + v & (1<<7) ? " Autonegotiation enable\n" : "", + v & (1<<6) ? " Must Be One\n" : "", + csr14_tp_comp[(v >> 4) & 0x3], + v & (1<<3) ? " Link pulse send enable\n" : "", + v & (1<<2) ? " Driver enable\n" : "", + v & (1<<1) ? " Loopback enable\n" : "", + v & (1<<0) ? " Encoder enable\n" : ""); + + /* + * CSR15 + */ + v = data[15]; + fprintf(stdout, + "0x78: CSR15 (SIA General) 0x%08x\n" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + " %s port selected\n" + "%s" + "%s" + "%s" + , + v, + v & (1<<15) ? " GP LED2 on\n" : "", + v & (1<<14) ? " GP LED2 enable\n" : "", + v & (1<<13) ? " Force receiver low\n" : "", + v & (1<<12) ? " PLL self-test start\n" : "", + v & (1<<11) ? " LED stretch disable\n" : "", + v & (1<<10) ? " Force link fail\n" : "", + v & (1<<9) ? " Force unsquelch\n" : "", + v & (1<<8) ? " Test clock\n" : "", + v & (1<<7) ? " GP LED1 on\n" : "", + v & (1<<6) ? " GP LED1 enable\n" : "", + v & (1<<5) ? " Receive watchdog release\n" : "", + v & (1<<4) ? " Receive watchdog disable\n" : "", + v & (1<<3) ? "AUI" : "BNC", + v & (1<<2) ? " Jabber clock\n" : "", + v & (1<<1) ? " Host unjab\n" : "", + v & (1<<0) ? " Jabber disable\n" : ""); +} + +int +de2104x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + unsigned int de21040 = regs->version & 1; + + if (de21040) + de21040_dump_regs(info, regs); + else + de21041_dump_regs(info, regs); + + return 0; +} + diff --git a/e100.c b/e100.c new file mode 100644 index 0000000..4d1cef3 --- /dev/null +++ b/e100.c @@ -0,0 +1,238 @@ +/* Copyright (c) 2002 Intel Corporation */ +#include +#include "ethtool-util.h" + +#define D102_REV_ID 12 + +#define MDI_MDIX_CONFIG_IS_OK 0x0010 +#define MDI_MDIX_STATUS 0x0020 + +#define SOFT_INT 0x0200 /* Generate a S/W interrupt */ + +/* Interrupt masks */ +#define ALL_INT_MASK 0x0100 /* Mask interrupts */ +#define FCP_INT_MASK 0x0400 /* Flow Control Pause */ +#define ER_INT_MASK 0x0800 /* Early Receive */ +#define RNR_INT_MASK 0x1000 /* RU Not Ready */ +#define CNA_INT_MASK 0x2000 /* CU Not Active */ +#define FR_INT_MASK 0x4000 /* Frame Received */ +#define CX_INT_MASK 0x8000 /* CU eXecution w/ I-bit done */ + +/* Interrupts pending */ +#define FCP_INT_PENDING 0x0100 /* Flow Control Pause */ +#define ER_INT_PENDING 0x0200 /* Early Receive */ +#define SWI_INT_PENDING 0x0400 /* S/W generated interrupt */ +#define MDI_INT_PENDING 0x0800 /* MDI read or write done */ +#define RNR_INT_PENDING 0x1000 /* RU Became Not Ready */ +#define CNA_INT_PENDING 0x2000 /* CU Became Inactive (IDLE) */ +#define FR_INT_PENDING 0x4000 /* RU Received A Frame */ +#define CX_INT_PENDING 0x8000 /* CU Completed Action Cmd */ + +/* Status */ +#define CU_STATUS 0x00C0 +#define RU_STATUS 0x003C + +/* Commands */ +#define CU_CMD 0x00F0 +#define RU_CMD 0x0007 + +int +e100_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + u32 *regs_buff = (u32 *)regs->data; + u8 version = (u8)(regs->version >> 24); + u8 rev_id = (u8)(regs->version); + u8 regs_len = regs->len / sizeof(u32); + u32 reg; + u16 scb_status, scb_cmd; + + if(version != 1) + return -1; + + reg = regs_buff[0]; + scb_status = reg & 0x0000ffff; + scb_cmd = reg >> 16; + fprintf(stdout, + "SCB Status Word (Lower Word) 0x%04X\n", + scb_status); + + switch ((scb_status & RU_STATUS) >> 2) { + case 0: + fprintf(stdout, + " RU Status: Idle\n"); + break; + case 1: + fprintf(stdout, + " RU Status: Suspended\n"); + break; + case 2: + fprintf(stdout, + " RU Status: No Resources\n"); + break; + case 4: + fprintf(stdout, + " RU Status: Ready\n"); + break; + case 9: + fprintf(stdout, + " RU Status: Suspended with no more RBDs\n"); + break; + case 10: + fprintf(stdout, + " RU Status: No Resources due to no more RBDs\n"); + break; + case 12: + fprintf(stdout, + " RU Status: Ready with no RBDs present\n"); + break; + default: + fprintf(stdout, + " RU Status: Unknown State\n"); + break; + } + + switch ((scb_status & CU_STATUS) >> 6) { + case 0: + fprintf(stdout, + " CU Status: Idle\n"); + break; + case 1: + fprintf(stdout, + " CU Status: Suspended\n"); + break; + case 2: + fprintf(stdout, + " CU Status: Active\n"); + break; + default: + fprintf(stdout, + " CU Status: Unknown State\n"); + break; + } + + fprintf(stdout, + " ---- Interrupts Pending ----\n" + " Flow Control Pause: %s\n" + " Early Receive: %s\n" + " Software Generated Interrupt: %s\n" + " MDI Done: %s\n" + " RU Not In Ready State: %s\n" + " CU Not in Active State: %s\n" + " RU Received Frame: %s\n" + " CU Completed Command: %s\n", + scb_status & FCP_INT_PENDING ? "yes" : "no", + scb_status & ER_INT_PENDING ? "yes" : "no", + scb_status & SWI_INT_PENDING ? "yes" : "no", + scb_status & MDI_INT_PENDING ? "yes" : "no", + scb_status & RNR_INT_PENDING ? "yes" : "no", + scb_status & CNA_INT_PENDING ? "yes" : "no", + scb_status & FR_INT_PENDING ? "yes" : "no", + scb_status & CX_INT_PENDING ? "yes" : "no"); + + fprintf(stdout, + "SCB Command Word (Upper Word) 0x%04X\n", + scb_cmd); + + switch (scb_cmd & RU_CMD) { + case 0: + fprintf(stdout, + " RU Command: No Command\n"); + break; + case 1: + fprintf(stdout, + " RU Command: RU Start\n"); + break; + case 2: + fprintf(stdout, + " RU Command: RU Resume\n"); + break; + case 4: + fprintf(stdout, + " RU Command: RU Abort\n"); + break; + case 6: + fprintf(stdout, + " RU Command: Load RU Base\n"); + break; + default: + fprintf(stdout, + " RU Command: Unknown\n"); + break; + } + + switch ((scb_cmd & CU_CMD) >> 4) { + case 0: + fprintf(stdout, + " CU Command: No Command\n"); + break; + case 1: + fprintf(stdout, + " CU Command: CU Start\n"); + break; + case 2: + fprintf(stdout, + " CU Command: CU Resume\n"); + break; + case 4: + fprintf(stdout, + " CU Command: Load Dump Counters Address\n"); + break; + case 5: + fprintf(stdout, + " CU Command: Dump Counters\n"); + break; + case 6: + fprintf(stdout, + " CU Command: Load CU Base\n"); + break; + case 7: + fprintf(stdout, + " CU Command: Dump & Reset Counters\n"); + break; + default: + fprintf(stdout, + " CU Command: Unknown\n"); + break; + } + + fprintf(stdout, + " Software Generated Interrupt: %s\n", + scb_cmd & SOFT_INT ? "yes" : "no"); + + fprintf(stdout, + " ---- Interrupts Masked ----\n" + " ALL Interrupts: %s\n" + " Flow Control Pause: %s\n" + " Early Receive: %s\n" + " RU Not In Ready State: %s\n" + " CU Not in Active State: %s\n" + " RU Received Frame: %s\n" + " CU Completed Command: %s\n", + scb_cmd & ALL_INT_MASK ? "yes" : "no", + scb_cmd & FCP_INT_MASK ? "yes" : "no", + scb_cmd & ER_INT_MASK ? "yes" : "no", + scb_cmd & RNR_INT_MASK ? "yes" : "no", + scb_cmd & CNA_INT_MASK ? "yes" : "no", + scb_cmd & FR_INT_MASK ? "yes" : "no", + scb_cmd & CX_INT_MASK ? "yes" : "no"); + + if(regs_len > 1) { + fprintf(stdout, "MDI/MDI-X Status: "); + if(rev_id < D102_REV_ID) + fprintf(stdout, "MDI\n"); + else { + u16 ctrl_reg = regs_buff[1]; + + if(ctrl_reg & MDI_MDIX_CONFIG_IS_OK) { + if(ctrl_reg & MDI_MDIX_STATUS) + fprintf(stdout, "MDI-X\n"); + else + fprintf(stdout, "MDI\n"); + } else + fprintf(stdout, "Unknown\n"); + } + } + + return 0; +} + diff --git a/e1000.c b/e1000.c new file mode 100644 index 0000000..dca7d9d --- /dev/null +++ b/e1000.c @@ -0,0 +1,438 @@ +/* Copyright (c) 2002 Intel Corporation */ +#include +#include "ethtool-util.h" + +/* Register Bit Masks */ +/* Device Control */ +#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ +#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ +#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ +#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ +#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ +#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ +#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ +#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ +#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ +#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ +#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ +#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ +#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ +#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ +#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ +#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ +#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ +#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ +#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ +#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ +#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ +#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ +#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ +#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ +#define E1000_CTRL_RST 0x04000000 /* Global reset */ +#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ +#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ +#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ +#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ +#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ + +/* Device Status */ +#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ +#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ +#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ +#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ +#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ +#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ +#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ +#define E1000_STATUS_SPEED_MASK 0x000000C0 +#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ +#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ +#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ +#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ +#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ +#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ +#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ +#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ +#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ + +/* Constants used to intrepret the masked PCI-X bus speed. */ +#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ +#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ +#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ + +/* Receive Control */ +#define E1000_RCTL_RST 0x00000001 /* Software reset */ +#define E1000_RCTL_EN 0x00000002 /* enable */ +#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ +#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ +#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ +#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ +#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ +#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ +#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ +#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_RDMTS 0x00000300 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ +#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ +#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ +#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ +#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ +#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ +#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ +#define E1000_RCTL_SZ 0x00030000 /* rx buffer size */ +/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ +#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ +#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ +#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ +#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ +/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ +#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ +#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ +#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ +#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ +#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ +#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ +#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ +#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ +#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ + +/* Transmit Control */ +#define E1000_TCTL_RST 0x00000001 /* software reset */ +#define E1000_TCTL_EN 0x00000002 /* enable tx */ +#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ +#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ +#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ +#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ +#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ +#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ +#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ +#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ + +/* PCI Device IDs */ +#define E1000_DEV_ID_82542 0x1000 +#define E1000_DEV_ID_82543GC_FIBER 0x1001 +#define E1000_DEV_ID_82543GC_COPPER 0x1004 +#define E1000_DEV_ID_82544EI_COPPER 0x1008 +#define E1000_DEV_ID_82544EI_FIBER 0x1009 +#define E1000_DEV_ID_82544GC_COPPER 0x100C +#define E1000_DEV_ID_82544GC_LOM 0x100D +#define E1000_DEV_ID_82540EM 0x100E +#define E1000_DEV_ID_82540EM_LOM 0x1015 +#define E1000_DEV_ID_82540EP_LOM 0x1016 +#define E1000_DEV_ID_82540EP 0x1017 +#define E1000_DEV_ID_82540EP_LP 0x101E +#define E1000_DEV_ID_82545EM_COPPER 0x100F +#define E1000_DEV_ID_82545EM_FIBER 0x1011 +#define E1000_DEV_ID_82545GM_COPPER 0x1026 +#define E1000_DEV_ID_82545GM_FIBER 0x1027 +#define E1000_DEV_ID_82545GM_SERDES 0x1028 +#define E1000_DEV_ID_82546EB_COPPER 0x1010 +#define E1000_DEV_ID_82546EB_FIBER 0x1012 +#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D +#define E1000_DEV_ID_82541EI 0x1013 +#define E1000_DEV_ID_82541EI_MOBILE 0x1018 +#define E1000_DEV_ID_82541ER 0x1078 +#define E1000_DEV_ID_82547GI 0x1075 +#define E1000_DEV_ID_82541GI 0x1076 +#define E1000_DEV_ID_82541GI_MOBILE 0x1077 +#define E1000_DEV_ID_82546GB_COPPER 0x1079 +#define E1000_DEV_ID_82546GB_FIBER 0x107A +#define E1000_DEV_ID_82546GB_SERDES 0x107B +#define E1000_DEV_ID_82547EI 0x1019 + +#define E1000_82542_2_0_REV_ID 2 +#define E1000_82542_2_1_REV_ID 3 + +/* Enumerated types specific to the e1000 hardware */ +/* Media Access Controlers */ +enum e1000_mac_type { + e1000_undefined = 0, + e1000_82542_rev2_0, + e1000_82542_rev2_1, + e1000_82543, + e1000_82544, + e1000_82540, + e1000_82545, + e1000_82545_rev_3, + e1000_82546, + e1000_82546_rev_3, + e1000_82541, + e1000_82541_rev_2, + e1000_82547, + e1000_82547_rev_2, + e1000_num_macs +}; + +static enum e1000_mac_type +e1000_get_mac_type(u16 device_id, u8 revision_id) +{ + enum e1000_mac_type mac_type = e1000_undefined; + + switch (device_id) { + case E1000_DEV_ID_82542: + switch (revision_id) { + case E1000_82542_2_0_REV_ID: + mac_type = e1000_82542_rev2_0; + break; + case E1000_82542_2_1_REV_ID: + mac_type = e1000_82542_rev2_1; + break; + default: + mac_type = e1000_82542_rev2_0; + } + break; + case E1000_DEV_ID_82543GC_FIBER: + case E1000_DEV_ID_82543GC_COPPER: + mac_type = e1000_82543; + break; + case E1000_DEV_ID_82544EI_COPPER: + case E1000_DEV_ID_82544EI_FIBER: + case E1000_DEV_ID_82544GC_COPPER: + case E1000_DEV_ID_82544GC_LOM: + mac_type = e1000_82544; + break; + case E1000_DEV_ID_82540EM: + case E1000_DEV_ID_82540EM_LOM: + case E1000_DEV_ID_82540EP: + case E1000_DEV_ID_82540EP_LOM: + case E1000_DEV_ID_82540EP_LP: + mac_type = e1000_82540; + break; + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + mac_type = e1000_82545; + break; + case E1000_DEV_ID_82545GM_COPPER: + case E1000_DEV_ID_82545GM_FIBER: + case E1000_DEV_ID_82545GM_SERDES: + mac_type = e1000_82545_rev_3; + break; + case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: + mac_type = e1000_82546; + break; + case E1000_DEV_ID_82546GB_COPPER: + case E1000_DEV_ID_82546GB_FIBER: + case E1000_DEV_ID_82546GB_SERDES: + mac_type = e1000_82546_rev_3; + break; + case E1000_DEV_ID_82541EI: + case E1000_DEV_ID_82541EI_MOBILE: + mac_type = e1000_82541; + break; + case E1000_DEV_ID_82541ER: + case E1000_DEV_ID_82541GI: + case E1000_DEV_ID_82541GI_MOBILE: + mac_type = e1000_82541_rev_2; + break; + case E1000_DEV_ID_82547EI: + mac_type = e1000_82547; + break; + case E1000_DEV_ID_82547GI: + mac_type = e1000_82547_rev_2; + break; + default: + /* list of supported devices probably needs updating */ + mac_type = e1000_82543; + break; + } + + return mac_type; +} + +int +e1000_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + u32 *regs_buff = (u32 *)regs->data; + u16 hw_device_id = (u16)regs->version; + u8 hw_revision_id = (u8)(regs->version >> 16); + u8 version = (u8)(regs->version >> 24); + enum e1000_mac_type mac_type; + u32 reg; + + if(version != 1) + return -1; + + mac_type = e1000_get_mac_type(hw_device_id, hw_revision_id); + + if(mac_type == e1000_undefined) + return -1; + + fprintf(stdout, "MAC Registers\n"); + fprintf(stdout, "-------------\n"); + + /* Device control register */ + reg = regs_buff[0]; + fprintf(stdout, + "0x00000: CTRL (Device control register) 0x%08X\n" + " Duplex: %s\n" + " Endian mode (buffers): %s\n" + " Link reset: %s\n" + " Set link up: %s\n" + " Invert Loss-Of-Signal: %s\n" + " Receive flow control: %s\n" + " Transmit flow control: %s\n" + " VLAN mode: %s\n", + reg, + reg & E1000_CTRL_FD ? "full" : "half", + reg & E1000_CTRL_BEM ? "big" : "little", + reg & E1000_CTRL_LRST ? "reset" : "normal", + reg & E1000_CTRL_SLU ? "1" : "0", + reg & E1000_CTRL_ILOS ? "yes" : "no", + reg & E1000_CTRL_RFCE ? "enabled" : "disabled", + reg & E1000_CTRL_TFCE ? "enabled" : "disabled", + reg & E1000_CTRL_VME ? "enabled" : "disabled"); + if(mac_type >= e1000_82543) { + fprintf(stdout, + " Auto speed detect: %s\n" + " Speed select: %s\n" + " Force speed: %s\n" + " Force duplex: %s\n", + reg & E1000_CTRL_ASDE ? "enabled" : "disabled", + (reg & E1000_CTRL_SPD_SEL) == E1000_CTRL_SPD_10 ? "10Mb/s" : + (reg & E1000_CTRL_SPD_SEL) == E1000_CTRL_SPD_100 ? "100Mb/s" : + (reg & E1000_CTRL_SPD_SEL) == E1000_CTRL_SPD_1000 ? "1000Mb/s" : + "not used", + reg & E1000_CTRL_FRCSPD ? "yes" : "no", + reg & E1000_CTRL_FRCDPX ? "yes" : "no"); + } + + /* Device status register */ + reg = regs_buff[1]; + fprintf(stdout, + "0x00008: STATUS (Device status register) 0x%08X\n" + " Duplex: %s\n" + " Link up: %s\n", + reg, + reg & E1000_STATUS_FD ? "full" : "half", + reg & E1000_STATUS_LU ? "link config" : "no link config"); + if(mac_type >= e1000_82543) { + fprintf(stdout, + " TBI mode: %s\n" + " Link speed: %s\n" + " Bus type: %s\n" + " Bus speed: %s\n" + " Bus width: %s\n", + reg & E1000_STATUS_TBIMODE ? "enabled" : "disabled", + (reg & E1000_STATUS_SPEED_MASK) == E1000_STATUS_SPEED_10 ? + "10Mb/s" : + (reg & E1000_STATUS_SPEED_MASK) == E1000_STATUS_SPEED_100 ? + "100Mb/s" : + (reg & E1000_STATUS_SPEED_MASK) == E1000_STATUS_SPEED_1000 ? + "1000Mb/s" : "not used", + (reg & E1000_STATUS_PCIX_MODE) ? "PCI-X" : "PCI", + (reg & E1000_STATUS_PCIX_MODE) ? + ((reg & E1000_STATUS_PCIX_SPEED_133) ? "133MHz" : + (reg & E1000_STATUS_PCIX_SPEED_100) ? "100MHz" : + "66MHz") : + ((reg & E1000_STATUS_PCI66) ? "66MHz" : "33MHz"), + (reg & E1000_STATUS_BUS64) ? "64-bit" : "32-bit"); + } + + /* Receive control register */ + reg = regs_buff[2]; + fprintf(stdout, + "0x00100: RCTL (Receive control register) 0x%08X\n" + " Receiver: %s\n" + " Store bad packets: %s\n" + " Unicast promiscuous: %s\n" + " Multicast promiscuous: %s\n" + " Long packet: %s\n" + " Descriptor minimum threshold size: %s\n" + " Broadcast accept mode: %s\n" + " VLAN filter: %s\n" + " Cononical form indicator: %s\n" + " Discard pause frames: %s\n" + " Pass MAC control frames: %s\n", + reg, + reg & E1000_RCTL_EN ? "enabled" : "disabled", + reg & E1000_RCTL_SBP ? "enabled" : "disabled", + reg & E1000_RCTL_UPE ? "enabled" : "disabled", + reg & E1000_RCTL_MPE ? "enabled" : "disabled", + reg & E1000_RCTL_LPE ? "enabled" : "disabled", + (reg & E1000_RCTL_RDMTS) == E1000_RCTL_RDMTS_HALF ? "1/2" : + (reg & E1000_RCTL_RDMTS) == E1000_RCTL_RDMTS_QUAT ? "1/4" : + (reg & E1000_RCTL_RDMTS) == E1000_RCTL_RDMTS_EIGTH ? "1/8" : + "reserved", + reg & E1000_RCTL_BAM ? "accept" : "ignore", + reg & E1000_RCTL_VFE ? "enabled" : "disabled", + reg & E1000_RCTL_CFIEN ? "enabled" : "disabled", + reg & E1000_RCTL_DPF ? "ignored" : "filtered", + reg & E1000_RCTL_PMCF ? "pass" : "don't pass"); + if(mac_type >= e1000_82543) { + fprintf(stdout, + " Receive buffer size: %s\n", + reg & E1000_RCTL_BSEX ? + ((reg & E1000_RCTL_SZ)==E1000_RCTL_SZ_16384 ? "16384" : + (reg & E1000_RCTL_SZ)==E1000_RCTL_SZ_8192 ? "8192" : + (reg & E1000_RCTL_SZ)==E1000_RCTL_SZ_4096 ? "4096" : + "reserved") : + ((reg & E1000_RCTL_SZ)==E1000_RCTL_SZ_2048 ? "2048" : + (reg & E1000_RCTL_SZ)==E1000_RCTL_SZ_1024 ? "1024" : + (reg & E1000_RCTL_SZ)==E1000_RCTL_SZ_512 ? "512" : + "256")); + } else { + fprintf(stdout, + " Receive buffer size: %s\n", + (reg & E1000_RCTL_SZ) == E1000_RCTL_SZ_2048 ? "2048" : + (reg & E1000_RCTL_SZ) == E1000_RCTL_SZ_1024 ? "1024" : + (reg & E1000_RCTL_SZ) == E1000_RCTL_SZ_512 ? "512" : + "256"); + } + + /* Receive descriptor registers */ + fprintf(stdout, + "0x02808: RDLEN (Receive desc length) 0x%08X\n", + regs_buff[3]); + fprintf(stdout, + "0x02810: RDH (Receive desc head) 0x%08X\n", + regs_buff[4]); + fprintf(stdout, + "0x02818: RDT (Receive desc tail) 0x%08X\n", + regs_buff[5]); + fprintf(stdout, + "0x02820: RDTR (Receive delay timer) 0x%08X\n", + regs_buff[6]); + + /* Transmit control register */ + reg = regs_buff[7]; + fprintf(stdout, + "0x00400: TCTL (Transmit ctrl register) 0x%08X\n" + " Transmitter: %s\n" + " Pad short packets: %s\n" + " Software XOFF Transmission: %s\n", + reg, + reg & E1000_TCTL_EN ? "enabled" : "disabled", + reg & E1000_TCTL_PSP ? "enabled" : "disabled", + reg & E1000_TCTL_SWXOFF ? "enabled" : "disabled"); + if(mac_type >= e1000_82543) { + fprintf(stdout, + " Re-transmit on late collision: %s\n", + reg & E1000_TCTL_RTLC ? "enabled" : "disabled"); + } + + /* Transmit descriptor registers */ + fprintf(stdout, + "0x03808: TDLEN (Transmit desc length) 0x%08X\n", + regs_buff[8]); + fprintf(stdout, + "0x03810: TDH (Transmit desc head) 0x%08X\n", + regs_buff[9]); + fprintf(stdout, + "0x03818: TDT (Transmit desc tail) 0x%08X\n", + regs_buff[10]); + fprintf(stdout, + "0x03820: TIDV (Transmit delay timer) 0x%08X\n", + regs_buff[11]); + + /* PHY type */ + fprintf(stdout, + "PHY type: %s\n", + regs_buff[12] == 0 ? "M88" : "IGP"); + + return 0; +} + diff --git a/ethtool-copy.h b/ethtool-copy.h new file mode 100644 index 0000000..41aae0d --- /dev/null +++ b/ethtool-copy.h @@ -0,0 +1,366 @@ +/* + * ethtool.h: Defines for Linux ethtool. + * + * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * Copyright 2001 Jeff Garzik + * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) + * Portions Copyright 2002 Intel (eli.kupermann@intel.com, + * christopher.leech@intel.com, + * scott.feldman@intel.com) + */ + +#ifndef _LINUX_ETHTOOL_H +#define _LINUX_ETHTOOL_H + + +/* This should work for both 32 and 64 bit userland. */ +struct ethtool_cmd { + u32 cmd; + u32 supported; /* Features this interface supports */ + u32 advertising; /* Features this interface advertises */ + u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ + u8 duplex; /* Duplex, half or full */ + u8 port; /* Which connector port */ + u8 phy_address; + u8 transceiver; /* Which tranceiver to use */ + u8 autoneg; /* Enable or disable autonegotiation */ + u32 maxtxpkt; /* Tx pkts before generating tx int */ + u32 maxrxpkt; /* Rx pkts before generating rx int */ + u32 reserved[4]; +}; + +#define ETHTOOL_BUSINFO_LEN 32 +/* these strings are set to whatever the driver author decides... */ +struct ethtool_drvinfo { + u32 cmd; + char driver[32]; /* driver short name, "tulip", "eepro100" */ + char version[32]; /* driver version string */ + char fw_version[32]; /* firmware version string, if applicable */ + char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ + /* For PCI devices, use pci_dev->slot_name. */ + char reserved1[32]; + char reserved2[16]; + u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ + u32 testinfo_len; + u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ + u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ +}; + +#define SOPASS_MAX 6 +/* wake-on-lan settings */ +struct ethtool_wolinfo { + u32 cmd; + u32 supported; + u32 wolopts; + u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ +}; + +/* for passing single values */ +struct ethtool_value { + u32 cmd; + u32 data; +}; + +/* for passing big chunks of data */ +struct ethtool_regs { + u32 cmd; + u32 version; /* driver-specific, indicates different chips/revs */ + u32 len; /* bytes */ + u8 data[0]; +}; + +/* for passing EEPROM chunks */ +struct ethtool_eeprom { + u32 cmd; + u32 magic; + u32 offset; /* in bytes */ + u32 len; /* in bytes */ + u8 data[0]; +}; + +/* for configuring coalescing parameters of chip */ +struct ethtool_coalesce { + u32 cmd; /* ETHTOOL_{G,S}COALESCE */ + + /* How many usecs to delay an RX interrupt after + * a packet arrives. If 0, only rx_max_coalesced_frames + * is used. + */ + u32 rx_coalesce_usecs; + + /* How many packets to delay an RX interrupt after + * a packet arrives. If 0, only rx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause RX interrupts to never be + * generated. + */ + u32 rx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being services by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 rx_coalesce_usecs_irq; + u32 rx_max_coalesced_frames_irq; + + /* How many usecs to delay a TX interrupt after + * a packet is sent. If 0, only tx_max_coalesced_frames + * is used. + */ + u32 tx_coalesce_usecs; + + /* How many packets to delay a TX interrupt after + * a packet is sent. If 0, only tx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause TX interrupts to never be + * generated. + */ + u32 tx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being services by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 tx_coalesce_usecs_irq; + u32 tx_max_coalesced_frames_irq; + + /* How many usecs to delay in-memory statistics + * block updates. Some drivers do not have an in-memory + * statistic block, and in such cases this value is ignored. + * This value must not be zero. + */ + u32 stats_block_coalesce_usecs; + + /* Adaptive RX/TX coalescing is an algorithm implemented by + * some drivers to improve latency under low packet rates and + * improve throughput under high packet rates. Some drivers + * only implement one of RX or TX adaptive coalescing. Anything + * not implemented by the driver causes these values to be + * silently ignored. + */ + u32 use_adaptive_rx_coalesce; + u32 use_adaptive_tx_coalesce; + + /* When the packet rate (measured in packets per second) + * is below pkt_rate_low, the {rx,tx}_*_low parameters are + * used. + */ + u32 pkt_rate_low; + u32 rx_coalesce_usecs_low; + u32 rx_max_coalesced_frames_low; + u32 tx_coalesce_usecs_low; + u32 tx_max_coalesced_frames_low; + + /* When the packet rate is below pkt_rate_high but above + * pkt_rate_low (both measured in packets per second) the + * normal {rx,tx}_* coalescing parameters are used. + */ + + /* When the packet rate is (measured in packets per second) + * is above pkt_rate_high, the {rx,tx}_*_high parameters are + * used. + */ + u32 pkt_rate_high; + u32 rx_coalesce_usecs_high; + u32 rx_max_coalesced_frames_high; + u32 tx_coalesce_usecs_high; + u32 tx_max_coalesced_frames_high; + + /* How often to do adaptive coalescing packet rate sampling, + * measured in seconds. Must not be zero. + */ + u32 rate_sample_interval; +}; + +/* for configuring RX/TX ring parameters */ +struct ethtool_ringparam { + u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ + + /* Read only attributes. These indicate the maximum number + * of pending RX/TX ring entries the driver will allow the + * user to set. + */ + u32 rx_max_pending; + u32 rx_mini_max_pending; + u32 rx_jumbo_max_pending; + u32 tx_max_pending; + + /* Values changeable by the user. The valid values are + * in the range 1 to the "*_max_pending" counterpart above. + */ + u32 rx_pending; + u32 rx_mini_pending; + u32 rx_jumbo_pending; + u32 tx_pending; +}; + +/* for configuring link flow control parameters */ +struct ethtool_pauseparam { + u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ + + /* If the link is being auto-negotiated (via ethtool_cmd.autoneg + * being true) the user may set 'autonet' here non-zero to have the + * pause parameters be auto-negotiated too. In such a case, the + * {rx,tx}_pause values below determine what capabilities are + * advertised. + * + * If 'autoneg' is zero or the link is not being auto-negotiated, + * then {rx,tx}_pause force the driver to use/not-use pause + * flow control. + */ + u32 autoneg; + u32 rx_pause; + u32 tx_pause; +}; + +#define ETH_GSTRING_LEN 32 +enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, +}; + +/* for passing string sets for data tagging */ +struct ethtool_gstrings { + u32 cmd; /* ETHTOOL_GSTRINGS */ + u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ + u32 len; /* number of strings in the string set */ + u8 data[0]; +}; + +enum ethtool_test_flags { + ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */ + ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */ +}; + +/* for requesting NIC test and getting results*/ +struct ethtool_test { + u32 cmd; /* ETHTOOL_TEST */ + u32 flags; /* ETH_TEST_FL_xxx */ + u32 reserved; + u32 len; /* result length, in number of u64 elements */ + u64 data[0]; +}; + +/* for dumping NIC-specific statistics */ +struct ethtool_stats { + u32 cmd; /* ETHTOOL_GSTATS */ + u32 n_stats; /* number of u64's being returned */ + u64 data[0]; +}; + +/* CMDs currently supported */ +#define ETHTOOL_GSET 0x00000001 /* Get settings. */ +#define ETHTOOL_SSET 0x00000002 /* Set settings, privileged. */ +#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ +#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers, privileged. */ +#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ +#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options, priv. */ +#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ +#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ +#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv. */ +#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */ +#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ +#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data, priv. */ +#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config, priv. */ +#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ +#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ +#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ +#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters, priv. */ +#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ +#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ +#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ +#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ +#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable + * (ethtool_value) */ +#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable + * (ethtool_value), priv. */ +#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ +#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ +#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ +#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ +#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ + +/* compatibility with older code */ +#define SPARC_ETH_GSET ETHTOOL_GSET +#define SPARC_ETH_SSET ETHTOOL_SSET + +/* Indicates what features are supported by the interface. */ +#define SUPPORTED_10baseT_Half (1 << 0) +#define SUPPORTED_10baseT_Full (1 << 1) +#define SUPPORTED_100baseT_Half (1 << 2) +#define SUPPORTED_100baseT_Full (1 << 3) +#define SUPPORTED_1000baseT_Half (1 << 4) +#define SUPPORTED_1000baseT_Full (1 << 5) +#define SUPPORTED_Autoneg (1 << 6) +#define SUPPORTED_TP (1 << 7) +#define SUPPORTED_AUI (1 << 8) +#define SUPPORTED_MII (1 << 9) +#define SUPPORTED_FIBRE (1 << 10) +#define SUPPORTED_BNC (1 << 11) +#define SUPPORTED_10000baseT_Full (1 << 12) + +/* Indicates what features are advertised by the interface. */ +#define ADVERTISED_10baseT_Half (1 << 0) +#define ADVERTISED_10baseT_Full (1 << 1) +#define ADVERTISED_100baseT_Half (1 << 2) +#define ADVERTISED_100baseT_Full (1 << 3) +#define ADVERTISED_1000baseT_Half (1 << 4) +#define ADVERTISED_1000baseT_Full (1 << 5) +#define ADVERTISED_Autoneg (1 << 6) +#define ADVERTISED_TP (1 << 7) +#define ADVERTISED_AUI (1 << 8) +#define ADVERTISED_MII (1 << 9) +#define ADVERTISED_FIBRE (1 << 10) +#define ADVERTISED_BNC (1 << 11) +#define ADVERTISED_10000baseT_Full (1 << 12) + +/* The following are all involved in forcing a particular link + * mode for the device for setting things. When getting the + * devices settings, these indicate the current mode and whether + * it was foced up into this mode or autonegotiated. + */ + +/* The forced speed, 10Mb, 100Mb, gigabit, 10GbE. */ +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define SPEED_10000 10000 + +/* Duplex, half or full. */ +#define DUPLEX_HALF 0x00 +#define DUPLEX_FULL 0x01 + +/* Which connector port. */ +#define PORT_TP 0x00 +#define PORT_AUI 0x01 +#define PORT_MII 0x02 +#define PORT_FIBRE 0x03 +#define PORT_BNC 0x04 + +/* Which tranceiver to use. */ +#define XCVR_INTERNAL 0x00 +#define XCVR_EXTERNAL 0x01 +#define XCVR_DUMMY1 0x02 +#define XCVR_DUMMY2 0x03 +#define XCVR_DUMMY3 0x04 + +/* Enable or disable autonegotiation. If this is set to enable, + * the forced link modes above are completely ignored. + */ +#define AUTONEG_DISABLE 0x00 +#define AUTONEG_ENABLE 0x01 + +/* Wake-On-Lan options. */ +#define WAKE_PHY (1 << 0) +#define WAKE_UCAST (1 << 1) +#define WAKE_MCAST (1 << 2) +#define WAKE_BCAST (1 << 3) +#define WAKE_ARP (1 << 4) +#define WAKE_MAGIC (1 << 5) +#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ + +#endif /* _LINUX_ETHTOOL_H */ diff --git a/ethtool-util.h b/ethtool-util.h new file mode 100644 index 0000000..a69fa86 --- /dev/null +++ b/ethtool-util.h @@ -0,0 +1,42 @@ +/* Portions Copyright 2001 Sun Microsystems (thockin@sun.com) */ +/* Portions Copyright 2002 Intel (scott.feldman@intel.com) */ +#ifndef ETHTOOL_UTIL_H__ +#define ETHTOOL_UTIL_H__ + +#include +typedef unsigned long long u64; /* hack, so we may include kernel's ethtool.h */ +typedef __uint32_t u32; /* ditto */ +typedef __uint16_t u16; /* ditto */ +typedef __uint8_t u8; /* ditto */ +#include "ethtool-copy.h" + +/* National Semiconductor DP83815, DP83816 */ +int natsemi_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); +int natsemi_dump_eeprom(struct ethtool_drvinfo *info, + struct ethtool_eeprom *ee); + +/* Digital/Intel 21040 and 21041 */ +int de2104x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +/* Intel(R) PRO/1000 Gigabit Adapter Family */ +int e1000_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +/* RealTek PCI */ +int realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +/* Intel(R) PRO/100 Fast Ethernet Adapter Family */ +int e100_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +/* Tigon3 */ +int tg3_dump_eeprom(struct ethtool_drvinfo *info, struct ethtool_eeprom *ee); + +/* Advanced Micro Devices AMD8111 based Adapter */ +int amd8111e_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +/* Advanced Micro Devices PCnet32 Adapter */ +int pcnet32_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +/* Motorola 8xx FEC Ethernet controller */ +int fec_8xx_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +#endif diff --git a/ethtool.8 b/ethtool.8 new file mode 100644 index 0000000..d760907 --- /dev/null +++ b/ethtool.8 @@ -0,0 +1,384 @@ +.\" -*- nroff -*- +.\" Copyright 1999 by David S. Miller. All Rights Reserved. +.\" Portions Copyright 2001 Sun Microsystems +.\" This file may be copied under the terms of the GNU Public License. +.\" +.\" .An - list of n alternative values as in "flav vanilla|strawberry" +.\" +.de A1 +\\fB\\$1\\fP|\\fB\\$2\\fP +.. +.de A2 +\\fB\\$1\\fP\ \\fB\\$2\\fP|\\fB\\$3\\fP +.. +.de A3 +\\fB\\$1\\fP\ \\fB\\$2\\fP|\\fB\\$3\\fP|\\fB\\$4\\fP +.. +.de A4 +\\fB\\$1\\fP\ \\fB\\$2\\fP|\\fB\\$3\\fP|\\fB\\$4\\fP|\\fB\\$5\\fP +.. +.\" +.\" .Bn - same as above but framed by square brackets +.\" +.de B1 +[\\fB\\$1\\fP|\\fB\\$2\\fP] +.. +.de B2 +[\\fB\\$1\\fP\ \\fB\\$2\\fP|\\fB\\$3\\fP] +.. +.de B3 +[\\fB\\$1\\fP\ \\fB\\$2\\fP|\\fB\\$3\\fP|\\fB\\$4\\fP] +.. +.de B4 +[\\fB\\$1\\fP\ \\fB\\$2\\fP|\\fB\\$3\\fP|\\fB\\$4\\fP|\\fB\\$5\\fP] +.. +.\" +.\" \(*MA - mac address +.\" +.ds MA \fIxx\fP\fB:\fP\fIyy\fP\fB:\fP\fIzz\fP\fB:\fP\fIaa\fP\fB:\fP\fIbb\fP\fB:\fP\fIcc\fP +.\" +.\" \(*WO - wol flags +.\" +.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBd\fP... +.TH ETHTOOL 8 "January 2005" "Ethtool version 3" +.SH NAME +ethtool \- Display or change ethernet card settings +.SH SYNOPSIS +.B ethtool +.I ethX + +.B ethtool \-h + +.B ethtool \-a +.I ethX + +.B ethtool \-A +.I ethX +.B2 autoneg on off +.B2 rx on off +.B2 tx on off + +.B ethtool \-c +.I ethX + +.B ethtool \-C +.I ethX +.B2 adaptive-rx on off +.B2 adaptive-tx on off +.RB [ rx-usecs +.IR N ] +.RB [ rx-frames +.IR N ] +.RB [ rx-usecs-irq +.IR N ] +.RB [ rx-frames-irq +.IR N ] +.RB [ tx-usecs +.IR N ] +.RB [ tx-frames +.IR N ] +.RB [ tx-usecs-irq +.IR N ] +.RB [ tx-frames-irq +.IR N ] +.RB [ stats-block-usecs +.IR N ] +.RB [ pkt-rate-low +.IR N ] +.RB [ rx-usecs-low +.IR N ] +.RB [ rx-frames-low +.IR N ] +.RB [ tx-usecs-low +.IR N ] +.RB [ tx-frames-low +.IR N ] +.RB [ pkt-rate-high +.IR N ] +.RB [ rx-usecs-high +.IR N ] +.RB [ rx-frames-high +.IR N ] +.RB [ tx-usecs-high +.IR N ] +.RB [ tx-frames-high +.IR N ] +.RB [ sample-interval +.IR N ] + +.B ethtool \-g +.I ethX + +.B ethtool \-G +.I ethX +.RB [ rx +.IR N ] +.RB [ rx-mini +.IR N ] +.RB [ rx-jumbo +.IR N ] +.RB [ tx +.IR N ] + +.B ethtool \-i +.I ethX + +.B ethtool \-d +.I ethX +.B2 raw on off + +.B ethtool \-e +.I ethX +.B2 raw on off +.RB [ offset +.IR N ] +.RB [ length +.IR N ] + +.B ethtool \-E +.I ethX +.RB [ magic +.IR N ] +.RB [ offset +.IR N ] +.RB [ value +.IR N ] + +.B ethtool \-k +.I ethX + +.B ethtool \-K +.I ethX +.B2 rx on off +.B2 tx on off +.B2 sg on off +.B2 tso on off + +.B ethtool \-p +.I ethX +.IR [ N ] + +.B ethtool \-r +.I ethX + +.B ethtool \-S +.I ethX + +.B ethtool \-t +.I ethX +.B1 offline online + +.B ethtool \-s +.I ethX +.B3 speed 10 100 1000 +.B2 duplex half full +.B4 port tp aui bnc mii fibre +.B2 autoneg on off +.RB [ phyad +.IR N ] +.B2 xcvr internal external +.RB [ wol \ \*(WO] +.RB [ sopass \ \*(MA] +.RB [ msglvl +.IR N ] +.SH DESCRIPTION +.BI ethtool +is used for querying settings of an ethernet device and changing them. + +.I ethX +is the name of the ethernet device to work on. + +.SH OPTIONS +.B ethtool +with a single argument specifying the device name prints current +setting of the specified device. +.TP +.B \-h +shows a short help message. +.TP +.B \-a +queries the specified ethernet device for pause parameter information. +.TP +.B \-A +change the pause parameters of the specified ethernet device. +.TP +.A2 autoneg on off +Specify if pause autonegotiation is enabled. +.TP +.A2 rx on off +Specify if RX pause is enabled. +.TP +.A2 tx on off +Specify if TX pause is enabled. +.TP +.B \-c +queries the specified ethernet device for coalescing information. +.TP +.B \-C +change the coalescing settings of the specified ethernet device. +.TP +.B \-g +queries the specified ethernet device for rx/tx ring parameter information. +.TP +.B \-G +change the rx/tx ring parameters of the specified ethernet device. +.TP +.BI rx \ N +Change number of ring entries for the Rx ring. +.TP +.BI rx-mini \ N +Change number of ring entries for the Rx Mini ring. +.TP +.BI rx-jumbo \ N +Change number of ring entries for the Rx Jumbo ring. +.TP +.BI tx \ N +Change number of ring entries for the Tx ring. +.TP +.B \-i +queries the specified ethernet device for associated driver information. +.TP +.B \-d +retrieves and prints a register dump for the specified ethernet device. +When raw is enabled, then it dumps the raw register data to stdout. +.TP +.B \-e +retrieves and prints an EEPROM dump for the specified ethernet device. +When raw is enabled, then it dumps the raw EEPROM data to stdout. The +length and offset parameters allow dumping certain portions of the EEPROM. +Default is to dump the entire EEPROM. +.TP +.B \-E +Changes EEPROM byte for the specified ethernet device. offset and value +specify which byte and it's new value. Because of the persistent nature +of writing to the EEPROM, a device-specific magic key must be specified +to prevent the accidental writing to the EEPROM. +.TP +.B \-k +queries the specified ethernet device for offload information. +.TP +.B \-K +change the offload parameters of the specified ethernet device. +.TP +.A2 rx on off +Specify if RX checksumming is enabled. +.TP +.A2 tx on off +Specify if TX checksumming is enabled. +.TP +.A2 sg on off +Specify if scatter-gather is enabled. +.TP +.A2 tso on off +Specify if tcp segmentation offload is enabled. +.TP +.B \-p +initiates adapter-specific action intended to enable an operator to +easily identify the adapter by sight. typically this involves +blinking one or more LEDs on the specific ethernet port. +.TP +.B N +Length of time to perform phys-id, in seconds. +.TP +.B \-r +restarts auto-negotiation on the specified ethernet device, if +auto-negotiation is enabled. +.TP +.B \-S +queries the specified ethernet device for NIC- and driver-specific +statistics. +.TP +.B \-t +executes adapter selftest on the specified ethernet device. Possible test modes are: +.TP +.A1 offline online +defines test type: +.B offline +(default) means to perform full set of tests possibly causing normal operation interruption during the tests, +.B online +means to perform limited set of tests do not interrupting normal adapter operation. +.TP +.B \-s +option allows changing some or all settings of the specified ethernet device. +All following options only apply if +.B \-s +was specified. +.TP +.A3 speed 10 100 1000 +Set speed in Mb/s. +.B ethtool +with single argument will show you the supported device speeds. +.TP +.A2 duplex half full +Set full or half duplex mode. +.TP +.A4 port tp aui bnc mii fibre +Select device port. +.TP +.A2 autoneg on off +Specify if autonegotiation is enabled. In the usual case it is, but might +cause some problems with some network devices, so you can turn it off. +.TP +.BI phyad \ N +PHY address. +.TP +.A2 xcvr internal external +Select transceiver type. Currently only internal and external can be +specified, in the future further types might be added. +.TP +.BR wol \ \*(WO +Set Wake-on-LAN options. Not all devices support this. The argument to +this option is a string of characters specifying which options to enable. +.RS +.PD 0 +.TP 3 +.B p +Wake on phy activity +.TP 3 +.B u +Wake on unicast messages +.TP 3 +.B m +Wake on multicast messages +.TP 3 +.B b +Wake on broadcast messages +.TP 3 +.B a +Wake on ARP +.TP 3 +.B g +Wake on MagicPacket(tm) +.TP 3 +.B s +Enable SecureOn(tm) password for MagicPacket(tm) +.TP 3 +.B d +Disable (wake on nothing). This option clears all previous options. +.PD +.RE +.TP +.B sopass \*(MA\c +Set the SecureOn(tm) password. The argument to this option must be 6 +bytes in ethernet MAC hex format (\*(MA). +.TP +.BI msglvl \ N +Set the driver message level. Meanings differ per driver. +.SH BUGS +Not supported (in part or whole) on all ethernet drivers. +.SH AUTHOR +.B ethtool +was written by David Miller. + +Modifications by +Jeff Garzik, +Tim Hockin, +Jakub Jelinek, +Andre Majorel, +Eli Kupermann, +Scott Feldman. +.SH AVAILABILITY +.B ethtool +is available over the Web on the SourceForge site at +http://sourceforge.net/projects/gkernel/ + diff --git a/ethtool.c b/ethtool.c new file mode 100644 index 0000000..1eceb63 --- /dev/null +++ b/ethtool.c @@ -0,0 +1,2003 @@ +/* + * ethtool.c: Linux ethernet device configuration tool. + * + * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com) + * Portions Copyright 2001 Sun Microsystems + * Kernel 2.4 update Copyright 2001 Jeff Garzik + * Wake-on-LAN,natsemi,misc support by Tim Hockin + * Portions Copyright 2002 Intel + * do_test support by Eli Kupermann + * ETHTOOL_PHYS_ID support by Chris Leech + * e1000 support by Scott Feldman + * e100 support by Wen Tao + * amd8111e support by Reeja John + * + * TODO: + * * no-args => summary of each device (mii-tool style) + * * better man page (steal from mii-tool?) + * * fall back on SIOCMII* ioctl()s and possibly SIOCDEVPRIVATE* + * * abstract ioctls to allow for fallback modes of data gathering + * * symbolic names for msglvl bitmask + */ + +#ifdef HAVE_CONFIG_H +# include "ethtool-config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "ethtool-util.h" + +#ifndef SIOCETHTOOL +#define SIOCETHTOOL 0x8946 +#endif +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +static int parse_wolopts(char *optstr, int *data); +static char *unparse_wolopts(int wolopts); +static int parse_sopass(char *src, unsigned char *dest); +static int do_gdrv(int fd, struct ifreq *ifr); +static int do_gset(int fd, struct ifreq *ifr); +static int do_sset(int fd, struct ifreq *ifr); +static int do_gregs(int fd, struct ifreq *ifr); +static int do_nway_rst(int fd, struct ifreq *ifr); +static int do_geeprom(int fd, struct ifreq *ifr); +static int do_seeprom(int fd, struct ifreq *ifr); +static int do_test(int fd, struct ifreq *ifr); +static int do_phys_id(int fd, struct ifreq *ifr); +static int do_gpause(int fd, struct ifreq *ifr); +static int do_spause(int fd, struct ifreq *ifr); +static int do_gring(int fd, struct ifreq *ifr); +static int do_sring(int fd, struct ifreq *ifr); +static int do_gcoalesce(int fd, struct ifreq *ifr); +static int do_scoalesce(int fd, struct ifreq *ifr); +static int do_goffload(int fd, struct ifreq *ifr); +static int do_soffload(int fd, struct ifreq *ifr); +static int do_gstats(int fd, struct ifreq *ifr); + +/* Syntax: + * + * ethtool DEVNAME + * ethtool -a DEVNAME + * ethtool -A DEVNAME \ + * [ autoneg on|off ] \ + * [ rx on|off ] \ + * [ tx on|off ] + * ethtool -c DEVNAME + * ethtool -C DEVNAME \ + * [adaptive-rx on|off] \ + * [adaptive-tx on|off] \ + * [rx-usecs N] \ + * [rx-frames N] \ + * [rx-usecs-irq N] \ + * [rx-frames-irq N] \ + * [tx-usecs N] \ + * [tx-frames N] \ + * [tx-usecs-irq N] \ + * [tx-frames-irq N] \ + * [stats-block-usecs N] \ + * [pkt-rate-low N] \ + * [rx-usecs-low N] \ + * [rx-frames-low N] \ + * [tx-usecs-low N] \ + * [tx-frames-low N] \ + * [pkt-rate-high N] \ + * [rx-usecs-high N] \ + * [rx-frames-high N] \ + * [tx-usecs-high N] \ + * [tx-frames-high N] \ + * [sample-interval N] + * ethtool -g DEVNAME + * ethtool -G DEVNAME \ + * [ rx N ] \ + * [ rx-mini N ] \ + * [ rx-jumbo N ] \ + * [ tx N ] + * ethtool -i DEVNAME + * ethtool -d DEVNAME [ raw on|off ] + * ethtool -e DEVNAME \ + * [ raw on|off ] \ + * [ offset N ] \ + * [ len N ] + * ethtool -E DEVNAME \ + * [ magic N ] \ + * [ offset N ] \ + * [ value N ] \ + * ethtool -k DEVNAME + * ethtool -K DEVNAME \ + * [ rx on|off ] \ + * [ tx on|off ] \ + * [ sg on|off ] \ + * [ tso on|off ] + * ethtool -r DEVNAME + * ethtool -p DEVNAME [ %d ] + * ethtool -t DEVNAME [ online|offline ] + * ethtool -s DEVNAME [ speed 10|100|1000 ] \ + * [ duplex half|full ] \ + * [ port tp|aui|bnc|mii|fibre ] \ + * [ autoneg on|off ] \ + * [ phyad %d ] \ + * [ xcvr internal|external ] \ + * [ wol p|u|m|b|a|g|s|d... ] \ + * [ sopass %x:%x:%x:%x:%x:%x ] \ + * [ msglvl %d ] + * ethtool -S DEVNAME + */ + +static void show_usage(int badarg) +{ + fprintf(stderr, PACKAGE " version " VERSION "\n"); + fprintf(stderr, + "Usage:\n" + " ethtool DEVNAME\n" + " ethtool -a DEVNAME\n" + " ethtool -A DEVNAME \\\n" + " [ autoneg on|off ] \\\n" + " [ rx on|off ] \\\n" + " [ tx on|off ]\n" + " ethtool -c DEVNAME\n" + " ethtool -C DEVNAME \\\n" + " [adaptive-rx on|off] \\\n" + " [adaptive-tx on|off] \\\n" + " [rx-usecs N] \\\n" + " [rx-frames N] \\\n" + " [rx-usecs-irq N] \\\n" + " [rx-frames-irq N] \\\n" + " [tx-usecs N] \\\n" + " [tx-frames N] \\\n" + " [tx-usecs-irq N] \\\n" + " [tx-frames-irq N] \\\n" + " [stats-block-usecs N] \\\n" + " [pkt-rate-low N] \\\n" + " [rx-usecs-low N] \\\n" + " [rx-frames-low N] \\\n" + " [tx-usecs-low N] \\\n" + " [tx-frames-low N] \\\n" + " [pkt-rate-high N] \\\n" + " [rx-usecs-high N] \\\n" + " [rx-frames-high N] \\\n" + " [tx-usecs-high N] \\\n" + " [tx-frames-high N] \\\n" + " [sample-interval N]\n" + " ethtool -g DEVNAME\n" + " ethtool -G DEVNAME \\\n" + " [ rx N ] \\\n" + " [ rx-mini N ] \\\n" + " [ rx-jumbo N ] \\\n" + " [ tx N ]\n" + " ethtool -i DEVNAME\n" + " ethtool -d DEVNAME [ raw on|off ]\n" + " ethtool -e DEVNAME \\\n" + " [ raw on|off ] \\\n" + " [ offset N ] \\\n" + " [ length N ]\n" + " ethtool -E DEVNAME \\\n" + " [ magic N ] \\\n" + " [ offset N ] \\\n" + " [ value N ]\n" + " ethtool -k DEVNAME\n" + " ethtool -K DEVNAME \\\n" + " [ rx on|off ] \\\n" + " [ tx on|off ] \\\n" + " [ sg on|off ] \\\n" + " [ tso on|off ]\n" + " ethtool -r DEVNAME\n" + " ethtool -p DEVNAME [ %%d ]\n" + " ethtool -t DEVNAME [online|(offline)]\n" + " ethtool -s DEVNAME \\\n" + " [ speed 10|100|1000 ] \\\n" + " [ duplex half|full ] \\\n" + " [ port tp|aui|bnc|mii|fibre ] \\\n" + " [ autoneg on|off ] \\\n" + " [ phyad %%d ] \\\n" + " [ xcvr internal|external ] \\\n" + " [ wol p|u|m|b|a|g|s|d... ] \\\n" + " [ sopass %%x:%%x:%%x:%%x:%%x:%%x ] \\\n" + " [ msglvl %%d ] \n" + " ethtool -S DEVNAME\n" + ); + exit(badarg); +} + +static char *devname = NULL; +static enum { + MODE_GSET=0, + MODE_SSET, + MODE_GDRV, + MODE_GREGS, + MODE_NWAY_RST, + MODE_GEEPROM, + MODE_SEEPROM, + MODE_TEST, + MODE_PHYS_ID, + MODE_GPAUSE, + MODE_SPAUSE, + MODE_GCOALESCE, + MODE_SCOALESCE, + MODE_GRING, + MODE_SRING, + MODE_GOFFLOAD, + MODE_SOFFLOAD, + MODE_GSTATS, +} mode = MODE_GSET; + +static int goffload_changed = 0; +static int off_csum_rx_wanted = -1; +static int off_csum_tx_wanted = -1; +static int off_sg_wanted = -1; +static int off_tso_wanted = -1; + +static struct ethtool_pauseparam epause; +static int gpause_changed = 0; +static int pause_autoneg_wanted = -1; +static int pause_rx_wanted = -1; +static int pause_tx_wanted = -1; + +static struct ethtool_ringparam ering; +static int gring_changed = 0; +static int ring_rx_wanted = -1; +static int ring_rx_mini_wanted = -1; +static int ring_rx_jumbo_wanted = -1; +static int ring_tx_wanted = -1; + +static struct ethtool_coalesce ecoal; +static int gcoalesce_changed = 0; +static int coal_stats_wanted = -1; +static int coal_adaptive_rx_wanted = -1; +static int coal_adaptive_tx_wanted = -1; +static int coal_sample_rate_wanted = -1; +static int coal_pkt_rate_low_wanted = -1; +static int coal_pkt_rate_high_wanted = -1; +static int coal_rx_usec_wanted = -1; +static int coal_rx_frames_wanted = -1; +static int coal_rx_usec_irq_wanted = -1; +static int coal_rx_frames_irq_wanted = -1; +static int coal_tx_usec_wanted = -1; +static int coal_tx_frames_wanted = -1; +static int coal_tx_usec_irq_wanted = -1; +static int coal_tx_frames_irq_wanted = -1; +static int coal_rx_usec_low_wanted = -1; +static int coal_rx_frames_low_wanted = -1; +static int coal_tx_usec_low_wanted = -1; +static int coal_tx_frames_low_wanted = -1; +static int coal_rx_usec_high_wanted = -1; +static int coal_rx_frames_high_wanted = -1; +static int coal_tx_usec_high_wanted = -1; +static int coal_tx_frames_high_wanted = -1; + +static int speed_wanted = -1; +static int duplex_wanted = -1; +static int port_wanted = -1; +static int autoneg_wanted = -1; +static int phyad_wanted = -1; +static int xcvr_wanted = -1; +static int advertising_wanted = -1; +static int gset_changed = 0; /* did anything in GSET change? */ +static u32 wol_wanted = 0; +static int wol_change = 0; +static u8 sopass_wanted[SOPASS_MAX]; +static int sopass_change = 0; +static int gwol_changed = 0; /* did anything in GWOL change? */ +static int msglvl_wanted = -1; +static int phys_id_time = 0; +static int gregs_changed = 0; +static int gregs_dump_raw = 0; +static int geeprom_changed = 0; +static int geeprom_dump_raw = 0; +static int geeprom_offset = 0; +static int geeprom_length = -1; +static int seeprom_changed = 0; +static int seeprom_magic = 0; +static int seeprom_offset = -1; +static int seeprom_value = 0; +static enum { + ONLINE=0, + OFFLINE, +} test_type = OFFLINE; + +typedef enum { + CMDL_NONE, + CMDL_BOOL, + CMDL_INT, +} cmdline_type_t; + +struct cmdline_info { + const char *name; + cmdline_type_t type; + void *wanted_val; + void *ioctl_val; +}; + +static struct cmdline_info cmdline_gregs[] = { + { "raw", CMDL_BOOL, &gregs_dump_raw, NULL }, +}; + +static struct cmdline_info cmdline_geeprom[] = { + { "offset", CMDL_INT, &geeprom_offset, NULL }, + { "length", CMDL_INT, &geeprom_length, NULL }, + { "raw", CMDL_BOOL, &geeprom_dump_raw, NULL }, +}; + +static struct cmdline_info cmdline_seeprom[] = { + { "magic", CMDL_INT, &seeprom_magic, NULL }, + { "offset", CMDL_INT, &seeprom_offset, NULL }, + { "value", CMDL_INT, &seeprom_value, NULL }, +}; + +static struct cmdline_info cmdline_offload[] = { + { "rx", CMDL_BOOL, &off_csum_rx_wanted, NULL }, + { "tx", CMDL_BOOL, &off_csum_tx_wanted, NULL }, + { "sg", CMDL_BOOL, &off_sg_wanted, NULL }, + { "tso", CMDL_BOOL, &off_tso_wanted, NULL }, +}; + +static struct cmdline_info cmdline_pause[] = { + { "autoneg", CMDL_BOOL, &pause_autoneg_wanted, &epause.autoneg }, + { "rx", CMDL_BOOL, &pause_rx_wanted, &epause.rx_pause }, + { "tx", CMDL_BOOL, &pause_tx_wanted, &epause.tx_pause }, +}; + +static struct cmdline_info cmdline_ring[] = { + { "rx", CMDL_INT, &ring_rx_wanted, &ering.rx_pending }, + { "rx-mini", CMDL_INT, &ring_rx_mini_wanted, &ering.rx_mini_pending }, + { "rx-jumbo", CMDL_INT, &ring_rx_jumbo_wanted, &ering.rx_jumbo_pending }, + { "tx", CMDL_INT, &ring_tx_wanted, &ering.tx_pending }, +}; + +static struct cmdline_info cmdline_coalesce[] = { + { "adaptive-rx", CMDL_BOOL, &coal_adaptive_rx_wanted, &ecoal.use_adaptive_rx_coalesce }, + { "adaptive-tx", CMDL_BOOL, &coal_adaptive_tx_wanted, &ecoal.use_adaptive_tx_coalesce }, + { "sample-interval", CMDL_INT, &coal_sample_rate_wanted, &ecoal.rate_sample_interval }, + { "stats-block-usecs", CMDL_INT, &coal_stats_wanted, &ecoal.stats_block_coalesce_usecs }, + { "pkt-rate-low", CMDL_INT, &coal_pkt_rate_low_wanted, &ecoal.pkt_rate_low }, + { "pkt-rate-high", CMDL_INT, &coal_pkt_rate_high_wanted, &ecoal.pkt_rate_high }, + { "rx-usecs", CMDL_INT, &coal_rx_usec_wanted, &ecoal.rx_coalesce_usecs }, + { "rx-frames", CMDL_INT, &coal_rx_frames_wanted, &ecoal.rx_max_coalesced_frames }, + { "rx-usecs-irq", CMDL_INT, &coal_rx_usec_irq_wanted, &ecoal.rx_coalesce_usecs_irq }, + { "rx-frames-irq", CMDL_INT, &coal_rx_frames_irq_wanted, &ecoal.rx_max_coalesced_frames_irq }, + { "tx-usecs", CMDL_INT, &coal_tx_usec_wanted, &ecoal.tx_coalesce_usecs }, + { "tx-frames", CMDL_INT, &coal_tx_frames_wanted, &ecoal.tx_max_coalesced_frames }, + { "tx-usecs-irq", CMDL_INT, &coal_tx_usec_irq_wanted, &ecoal.tx_coalesce_usecs_irq }, + { "tx-frames-irq", CMDL_INT, &coal_tx_frames_irq_wanted, &ecoal.tx_max_coalesced_frames_irq }, + { "rx-usecs-low", CMDL_INT, &coal_rx_usec_low_wanted, &ecoal.rx_coalesce_usecs_low }, + { "rx-frames-low", CMDL_INT, &coal_rx_frames_low_wanted, &ecoal.rx_max_coalesced_frames_low }, + { "tx-usecs-low", CMDL_INT, &coal_tx_usec_low_wanted, &ecoal.tx_coalesce_usecs_low }, + { "tx-frames-low", CMDL_INT, &coal_tx_frames_low_wanted, &ecoal.tx_max_coalesced_frames_low }, + { "rx-usecs-high", CMDL_INT, &coal_rx_usec_high_wanted, &ecoal.rx_coalesce_usecs_high }, + { "rx-frames-high", CMDL_INT, &coal_rx_frames_high_wanted, &ecoal.rx_max_coalesced_frames_high }, + { "tx-usecs-high", CMDL_INT, &coal_tx_usec_high_wanted, &ecoal.tx_coalesce_usecs_high }, + { "tx-frames-high", CMDL_INT, &coal_tx_frames_high_wanted, &ecoal.tx_max_coalesced_frames_high }, +}; + +static void parse_generic_cmdline(int argc, char **argp, + int first_arg, int *changed, + struct cmdline_info *info, + unsigned int n_info) +{ + int i, idx, *p; + + for (i = first_arg; i < argc; i++) { + for (idx = 0; idx < n_info; idx++) { + if (!strcmp(info[idx].name, argp[i])) { + *changed = 1; + i += 1; + if (i >= argc) + show_usage(1); + p = info[idx].wanted_val; + if (info[idx].type == CMDL_BOOL) { + if (!strcmp(argp[i], "on")) + *p = 1; + else if (!strcmp(argp[i], "off")) + *p = 0; + else + show_usage(1); + } else if (info[idx].type == CMDL_INT) { + long v; + v = strtol(argp[i], NULL, 0); + if (v < 0) + show_usage(1); + *p = (int) v; + } else { + show_usage(1); + } + } + } + } +} + +static void parse_cmdline(int argc, char **argp) +{ + int i; + + for (i = 1; i < argc; i++) { + switch (i) { + case 1: + if (!strcmp(argp[i], "-s")) + mode = MODE_SSET; + else if (!strcmp(argp[i], "-a")) + mode = MODE_GPAUSE; + else if (!strcmp(argp[i], "-A")) + mode = MODE_SPAUSE; + else if (!strcmp(argp[i], "-c")) + mode = MODE_GCOALESCE; + else if (!strcmp(argp[i], "-C")) + mode = MODE_SCOALESCE; + else if (!strcmp(argp[i], "-g")) + mode = MODE_GRING; + else if (!strcmp(argp[i], "-G")) + mode = MODE_SRING; + else if (!strcmp(argp[i], "-k")) + mode = MODE_GOFFLOAD; + else if (!strcmp(argp[i], "-K")) + mode = MODE_SOFFLOAD; + else if (!strcmp(argp[i], "-i")) + mode = MODE_GDRV; + else if (!strcmp(argp[i], "-d")) + mode = MODE_GREGS; + else if (!strcmp(argp[i], "-e")) + mode = MODE_GEEPROM; + else if (!strcmp(argp[i], "-E")) + mode = MODE_SEEPROM; + else if (!strcmp(argp[i], "-r")) + mode = MODE_NWAY_RST; + else if (!strcmp(argp[i], "-p")) + mode = MODE_PHYS_ID; + else if (!strcmp(argp[i], "-t")) + mode = MODE_TEST; + else if (!strcmp(argp[i], "-S")) + mode = MODE_GSTATS; + else if (!strcmp(argp[i], "-h")) + show_usage(0); + else + devname = argp[i]; + break; + case 2: + if ((mode == MODE_SSET) || + (mode == MODE_GDRV) || + (mode == MODE_GREGS)|| + (mode == MODE_NWAY_RST) || + (mode == MODE_TEST) || + (mode == MODE_GEEPROM) || + (mode == MODE_SEEPROM) || + (mode == MODE_GPAUSE) || + (mode == MODE_SPAUSE) || + (mode == MODE_GCOALESCE) || + (mode == MODE_SCOALESCE) || + (mode == MODE_GRING) || + (mode == MODE_SRING) || + (mode == MODE_GOFFLOAD) || + (mode == MODE_SOFFLOAD) || + (mode == MODE_GSTATS) || + (mode == MODE_PHYS_ID)) { + devname = argp[i]; + break; + } + /* fallthrough */ + case 3: + if (mode == MODE_TEST) { + if (!strcmp(argp[i], "online")) { + test_type = ONLINE; + } else if (!strcmp(argp[i], "offline")) { + test_type = OFFLINE; + } else { + show_usage(1); + } + break; + } else if (mode == MODE_PHYS_ID) { + phys_id_time = strtol(argp[i], NULL, 0); + if (phys_id_time < 0) + show_usage(1); + break; + } + /* fallthrough */ + default: + if (mode == MODE_GREGS) { + parse_generic_cmdline(argc, argp, i, + &gregs_changed, + cmdline_gregs, + ARRAY_SIZE(cmdline_gregs)); + i = argc; + break; + } + if (mode == MODE_GEEPROM) { + parse_generic_cmdline(argc, argp, i, + &geeprom_changed, + cmdline_geeprom, + ARRAY_SIZE(cmdline_geeprom)); + i = argc; + break; + } + if (mode == MODE_SEEPROM) { + parse_generic_cmdline(argc, argp, i, + &seeprom_changed, + cmdline_seeprom, + ARRAY_SIZE(cmdline_seeprom)); + i = argc; + break; + } + if (mode == MODE_SPAUSE) { + parse_generic_cmdline(argc, argp, i, + &gpause_changed, + cmdline_pause, + ARRAY_SIZE(cmdline_pause)); + i = argc; + break; + } + if (mode == MODE_SRING) { + parse_generic_cmdline(argc, argp, i, + &gring_changed, + cmdline_ring, + ARRAY_SIZE(cmdline_ring)); + i = argc; + break; + } + if (mode == MODE_SCOALESCE) { + parse_generic_cmdline(argc, argp, i, + &gcoalesce_changed, + cmdline_coalesce, + ARRAY_SIZE(cmdline_coalesce)); + i = argc; + break; + } + if (mode == MODE_SOFFLOAD) { + parse_generic_cmdline(argc, argp, i, + &goffload_changed, + cmdline_offload, + ARRAY_SIZE(cmdline_offload)); + i = argc; + break; + } + if (mode != MODE_SSET) + show_usage(1); + if (!strcmp(argp[i], "speed")) { + gset_changed = 1; + i += 1; + if (i >= argc) + show_usage(1); + if (!strcmp(argp[i], "10")) + speed_wanted = SPEED_10; + else if (!strcmp(argp[i], "100")) + speed_wanted = SPEED_100; + else if (!strcmp(argp[i], "1000")) + speed_wanted = SPEED_1000; + else + show_usage(1); + break; + } else if (!strcmp(argp[i], "duplex")) { + gset_changed = 1; + i += 1; + if (i >= argc) + show_usage(1); + if (!strcmp(argp[i], "half")) + duplex_wanted = DUPLEX_HALF; + else if (!strcmp(argp[i], "full")) + duplex_wanted = DUPLEX_FULL; + else + show_usage(1); + break; + } else if (!strcmp(argp[i], "port")) { + gset_changed = 1; + i += 1; + if (i >= argc) + show_usage(1); + if (!strcmp(argp[i], "tp")) + port_wanted = PORT_TP; + else if (!strcmp(argp[i], "aui")) + port_wanted = PORT_AUI; + else if (!strcmp(argp[i], "bnc")) + port_wanted = PORT_BNC; + else if (!strcmp(argp[i], "mii")) + port_wanted = PORT_MII; + else if (!strcmp(argp[i], "fibre")) + port_wanted = PORT_FIBRE; + else + show_usage(1); + break; + } else if (!strcmp(argp[i], "autoneg")) { + i += 1; + if (i >= argc) + show_usage(1); + if (!strcmp(argp[i], "on")) { + gset_changed = 1; + autoneg_wanted = AUTONEG_ENABLE; + } else if (!strcmp(argp[i], "off")) { + gset_changed = 1; + autoneg_wanted = AUTONEG_DISABLE; + } else { + show_usage(1); + } + break; + } else if (!strcmp(argp[i], "phyad")) { + gset_changed = 1; + i += 1; + if (i >= argc) + show_usage(1); + phyad_wanted = strtol(argp[i], NULL, 0); + if (phyad_wanted < 0) + show_usage(1); + break; + } else if (!strcmp(argp[i], "xcvr")) { + gset_changed = 1; + i += 1; + if (i >= argc) + show_usage(1); + if (!strcmp(argp[i], "internal")) + xcvr_wanted = XCVR_INTERNAL; + else if (!strcmp(argp[i], "external")) + xcvr_wanted = XCVR_EXTERNAL; + else + show_usage(1); + break; + } else if (!strcmp(argp[i], "wol")) { + gwol_changed = 1; + i++; + if (i >= argc) + show_usage(1); + if (parse_wolopts(argp[i], &wol_wanted) < 0) + show_usage(1); + wol_change = 1; + break; + } else if (!strcmp(argp[i], "sopass")) { + gwol_changed = 1; + i++; + if (i >= argc) + show_usage(1); + if (parse_sopass(argp[i], sopass_wanted) < 0) + show_usage(1); + sopass_change = 1; + break; + } else if (!strcmp(argp[i], "msglvl")) { + i++; + if (i >= argc) + show_usage(1); + msglvl_wanted = strtol(argp[i], NULL, 0); + if (msglvl_wanted < 0) + show_usage(1); + break; + } + show_usage(1); + } + } + + if (autoneg_wanted == AUTONEG_ENABLE){ + if (speed_wanted == SPEED_10 && duplex_wanted == DUPLEX_HALF) + advertising_wanted = ADVERTISED_10baseT_Half; + else if (speed_wanted == SPEED_10 && + duplex_wanted == DUPLEX_FULL) + advertising_wanted = ADVERTISED_10baseT_Full; + else if (speed_wanted == SPEED_100 && + duplex_wanted == DUPLEX_HALF) + advertising_wanted = ADVERTISED_100baseT_Half; + else if (speed_wanted == SPEED_100 && + duplex_wanted == DUPLEX_FULL) + advertising_wanted = ADVERTISED_100baseT_Full; + else if (speed_wanted == SPEED_1000 && + duplex_wanted == DUPLEX_HALF) + advertising_wanted = ADVERTISED_1000baseT_Half; + else if (speed_wanted == SPEED_1000 && + duplex_wanted == DUPLEX_FULL) + advertising_wanted = ADVERTISED_1000baseT_Full; + else + /* auto negotiate without forcing */ + advertising_wanted = ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_10baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half; + + } + + if (devname == NULL) { + show_usage(1); + } +} + +static void dump_supported(struct ethtool_cmd *ep) +{ + u_int32_t mask = ep->supported; + int did1; + + fprintf(stdout, " Supported ports: [ "); + if (mask & SUPPORTED_TP) + fprintf(stdout, "TP "); + if (mask & SUPPORTED_AUI) + fprintf(stdout, "AUI "); + if (mask & SUPPORTED_BNC) + fprintf(stdout, "BNC "); + if (mask & SUPPORTED_MII) + fprintf(stdout, "MII "); + if (mask & SUPPORTED_FIBRE) + fprintf(stdout, "FIBRE "); + fprintf(stdout, "]\n"); + + fprintf(stdout, " Supported link modes: "); + did1 = 0; + if (mask & SUPPORTED_10baseT_Half) { + did1++; fprintf(stdout, "10baseT/Half "); + } + if (mask & SUPPORTED_10baseT_Full) { + did1++; fprintf(stdout, "10baseT/Full "); + } + if (did1 && (mask & (SUPPORTED_100baseT_Half|SUPPORTED_100baseT_Full))) { + fprintf(stdout, "\n"); + fprintf(stdout, " "); + } + if (mask & SUPPORTED_100baseT_Half) { + did1++; fprintf(stdout, "100baseT/Half "); + } + if (mask & SUPPORTED_100baseT_Full) { + did1++; fprintf(stdout, "100baseT/Full "); + } + if (did1 && (mask & (SUPPORTED_1000baseT_Half|SUPPORTED_1000baseT_Full))) { + fprintf(stdout, "\n"); + fprintf(stdout, " "); + } + if (mask & SUPPORTED_1000baseT_Half) { + did1++; fprintf(stdout, "1000baseT/Half "); + } + if (mask & SUPPORTED_1000baseT_Full) { + did1++; fprintf(stdout, "1000baseT/Full "); + } + fprintf(stdout, "\n"); + + fprintf(stdout, " Supports auto-negotiation: "); + if (mask & SUPPORTED_Autoneg) + fprintf(stdout, "Yes\n"); + else + fprintf(stdout, "No\n"); +} + +static void dump_advertised(struct ethtool_cmd *ep) +{ + u_int32_t mask = ep->advertising; + int did1; + + fprintf(stdout, " Advertised link modes: "); + did1 = 0; + if (mask & ADVERTISED_10baseT_Half) { + did1++; fprintf(stdout, "10baseT/Half "); + } + if (mask & ADVERTISED_10baseT_Full) { + did1++; fprintf(stdout, "10baseT/Full "); + } + if (did1 && (mask & (ADVERTISED_100baseT_Half|ADVERTISED_100baseT_Full))) { + fprintf(stdout, "\n"); + fprintf(stdout, " "); + } + if (mask & ADVERTISED_100baseT_Half) { + did1++; fprintf(stdout, "100baseT/Half "); + } + if (mask & ADVERTISED_100baseT_Full) { + did1++; fprintf(stdout, "100baseT/Full "); + } + if (did1 && (mask & (ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full))) { + fprintf(stdout, "\n"); + fprintf(stdout, " "); + } + if (mask & ADVERTISED_1000baseT_Half) { + did1++; fprintf(stdout, "1000baseT/Half "); + } + if (mask & ADVERTISED_1000baseT_Full) { + did1++; fprintf(stdout, "1000baseT/Full "); + } + if (did1 == 0) + fprintf(stdout, "Not reported"); + fprintf(stdout, "\n"); + + fprintf(stdout, " Advertised auto-negotiation: "); + if (mask & ADVERTISED_Autoneg) + fprintf(stdout, "Yes\n"); + else + fprintf(stdout, "No\n"); +} + +static int dump_ecmd(struct ethtool_cmd *ep) +{ + dump_supported(ep); + dump_advertised(ep); + + fprintf(stdout, " Speed: "); + switch (ep->speed) { + case SPEED_10: + fprintf(stdout, "10Mb/s\n"); + break; + case SPEED_100: + fprintf(stdout, "100Mb/s\n"); + break; + case SPEED_1000: + fprintf(stdout, "1000Mb/s\n"); + break; + default: + fprintf(stdout, "Unknown! (%i)\n", ep->speed); + break; + }; + + fprintf(stdout, " Duplex: "); + switch (ep->duplex) { + case DUPLEX_HALF: + fprintf(stdout, "Half\n"); + break; + case DUPLEX_FULL: + fprintf(stdout, "Full\n"); + break; + default: + fprintf(stdout, "Unknown! (%i)\n", ep->duplex); + break; + }; + + fprintf(stdout, " Port: "); + switch (ep->port) { + case PORT_TP: + fprintf(stdout, "Twisted Pair\n"); + break; + case PORT_AUI: + fprintf(stdout, "AUI\n"); + break; + case PORT_BNC: + fprintf(stdout, "BNC\n"); + break; + case PORT_MII: + fprintf(stdout, "MII\n"); + break; + case PORT_FIBRE: + fprintf(stdout, "FIBRE\n"); + break; + default: + fprintf(stdout, "Unknown! (%i)\n", ep->port); + break; + }; + + fprintf(stdout, " PHYAD: %d\n", ep->phy_address); + fprintf(stdout, " Transceiver: "); + switch (ep->transceiver) { + case XCVR_INTERNAL: + fprintf(stdout, "internal\n"); + break; + case XCVR_EXTERNAL: + fprintf(stdout, "external\n"); + break; + default: + fprintf(stdout, "Unknown!\n"); + break; + }; + + fprintf(stdout, " Auto-negotiation: %s\n", + (ep->autoneg == AUTONEG_DISABLE) ? + "off" : "on"); + return 0; +} + +static int dump_drvinfo(struct ethtool_drvinfo *info) +{ + fprintf(stdout, + "driver: %s\n" + "version: %s\n" + "firmware-version: %s\n" + "bus-info: %s\n", + info->driver, + info->version, + info->fw_version, + info->bus_info); + + return 0; +} + +static int dump_wol(struct ethtool_wolinfo *wol) +{ + fprintf(stdout, " Supports Wake-on: %s\n", + unparse_wolopts(wol->supported)); + fprintf(stdout, " Wake-on: %s\n", + unparse_wolopts(wol->wolopts)); + if (wol->supported & WAKE_MAGICSECURE) { + int i; + int delim = 0; + fprintf(stdout, " SecureOn password: "); + for (i = 0; i < SOPASS_MAX; i++) { + fprintf(stdout, "%s%02x", delim?":":"", wol->sopass[i]); + delim=1; + } + fprintf(stdout, "\n"); + } + + return 0; +} + +static int parse_wolopts(char *optstr, int *data) +{ + *data = 0; + while (*optstr) { + switch (*optstr) { + case 'p': + *data |= WAKE_PHY; + break; + case 'u': + *data |= WAKE_UCAST; + break; + case 'm': + *data |= WAKE_MCAST; + break; + case 'b': + *data |= WAKE_BCAST; + break; + case 'a': + *data |= WAKE_ARP; + break; + case 'g': + *data |= WAKE_MAGIC; + break; + case 's': + *data |= WAKE_MAGICSECURE; + break; + case 'd': + *data = 0; + break; + default: + return -1; + } + optstr++; + } + return 0; +} + +static char *unparse_wolopts(int wolopts) +{ + static char buf[16]; + char *p = buf; + + memset(buf, 0, sizeof(buf)); + + if (wolopts) { + if (wolopts & WAKE_PHY) + *p++ = 'p'; + if (wolopts & WAKE_UCAST) + *p++ = 'u'; + if (wolopts & WAKE_MCAST) + *p++ = 'm'; + if (wolopts & WAKE_BCAST) + *p++ = 'b'; + if (wolopts & WAKE_ARP) + *p++ = 'a'; + if (wolopts & WAKE_MAGIC) + *p++ = 'g'; + if (wolopts & WAKE_MAGICSECURE) + *p++ = 's'; + } else { + *p = 'd'; + } + + return buf; +} + +static int parse_sopass(char *src, unsigned char *dest) +{ + int count; + int i; + int buf[SOPASS_MAX]; + + count = sscanf(src, "%2x:%2x:%2x:%2x:%2x:%2x", + &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]); + if (count != SOPASS_MAX) { + return -1; + } + + for (i = 0; i < count; i++) { + dest[i] = buf[i]; + } + return 0; +} + +static struct { + const char *name; + int (*func)(struct ethtool_drvinfo *info, struct ethtool_regs *regs); + +} driver_list[] = { + { "8139cp", realtek_dump_regs }, + { "8139too", realtek_dump_regs }, + { "r8169", realtek_dump_regs }, + { "de2104x", de2104x_dump_regs }, + { "e1000", e1000_dump_regs }, + { "natsemi", natsemi_dump_regs }, + { "e100", e100_dump_regs }, + { "amd8111e", amd8111e_dump_regs }, + { "pcnet32", pcnet32_dump_regs }, + { "fec_8xx", fec_8xx_dump_regs }, +}; + +static int dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + int i; + + if (gregs_dump_raw) { + fwrite(regs->data, regs->len, 1, stdout); + return 0; + } + + for (i = 0; i < ARRAY_SIZE(driver_list); i++) + if (!strncmp(driver_list[i].name, info->driver, + ETHTOOL_BUSINFO_LEN)) + return driver_list[i].func(info, regs); + + fprintf(stdout, "Offset\tValue\n"); + fprintf(stdout, "--------\t-----\n"); + for (i = 0; i < regs->len; i++) + fprintf(stdout, "%02d\t0x%02x\n", i, regs->data[i]); + fprintf(stdout, "\n"); + return 0; +} + +static int dump_eeprom(struct ethtool_drvinfo *info, struct ethtool_eeprom *ee) +{ + int i; + + if (geeprom_dump_raw) { + fwrite(ee->data, 1, ee->len, stdout); + return 0; + } + + if (!strncmp("natsemi", info->driver, ETHTOOL_BUSINFO_LEN)) { + return natsemi_dump_eeprom(info, ee); + } else if (!strncmp("tg3", info->driver, ETHTOOL_BUSINFO_LEN)) { + return tg3_dump_eeprom(info, ee); + } + + fprintf(stdout, "Offset\t\tValues\n"); + fprintf(stdout, "------\t\t------"); + for (i = 0; i < ee->len; i++) { + if(!(i%16)) fprintf(stdout, "\n0x%04x\t\t", i + ee->offset); + fprintf(stdout, "%02x ", ee->data[i]); + } + fprintf(stdout, "\n"); + return 0; +} + +static int dump_test(struct ethtool_drvinfo *info, struct ethtool_test *test, + struct ethtool_gstrings *strings) +{ + int i, rc; + + rc = test->flags & ETH_TEST_FL_FAILED; + fprintf(stdout, "The test result is %s\n", rc ? "FAIL" : "PASS"); + + if (info->testinfo_len) + fprintf(stdout, "The test extra info:\n"); + + for (i = 0; i < info->testinfo_len; i++) { + fprintf(stdout, "%s\t %d\n", + (char *)(strings->data + i * ETH_GSTRING_LEN), + (u32) test->data[i]); + } + + fprintf(stdout, "\n"); + return rc; +} + +static int dump_pause(void) +{ + fprintf(stdout, + "Autonegotiate: %s\n" + "RX: %s\n" + "TX: %s\n", + epause.autoneg ? "on" : "off", + epause.rx_pause ? "on" : "off", + epause.tx_pause ? "on" : "off"); + + fprintf(stdout, "\n"); + return 0; +} + +static int dump_ring(void) +{ + fprintf(stdout, + "Pre-set maximums:\n" + "RX: %u\n" + "RX Mini: %u\n" + "RX Jumbo: %u\n" + "TX: %u\n", + ering.rx_max_pending, + ering.rx_mini_max_pending, + ering.rx_jumbo_max_pending, + ering.tx_max_pending); + + fprintf(stdout, + "Current hardware settings:\n" + "RX: %u\n" + "RX Mini: %u\n" + "RX Jumbo: %u\n" + "TX: %u\n", + ering.rx_pending, + ering.rx_mini_pending, + ering.rx_jumbo_pending, + ering.tx_pending); + + fprintf(stdout, "\n"); + return 0; +} + +static int dump_coalesce(void) +{ + fprintf(stdout, "Adaptive RX: %s TX: %s\n", + ecoal.use_adaptive_rx_coalesce ? "on" : "off", + ecoal.use_adaptive_tx_coalesce ? "on" : "off"); + + fprintf(stdout, + "stats-block-usecs: %u\n" + "sample-interval: %u\n" + "pkt-rate-low: %u\n" + "pkt-rate-high: %u\n" + "\n" + "rx-usecs: %u\n" + "rx-frames: %u\n" + "rx-usecs-irq: %u\n" + "rx-frames-irq: %u\n" + "\n" + "tx-usecs: %u\n" + "tx-frames: %u\n" + "tx-usecs-irq: %u\n" + "tx-frames-irq: %u\n" + "\n" + "rx-usecs-low: %u\n" + "rx-frame-low: %u\n" + "tx-usecs-low: %u\n" + "tx-frame-low: %u\n" + "\n" + "rx-usecs-high: %u\n" + "rx-frame-high: %u\n" + "tx-usecs-high: %u\n" + "tx-frame-high: %u\n" + "\n", + ecoal.stats_block_coalesce_usecs, + ecoal.rate_sample_interval, + ecoal.pkt_rate_low, + ecoal.pkt_rate_high, + + ecoal.rx_coalesce_usecs, + ecoal.rx_max_coalesced_frames, + ecoal.rx_coalesce_usecs_irq, + ecoal.rx_max_coalesced_frames_irq, + + ecoal.tx_coalesce_usecs, + ecoal.tx_max_coalesced_frames, + ecoal.tx_coalesce_usecs_irq, + ecoal.tx_max_coalesced_frames_irq, + + ecoal.rx_coalesce_usecs_low, + ecoal.rx_max_coalesced_frames_low, + ecoal.tx_coalesce_usecs_low, + ecoal.tx_max_coalesced_frames_low, + + ecoal.rx_coalesce_usecs_high, + ecoal.rx_max_coalesced_frames_high, + ecoal.tx_coalesce_usecs_high, + ecoal.tx_max_coalesced_frames_high); + + return 0; +} + +static int dump_offload (int rx, int tx, int sg, int tso) +{ + fprintf(stdout, + "rx-checksumming: %s\n" + "tx-checksumming: %s\n" + "scatter-gather: %s\n" + "tcp segmentation offload: %s\n", + rx ? "on" : "off", + tx ? "on" : "off", + sg ? "on" : "off", + tso ? "on" : "off"); + + return 0; +} + +static int doit(void) +{ + struct ifreq ifr; + int fd; + + /* Setup our control structures. */ + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, devname); + + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + perror("Cannot get control socket"); + return 70; + } + + /* all of these are expected to populate ifr->ifr_data as needed */ + if (mode == MODE_GDRV) { + return do_gdrv(fd, &ifr); + } else if (mode == MODE_GSET) { + return do_gset(fd, &ifr); + } else if (mode == MODE_SSET) { + return do_sset(fd, &ifr); + } else if (mode == MODE_GREGS) { + return do_gregs(fd, &ifr); + } else if (mode == MODE_NWAY_RST) { + return do_nway_rst(fd, &ifr); + } else if (mode == MODE_GEEPROM) { + return do_geeprom(fd, &ifr); + } else if (mode == MODE_SEEPROM) { + return do_seeprom(fd, &ifr); + } else if (mode == MODE_TEST) { + return do_test(fd, &ifr); + } else if (mode == MODE_PHYS_ID) { + return do_phys_id(fd, &ifr); + } else if (mode == MODE_GPAUSE) { + return do_gpause(fd, &ifr); + } else if (mode == MODE_SPAUSE) { + return do_spause(fd, &ifr); + } else if (mode == MODE_GCOALESCE) { + return do_gcoalesce(fd, &ifr); + } else if (mode == MODE_SCOALESCE) { + return do_scoalesce(fd, &ifr); + } else if (mode == MODE_GRING) { + return do_gring(fd, &ifr); + } else if (mode == MODE_SRING) { + return do_sring(fd, &ifr); + } else if (mode == MODE_GOFFLOAD) { + return do_goffload(fd, &ifr); + } else if (mode == MODE_SOFFLOAD) { + return do_soffload(fd, &ifr); + } else if (mode == MODE_GSTATS) { + return do_gstats(fd, &ifr); + } + + return 69; +} + +static int do_gdrv(int fd, struct ifreq *ifr) +{ + int err; + struct ethtool_drvinfo drvinfo; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr->ifr_data = (caddr_t)&drvinfo; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get driver information"); + return 71; + } + return dump_drvinfo(&drvinfo); +} + +static int do_gpause(int fd, struct ifreq *ifr) +{ + int err; + + fprintf(stdout, "Pause parameters for %s:\n", devname); + + epause.cmd = ETHTOOL_GPAUSEPARAM; + ifr->ifr_data = (caddr_t)&epause; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + err = dump_pause(); + if (err) + return err; + } else { + perror("Cannot get device pause settings"); + return 76; + } + + return 0; +} + +static void do_generic_set1(struct cmdline_info *info, int *changed_out) +{ + int wanted, *v1, *v2; + + v1 = info->wanted_val; + wanted = *v1; + + if (wanted < 0) + return; + + v2 = info->ioctl_val; + if (wanted == *v2) { + fprintf(stderr, "%s unmodified, ignoring\n", info->name); + } else { + *v2 = wanted; + *changed_out = 1; + } +} + +static void do_generic_set(struct cmdline_info *info, + unsigned int n_info, + int *changed_out) +{ + unsigned int i; + + for (i = 0; i < n_info; i++) + do_generic_set1(&info[i], changed_out); +} + +static int do_spause(int fd, struct ifreq *ifr) +{ + int err, changed = 0; + + epause.cmd = ETHTOOL_GPAUSEPARAM; + ifr->ifr_data = (caddr_t)&epause; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot get device pause settings"); + return 77; + } + + do_generic_set(cmdline_pause, ARRAY_SIZE(cmdline_pause), &changed); + + if (!changed) { + fprintf(stderr, "no pause parameters changed, aborting\n"); + return 78; + } + + epause.cmd = ETHTOOL_SPAUSEPARAM; + ifr->ifr_data = (caddr_t)&epause; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device pause parameters"); + return 79; + } + + return 0; +} + +static int do_sring(int fd, struct ifreq *ifr) +{ + int err, changed = 0; + + ering.cmd = ETHTOOL_GRINGPARAM; + ifr->ifr_data = (caddr_t)&ering; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot get device ring settings"); + return 76; + } + + do_generic_set(cmdline_ring, ARRAY_SIZE(cmdline_ring), &changed); + + if (!changed) { + fprintf(stderr, "no ring parameters changed, aborting\n"); + return 80; + } + + ering.cmd = ETHTOOL_SRINGPARAM; + ifr->ifr_data = (caddr_t)&ering; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device ring parameters"); + return 81; + } + + return 0; +} + +static int do_gring(int fd, struct ifreq *ifr) +{ + int err; + + fprintf(stdout, "Ring parameters for %s:\n", devname); + + ering.cmd = ETHTOOL_GRINGPARAM; + ifr->ifr_data = (caddr_t)&ering; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + err = dump_ring(); + if (err) + return err; + } else { + perror("Cannot get device ring settings"); + return 76; + } + + return 0; +} + +static int do_gcoalesce(int fd, struct ifreq *ifr) +{ + int err; + + fprintf(stdout, "Coalesce parameters for %s:\n", devname); + + ecoal.cmd = ETHTOOL_GCOALESCE; + ifr->ifr_data = (caddr_t)&ecoal; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + err = dump_coalesce(); + if (err) + return err; + } else { + perror("Cannot get device coalesce settings"); + return 82; + } + + return 0; +} + +static int do_scoalesce(int fd, struct ifreq *ifr) +{ + int err, changed = 0; + + ecoal.cmd = ETHTOOL_GCOALESCE; + ifr->ifr_data = (caddr_t)&ecoal; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot get device coalesce settings"); + return 76; + } + + do_generic_set(cmdline_coalesce, ARRAY_SIZE(cmdline_coalesce), + &changed); + + if (!changed) { + fprintf(stderr, "no ring parameters changed, aborting\n"); + return 80; + } + + ecoal.cmd = ETHTOOL_SCOALESCE; + ifr->ifr_data = (caddr_t)&ecoal; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device ring parameters"); + return 81; + } + + return 0; +} + +static int do_goffload(int fd, struct ifreq *ifr) +{ + struct ethtool_value eval; + int err, allfail = 1, rx = 0, tx = 0, sg = 0, tso = 0; + + fprintf(stdout, "Offload parameters for %s:\n", devname); + + eval.cmd = ETHTOOL_GRXCSUM; + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) + perror("Cannot get device rx csum settings"); + else { + rx = eval.data; + allfail = 0; + } + + eval.cmd = ETHTOOL_GTXCSUM; + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) + perror("Cannot get device tx csum settings"); + else { + tx = eval.data; + allfail = 0; + } + + eval.cmd = ETHTOOL_GSG; + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) + perror("Cannot get device scatter-gather settings"); + else { + sg = eval.data; + allfail = 0; + } + + eval.cmd = ETHTOOL_GTSO; + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) + perror("Cannot get device tcp segmentation offload settings"); + else { + tso = eval.data; + allfail = 0; + } + + if (allfail) { + fprintf(stdout, "no offload info available\n"); + return 83; + } + + return dump_offload(rx, tx, sg, tso); +} + +static int do_soffload(int fd, struct ifreq *ifr) +{ + struct ethtool_value eval; + int err, changed = 0; + + if (off_csum_rx_wanted >= 0) { + changed = 1; + eval.cmd = ETHTOOL_SRXCSUM; + eval.data = (off_csum_rx_wanted == 1); + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device rx csum settings"); + return 84; + } + } + + if (off_csum_tx_wanted >= 0) { + changed = 1; + eval.cmd = ETHTOOL_STXCSUM; + eval.data = (off_csum_tx_wanted == 1); + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device tx csum settings"); + return 85; + } + } + + if (off_sg_wanted >= 0) { + changed = 1; + eval.cmd = ETHTOOL_SSG; + eval.data = (off_sg_wanted == 1); + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device scatter-gather settings"); + return 86; + } + } + + if (off_tso_wanted >= 0) { + changed = 1; + eval.cmd = ETHTOOL_STSO; + eval.data = (off_tso_wanted == 1); + ifr->ifr_data = (caddr_t)&eval; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set device tcp segmentation offload settings"); + return 88; + } + } + if (!changed) { + fprintf(stdout, "no offload settings changed\n"); + } + + return 0; +} + +static int do_gset(int fd, struct ifreq *ifr) +{ + int err; + struct ethtool_cmd ecmd; + struct ethtool_wolinfo wolinfo; + struct ethtool_value edata; + int allfail = 1; + + fprintf(stdout, "Settings for %s:\n", devname); + + ecmd.cmd = ETHTOOL_GSET; + ifr->ifr_data = (caddr_t)&ecmd; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + err = dump_ecmd(&ecmd); + if (err) + return err; + allfail = 0; + } else if (errno != EOPNOTSUPP) { + perror("Cannot get device settings"); + } + + wolinfo.cmd = ETHTOOL_GWOL; + ifr->ifr_data = (caddr_t)&wolinfo; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + err = dump_wol(&wolinfo); + if (err) + return err; + allfail = 0; + } else if (errno != EOPNOTSUPP) { + perror("Cannot get wake-on-lan settings"); + } + + edata.cmd = ETHTOOL_GMSGLVL; + ifr->ifr_data = (caddr_t)&edata; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + fprintf(stdout, " Current message level: 0x%08x (%d)\n", + edata.data, edata.data); + allfail = 0; + } else if (errno != EOPNOTSUPP) { + perror("Cannot get message level"); + } + + edata.cmd = ETHTOOL_GLINK; + ifr->ifr_data = (caddr_t)&edata; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err == 0) { + fprintf(stdout, " Link detected: %s\n", + edata.data ? "yes":"no"); + allfail = 0; + } else if (errno != EOPNOTSUPP) { + perror("Cannot get link status"); + } + + if (allfail) { + fprintf(stdout, "No data available\n"); + return 75; + } + return 0; +} + +static int do_sset(int fd, struct ifreq *ifr) +{ + int err; + + if (gset_changed) { + struct ethtool_cmd ecmd; + + ecmd.cmd = ETHTOOL_GSET; + ifr->ifr_data = (caddr_t)&ecmd; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get current device settings"); + } else { + /* Change everything the user specified. */ + if (speed_wanted != -1) + ecmd.speed = speed_wanted; + if (duplex_wanted != -1) + ecmd.duplex = duplex_wanted; + if (port_wanted != -1) + ecmd.port = port_wanted; + if (autoneg_wanted != -1) + ecmd.autoneg = autoneg_wanted; + if (phyad_wanted != -1) + ecmd.phy_address = phyad_wanted; + if (xcvr_wanted != -1) + ecmd.transceiver = xcvr_wanted; + if (advertising_wanted != -1) + ecmd.advertising = advertising_wanted; + + /* Try to perform the update. */ + ecmd.cmd = ETHTOOL_SSET; + ifr->ifr_data = (caddr_t)&ecmd; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) + perror("Cannot set new settings"); + } + if (err < 0) { + if (speed_wanted != -1) + fprintf(stderr, " not setting speed\n"); + if (duplex_wanted != -1) + fprintf(stderr, " not setting duplex\n"); + if (port_wanted != -1) + fprintf(stderr, " not setting port\n"); + if (autoneg_wanted != -1) + fprintf(stderr, " not setting autoneg\n"); + if (phyad_wanted != -1) + fprintf(stderr, " not setting phy_address\n"); + if (xcvr_wanted != -1) + fprintf(stderr, " not setting transceiver\n"); + } + } + + if (gwol_changed) { + struct ethtool_wolinfo wol; + + wol.cmd = ETHTOOL_GWOL; + ifr->ifr_data = (caddr_t)&wol; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get current wake-on-lan settings"); + } else { + /* Change everything the user specified. */ + if (wol_change) { + wol.wolopts = wol_wanted; + } + if (sopass_change) { + int i; + for (i = 0; i < SOPASS_MAX; i++) { + wol.sopass[i] = sopass_wanted[i]; + } + } + + /* Try to perform the update. */ + wol.cmd = ETHTOOL_SWOL; + ifr->ifr_data = (caddr_t)&wol; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) + perror("Cannot set new wake-on-lan settings"); + } + if (err < 0) { + if (wol_change) + fprintf(stderr, " not setting wol\n"); + if (sopass_change) + fprintf(stderr, " not setting sopass\n"); + } + } + + if (msglvl_wanted != -1) { + struct ethtool_value edata; + + edata.cmd = ETHTOOL_SMSGLVL; + edata.data = msglvl_wanted; + ifr->ifr_data = (caddr_t)&edata;; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) + perror("Cannot set new msglvl"); + } + + return 0; +} + +static int do_gregs(int fd, struct ifreq *ifr) +{ + int err; + struct ethtool_drvinfo drvinfo; + struct ethtool_regs *regs; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr->ifr_data = (caddr_t)&drvinfo; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get driver information"); + return 72; + } + + regs = calloc(1, sizeof(*regs)+drvinfo.regdump_len); + if (!regs) { + perror("Cannot allocate memory for register dump"); + return 73; + } + regs->cmd = ETHTOOL_GREGS; + regs->len = drvinfo.regdump_len; + ifr->ifr_data = (caddr_t)regs; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get register dump"); + free(regs); + return 74; + } + if(dump_regs(&drvinfo, regs) < 0) { + perror("Cannot dump registers"); + free(regs); + return 75; + } + free(regs); + + return 0; +} + +static int do_nway_rst(int fd, struct ifreq *ifr) +{ + struct ethtool_value edata; + int err; + + edata.cmd = ETHTOOL_NWAY_RST; + ifr->ifr_data = (caddr_t)&edata; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) + perror("Cannot restart autonegotiation"); + + return err; +} + +static int do_geeprom(int fd, struct ifreq *ifr) +{ + int err; + struct ethtool_drvinfo drvinfo; + struct ethtool_eeprom *eeprom; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr->ifr_data = (caddr_t)&drvinfo; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get driver information"); + return 74; + } + + if (geeprom_length <= 0) + geeprom_length = drvinfo.eedump_len; + + if (drvinfo.eedump_len < geeprom_offset + geeprom_length) + geeprom_length = drvinfo.eedump_len - geeprom_offset; + + eeprom = calloc(1, sizeof(*eeprom)+geeprom_length); + if (!eeprom) { + perror("Cannot allocate memory for EEPROM data"); + return 75; + } + eeprom->cmd = ETHTOOL_GEEPROM; + eeprom->len = geeprom_length; + eeprom->offset = geeprom_offset; + ifr->ifr_data = (caddr_t)eeprom; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get EEPROM data"); + free(eeprom); + return 74; + } + err = dump_eeprom(&drvinfo, eeprom); + free(eeprom); + + return err; +} + +static int do_seeprom(int fd, struct ifreq *ifr) +{ + int err; + struct { + struct ethtool_eeprom eeprom; + u8 data; + } edata; + + edata.eeprom.cmd = ETHTOOL_SEEPROM; + edata.eeprom.len = 1; + edata.eeprom.offset = seeprom_offset; + edata.eeprom.magic = seeprom_magic; + edata.data = seeprom_value; + ifr->ifr_data = (caddr_t)&edata.eeprom; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot set EEPROM data"); + return 87; + } + + return err; +} + +static int do_test(int fd, struct ifreq *ifr) +{ + int err; + struct ethtool_drvinfo drvinfo; + struct ethtool_test *test; + struct ethtool_gstrings *strings; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr->ifr_data = (caddr_t)&drvinfo; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get driver information"); + return 72; + } + + test = calloc(1, sizeof(*test) + drvinfo.testinfo_len * sizeof(u64)); + if (!test) { + perror("Cannot allocate memory for test info"); + return 73; + } + memset (test->data, 0, drvinfo.testinfo_len * sizeof(u64)); + test->cmd = ETHTOOL_TEST; + test->len = drvinfo.testinfo_len; + if (test_type == OFFLINE) + test->flags = ETH_TEST_FL_OFFLINE; + else + test->flags = 0; + ifr->ifr_data = (caddr_t)test; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot test"); + free (test); + return 74; + } + + strings = calloc(1, sizeof(*strings) + + drvinfo.testinfo_len * ETH_GSTRING_LEN); + if (!strings) { + perror("Cannot allocate memory for strings"); + free(test); + return 73; + } + memset (strings->data, 0, drvinfo.testinfo_len * ETH_GSTRING_LEN); + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = ETH_SS_TEST; + strings->len = drvinfo.testinfo_len; + ifr->ifr_data = (caddr_t)strings; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get strings"); + free (test); + free (strings); + return 74; + } + err = dump_test(&drvinfo, test, strings); + free(test); + free(strings); + + return err; +} + +static int do_phys_id(int fd, struct ifreq *ifr) +{ + int err; + struct ethtool_value edata; + + edata.cmd = ETHTOOL_PHYS_ID; + edata.data = phys_id_time; + ifr->ifr_data = (caddr_t)&edata; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) + perror("Cannot identify NIC"); + + return err; +} + +static int do_gstats(int fd, struct ifreq *ifr) +{ + struct ethtool_drvinfo drvinfo; + struct ethtool_gstrings *strings; + struct ethtool_stats *stats; + unsigned int n_stats, sz_str, sz_stats, i; + int err; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr->ifr_data = (caddr_t)&drvinfo; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get driver information"); + return 71; + } + + n_stats = drvinfo.n_stats; + if (n_stats < 1) { + fprintf(stderr, "no stats available\n"); + return 94; + } + + sz_str = n_stats * ETH_GSTRING_LEN; + sz_stats = n_stats * sizeof(u64); + + strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings)); + stats = calloc(1, sz_stats + sizeof(struct ethtool_stats)); + if (!strings || !stats) { + fprintf(stderr, "no memory available\n"); + return 95; + } + + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = ETH_SS_STATS; + strings->len = n_stats; + ifr->ifr_data = (caddr_t) strings; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get stats strings information"); + free(strings); + free(stats); + return 96; + } + + stats->cmd = ETHTOOL_GSTATS; + stats->n_stats = n_stats; + ifr->ifr_data = (caddr_t) stats; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err < 0) { + perror("Cannot get stats information"); + free(strings); + free(stats); + return 97; + } + + /* todo - pretty-print the strings per-driver */ + fprintf(stdout, "NIC statistics:\n"); + for (i = 0; i < n_stats; i++) { + char s[ETH_GSTRING_LEN]; + + strncpy(s, &strings->data[i * ETH_GSTRING_LEN], + ETH_GSTRING_LEN); + fprintf(stdout, " %s: %llu\n", + s, stats->data[i]); + } + free(strings); + free(stats); + + return 0; +} + +int main(int argc, char **argp, char **envp) +{ + parse_cmdline(argc, argp); + return doit(); +} diff --git a/ethtool.spec.in b/ethtool.spec.in new file mode 100644 index 0000000..1705d7f --- /dev/null +++ b/ethtool.spec.in @@ -0,0 +1,42 @@ +Name : @PACKAGE@ +Version : @VERSION@ +Release : 1 +Group : Utilities + +Summary : A tool for setting ethernet parameters + +Copyright : GPL +URL : http://sourceforge.net/projects/gkernel/ + +Buildroot : %{_tmppath}/%{name}-%{version} +Source : %{name}-%{version}.tar.gz + + +%description +Ethtool is a small utility to get and set values from your your ethernet +controllers. Not all ethernet drivers support ethtool, but it is getting +better. If your ethernet driver doesn't support it, ask the maintainer to +write support - it's not hard! + + +%prep +%setup -q + + +%build +CFLAGS="${RPM_OPT_FLAGS}" ./configure --prefix=/usr --mandir=%{_mandir} +make + + +%install +make install DESTDIR=${RPM_BUILD_ROOT} + + +%files +%defattr(-,root,root) +/usr/sbin/ethtool +%{_mandir}/man8/ethtool.8* +%doc AUTHORS COPYING INSTALL NEWS README ChangeLog + + +%changelog diff --git a/fec_8xx.c b/fec_8xx.c new file mode 100644 index 0000000..969a14e --- /dev/null +++ b/fec_8xx.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2004 Intracom S.A. + * Pantelis Antoniou + */ + +#include +#include +#include + +#include "ethtool-util.h" + +struct fec { + uint32_t addr_low; /* lower 32 bits of station address */ + uint32_t addr_high; /* upper 16 bits of station address||0 */ + uint32_t hash_table_high;/* upper 32-bits of hash table */ + uint32_t hash_table_low; /* lower 32-bits of hash table */ + uint32_t r_des_start; /* beginning of Rx descriptor ring */ + uint32_t x_des_start; /* beginning of Tx descriptor ring */ + uint32_t r_buff_size; /* Rx buffer size */ + uint32_t res2[9]; /* reserved */ + uint32_t ecntrl; /* ethernet control register */ + uint32_t ievent; /* interrupt event register */ + uint32_t imask; /* interrupt mask register */ + uint32_t ivec; /* interrupt level and vector status */ + uint32_t r_des_active; /* Rx ring updated flag */ + uint32_t x_des_active; /* Tx ring updated flag */ + uint32_t res3[10]; /* reserved */ + uint32_t mii_data; /* MII data register */ + uint32_t mii_speed; /* MII speed control register */ + uint32_t res4[17]; /* reserved */ + uint32_t r_bound; /* end of RAM (read-only) */ + uint32_t r_fstart; /* Rx FIFO start address */ + uint32_t res5[6]; /* reserved */ + uint32_t x_fstart; /* Tx FIFO start address */ + uint32_t res6[17]; /* reserved */ + uint32_t fun_code; /* fec SDMA function code */ + uint32_t res7[3]; /* reserved */ + uint32_t r_cntrl; /* Rx control register */ + uint32_t r_hash; /* Rx hash register */ + uint32_t res8[14]; /* reserved */ + uint32_t x_cntrl; /* Tx control register */ + uint32_t res9[0x1e]; /* reserved */ +}; + +#define DUMP_REG(f, x) fprintf(stdout, \ + "0x%04lx: %-16s 0x%08x\n", \ + (unsigned long)(offsetof(struct fec, x)), \ + #x, f->x) + +int fec_8xx_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + struct fec *f = (struct fec *)regs->data; + + fprintf(stdout, "Descriptor Registers\n"); + fprintf(stdout, "---------------------\n"); + + DUMP_REG(f, addr_low); + DUMP_REG(f, addr_high); + DUMP_REG(f, hash_table_high); + DUMP_REG(f, hash_table_low); + DUMP_REG(f, r_des_start); + DUMP_REG(f, x_des_start); + DUMP_REG(f, r_buff_size); + DUMP_REG(f, ecntrl); + DUMP_REG(f, ievent); + DUMP_REG(f, imask); + DUMP_REG(f, ivec); + DUMP_REG(f, r_des_active); + DUMP_REG(f, x_des_active); + DUMP_REG(f, mii_data); + DUMP_REG(f, mii_speed); + DUMP_REG(f, r_bound); + DUMP_REG(f, r_fstart); + DUMP_REG(f, x_fstart); + DUMP_REG(f, fun_code); + DUMP_REG(f, r_cntrl); + DUMP_REG(f, r_hash); + DUMP_REG(f, x_cntrl); + + return 0; +} diff --git a/natsemi.c b/natsemi.c new file mode 100644 index 0000000..24a7cb3 --- /dev/null +++ b/natsemi.c @@ -0,0 +1,985 @@ +/* Copyright 2001 Sun Microsystems (thockin@sun.com) */ +#include +#include "ethtool-util.h" + +#define PCI_VENDOR_NATSEMI 0x100b +#define PCI_DEVICE_DP83815 0x0020 +#define NATSEMI_MAGIC (PCI_VENDOR_NATSEMI | \ + (PCI_DEVICE_DP83815<<16)) + +/* register indices in the ethtool_regs->data */ +#define REG_CR 0 +#define BIT_CR_TXE (1<<0) +#define BIT_CR_RXE (1<<2) +#define BIT_CR_RST (1<<8) +#define REG_CFG 1 +#define BIT_CFG_BEM (1<<0) +#define BIT_CFG_BROM_DIS (1<<2) +#define BIT_CFG_PHY_DIS (1<<9) +#define BIT_CFG_PHY_RST (1<<10) +#define BIT_CFG_EXT_PHY (1<<12) +#define BIT_CFG_ANEG_EN (1<<13) +#define BIT_CFG_ANEG_100 (1<<14) +#define BIT_CFG_ANEG_FDUP (1<<15) +#define BIT_CFG_PINT_ACEN (1<<17) +#define BIT_CFG_PHY_CFG (0x3f<<18) +#define BIT_CFG_ANEG_DN (1<<27) +#define BIT_CFG_POL (1<<28) +#define BIT_CFG_FDUP (1<<29) +#define BIT_CFG_SPEED100 (1<<30) +#define BIT_CFG_LNKSTS (1<<31) + +#define REG_MEAR 2 +#define REG_PTSCR 3 +#define BIT_PTSCR_EEBIST_FAIL (1<<0) +#define BIT_PTSCR_EELOAD_EN (1<<2) +#define BIT_PTSCR_RBIST_RXFFAIL (1<<3) +#define BIT_PTSCR_RBIST_TXFAIL (1<<4) +#define BIT_PTSCR_RBIST_RXFAIL (1<<5) +#define REG_ISR 4 +#define REG_IMR 5 +#define BIT_INTR_RXOK (1<<0) +#define NAME_INTR_RXOK "Rx Complete" +#define BIT_INTR_RXDESC (1<<1) +#define NAME_INTR_RXDESC "Rx Descriptor" +#define BIT_INTR_RXERR (1<<2) +#define NAME_INTR_RXERR "Rx Packet Error" +#define BIT_INTR_RXEARLY (1<<3) +#define NAME_INTR_RXEARLY "Rx Early Threshold" +#define BIT_INTR_RXIDLE (1<<4) +#define NAME_INTR_RXIDLE "Rx Idle" +#define BIT_INTR_RXORN (1<<5) +#define NAME_INTR_RXORN "Rx Overrun" +#define BIT_INTR_TXOK (1<<6) +#define NAME_INTR_TXOK "Tx Packet OK" +#define BIT_INTR_TXDESC (1<<7) +#define NAME_INTR_TXDESC "Tx Descriptor" +#define BIT_INTR_TXERR (1<<8) +#define NAME_INTR_TXERR "Tx Packet Error" +#define BIT_INTR_TXIDLE (1<<9) +#define NAME_INTR_TXIDLE "Tx Idle" +#define BIT_INTR_TXURN (1<<10) +#define NAME_INTR_TXURN "Tx Underrun" +#define BIT_INTR_MIB (1<<11) +#define NAME_INTR_MIB "MIB Service" +#define BIT_INTR_SWI (1<<12) +#define NAME_INTR_SWI "Software" +#define BIT_INTR_PME (1<<13) +#define NAME_INTR_PME "Power Management Event" +#define BIT_INTR_PHY (1<<14) +#define NAME_INTR_PHY "Phy" +#define BIT_INTR_HIBERR (1<<15) +#define NAME_INTR_HIBERR "High Bits Error" +#define BIT_INTR_RXSOVR (1<<16) +#define NAME_INTR_RXSOVR "Rx Status FIFO Overrun" +#define BIT_INTR_RTABT (1<<20) +#define NAME_INTR_RTABT "Received Target Abort" +#define BIT_INTR_RMABT (1<<20) +#define NAME_INTR_RMABT "Received Master Abort" +#define BIT_INTR_SSERR (1<<20) +#define NAME_INTR_SSERR "Signaled System Error" +#define BIT_INTR_DPERR (1<<20) +#define NAME_INTR_DPERR "Detected Parity Error" +#define BIT_INTR_RXRCMP (1<<20) +#define NAME_INTR_RXRCMP "Rx Reset Complete" +#define BIT_INTR_TXRCMP (1<<20) +#define NAME_INTR_TXRCMP "Tx Reset Complete" +#define REG_IER 6 +#define BIT_IER_IE (1<<0) +#define REG_TXDP 8 +#define REG_TXCFG 9 +#define BIT_TXCFG_DRTH (0x3f<<0) +#define BIT_TXCFG_FLTH (0x3f<<8) +#define BIT_TXCFG_MXDMA (0x7<<20) +#define BIT_TXCFG_ATP (1<<28) +#define BIT_TXCFG_MLB (1<<29) +#define BIT_TXCFG_HBI (1<<30) +#define BIT_TXCFG_CSI (1<<31) +#define REG_RXDP 12 +#define REG_RXCFG 13 +#define BIT_RXCFG_DRTH (0x1f<<1) +#define BIT_RXCFG_MXDMA (0x7<<20) +#define BIT_RXCFG_ALP (1<<27) +#define BIT_RXCFG_ATX (1<<28) +#define BIT_RXCFG_ARP (1<<30) +#define BIT_RXCFG_AEP (1<<31) +#define REG_CCSR 15 +#define BIT_CCSR_CLKRUN_EN (1<<0) +#define BIT_CCSR_PMEEN (1<<8) +#define BIT_CCSR_PMESTS (1<<15) +#define REG_WCSR 16 +#define BIT_WCSR_WKPHY (1<<0) +#define BIT_WCSR_WKUCP (1<<1) +#define BIT_WCSR_WKMCP (1<<2) +#define BIT_WCSR_WKBCP (1<<3) +#define BIT_WCSR_WKARP (1<<4) +#define BIT_WCSR_WKPAT0 (1<<5) +#define BIT_WCSR_WKPAT1 (1<<6) +#define BIT_WCSR_WKPAT2 (1<<7) +#define BIT_WCSR_WKPAT3 (1<<8) +#define BIT_WCSR_WKMAG (1<<9) +#define BIT_WCSR_MPSOE (1<<10) +#define BIT_WCSR_SOHACK (1<<20) +#define BIT_WCSR_PHYINT (1<<22) +#define BIT_WCSR_UCASTR (1<<23) +#define BIT_WCSR_MCASTR (1<<24) +#define BIT_WCSR_BCASTR (1<<25) +#define BIT_WCSR_ARPR (1<<26) +#define BIT_WCSR_PATM0 (1<<27) +#define BIT_WCSR_PATM1 (1<<28) +#define BIT_WCSR_PATM2 (1<<29) +#define BIT_WCSR_PATM3 (1<<30) +#define BIT_WCSR_MPR (1<<31) +#define REG_PCR 17 +#define BIT_PCR_PAUSE_CNT (0xffff<<0) +#define BIT_PCR_PSNEG (1<<21) +#define BIT_PCR_PS_RCVD (1<<22) +#define BIT_PCR_PS_DA (1<<29) +#define BIT_PCR_PSMCAST (1<<30) +#define BIT_PCR_PSEN (1<<31) +#define REG_RFCR 18 +#define BIT_RFCR_UHEN (1<<20) +#define BIT_RFCR_MHEN (1<<21) +#define BIT_RFCR_AARP (1<<22) +#define BIT_RFCR_APAT0 (1<<23) +#define BIT_RFCR_APAT1 (1<<24) +#define BIT_RFCR_APAT2 (1<<25) +#define BIT_RFCR_APAT3 (1<<26) +#define BIT_RFCR_APM (1<<27) +#define BIT_RFCR_AAU (1<<28) +#define BIT_RFCR_AAM (1<<29) +#define BIT_RFCR_AAB (1<<30) +#define BIT_RFCR_RFEN (1<<31) +#define REG_RFDR 19 +#define REG_BRAR 20 +#define BIT_BRAR_AUTOINC (1<<31) +#define REG_BRDR 21 +#define REG_SRR 22 +#define REG_MIBC 23 +#define BIT_MIBC_WRN (1<<0) +#define BIT_MIBC_FRZ (1<<1) +#define REG_MIB0 24 +#define REG_MIB1 25 +#define REG_MIB2 26 +#define REG_MIB3 27 +#define REG_MIB4 28 +#define REG_MIB5 29 +#define REG_MIB6 30 +#define REG_BMCR 32 +#define BIT_BMCR_FDUP (1<<8) +#define BIT_BMCR_ANRST (1<<9) +#define BIT_BMCR_ISOL (1<<10) +#define BIT_BMCR_PDOWN (1<<11) +#define BIT_BMCR_ANEN (1<<12) +#define BIT_BMCR_SPEED (1<<13) +#define BIT_BMCR_LOOP (1<<14) +#define BIT_BMCR_RST (1<<15) +#define REG_BMSR 33 +#define BIT_BMSR_JABBER (1<<1) +#define BIT_BMSR_LNK (1<<2) +#define BIT_BMSR_ANCAP (1<<3) +#define BIT_BMSR_RFAULT (1<<4) +#define BIT_BMSR_ANDONE (1<<5) +#define BIT_BMSR_PREAMBLE (1<<6) +#define BIT_BMSR_10HCAP (1<<11) +#define BIT_BMSR_10FCAP (1<<12) +#define BIT_BMSR_100HCAP (1<<13) +#define BIT_BMSR_100FCAP (1<<14) +#define BIT_BMSR_100T4CAP (1<<15) +#define REG_PHYIDR1 34 +#define REG_PHYIDR2 35 +#define BIT_PHYIDR2_OUILSB (0x3f<<10) +#define BIT_PHYIDR2_MODEL (0x3f<<4) +#define BIT_PHYIDR2_REV (0xf) +#define REG_ANAR 36 +#define BIT_ANAR_PROTO (0x1f<<0) +#define BIT_ANAR_10 (1<<5) +#define BIT_ANAR_10_FD (1<<6) +#define BIT_ANAR_TX (1<<7) +#define BIT_ANAR_TXFD (1<<8) +#define BIT_ANAR_T4 (1<<9) +#define BIT_ANAR_PAUSE (1<<10) +#define BIT_ANAR_RF (1<<13) +#define BIT_ANAR_NP (1<<15) +#define REG_ANLPAR 37 +#define BIT_ANLPAR_PROTO (0x1f<<0) +#define BIT_ANLPAR_10 (1<<5) +#define BIT_ANLPAR_10_FD (1<<6) +#define BIT_ANLPAR_TX (1<<7) +#define BIT_ANLPAR_TXFD (1<<8) +#define BIT_ANLPAR_T4 (1<<9) +#define BIT_ANLPAR_PAUSE (1<<10) +#define BIT_ANLPAR_RF (1<<13) +#define BIT_ANLPAR_ACK (1<<14) +#define BIT_ANLPAR_NP (1<<15) +#define REG_ANER 38 +#define BIT_ANER_LP_AN_ENABLE (1<<0) +#define BIT_ANER_PAGE_RX (1<<1) +#define BIT_ANER_NP_ABLE (1<<2) +#define BIT_ANER_LP_NP_ABLE (1<<3) +#define BIT_ANER_PDF (1<<4) +#define REG_ANNPTR 39 +#define REG_PHYSTS 48 +#define BIT_PHYSTS_LNK (1<<0) +#define BIT_PHYSTS_SPD10 (1<<1) +#define BIT_PHYSTS_FDUP (1<<2) +#define BIT_PHYSTS_LOOP (1<<3) +#define BIT_PHYSTS_ANDONE (1<<4) +#define BIT_PHYSTS_JABBER (1<<5) +#define BIT_PHYSTS_RF (1<<6) +#define BIT_PHYSTS_MINT (1<<7) +#define BIT_PHYSTS_FC (1<<11) +#define BIT_PHYSTS_POL (1<<12) +#define BIT_PHYSTS_RXERR (1<<13) +#define REG_MICR 49 +#define BIT_MICR_INTEN (1<<1) +#define REG_MISR 50 +#define BIT_MISR_MSK_RHF (1<<9) +#define BIT_MISR_MSK_FHF (1<<10) +#define BIT_MISR_MSK_ANC (1<<11) +#define BIT_MISR_MSK_RF (1<<12) +#define BIT_MISR_MSK_JAB (1<<13) +#define BIT_MISR_MSK_LNK (1<<14) +#define BIT_MISR_MINT (1<<15) +#define REG_PGSEL 51 +#define REG_FCSCR 52 +#define REG_RECR 53 +#define REG_PCSR 54 +#define BIT_PCSR_NRZI (1<<2) +#define BIT_PCSR_FORCE_100 (1<<5) +#define BIT_PCSR_SDOPT (1<<8) +#define BIT_PCSR_SDFORCE (1<<9) +#define BIT_PCSR_TQM (1<<10) +#define BIT_PCSR_CLK (1<<11) +#define BIT_PCSR_4B5B (1<<12) +#define REG_PHYCR 57 +#define BIT_PHYCR_PHYADDR (0x1f<<0) +#define BIT_PHYCR_PAUSE_STS (1<<7) +#define BIT_PHYCR_STRETCH (1<<8) +#define BIT_PHYCR_BIST (1<<9) +#define BIT_PHYCR_BIST_STAT (1<<10) +#define BIT_PHYCR_PSR15 (1<<11) +#define REG_TBTSCR 58 +#define BIT_TBTSCR_JAB (1<<0) +#define BIT_TBTSCR_BEAT (1<<1) +#define BIT_TBTSCR_AUTOPOL (1<<3) +#define BIT_TBTSCR_POL (1<<4) +#define BIT_TBTSCR_FPOL (1<<5) +#define BIT_TBTSCR_FORCE_10 (1<<6) +#define BIT_TBTSCR_PULSE (1<<7) +#define BIT_TBTSCR_LOOP (1<<8) +#define REG_PMDCSR 64 +#define REG_TSTDAT 65 +#define REG_DSPCFG 66 +#define REG_SDCFG 67 +#define REG_PMATCH0 68 +#define REG_PMATCH1 69 +#define REG_PMATCH2 70 +#define REG_PCOUNT0 71 +#define REG_PCOUNT1 72 +#define REG_SOPASS0 73 +#define REG_SOPASS1 74 +#define REG_SOPASS2 75 + +static void __print_intr(int d, int intr, const char *name, + const char *s1, const char *s2) +{ + if ((d) & intr) + fprintf(stdout, " %s Interrupt: %s\n", name, s1); + else if (s2) + fprintf(stdout, " %s Interrupt: %s\n", name, s2); +} + +#define PRINT_INTR(d, i, s1, s2) do { \ + int intr = BIT_INTR_ ## i; \ + const char *name = NAME_INTR_ ## i; \ + __print_intr(d, intr, name, s1, s2); \ +} while (0) + +#define PRINT_INTRS(d, s1, s2) do { \ + PRINT_INTR((d), RXOK, s1, s2); \ + PRINT_INTR((d), RXDESC, s1, s2); \ + PRINT_INTR((d), RXERR, s1, s2); \ + PRINT_INTR((d), RXEARLY, s1, s2); \ + PRINT_INTR((d), RXIDLE, s1, s2); \ + PRINT_INTR((d), RXORN, s1, s2); \ + PRINT_INTR((d), TXOK, s1, s2); \ + PRINT_INTR((d), TXDESC, s1, s2); \ + PRINT_INTR((d), TXERR, s1, s2); \ + PRINT_INTR((d), TXIDLE, s1, s2); \ + PRINT_INTR((d), TXURN, s1, s2); \ + PRINT_INTR((d), MIB, s1, s2); \ + PRINT_INTR((d), SWI, s1, s2); \ + PRINT_INTR((d), PME, s1, s2); \ + PRINT_INTR((d), PHY, s1, s2); \ + PRINT_INTR((d), HIBERR, s1, s2); \ + PRINT_INTR((d), RXSOVR, s1, s2); \ + PRINT_INTR((d), RTABT, s1, s2); \ + PRINT_INTR((d), RMABT, s1, s2); \ + PRINT_INTR((d), SSERR, s1, s2); \ + PRINT_INTR((d), DPERR, s1, s2); \ + PRINT_INTR((d), RXRCMP, s1, s2); \ + PRINT_INTR((d), TXRCMP, s1, s2); \ +} while (0) + +int +natsemi_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + u32 *data = (u32 *)regs->data; + u32 tmp; + + fprintf(stdout, "Mac/BIU Registers\n"); + fprintf(stdout, "-----------------\n"); + + /* command register */ + fprintf(stdout, + "0x00: CR (Command): 0x%08x\n", + data[REG_CR]); + fprintf(stdout, + " Transmit %s\n" + " Receive %s\n", + data[REG_CR] & BIT_CR_TXE ? "Active" : "Idle", + data[REG_CR] & BIT_CR_RXE ? "Active" : "Idle"); + if (data[REG_CR] & BIT_CR_RST) fprintf(stdout, + " Reset In Progress\n"); + + /* configuration register */ + fprintf(stdout, + "0x04: CFG (Configuration): 0x%08x\n", + data[REG_CFG]); + fprintf(stdout, + " %s Endian\n" + " Boot ROM %s\n" + " Internal Phy %s\n" + " Phy Reset %s\n" + " External Phy %s\n" + " Default Auto-Negotiation %s, %s %s Mb %s Duplex\n" + " Phy Interrupt %sAuto-Cleared\n" + " Phy Configuration = 0x%02x\n" + " Auto-Negotiation %s\n" + " %s Polarity\n" + " %s Duplex\n" + " %d Mb/s\n" + " Link %s\n", + data[REG_CFG] & BIT_CFG_BEM ? "Big" : "Little", + data[REG_CFG] & BIT_CFG_BROM_DIS ? "Disabled" : "Enabled", + data[REG_CFG] & BIT_CFG_PHY_DIS ? "Disabled" : "Enabled", + data[REG_CFG] & BIT_CFG_PHY_RST ? "In Progress" : "Idle", + data[REG_CFG] & BIT_CFG_EXT_PHY ? "Enabled" : "Disabled", + data[REG_CFG] & BIT_CFG_ANEG_EN ? "Enabled" : "Disabled", + data[REG_CFG] & BIT_CFG_ANEG_EN ? "Advertise" : "Force", + data[REG_CFG] & BIT_CFG_ANEG_100 ? + (data[REG_CFG] & BIT_CFG_ANEG_EN ? "10/100" : "100") + : "10", + data[REG_CFG] & BIT_CFG_ANEG_FDUP ? + (data[REG_CFG] & BIT_CFG_ANEG_EN ? "Half/Full" : "Full") + : "Half", + data[REG_CFG] & BIT_CFG_PINT_ACEN ? "" : "Not ", + data[REG_CFG] & BIT_CFG_PHY_CFG >> 18, + data[REG_CFG] & BIT_CFG_ANEG_DN ? "Done" : "Not Done", + data[REG_CFG] & BIT_CFG_POL ? "Reversed" : "Normal", + data[REG_CFG] & BIT_CFG_FDUP ? "Full" : "Half", + data[REG_CFG] & BIT_CFG_SPEED100 ? 100 : 10, + data[REG_CFG] & BIT_CFG_LNKSTS ? "Up" : "Down"); + + /* EEPROM access register */ + fprintf(stdout, + "0x08: MEAR (EEPROM Access): 0x%08x\n", + data[REG_MEAR]); + + /* PCI test control register */ + fprintf(stdout, + "0x0c: PTSCR (PCI Test Control): 0x%08x\n", + data[REG_PTSCR]); + fprintf(stdout, + " EEPROM Self Test %s\n" + " Rx Filter Self Test %s\n" + " Tx FIFO Self Test %s\n" + " Rx FIFO Self Test %s\n", + data[REG_PTSCR] & BIT_PTSCR_EEBIST_FAIL ? "Failed" : "Passed", + data[REG_PTSCR] & BIT_PTSCR_RBIST_RXFFAIL ? "Failed" : "Passed", + data[REG_PTSCR] & BIT_PTSCR_RBIST_TXFAIL ? "Failed" : "Passed", + data[REG_PTSCR] & BIT_PTSCR_RBIST_RXFAIL ? "Failed" : "Passed"); + if (data[REG_PTSCR] & BIT_PTSCR_EELOAD_EN) fprintf(stdout, + " EEPROM Reload In Progress\n"); + + /* Interrupt status register */ + fprintf(stdout, + "0x10: ISR (Interrupt Status): 0x%08x\n", + data[REG_ISR]); + if (data[REG_ISR]) + PRINT_INTRS(data[REG_ISR], "Active", (char *)NULL); + else + fprintf(stdout, " No Interrupts Active\n"); + + /* Interrupt mask register */ + fprintf(stdout, + "0x14: IMR (Interrupt Mask): 0x%08x\n", + data[REG_IMR]); + PRINT_INTRS(data[REG_IMR], "Enabled", "Masked"); + + /* Interrupt enable register */ + fprintf(stdout, + "0x18: IER (Interrupt Enable): 0x%08x\n", + data[REG_IER]); + fprintf(stdout, + " Interrupts %s\n", + data[REG_IER] & BIT_IER_IE ? "Enabled" : "Disabled"); + + /* Tx descriptor pointer register */ + fprintf(stdout, + "0x20: TXDP (Tx Descriptor Pointer): 0x%08x\n", + data[REG_TXDP]); + + /* Tx configuration register */ + fprintf(stdout, + "0x24: TXCFG (Tx Config): 0x%08x\n", + data[REG_TXCFG]); + tmp = (data[REG_TXCFG] & BIT_TXCFG_MXDMA)>>20; + fprintf(stdout, + " Drain Threshhold = %d bytes (%d)\n" + " Fill Threshhold = %d bytes (%d)\n" + " Max DMA Burst per Tx = %d bytes\n" + " Automatic Tx Padding %s\n" + " Mac Loopback %s\n" + " Heartbeat Ignore %s\n" + " Carrier Sense Ignore %s\n", + (data[REG_TXCFG] & BIT_TXCFG_DRTH) * 32, + data[REG_TXCFG] & BIT_TXCFG_DRTH, + ((data[REG_TXCFG] & BIT_TXCFG_FLTH)>>8) * 32, + data[REG_TXCFG] & BIT_TXCFG_FLTH, + tmp ? (1<<(tmp-1))*4 : 512, + data[REG_TXCFG] & BIT_TXCFG_ATP ? "Enabled" : "Disabled", + data[REG_TXCFG] & BIT_TXCFG_MLB ? "Enabled" : "Disabled", + data[REG_TXCFG] & BIT_TXCFG_HBI ? "Enabled" : "Disabled", + data[REG_TXCFG] & BIT_TXCFG_CSI ? "Enabled" : "Disabled"); + + + /* Rx descriptor pointer register */ + fprintf(stdout, + "0x30: RXDP (Rx Descriptor Pointer): 0x%08x\n", + data[REG_RXDP]); + + /* Rx configuration register */ + fprintf(stdout, + "0x34: RXCFG (Rx Config): 0x%08x\n", + data[REG_RXCFG]); + tmp = (data[REG_RXCFG] & BIT_RXCFG_MXDMA)>>20; + fprintf(stdout, + " Drain Threshhold = %d bytes (%d)\n" + " Max DMA Burst per Rx = %d bytes\n" + " Long Packets %s\n" + " Tx Packets %s\n" + " Runt Packets %s\n" + " Error Packets %s\n", + ((data[REG_RXCFG] & BIT_RXCFG_DRTH) >> 1) * 8, + (data[REG_RXCFG] & BIT_RXCFG_DRTH) >> 1, + tmp ? (1<<(tmp-1))*4 : 512, + data[REG_RXCFG] & BIT_RXCFG_ALP ? "Accepted" : "Rejected", + data[REG_RXCFG] & BIT_RXCFG_ATX ? "Accepted" : "Rejected", + data[REG_RXCFG] & BIT_RXCFG_ARP ? "Accepted" : "Rejected", + data[REG_RXCFG] & BIT_RXCFG_AEP ? "Accepted" : "Rejected"); + + /* CLKRUN control/status register */ + fprintf(stdout, + "0x3c: CCSR (CLKRUN Control/Status): 0x%08x\n", + data[REG_CCSR]); + fprintf(stdout, + " CLKRUNN %s\n" + " Power Management %s\n", + data[REG_CCSR] & BIT_CCSR_CLKRUN_EN ? "Enabled" : "Disabled", + data[REG_CCSR] & BIT_CCSR_PMEEN ? "Enabled" : "Disabled"); + if (data[REG_CCSR] & BIT_CCSR_PMESTS) fprintf(stdout, + " Power Management Event Pending\n"); + + /* WoL control/status register */ + fprintf(stdout, + "0x40: WCSR (Wake-on-LAN Control/Status): 0x%08x\n", + data[REG_WCSR]); + if (data[REG_WCSR] & BIT_WCSR_WKPHY) fprintf(stdout, + " Wake on Phy Interrupt Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKUCP) fprintf(stdout, + " Wake on Unicast Packet Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKMCP) fprintf(stdout, + " Wake on Multicast Packet Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKBCP) fprintf(stdout, + " Wake on Broadcast Packet Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKARP) fprintf(stdout, + " Wake on Arp Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKPAT0) fprintf(stdout, + " Wake on Pattern 0 Match Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKPAT1) fprintf(stdout, + " Wake on Pattern 1 Match Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKPAT2) fprintf(stdout, + " Wake on Pattern 2 Match Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKPAT3) fprintf(stdout, + " Wake on Pattern 3 Match Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_WKMAG) fprintf(stdout, + " Wake on Magic Packet Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_MPSOE) fprintf(stdout, + " Magic Packet SecureOn Enabled\n"); + if (data[REG_WCSR] & BIT_WCSR_SOHACK) fprintf(stdout, + " SecureOn Hack Detected\n"); + if (data[REG_WCSR] & BIT_WCSR_PHYINT) fprintf(stdout, + " Phy Interrupt Received\n"); + if (data[REG_WCSR] & BIT_WCSR_UCASTR) fprintf(stdout, + " Unicast Packet Received\n"); + if (data[REG_WCSR] & BIT_WCSR_MCASTR) fprintf(stdout, + " Multicast Packet Received\n"); + if (data[REG_WCSR] & BIT_WCSR_BCASTR) fprintf(stdout, + " Broadcast Packet Received\n"); + if (data[REG_WCSR] & BIT_WCSR_ARPR) fprintf(stdout, + " Arp Received\n"); + if (data[REG_WCSR] & BIT_WCSR_PATM0) fprintf(stdout, + " Pattern 0 Received\n"); + if (data[REG_WCSR] & BIT_WCSR_PATM1) fprintf(stdout, + " Pattern 1 Received\n"); + if (data[REG_WCSR] & BIT_WCSR_PATM2) fprintf(stdout, + " Pattern 2 Received\n"); + if (data[REG_WCSR] & BIT_WCSR_PATM3) fprintf(stdout, + " Pattern 3 Received\n"); + if (data[REG_WCSR] & BIT_WCSR_MPR) fprintf(stdout, + " Magic Packet Received\n"); + + /* Pause control/status register */ + fprintf(stdout, + "0x44: PCR (Pause Control/Status): 0x%08x\n", + data[REG_PCR]); + fprintf(stdout, + " Pause Counter = %d\n" + " Pause %sNegotiated\n" + " Pause on DA %s\n" + " Pause on Mulitcast %s\n" + " Pause %s\n", + data[REG_PCR] & BIT_PCR_PAUSE_CNT, + data[REG_PCR] & BIT_PCR_PSNEG ? "" : "Not ", + data[REG_PCR] & BIT_PCR_PS_DA ? "Enabled" : "Disabled", + data[REG_PCR] & BIT_PCR_PSMCAST ? "Enabled" : "Disabled", + data[REG_PCR] & BIT_PCR_PSEN ? "Enabled" : "Disabled"); + if (data[REG_PCR] & BIT_PCR_PS_RCVD) fprintf(stdout, + " PS_RCVD: Pause Frame Received\n"); + + /* Rx Filter Control */ + fprintf(stdout, + "0x48: RFCR (Rx Filter Control): 0x%08x\n", + data[REG_RFCR]); + fprintf(stdout, + " Unicast Hash %s\n" + " Multicast Hash %s\n" + " Arp %s\n" + " Pattern 0 Match %s\n" + " Pattern 1 Match %s\n" + " Pattern 2 Match %s\n" + " Pattern 3 Match %s\n" + " Perfect Match %s\n" + " All Unicast %s\n" + " All Multicast %s\n" + " All Broadcast %s\n" + " Rx Filter %s\n", + data[REG_RFCR] & BIT_RFCR_UHEN ? "Enabled" : "Disabled", + data[REG_RFCR] & BIT_RFCR_MHEN ? "Enabled" : "Disabled", + data[REG_RFCR] & BIT_RFCR_AARP ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_APAT0 ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_APAT1 ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_APAT2 ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_APAT3 ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_APM ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_AAU ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_AAM ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_AAB ? "Accepted" : "Rejected", + data[REG_RFCR] & BIT_RFCR_RFEN ? "Enabled" : "Disabled"); + + /* Rx filter data register */ + fprintf(stdout, + "0x4c: RFDR (Rx Filter Data): 0x%08x\n", + data[REG_RFDR]); + if (regs->version >= 1) fprintf(stdout, + " PMATCH 1-0 = 0x%08x\n" + " PMATCH 3-2 = 0x%08x\n" + " PMATCH 5-4 = 0x%08x\n" + " PCOUNT 1-0 = 0x%08x\n" + " PCOUNT 3-2 = 0x%08x\n" + " SOPASS 1-0 = 0x%08x\n" + " SOPASS 3-2 = 0x%08x\n" + " SOPASS 5-4 = 0x%08x\n", + data[REG_PMATCH0], data[REG_PMATCH1], data[REG_PMATCH2], + data[REG_PCOUNT0], data[REG_PCOUNT1], + data[REG_SOPASS0], data[REG_SOPASS1], data[REG_SOPASS2]); + + + /* Boot ROM address register */ + fprintf(stdout, + "0x50: BRAR (Boot ROM Address): 0x%08x\n", + data[REG_BRAR]); + if (data[REG_BRAR] & BIT_BRAR_AUTOINC) fprintf(stdout, + " Automatically Increment Address\n"); + + /* Boot ROM data register */ + fprintf(stdout, + "0x54: BRDR (Boot ROM Data): 0x%08x\n", + data[REG_BRDR]); + + /* Silicon revison register */ + fprintf(stdout, + "0x58: SRR (Silicon Revision): 0x%08x\n", + data[REG_SRR]); + + /* Management information base control register */ + fprintf(stdout, + "0x5c: MIBC (Mgmt Info Base Control): 0x%08x\n", + data[REG_MIBC]); + if (data[REG_MIBC] & BIT_MIBC_WRN) fprintf(stdout, + " Counter Overflow Warning\n"); + if (data[REG_MIBC] & BIT_MIBC_FRZ) fprintf(stdout, + " Counters Frozen\n"); + + /* MIB registers */ + fprintf(stdout, + "0x60: MIB[0] (Rx Errored Packets): 0x%04x\n", + data[REG_MIB0]); + fprintf(stdout, " Value = %d\n", data[REG_MIB0]); + fprintf(stdout, + "0x64: MIB[1] (Rx Frame Sequence Errors): 0x%02x\n", + data[REG_MIB1]); + fprintf(stdout, " Value = %d\n", data[REG_MIB1]); + fprintf(stdout, + "0x68: MIB[2] (Rx Missed Packets): 0x%02x\n", + data[REG_MIB2]); + fprintf(stdout, " Value = %d\n", data[REG_MIB2]); + fprintf(stdout, + "0x6c: MIB[3] (Rx Alignment Errors): 0x%02x\n", + data[REG_MIB3]); + fprintf(stdout, " Value = %d\n", data[REG_MIB3]); + fprintf(stdout, + "0x70: MIB[4] (Rx Symbol Errors): 0x%02x\n", + data[REG_MIB4]); + fprintf(stdout, " Value = %d\n", data[REG_MIB4]); + fprintf(stdout, + "0x74: MIB[5] (Rx Long Frame Errors): 0x%02x\n", + data[REG_MIB5]); + fprintf(stdout, " Value = %d\n", data[REG_MIB5]); + fprintf(stdout, + "0x78: MIB[6] (Tx Heartbeat Errors): 0x%02x\n", + data[REG_MIB6]); + fprintf(stdout, " Value = %d\n", data[REG_MIB6]); + + fprintf(stdout, "\n"); + fprintf(stdout, "Internal Phy Registers\n"); + fprintf(stdout, "----------------------\n"); + + /* Basic mode control register */ + fprintf(stdout, + "0x80: BMCR (Basic Mode Control): 0x%04x\n", + data[REG_BMCR]); + fprintf(stdout, + " %s Duplex\n" + " Port is Powered %s\n" + " Auto-Negotiation %s\n" + " %d Mb/s\n", + data[REG_BMCR] & BIT_BMCR_FDUP ? "Full" : "Half", + data[REG_BMCR] & BIT_BMCR_PDOWN ? "Down" : "Up", + data[REG_BMCR] & BIT_BMCR_ANEN ? "Enabled" : "Disabled", + data[REG_BMCR] & BIT_BMCR_SPEED ? 100 : 10); + if (data[REG_BMCR] & BIT_BMCR_ANRST) fprintf(stdout, + " Auto-Negotiation Restarting\n"); + if (data[REG_BMCR] & BIT_BMCR_ISOL) fprintf(stdout, + " Port Isolated\n"); + if (data[REG_BMCR] & BIT_BMCR_LOOP) fprintf(stdout, + " Loopback Enabled\n"); + if (data[REG_BMCR] & BIT_BMCR_RST) fprintf(stdout, + " Reset In Progress\n"); + + /* Basic mode status register */ + fprintf(stdout, + "0x84: BMSR (Basic Mode Status): 0x%04x\n", + data[REG_BMSR]); + fprintf(stdout, + " Link %s\n" + " %sCapable of Auto-Negotiation\n" + " Auto-Negotiation %sComplete\n" + " %sCapable of Preamble Suppression\n" + " %sCapable of 10Base-T Half Duplex\n" + " %sCapable of 10Base-T Full Duplex\n" + " %sCapable of 100Base-TX Half Duplex\n" + " %sCapable of 100Base-TX Full Duplex\n" + " %sCapable of 100Base-T4\n", + data[REG_BMSR] & BIT_BMSR_LNK ? "Up" : "Down", + data[REG_BMSR] & BIT_BMSR_ANCAP ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_ANDONE ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_PREAMBLE ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_10HCAP ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_10FCAP ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_100HCAP ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_100FCAP ? "" : "Not ", + data[REG_BMSR] & BIT_BMSR_100T4CAP ? "" : "Not "); + if (data[REG_BMSR] & BIT_BMSR_JABBER) fprintf(stdout, + " Jabber Condition Detected\n"); + if (data[REG_BMSR] & BIT_BMSR_RFAULT) fprintf(stdout, + " Remote Fault Detected\n"); + + /* PHY identification registers */ + fprintf(stdout, + "0x88: PHYIDR1 (PHY ID #1): 0x%04x\n", + data[REG_PHYIDR1]); + fprintf(stdout, + "0x8c: PHYIDR2 (PHY ID #2): 0x%04x\n", + data[REG_PHYIDR2]); + fprintf(stdout, + " OUI = 0x%06x\n" + " Model = 0x%02x (%d)\n" + " Revision = 0x%01x (%d)\n", + (data[REG_PHYIDR1] << 6) | (data[REG_PHYIDR2] >> 10), + (data[REG_PHYIDR2] & BIT_PHYIDR2_MODEL) >> 4 & 0x3f, + (data[REG_PHYIDR2] & BIT_PHYIDR2_MODEL) >> 4 & 0x3f, + data[REG_PHYIDR2] & BIT_PHYIDR2_REV, + data[REG_PHYIDR2] & BIT_PHYIDR2_REV); + + /* autonegotiation advertising register */ + fprintf(stdout, + "0x90: ANAR (Autoneg Advertising): 0x%04x\n", + data[REG_ANAR]); + fprintf(stdout, + " Protocol Selector = 0x%02x (%d)\n", + data[REG_ANAR] & BIT_ANAR_PROTO, + data[REG_ANAR] & BIT_ANAR_PROTO); + if (data[REG_ANAR] & BIT_ANAR_10) fprintf(stdout, + " Advertising 10Base-T Half Duplex\n"); + if (data[REG_ANAR] & BIT_ANAR_10_FD) fprintf(stdout, + " Advertising 10Base-T Full Duplex\n"); + if (data[REG_ANAR] & BIT_ANAR_TX) fprintf(stdout, + " Advertising 100Base-TX Half Duplex\n"); + if (data[REG_ANAR] & BIT_ANAR_TXFD) fprintf(stdout, + " Advertising 100Base-TX Full Duplex\n"); + if (data[REG_ANAR] & BIT_ANAR_T4) fprintf(stdout, + " Advertising 100Base-T4\n"); + if (data[REG_ANAR] & BIT_ANAR_PAUSE) fprintf(stdout, + " Advertising Pause\n"); + if (data[REG_ANAR] & BIT_ANAR_RF) fprintf(stdout, + " Indicating Remote Fault\n"); + if (data[REG_ANAR] & BIT_ANAR_NP) fprintf(stdout, + " Next Page Desired\n"); + + /* Autonegotiation link partner ability register */ + fprintf(stdout, + "0x94: ANLPAR (Autoneg Partner): 0x%04x\n", + data[REG_ANLPAR]); + fprintf(stdout, + " Protocol Selector = 0x%02x (%d)\n", + data[REG_ANLPAR] & BIT_ANLPAR_PROTO, + data[REG_ANLPAR] & BIT_ANLPAR_PROTO); + if (data[REG_ANLPAR] & BIT_ANLPAR_10) fprintf(stdout, + " Supports 10Base-T Half Duplex\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_10_FD) fprintf(stdout, + " Supports 10Base-T Full Duplex\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_TX) fprintf(stdout, + " Supports 100Base-TX Half Duplex\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_TXFD) fprintf(stdout, + " Supports 100Base-TX Full Duplex\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_T4) fprintf(stdout, + " Supports 100Base-T4\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_PAUSE) fprintf(stdout, + " Supports Pause\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_RF) fprintf(stdout, + " Indicates Remote Fault\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_ACK) fprintf(stdout, + " Indicates Acknowledgement\n"); + if (data[REG_ANLPAR] & BIT_ANLPAR_NP) fprintf(stdout, + " Next Page Desired\n"); + + /* Autonegotiation expansion register */ + fprintf(stdout, + "0x98: ANER (Autoneg Expansion): 0x%04x\n", + data[REG_ANER]); + fprintf(stdout, + " Link Partner Can %sAuto-Negotiate\n" + " Link Code Word %sReceived\n" + " Next Page %sSupported\n" + " Link Partner Next Page %sSupported\n", + data[REG_ANER] & BIT_ANER_LP_AN_ENABLE ? "" : "Not ", + data[REG_ANER] & BIT_ANER_PAGE_RX ? "" : "Not ", + data[REG_ANER] & BIT_ANER_NP_ABLE ? "" : "Not ", + data[REG_ANER] & BIT_ANER_LP_NP_ABLE ? "" : "Not "); + if (data[REG_ANER] & BIT_ANER_PDF) fprintf(stdout, + " Parallel Detection Fault\n"); + + /* Autonegotiation next-page tx register */ + fprintf(stdout, + "0x9c: ANNPTR (Autoneg Next Page Tx): 0x%04x\n", + data[REG_ANNPTR]); + + /* Phy status register */ + fprintf(stdout, + "0xc0: PHYSTS (Phy Status): 0x%04x\n", + data[REG_PHYSTS]); + fprintf(stdout, + " Link %s\n" + " %d Mb/s\n" + " %s Duplex\n" + " Auto-Negotiation %sComplete\n" + " %s Polarity\n", + data[REG_PHYSTS] & BIT_PHYSTS_LNK ? "Up" : "Down", + data[REG_PHYSTS] & BIT_PHYSTS_SPD10 ? 10 : 100, + data[REG_PHYSTS] & BIT_PHYSTS_FDUP ? "Full" : "Half", + data[REG_PHYSTS] & BIT_PHYSTS_ANDONE ? "" : "Not ", + data[REG_PHYSTS] & BIT_PHYSTS_POL ? "Reverse" : "Normal"); + if (data[REG_PHYSTS] & BIT_PHYSTS_LOOP) fprintf(stdout, + " Loopback Enabled\n"); + if (data[REG_PHYSTS] & BIT_PHYSTS_JABBER) fprintf(stdout, + " Jabber Condition Detected\n"); + if (data[REG_PHYSTS] & BIT_PHYSTS_RF) fprintf(stdout, + " Remote Fault Detected\n"); + if (data[REG_PHYSTS] & BIT_PHYSTS_MINT) fprintf(stdout, + " MII Interrupt Detected\n"); + if (data[REG_PHYSTS] & BIT_PHYSTS_FC) fprintf(stdout, + " False Carrier Detected\n"); + if (data[REG_PHYSTS] & BIT_PHYSTS_RXERR) fprintf(stdout, + " Rx Error Detected\n"); + + fprintf(stdout, + "0xc4: MICR (MII Interrupt Control): 0x%04x\n", + data[REG_MICR]); + fprintf(stdout, + " MII Interrupts %s\n", + data[REG_MICR] & BIT_MICR_INTEN ? "Enabled" : "Disabled"); + + fprintf(stdout, + "0xc8: MISR (MII Interrupt Status): 0x%04x\n", + data[REG_MISR]); + fprintf(stdout, + " Rx Error Counter Half-Full Interrupt %s\n" + " False Carrier Counter Half-Full Interrupt %s\n" + " Auto-Negotiation Complete Interrupt %s\n" + " Remote Fault Interrupt %s\n" + " Jabber Interrupt %s\n" + " Link Change Interrupt %s\n", + data[REG_MISR] & BIT_MISR_MSK_RHF ? "Masked" : "Enabled", + data[REG_MISR] & BIT_MISR_MSK_FHF ? "Masked" : "Enabled", + data[REG_MISR] & BIT_MISR_MSK_ANC ? "Masked" : "Enabled", + data[REG_MISR] & BIT_MISR_MSK_RF ? "Masked" : "Enabled", + data[REG_MISR] & BIT_MISR_MSK_JAB ? "Masked" : "Enabled", + data[REG_MISR] & BIT_MISR_MSK_LNK ? "Masked" : "Enabled"); + if (data[REG_MISR] & BIT_MISR_MINT) fprintf(stdout, + " MII Interrupt Pending\n"); + + /* Page select register (from section of spec on 'suggested values') */ + fprintf(stdout, + "0xcc: PGSEL (Phy Register Page Select): 0x%04x\n", + data[REG_PGSEL]); + + /* counters */ + fprintf(stdout, + "0xd0: FCSCR (False Carrier Counter): 0x%04x\n", + data[REG_FCSCR]); + fprintf(stdout, + " Value = %d\n", data[REG_FCSCR] & 0xff); + fprintf(stdout, + "0xd4: RECR (Rx Error Counter): 0x%04x\n", + data[REG_RECR]); + fprintf(stdout, + " Value = %d\n", data[REG_RECR] & 0xff); + + /* 100 Mbit configuration register */ + fprintf(stdout, + "0xd8: PCSR (100Mb/s PCS Config/Status): 0x%04x\n", + data[REG_PCSR]); + fprintf(stdout, + " NRZI Bypass %s\n" + " %s Signal Detect Algorithm\n" + " %s Signal Detect Operation\n" + " True Quiet Mode %s\n" + " Rx Clock is %s\n" + " 4B/5B Operation %s\n", + data[REG_PCSR] & BIT_PCSR_NRZI ? "Enabled" : "Disabled", + data[REG_PCSR] & BIT_PCSR_SDOPT ? "Enhanced" : "Reduced", + data[REG_PCSR] & BIT_PCSR_SDFORCE ? "Forced" : "Normal", + data[REG_PCSR] & BIT_PCSR_TQM ? "Enabled" : "Disabled", + data[REG_PCSR] & BIT_PCSR_CLK ? + "Free-Running" : "Phase-Adjusted", + data[REG_PCSR] & BIT_PCSR_4B5B ? "Bypassed" : "Normal"); + if (data[REG_PCSR] & BIT_PCSR_FORCE_100) fprintf(stdout, + " Forced 100 Mb/s Good Link\n"); + + /* Phy control register */ + fprintf(stdout, + "0xe4: PHYCR (Phy Control): 0x%04x\n", + data[REG_PHYCR]); + fprintf(stdout, + " Phy Address = 0x%x (%d)\n" + " %sPause Compatible with Link Partner\n" + " LED Stretching %s\n" + " Phy Self Test %s\n" + " Self Test Sequence = PSR%d\n", + data[REG_PHYCR] & BIT_PHYCR_PHYADDR, + data[REG_PHYCR] & BIT_PHYCR_PHYADDR, + data[REG_PHYCR] & BIT_PHYCR_PAUSE_STS ? "" : "Not ", + data[REG_PHYCR] & BIT_PHYCR_STRETCH ? "Bypassed" : "Enabled", + data[REG_PHYCR] & BIT_PHYCR_BIST ? "In Progress" : + data[REG_PHYCR] & BIT_PHYCR_BIST_STAT ? + "Passed" : "Failed or Not Run", + data[REG_PHYCR] & BIT_PHYCR_PSR15 ? 15 : 9); + + + /* 10 Mbit control and status register */ + fprintf(stdout, + "0xe8: TBTSCR (10Base-T Status/Control): 0x%04x\n", + data[REG_TBTSCR]); + fprintf(stdout, + " Jabber %s\n" + " Heartbeat %s\n" + " Polarity Auto-Sense/Correct %s\n" + " %s Polarity %s\n" + " Normal Link Pulse %s\n" + " 10 Mb/s Loopback %s\n", + data[REG_TBTSCR] & BIT_TBTSCR_JAB ? "Disabled" : "Enabled", + data[REG_TBTSCR] & BIT_TBTSCR_BEAT ? "Disabled" : "Enabled", + data[REG_TBTSCR] & BIT_TBTSCR_AUTOPOL ? "Disabled" : "Enabled", + data[REG_TBTSCR] & BIT_TBTSCR_AUTOPOL ? + data[REG_TBTSCR]&BIT_TBTSCR_FPOL ? "Reverse":"Normal" : + data[REG_TBTSCR]&BIT_TBTSCR_POL ? "Reverse":"Normal", + data[REG_TBTSCR] & BIT_TBTSCR_AUTOPOL ? "Forced" : "Detected", + data[REG_TBTSCR] & BIT_TBTSCR_PULSE ? "Disabled" : "Enabled", + data[REG_TBTSCR] & BIT_TBTSCR_LOOP ? "Enabled" : "Disabled"); + if (data[REG_TBTSCR] & BIT_TBTSCR_FORCE_10) fprintf(stdout, + " Forced 10 Mb/s Good Link\n"); + + /* the spec says to set these */ + fprintf(stdout, "\n"); + fprintf(stdout, "'Magic' Phy Registers\n"); + fprintf(stdout, "---------------------\n"); + fprintf(stdout, + "0xe4: PMDCSR: 0x%04x\n", + data[REG_PMDCSR]); + fprintf(stdout, + "0xf4: DSPCFG: 0x%04x\n", + data[REG_DSPCFG]); + fprintf(stdout, + "0xf8: SDCFG: 0x%04x\n", + data[REG_SDCFG]); + fprintf(stdout, + "0xfc: TSTDAT: 0x%04x\n", + data[REG_TSTDAT]); + + return 0; +} + +int +natsemi_dump_eeprom(struct ethtool_drvinfo *info, struct ethtool_eeprom *ee) +{ + int i; + u16 *eebuf = (u16 *)ee->data; + + if (ee->magic != NATSEMI_MAGIC) { + fprintf(stderr, "Magic number 0x%08x does not match 0x%08x\n", + ee->magic, NATSEMI_MAGIC); + return -1; + } + + fprintf(stdout, "Address\tData\n"); + fprintf(stdout, "-------\t------\n"); + for (i = 0; i < ee->len/2; i++) { + fprintf(stdout, "0x%02x \t0x%04x\n", i + ee->offset, eebuf[i]); + } + + return 0; +} + diff --git a/pcnet32.c b/pcnet32.c new file mode 100644 index 0000000..a4641ca --- /dev/null +++ b/pcnet32.c @@ -0,0 +1,222 @@ +/* Copyright 2004 IBM Corporation (jklewis@us.ibm.com) */ + +#include +#include +#include "ethtool-util.h" + +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 + +int pcnet32_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + int i, csr; + u16 *data = (u16 *) regs->data; + int len = regs->len / 2; + u16 temp,*ptr; + + printf("Driver: %s\n",info->driver); + printf("Version: %s\n",info->version); + + printf("APROM: "); + for (i=0; i<8; i++) + printf(" %04x ", data[i]); + printf("\n"); + + csr = i; + for (; i<100; i++) + { + if (((i-csr) & 7) == 0) printf("CSR%02d: ", i-csr); + printf(" %04x ", data[i]); + if (((i-csr) & 7) == 7) printf("\n"); + } + if (((i-csr) & 7) != 7) printf("\n"); + + csr = i; + for (; i<136; i++) + { + if (((i-csr) & 7) == 0) printf("BCR%02d: ", i-csr); + printf(" %04x ", data[i]); + if (((i-csr) & 7) == 7) printf("\n"); + } + if (((i-csr) & 7) != 7) printf("\n"); + + csr = i; + for (; i> 12,temp & 0x00000fff); + + printf("CSR112: Missed Frame Count 0x%04x\n",ptr[90]); /* 90 is 112 */ + printf("CSR114: RX Collision Count 0x%04x\n",ptr[91]); + + printf("\n"); + + ptr=&data[100]; /* point to BCR 0 */ + + printf("BCR2: Misc. Configuration 0x%04x\n ",ptr[2]); + temp=ptr[2]; + + if(temp & BIT14) printf("TMAULOOP "); + if(temp & BIT12) printf("LEDPE "); + + if(temp & BIT8) printf("APROMWE "); + if(temp & BIT7) printf("INTLEVEL "); + + if(temp & BIT3) printf("EADISEL "); + if(temp & BIT2) printf("AWAKE "); + if(temp & BIT1) printf("ASEL "); + if(temp & BIT0) printf("XMAUSEL "); + + printf("\n"); + + printf("BCR9: Full-Duplex Control 0x%04x\n",ptr[9]); + printf("BCR18: Burst and Bus Control 0x%04x\n",ptr[18]); + + printf("BCR19: EEPROM Control and Status 0x%04x\n ",ptr[19]); + temp=ptr[19]; + if(temp & BIT15) printf("PVALID "); + if(temp & BIT13) printf("EEDET "); + printf("\n"); + + printf("BCR23: PCI Subsystem Vendor ID 0x%04x\n",ptr[23]); + printf("BCR24: PCI Subsystem ID 0x%04x\n",ptr[24]); + printf("BCR31: Software Timer 0x%04x\n",ptr[31]); + printf("BCR32: MII Control and Status 0x%04x\n",ptr[32]); + printf("BCR35: PCI Vendor ID 0x%04x\n",ptr[35]); + + return(0); +} + diff --git a/realtek.c b/realtek.c new file mode 100644 index 0000000..64ab7f8 --- /dev/null +++ b/realtek.c @@ -0,0 +1,517 @@ +/* Copyright 2001 Sun Microsystems (thockin@sun.com) */ +#include +#include +#include "ethtool-util.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ + (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) + +enum chip_type { + RTLNONE, + RTL8139, + RTL8139_K, + RTL8139A, + RTL8139A_G, + RTL8139B, + RTL8130, + RTL8139C, + RTL8100, + RTL8100B_8139D, + RTL8139Cp, + RTL8101, + RTL8169, + RTL8169s, + RTL8110 +}; + +enum { + chip_type_mask = HW_REVID(1, 1, 1, 1, 1, 1, 1) +}; + +static struct chip_info { + const char *name; + u32 id_mask; +} rtl_info_tbl[] = { + { "RTL-8139", HW_REVID(1, 0, 0, 0, 0, 0, 0) }, + { "RTL-8139-K", HW_REVID(1, 1, 0, 0, 0, 0, 0) }, + { "RTL-8139A", HW_REVID(1, 1, 1, 0, 0, 0, 0) }, + { "RTL-8139A-G", HW_REVID(1, 1, 1, 0, 0, 1, 0) }, + { "RTL-8139B", HW_REVID(1, 1, 1, 1, 0, 0, 0) }, + { "RTL-8130", HW_REVID(1, 1, 1, 1, 1, 0, 0) }, + { "RTL-8139C", HW_REVID(1, 1, 1, 0, 1, 0, 0) }, + { "RTL-8100", HW_REVID(1, 1, 1, 1, 0, 1, 0) }, + { "RTL-8100B/8139D", HW_REVID(1, 1, 1, 0, 1, 0, 1) }, + { "RTL-8139C+", HW_REVID(1, 1, 1, 0, 1, 1, 0) }, + { "RTL-8101", HW_REVID(1, 1, 1, 0, 1, 1, 1) }, + { "RTL-8169", HW_REVID(0, 0, 0, 0, 0, 0, 0) }, + { "RTL-8169s", HW_REVID(0, 0, 0, 0, 1, 0, 0) }, + { "RTL-8110", HW_REVID(0, 0, 1, 0, 0, 0, 0) }, + { } +}; + +static void +print_intr_bits(u16 mask) +{ + fprintf(stdout, + " %s%s%s%s%s%s%s%s%s%s%s\n", + mask & (1 << 15) ? "SERR " : "", + mask & (1 << 14) ? "TimeOut " : "", + mask & (1 << 8) ? "SWInt " : "", + mask & (1 << 7) ? "TxNoBuf " : "", + mask & (1 << 6) ? "RxFIFO " : "", + mask & (1 << 5) ? "LinkChg " : "", + mask & (1 << 4) ? "RxNoBuf " : "", + mask & (1 << 3) ? "TxErr " : "", + mask & (1 << 2) ? "TxOK " : "", + mask & (1 << 1) ? "RxErr " : "", + mask & (1 << 0) ? "RxOK " : ""); +} + +int +realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs) +{ + u32 *data = (u32 *) regs->data; + u8 *data8 = (u8 *) regs->data; + u32 v; + struct chip_info *ci; + unsigned int board_type = RTLNONE, i; + + v = data[0x40 >> 2] & chip_type_mask; + + ci = &rtl_info_tbl[0]; + while (ci->name) { + if (v == ci->id_mask) + break; + ci++; + } + if (v != ci->id_mask) { + fprintf(stderr, "unknown RealTek chip\n"); + return 91; + } + for (i = 0; i < ARRAY_SIZE(rtl_info_tbl); i++) { + if (ci == &rtl_info_tbl[i]) + board_type = i + 1; + } + if (board_type == RTLNONE) + abort(); + + fprintf(stdout, + "RealTek %s registers:\n" + "------------------------------\n", + ci->name); + + fprintf(stdout, + "0x00: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", + data8[0x00], + data8[0x01], + data8[0x02], + data8[0x03], + data8[0x04], + data8[0x05]); + + fprintf(stdout, + "0x08: Multicast Address Filter 0x%08x 0x%08x\n", + data[0x08 >> 2], + data[0x0c >> 2]); + + if (board_type == RTL8139Cp || + board_type == RTL8169 || + board_type == RTL8169s || + board_type == RTL8110) { + fprintf(stdout, + "0x10: Dump Tally Counter Command 0x%08x 0x%08x\n", + data[0x10 >> 2], + data[0x14 >> 2]); + + fprintf(stdout, + "0x20: Tx Normal Priority Ring Addr 0x%08x 0x%08x\n", + data[0x20 >> 2], + data[0x24 >> 2]); + + fprintf(stdout, + "0x28: Tx High Priority Ring Addr 0x%08x 0x%08x\n", + data[0x28 >> 2], + data[0x2C >> 2]); + } else { + fprintf(stdout, + "0x10: Transmit Status Desc 0 0x%08x\n" + "0x14: Transmit Status Desc 1 0x%08x\n" + "0x18: Transmit Status Desc 2 0x%08x\n" + "0x1C: Transmit Status Desc 3 0x%08x\n", + data[0x10 >> 2], + data[0x14 >> 2], + data[0x18 >> 2], + data[0x1C >> 2]); + fprintf(stdout, + "0x20: Transmit Start Addr 0 0x%08x\n" + "0x24: Transmit Start Addr 1 0x%08x\n" + "0x28: Transmit Start Addr 2 0x%08x\n" + "0x2C: Transmit Start Addr 3 0x%08x\n", + data[0x20 >> 2], + data[0x24 >> 2], + data[0x28 >> 2], + data[0x2C >> 2]); + } + + if (board_type == RTL8169 || + board_type == RTL8169s || + board_type == RTL8110) { + fprintf(stdout, + "0x30: Flash memory read/write 0x%08x\n", + data[0x30 >> 2]); + } else { + fprintf(stdout, + "0x30: Rx buffer addr (C mode) 0x%08x\n", + data[0x30 >> 2]); + } + + v = data8[0x36]; + fprintf(stdout, + "0x34: Early Rx Byte Count %8u\n" + "0x36: Early Rx Status 0x%02x\n", + data[0x34 >> 2] & 0xffff, + v); + + if (v & 0xf) { + fprintf(stdout, + " %s%s%s%s\n", + v & (1 << 3) ? "ERxGood " : "", + v & (1 << 2) ? "ERxBad " : "", + v & (1 << 1) ? "ERxOverWrite " : "", + v & (1 << 0) ? "ERxOK " : ""); + } + + v = data8[0x37]; + fprintf(stdout, + "0x37: Command 0x%02x\n" + " Rx %s, Tx %s%s\n", + data8[0x37], + v & (1 << 3) ? "on" : "off", + v & (1 << 2) ? "on" : "off", + v & (1 << 4) ? ", RESET" : ""); + + if (board_type != RTL8169 && + board_type != RTL8169s && + board_type != RTL8110) { + fprintf(stdout, + "0x38: Current Address of Packet Read (C mode) 0x%04x\n" + "0x3A: Current Rx buffer address (C mode) 0x%04x\n", + data[0x38 >> 2] & 0xffff, + data[0x38 >> 2] >> 16); + } + + fprintf(stdout, + "0x3C: Interrupt Mask 0x%04x\n", + data[0x3c >> 2] & 0xffff); + print_intr_bits(data[0x3c >> 2] & 0xffff); + fprintf(stdout, + "0x3E: Interrupt Status 0x%04x\n", + data[0x3c >> 2] >> 16); + print_intr_bits(data[0x3c >> 2] >> 16); + + fprintf(stdout, + "0x40: Tx Configuration 0x%08x\n" + "0x44: Rx Configuration 0x%08x\n" + "0x48: Timer count 0x%08x\n" + "0x4C: Missed packet counter 0x%06x\n", + data[0x40 >> 2], + data[0x44 >> 2], + data[0x48 >> 2], + data[0x4C >> 2] & 0xffffff); + + fprintf(stdout, + "0x50: EEPROM Command 0x%02x\n" + "0x51: Config 0 0x%02x\n" + "0x52: Config 1 0x%02x\n", + data8[0x50], + data8[0x51], + data8[0x52]); + + if (board_type == RTL8169 || + board_type == RTL8169s || + board_type == RTL8110) { + fprintf(stdout, + "0x53: Config 2 0x%02x\n" + "0x54: Config 3 0x%02x\n" + "0x55: Config 4 0x%02x\n" + "0x56: Config 5 0x%02x\n", + data8[0x53], + data8[0x54], + data8[0x55], + data8[0x56]); + fprintf(stdout, + "0x58: Timer interrupt 0x%08x\n", + data[0x58 >> 2]); + } + else { + if (board_type >= RTL8139A) { + fprintf(stdout, + "0x54: Timer interrupt 0x%08x\n", + data[0x54 >> 2]); + } + fprintf(stdout, + "0x58: Media status 0x%02x\n", + data8[0x58]); + if (board_type >= RTL8139A) { + fprintf(stdout, + "0x59: Config 3 0x%02x\n", + data8[0x59]); + } + if (board_type >= RTL8139B) { + fprintf(stdout, + "0x5A: Config 4 0x%02x\n", + data8[0x5A]); + } + } + + fprintf(stdout, + "0x5C: Multiple Interrupt Select 0x%04x\n", + data[0x5c >> 2] & 0xffff); + + if (board_type == RTL8169 || + board_type == RTL8169s || + board_type == RTL8110) { + fprintf(stdout, + "0x60: PHY access 0x%08x\n" + "0x64: TBI control and status 0x%08x\n", + data[0x60 >> 2], + data[0x64 >> 2]); + + fprintf(stdout, + "0x68: TBI Autonegotiation advertisement (ANAR) 0x%04x\n" + "0x6A: TBI Link partner ability (LPAR) 0x%04x\n", + data[0x68 >> 2] & 0xffff, + data[0x68 >> 2] >> 16); + + fprintf(stdout, + "0x6C: PHY status 0x%02x\n", + data8[0x6C]); + + fprintf(stdout, + "0x84: PM wakeup frame 0 0x%08x 0x%08x\n" + "0x8C: PM wakeup frame 1 0x%08x 0x%08x\n", + data[0x84 >> 2], + data[0x88 >> 2], + data[0x8C >> 2], + data[0x90 >> 2]); + + fprintf(stdout, + "0x94: PM wakeup frame 2 (low) 0x%08x 0x%08x\n" + "0x9C: PM wakeup frame 2 (high) 0x%08x 0x%08x\n", + data[0x94 >> 2], + data[0x98 >> 2], + data[0x9C >> 2], + data[0xA0 >> 2]); + + fprintf(stdout, + "0xA4: PM wakeup frame 3 (low) 0x%08x 0x%08x\n" + "0xAC: PM wakeup frame 3 (high) 0x%08x 0x%08x\n", + data[0xA4 >> 2], + data[0xA8 >> 2], + data[0xAC >> 2], + data[0xB0 >> 2]); + + fprintf(stdout, + "0xB4: PM wakeup frame 4 (low) 0x%08x 0x%08x\n" + "0xBC: PM wakeup frame 4 (high) 0x%08x 0x%08x\n", + data[0xB4 >> 2], + data[0xB8 >> 2], + data[0xBC >> 2], + data[0xC0 >> 2]); + + fprintf(stdout, + "0xC4: Wakeup frame 0 CRC 0x%04x\n" + "0xC6: Wakeup frame 1 CRC 0x%04x\n" + "0xC8: Wakeup frame 2 CRC 0x%04x\n" + "0xCA: Wakeup frame 3 CRC 0x%04x\n" + "0xCC: Wakeup frame 4 CRC 0x%04x\n", + data[0xC4 >> 2] & 0xffff, + data[0xC4 >> 2] >> 16, + data[0xC8 >> 2] & 0xffff, + data[0xC8 >> 2] >> 16, + data[0xCC >> 2] & 0xffff); + fprintf(stdout, + "0xDA: RX packet maximum size 0x%04x\n", + data[0xD8 >> 2] >> 16); + } + else { + fprintf(stdout, + "0x5E: PCI revision id 0x%02x\n", + data8[0x5e]); + fprintf(stdout, + "0x60: Transmit Status of All Desc (C mode) 0x%04x\n" + "0x62: MII Basic Mode Control Register 0x%04x\n", + data[0x60 >> 2] & 0xffff, + data[0x60 >> 2] >> 16); + fprintf(stdout, + "0x64: MII Basic Mode Status Register 0x%04x\n" + "0x66: MII Autonegotiation Advertising 0x%04x\n", + data[0x64 >> 2] & 0xffff, + data[0x64 >> 2] >> 16); + fprintf(stdout, + "0x68: MII Link Partner Ability 0x%04x\n" + "0x6A: MII Expansion 0x%04x\n", + data[0x68 >> 2] & 0xffff, + data[0x68 >> 2] >> 16); + fprintf(stdout, + "0x6C: MII Disconnect counter 0x%04x\n" + "0x6E: MII False carrier sense counter 0x%04x\n", + data[0x6C >> 2] & 0xffff, + data[0x6C >> 2] >> 16); + fprintf(stdout, + "0x70: MII Nway test 0x%04x\n" + "0x72: MII RX_ER counter 0x%04x\n", + data[0x70 >> 2] & 0xffff, + data[0x70 >> 2] >> 16); + fprintf(stdout, + "0x74: MII CS configuration 0x%04x\n", + data[0x74 >> 2] & 0xffff); + if (board_type >= RTL8139_K) { + fprintf(stdout, + "0x78: PHY parameter 1 0x%08x\n" + "0x7C: Twister parameter 0x%08x\n", + data[0x78 >> 2], + data[0x7C >> 2]); + if (board_type >= RTL8139A) { + fprintf(stdout, + "0x80: PHY parameter 2 0x%02x\n", + data8[0x80]); + } + } + if (board_type == RTL8139Cp) { + fprintf(stdout, + "0x82: Low addr of a Tx Desc w/ Tx DMA OK 0x%04x\n", + data[0x80 >> 2] >> 16); + } else if (board_type == RTL8130) { + fprintf(stdout, + "0x82: MII register 0x%02x\n", + data8[0x82]); + } + if (board_type >= RTL8139A) { + fprintf(stdout, + "0x84: PM CRC for wakeup frame 0 0x%02x\n" + "0x85: PM CRC for wakeup frame 1 0x%02x\n" + "0x86: PM CRC for wakeup frame 2 0x%02x\n" + "0x87: PM CRC for wakeup frame 3 0x%02x\n" + "0x88: PM CRC for wakeup frame 4 0x%02x\n" + "0x89: PM CRC for wakeup frame 5 0x%02x\n" + "0x8A: PM CRC for wakeup frame 6 0x%02x\n" + "0x8B: PM CRC for wakeup frame 7 0x%02x\n", + data8[0x84], + data8[0x85], + data8[0x86], + data8[0x87], + data8[0x88], + data8[0x89], + data8[0x8A], + data8[0x8B]); + fprintf(stdout, + "0x8C: PM wakeup frame 0 0x%08x 0x%08x\n" + "0x94: PM wakeup frame 1 0x%08x 0x%08x\n" + "0x9C: PM wakeup frame 2 0x%08x 0x%08x\n" + "0xA4: PM wakeup frame 3 0x%08x 0x%08x\n" + "0xAC: PM wakeup frame 4 0x%08x 0x%08x\n" + "0xB4: PM wakeup frame 5 0x%08x 0x%08x\n" + "0xBC: PM wakeup frame 6 0x%08x 0x%08x\n" + "0xC4: PM wakeup frame 7 0x%08x 0x%08x\n", + data[0x8C >> 2], + data[0x90 >> 2], + data[0x94 >> 2], + data[0x98 >> 2], + data[0x9C >> 2], + data[0xA0 >> 2], + data[0xA4 >> 2], + data[0xA8 >> 2], + data[0xAC >> 2], + data[0xB0 >> 2], + data[0xB4 >> 2], + data[0xB8 >> 2], + data[0xBC >> 2], + data[0xC0 >> 2], + data[0xC4 >> 2], + data[0xC8 >> 2]); + fprintf(stdout, + "0xCC: PM LSB CRC for wakeup frame 0 0x%02x\n" + "0xCD: PM LSB CRC for wakeup frame 1 0x%02x\n" + "0xCE: PM LSB CRC for wakeup frame 2 0x%02x\n" + "0xCF: PM LSB CRC for wakeup frame 3 0x%02x\n" + "0xD0: PM LSB CRC for wakeup frame 4 0x%02x\n" + "0xD1: PM LSB CRC for wakeup frame 5 0x%02x\n" + "0xD2: PM LSB CRC for wakeup frame 6 0x%02x\n" + "0xD3: PM LSB CRC for wakeup frame 7 0x%02x\n", + data8[0xCC], + data8[0xCD], + data8[0xCE], + data8[0xCF], + data8[0xD0], + data8[0xD1], + data8[0xD2], + data8[0xD3]); + } + if (board_type >= RTL8139B) { + if (board_type != RTL8100 && board_type != RTL8100B_8139D && + board_type != RTL8101) + fprintf(stdout, + "0xD4: Flash memory read/write 0x%08x\n", + data[0xD4 >> 2]); + if (board_type != RTL8130) + fprintf(stdout, + "0xD8: Config 5 0x%02x\n", + data8[0xD8]); + } + } + + if (board_type == RTL8139Cp || + board_type == RTL8169 || + board_type == RTL8169s || + board_type == RTL8110) { + v = data[0xE0 >> 2] & 0xffff; + fprintf(stdout, + "0xE0: C+ Command 0x%04x\n", + v); + if (v & (1 << 9)) + fprintf(stdout, " Big-endian mode\n"); + if (v & (1 << 8)) + fprintf(stdout, " Home LAN enable\n"); + if (v & (1 << 6)) + fprintf(stdout, " VLAN de-tagging\n"); + if (v & (1 << 5)) + fprintf(stdout, " RX checksumming\n"); + if (v & (1 << 4)) + fprintf(stdout, " PCI 64-bit DAC\n"); + if (v & (1 << 3)) + fprintf(stdout, " PCI Multiple RW\n"); + + v = data[0xe0 >> 2] >> 16; + fprintf(stdout, + "0xE2: Interrupt Mitigation 0x%04x\n" + " TxTimer: %u\n" + " TxPackets: %u\n" + " RxTimer: %u\n" + " RxPackets: %u\n", + v, + v >> 12, + (v >> 8) & 0xf, + (v >> 4) & 0xf, + v & 0xf); + + fprintf(stdout, + "0xE4: Rx Ring Addr 0x%08x 0x%08x\n", + data[0xE4 >> 2], + data[0xE8 >> 2]); + + fprintf(stdout, + "0xEC: Early Tx threshold 0x%02x\n", + data8[0xEC]); + + if (board_type == RTL8139Cp) { + fprintf(stdout, + "0xFC: External MII register 0x%08x\n", + data[0xFC >> 2]); + } + } + + return 0; +} diff --git a/tg3.c b/tg3.c new file mode 100644 index 0000000..97613e9 --- /dev/null +++ b/tg3.c @@ -0,0 +1,23 @@ +#include +#include "ethtool-util.h" + +#define TG3_MAGIC 0x669955aa + +int +tg3_dump_eeprom(struct ethtool_drvinfo *info, struct ethtool_eeprom *ee) +{ + int i; + + if (ee->magic != TG3_MAGIC) { + fprintf(stderr, "Magic number 0x%08x does not match 0x%08x\n", + ee->magic, TG3_MAGIC); + return -1; + } + + fprintf(stdout, "Address \tData\n"); + fprintf(stdout, "----------\t----\n"); + for (i = 0; i < ee->len; i++) + fprintf(stdout, "0x%08x\t0x%02x\n", i + ee->offset, ee->data[i]); + + return 0; +} -- cgit v1.2.1