diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-25 01:56:48 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-25 01:56:48 -0400 |
commit | 32c8037055f5fdaba9c9f401fd532c02571b66d7 (patch) | |
tree | 9bfb9a987fc4a1046530bcac0cb9245c1b3db3ba | |
download | ethtool-32c8037055f5fdaba9c9f401fd532c02571b66d7.tar.gz |
Initial import of ethtool version 3 + a few patches.
-rw-r--r-- | AUTHORS | 7 | ||||
-rw-r--r-- | ChangeLog | 351 | ||||
-rw-r--r-- | Makefile.am | 13 | ||||
-rw-r--r-- | NEWS | 78 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | amd8111e.c | 305 | ||||
-rwxr-xr-x | autogen.sh | 11 | ||||
-rw-r--r-- | configure.ac | 26 | ||||
-rw-r--r-- | de2104x.c | 783 | ||||
-rw-r--r-- | e100.c | 238 | ||||
-rw-r--r-- | e1000.c | 438 | ||||
-rw-r--r-- | ethtool-copy.h | 366 | ||||
-rw-r--r-- | ethtool-util.h | 42 | ||||
-rw-r--r-- | ethtool.8 | 384 | ||||
-rw-r--r-- | ethtool.c | 2003 | ||||
-rw-r--r-- | ethtool.spec.in | 42 | ||||
-rw-r--r-- | fec_8xx.c | 81 | ||||
-rw-r--r-- | natsemi.c | 985 | ||||
-rw-r--r-- | pcnet32.c | 222 | ||||
-rw-r--r-- | realtek.c | 517 | ||||
-rw-r--r-- | tg3.c | 23 |
21 files changed, 6917 insertions, 0 deletions
@@ -0,0 +1,7 @@ +David Miller <davem@redhat.com> +Jakub Jelinek <jj@ultra.linux.cz> +Jeff Garzik <jgarzik@mandrakesoft.com> +Tim Hockin <thockin@sun.com> +Eli Kupermann <eli.kupermann@intel.com> +Chris Leech <christopher.leech@intel.com> +Scott Feldman <scott.feldman@intel.com> 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 <jgarzik@pobox.com> + + * NEWS, configure.ac: Release version 2 + +Fri Jul 2 2004 Jeff Garzik <jgarzik@pobox.com> + + Merged + * fec_8xx.c, ethtool-util.h, Makefile.am: Add fec_8xx register dump. + Contributed by Pantelis Antoniou <panto@intracom.gr> + + * Update ethtool.c to iterate through a list of drivers + * Fixed fec_8xx.c warnings on 64-bit + +Fri Jul 2 2004 Jim Lewis <jim@jklewis.com> + + * pcnet32.c, ethtool-util.h, Makefile.am: Add pcnet32 register dump. + +Fri Apr 9 2004 Jason Lunz <lunz@reflexsecurity.com> + + * ethtool.c: Remove incorrect restriction on ethernet interface + names. + +Fri Apr 9 2004 OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> + + * ethtool.c: This fixes the bogus tail backslash that I did. + +Fri Apr 9 2004 Jim Lewis <jim@jklewis.com> + + * ethtool.c: Return results of self-test back to OS, + via exit(2). + +Fri Apr 9 2004 Jeb Cramer <cramerj@intel.com> + + * 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 <jgarzik@pobox.com> + + * configure.ac, Makefile.am, ethtool.c, etc.: + convert to more recent autoconf. + +Sat Aug 30 2003 OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> + + * ethtool.8, ethtool.c: ethtool register dump raw mode + +Sat Jul 19 2003 Scott Feldman <scott.feldman@intel.com> + + * 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 <ganesh.venkatesan@intel.com> + + * ethtool-copy.h: new definitions for 10GbE + +Thu May 28 2003 Scott Feldman <scott.feldman@intel.com> + + * 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 <reeja.john@amd.com> + + * amd8111e.c: new file, support for AMD-8111e NICs + * ethtool.c: properly set ecmd.advertising + +Sat Mar 29 2003 OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> + + * realtek.c: clean up chip enumeration, support additional chips + +Fri Mar 28 2003 Jeb Cramer <cramerj@intel.com> + + * 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 <jgarzik@pobox.com> + + * 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 <jeb.j.cramer@intel.com> + + * 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 <bcollins@debian.org> + + * 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 <thockin@sun.com> + + * ethtool.c: make calls to strtol() use base 0 + +Wed Sep 18 2002 Scott Feldman <scott.feldman@intel.com> + + * 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 <jgarzik@mandrakesoft.com> + + * ethtool.8: document new -S stats dump argument + * configure.in, NEWS: release version 1.6 + +Fri Jun 14 2002 Jeff Garzik <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * realtek.c (realtek_dump_regs): dump RTL8139C+ registers + +Fri Jun 14 2002 Jeff Garzik <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * 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 <christopher.leech@intel.com> + Scott Feldman <scott.feldman@intel.com> + + * 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 <eli.kupermann@intel.com> + + * 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 <jes@wildopensource.com> + + * 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 <eli.kupermann@intel.com> + + * ethtool.8: document new -t test option + +Wed May 1 2002 Christoph Hellwig <hch@lst.de> + + * Makefile.am (dist-hook): Use $(top-srcdir) for refering to sources. + +Mon Apr 29 2002 Christoph Hellwig <hch@lst.de> + + * 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 <jgarzik@mandrakesoft.com> + + * 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 <eli.kupermann@intel.com> + + * 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 <bhards@bigpond.net.au> + + * ethtool.c (parse_cmdline): Support "usb" + as well as "eth" network interfaces. USB networking + uses a different prefix. + +Fri Feb 8 2002 "Noam, Amir" <amir.noam@intel.com>, + "Kupermann, Eli" <eli.kupermann@intel.com> + + * ethtool.c (dump_advertised): new function. + (dump_ecmd): Call it. + Elsewhere: reformat code. + +Wed Nov 28 2001 Jeff Garzik <jgarzik@mandrakesoft.com> + + * configure.in, Makefile.am, redhat/Makefile.am: + make sure redhat spec is included in dist tarball. + +Tue Nov 27 2001 Tim Hockin <thockin@sun.com> + + * natsemi.c: strings changes + * ethtool.c: print messagelevel as hex (netif_msg_* shows better :) + +Sun Nov 18 2001 Jeff Garzik <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * Makefile.am, de2104x.c, ethtool-util.h, ethtool.c: + Support register dumps for de2104x driver. + +Tue Nov 13 2001 Tim Hockin <thockin@sun.com> + + * 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 <thockin@sun.com> + + * natsemi.c: check version, conditionally print RFCR-indexed data + +Wed Nov 07 2001 Tim Hockin <thockin@sun.com> + + * 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 <jgarzik@mandrakesoft.com> + + * ethtool.c, ethtool.8: support bnc port/media + +Tue Nov 06 2001 Tim Hockin <thockin@sun.com> + + * 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 <thockin@sun.com> + + * natsemi.c: first cut at 'pretty-printing' register dumps + +Fri Nov 02 2001 Tim Hockin <thockin@sun.com> + + * 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 <thockin@sun.com> + + * 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 <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * 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 <jgarzik@mandrakesoft.com> + + * ethtool.c, ethtool-copy.h: + Import copy of kernel 2.4.10-pre12's ethtool.h. + +Wed Sep 19 2001 Tim Hockin <thockin@sun.com> + + * Makefile.am, redhat/ethtool.spec.in: + Basic "make rpm" support. + +Wed Sep 19 2001 Tim Hockin <thockin@sun.com> + + * AUTHORS, NEWS, ethtool.8, ethtool.c: + Wake-on-LAN support. + +Thu May 17 2001 Jeff Garzik <jgarzik@mandrakesoft.com> + + * configure.in, NEWS, README: Version 1.2 release + + * ethtool.c: Support ETHTOOL_GDRVINFO. + * ethtool.8: Document it. + +Fri Mar 20 2001 Jeff Garzik <jgarzik@mandrakesoft.com> + + * 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) + @@ -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. + @@ -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 <stdio.h> +#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 <jgarzik@pobox.com>]) +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 <stdio.h> +#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; +} + @@ -0,0 +1,238 @@ +/* Copyright (c) 2002 Intel Corporation */ +#include <stdio.h> +#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; +} + @@ -0,0 +1,438 @@ +/* Copyright (c) 2002 Intel Corporation */ +#include <stdio.h> +#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 <jgarzik@mandrakesoft.com> + * 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 <sys/types.h> +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 <jgarzik@mandrakesoft.com> + * Wake-on-LAN,natsemi,misc support by Tim Hockin <thockin@sun.com> + * Portions Copyright 2002 Intel + * do_test support by Eli Kupermann <eli.kupermann@intel.com> + * ETHTOOL_PHYS_ID support by Chris Leech <christopher.leech@intel.com> + * e1000 support by Scott Feldman <scott.feldman@intel.com> + * e100 support by Wen Tao <wen-hwa.tao@intel.com> + * amd8111e support by Reeja John <reeja.john@amd.com> + * + * 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 <sys/types.h> +#include <string.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <net/if.h> + +#include <linux/sockios.h> +#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 <panto@intracom.gr> + */ + +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> + +#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 <stdio.h> +#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 <stdio.h> +#include <stdlib.h> +#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<len; i++) + { + if (((i-csr) & 7) == 0) printf("MII%02d: ", i-csr); + printf(" %04x ", data[i]); + if (((i-csr) & 7) == 7) printf("\n"); + } + if (((i-csr) & 7) != 7) printf("\n"); + printf("\n"); + + ptr=&data[8]; /* start of the CSRs */ + + printf("CSR0: Status and Control 0x%04x\n ",ptr[0]); + temp=ptr[0]; + + if(temp & BIT15) printf("ERR "); + if(temp & BIT14) printf("BABL "); + if(temp & BIT13) printf("CERR "); + if(temp & BIT12) printf("MISS "); + if(temp & BIT11) printf("MERR "); + if(temp & BIT10) printf("RINT "); + if(temp & BIT9) printf("TINT "); + if(temp & BIT8) printf("IDON "); + if(temp & BIT7) printf("INTR "); + if(temp & BIT6) printf("INT "); + if(temp & BIT5) printf("RXON "); + if(temp & BIT4) printf("TXON "); + if(temp & BIT3) printf("TDMD "); + if(temp & BIT2) printf("STOP "); + if(temp & BIT1) printf("STRT "); + if(temp & BIT0) printf("INIT "); + + printf("\n"); + + printf("CSR3: Interrupt Mask 0x%04x\n ",ptr[3]); + temp=ptr[3]; + + if(temp & BIT14) printf("BABLM "); + if(temp & BIT12) printf("MISSM "); + if(temp & BIT11) printf("MERRM "); + if(temp & BIT10) printf("RINTM "); + if(temp & BIT9) printf("TINTM "); + if(temp & BIT8) printf("IDONM "); + if(temp & BIT6) printf("DXSUFLO "); + if(temp & BIT5) printf("LAPPEN "); + if(temp & BIT4) printf("DXMT2PD "); + if(temp & BIT3) printf("EMBA "); + if(temp & BIT2) printf("BSWP "); + + printf("\n"); + + printf("CSR4: Test and Features 0x%04x\n ",ptr[4]); + temp=ptr[4]; + + if(temp & BIT15) printf("EN124 "); + if(temp & BIT14) printf("DMAPLUS "); + if(temp & BIT12) printf("TXDPOLL "); + if(temp & BIT11) printf("APAD_XMT "); + if(temp & BIT10) printf("ASTRP_RCV "); + if(temp & BIT9) printf("MFCO "); + if(temp & BIT8) printf("MFCON "); + if(temp & BIT7) printf("UINTCMD "); + if(temp & BIT6) printf("UINT "); + if(temp & BIT5) printf("RCVCCO "); + if(temp & BIT4) printf("RCVCCOM "); + if(temp & BIT3) printf("TXSTRT "); + if(temp & BIT2) printf("TXSTRTM "); + if(temp & BIT1) printf("JAB "); + if(temp & BIT0) printf("JABM "); + + printf("\n"); + + printf("CSR5: Ext Control and Int 1 0x%04x\n ",ptr[5]); + temp=ptr[5]; + + if(temp & BIT15) printf("TOKINTD "); + if(temp & BIT14) printf("LTINTEN "); + if(temp & BIT11) printf("SINT "); + if(temp & BIT10) printf("SINTE "); + if(temp & BIT9) printf("SLPINT "); + if(temp & BIT8) printf("SLPINTE "); + if(temp & BIT7) printf("EXDINT "); + if(temp & BIT6) printf("EXDINTE "); + if(temp & BIT5) printf("MPPLBA "); + if(temp & BIT4) printf("MPINT "); + if(temp & BIT3) printf("MPINTE "); + if(temp & BIT2) printf("MPEN "); + if(temp & BIT1) printf("MPMODE "); + if(temp & BIT0) printf("SPND "); + + printf("\n"); + + printf("CSR7: Ext Control and Int 2 0x%04x\n ",ptr[7]); + temp=ptr[7]; + + if(temp & BIT15) printf("FASTSPNDE "); + if(temp & BIT14) printf("RXFRTG "); + if(temp & BIT13) printf("RDMD "); + if(temp & BIT12) printf("RXDPOLL "); + if(temp & BIT11) printf("STINT "); + if(temp & BIT10) printf("STINTE "); + if(temp & BIT9) printf("MREINT "); + if(temp & BIT8) printf("MREINTE "); + if(temp & BIT7) printf("MAPINT "); + if(temp & BIT6) printf("MAPINTE "); + if(temp & BIT5) printf("MCCINT "); + if(temp & BIT4) printf("MCCINTE "); + if(temp & BIT3) printf("MCCIINT "); + if(temp & BIT2) printf("MCCIINTE "); + if(temp & BIT1) printf("MIIPDTINT "); + if(temp & BIT0) printf("MIIPDTINTE "); + + printf("\n"); + + printf("CSR15: Mode 0x%04x\n",ptr[15]); + printf("CSR40: Current RX Byte Count 0x%04x\n",ptr[40]); + printf("CSR41: Current RX Status 0x%04x\n",ptr[41]); + printf("CSR42: Current TX Byte Count 0x%04x\n",ptr[42]); + printf("CSR43: Current TX Status 0x%04x\n",ptr[43]); + printf("CSR88: Chip ID Lower 0x%04x\n",ptr[88]); + + printf("CSR89: Chip ID Upper 0x%04x\n ",ptr[89]); + temp=ptr[89]; + printf("VER: %04x PARTIDU: %04x\n",temp >> 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 <stdio.h> +#include <stdlib.h> +#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; +} @@ -0,0 +1,23 @@ +#include <stdio.h> +#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; +} |