Author: sam
Date: Mon Jun  1 18:27:16 2009
New Revision: 193242
URL: http://svn.freebsd.org/changeset/base/193242

Log:
  tools for mwl driver

Added:
  head/tools/tools/mwl/
  head/tools/tools/mwl/Makefile   (contents, props changed)
  head/tools/tools/mwl/mwldebug/
  head/tools/tools/mwl/mwldebug/Makefile   (contents, props changed)
  head/tools/tools/mwl/mwldebug/mwldebug.c   (contents, props changed)
  head/tools/tools/mwl/mwlstats/
  head/tools/tools/mwl/mwlstats/Makefile   (contents, props changed)
  head/tools/tools/mwl/mwlstats/main.c   (contents, props changed)
  head/tools/tools/mwl/mwlstats/mwlstats.c   (contents, props changed)
  head/tools/tools/mwl/mwlstats/mwlstats.h   (contents, props changed)
  head/tools/tools/mwl/mwlstats/statfoo.c   (contents, props changed)
  head/tools/tools/mwl/mwlstats/statfoo.h   (contents, props changed)
Modified:
  head/tools/tools/README

Modified: head/tools/tools/README
==============================================================================
--- head/tools/tools/README     Mon Jun  1 18:07:38 2009        (r193241)
+++ head/tools/tools/README     Mon Jun  1 18:27:16 2009        (r193242)
@@ -46,6 +46,7 @@ mctest                A multicast test program
 mfc            Merge a directory from HEAD to a branch where it does not
                already exist and other MFC related script(s).
 mid            Create a Message-ID database for mailing lists.
+mwl            Tools specific to the Marvell 88W8363 support
 ncpus          Count the number of processors
 npe            Tools specific to the Intel IXP4XXX NPE device
 nxge           A diagnostic tool for the nxge(4) driver

Added: head/tools/tools/mwl/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/Makefile       Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,5 @@
+#      $FreeBSD$
+
+SUBDIR=        mwlstats mwldebug
+
+.include <bsd.subdir.mk>

Added: head/tools/tools/mwl/mwldebug/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/mwldebug/Makefile      Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG=  mwldebug
+BINDIR=        /usr/local/bin
+NO_MAN=
+
+.include <bsd.prog.mk>

Added: head/tools/tools/mwl/mwldebug/mwldebug.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/mwldebug/mwldebug.c    Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * mwldebug [-i interface] flags
+ * (default interface is mwl0).
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <string.h>
+#include <err.h>
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+const char *progname;
+
+enum {
+       MWL_DEBUG_XMIT          = 0x00000001,   /* basic xmit operation */
+       MWL_DEBUG_XMIT_DESC     = 0x00000002,   /* xmit descriptors */
+       MWL_DEBUG_RECV          = 0x00000004,   /* basic recv operation */
+       MWL_DEBUG_RECV_DESC     = 0x00000008,   /* recv descriptors */
+       MWL_DEBUG_RESET         = 0x00000010,   /* reset processing */
+       MWL_DEBUG_BEACON        = 0x00000020,   /* beacon handling */
+       MWL_DEBUG_INTR          = 0x00000040,   /* ISR */
+       MWL_DEBUG_TX_PROC       = 0x00000080,   /* tx ISR proc */
+       MWL_DEBUG_RX_PROC       = 0x00000100,   /* rx ISR proc */
+       MWL_DEBUG_KEYCACHE      = 0x00000200,   /* key cache management */
+       MWL_DEBUG_STATE         = 0x00000400,   /* 802.11 state transitions */
+       MWL_DEBUG_NODE          = 0x00000800,   /* node management */
+       MWL_DEBUG_RECV_ALL      = 0x00001000,   /* trace all frames (beacons) */
+       MWL_DEBUG_TSO           = 0x00002000,   /* TSO processing */
+       MWL_DEBUG_AMPDU         = 0x00004000,   /* BA stream handling */
+       MWL_DEBUG_ANY           = 0xffffffff
+};
+
+static struct {
+       const char      *name;
+       u_int           bit;
+} flags[] = {
+       { "xmit",       MWL_DEBUG_XMIT },
+       { "xmit_desc",  MWL_DEBUG_XMIT_DESC },
+       { "recv",       MWL_DEBUG_RECV },
+       { "recv_desc",  MWL_DEBUG_RECV_DESC },
+       { "reset",      MWL_DEBUG_RESET },
+       { "beacon",     MWL_DEBUG_BEACON },
+       { "intr",       MWL_DEBUG_INTR },
+       { "xmit_proc",  MWL_DEBUG_TX_PROC },
+       { "recv_proc",  MWL_DEBUG_RX_PROC },
+       { "keycache",   MWL_DEBUG_KEYCACHE },
+       { "state",      MWL_DEBUG_STATE },
+       { "node",       MWL_DEBUG_NODE },
+       { "recv_all",   MWL_DEBUG_RECV_ALL },
+       { "tso",        MWL_DEBUG_TSO },
+       { "ampdu",      MWL_DEBUG_AMPDU },
+       /* XXX these are a hack; there should be a separate sysctl knob */
+       { "hal",        0x02000000 },           /* cmd-completion processing */
+       { "hal2",       0x01000000 },           /* cmd submission processing */
+       { "halhang",    0x04000000 },           /* disable fw hang stuff */
+};
+
+static u_int
+getflag(const char *name, int len)
+{
+       int i;
+
+       for (i = 0; i < N(flags); i++)
+               if (strncasecmp(flags[i].name, name, len) == 0)
+                       return flags[i].bit;
+       return 0;
+}
+
+#if 0
+static const char *
+getflagname(u_int flag)
+{
+       int i;
+
+       for (i = 0; i < N(flags); i++)
+               if (flags[i].bit == flag)
+                       return flags[i].name;
+       return "???";
+}
+#endif
+
+static void
+usage(void)
+{
+       int i;
+
+       fprintf(stderr, "usage: %s [-i device] [flags]\n", progname);
+       fprintf(stderr, "where flags are:\n");
+       for (i = 0; i < N(flags); i++)
+               printf("%s\n", flags[i].name);
+       exit(-1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       const char *ifname = "mwl0";
+       const char *cp, *tp;
+       const char *sep;
+       int c, op, i;
+       u_int32_t debug, ndebug;
+       size_t debuglen;
+       char oid[256];
+
+       progname = argv[0];
+       if (argc > 1) {
+               if (strcmp(argv[1], "-i") == 0) {
+                       if (argc < 2)
+                               errx(1, "missing interface name for -i option");
+                       ifname = argv[2];
+                       if (strncmp(ifname, "mv", 2) != 0)
+                               errx(2, "huh, this is for mv devices?");
+                       argc -= 2, argv += 2;
+               } else if (strcmp(argv[1], "-?") == 0)
+                       usage();
+       }
+
+       snprintf(oid, sizeof(oid), "dev.mwl.%s.debug", ifname+3);
+       debuglen = sizeof(debug);
+       if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0)
+               err(1, "sysctl-get(%s)", oid);
+       ndebug = debug;
+       for (; argc > 1; argc--, argv++) {
+               cp = argv[1];
+               do {
+                       u_int bit;
+
+                       if (*cp == '-') {
+                               cp++;
+                               op = -1;
+                       } else if (*cp == '+') {
+                               cp++;
+                               op = 1;
+                       } else
+                               op = 0;
+                       for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';)
+                               tp++;
+                       bit = getflag(cp, tp-cp);
+                       if (op < 0)
+                               ndebug &= ~bit;
+                       else if (op > 0)
+                               ndebug |= bit;
+                       else {
+                               if (bit == 0) {
+                                       c = *cp;
+                                       if (isdigit(c))
+                                               bit = strtoul(cp, NULL, 0);
+                                       else
+                                               errx(1, "unknown flag %.*s",
+                                                       (int)(tp-cp), cp);
+                               }
+                               ndebug = bit;
+                       }
+               } while (*(cp = tp) != '\0');
+       }
+       if (debug != ndebug) {
+               printf("%s: 0x%x => ", oid, debug);
+               if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0)
+                       err(1, "sysctl-set(%s)", oid);
+               printf("0x%x", ndebug);
+               debug = ndebug;
+       } else
+               printf("%s: 0x%x", oid, debug);
+       sep = "<";
+       for (i = 0; i < N(flags); i++)
+               if (debug & flags[i].bit) {
+                       printf("%s%s", sep, flags[i].name);
+                       sep = ",";
+               }
+       printf("%s\n", *sep != '<' ? ">" : "");
+       return 0;
+}

Added: head/tools/tools/mwl/mwlstats/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/mwlstats/Makefile      Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+PROG=  mwlstats
+BINDIR=        /usr/local/bin
+NO_MAN=
+
+SRCS=  main.c statfoo.c mwlstats.c
+
+.include <bsd.prog.mk>
+
+CFLAGS+= -I.

Added: head/tools/tools/mwl/mwlstats/main.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/mwlstats/main.c        Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Simple Marvell-specific tool to inspect and monitor network traffic
+ * statistics.
+ *
+ *     mwlstats [-i interface] [-l] [-o fmtstring] [interval]
+ *
+ * (default interface is mv0).  If interval is specified a rolling output
+ * a la netstat -i is displayed every interval seconds.  The format of
+ * the rolling display can be controlled a la ps.  The -l option will
+ * print a list of all possible statistics for use with the -o option.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <err.h>
+
+#include "mwlstats.h"
+
+#define        S_DEFAULT \
+       
"input,output,txtry,txretry,txmretry,txdoneput,rxfcs,rxcrypt,rxicv,rssi,rate"
+
+static int signalled;
+
+static void
+catchalarm(int signo __unused)
+{
+       signalled = 1;
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct mwlstatfoo *wf;
+       int c;
+
+       wf = mwlstats_new("mwl0", S_DEFAULT);
+       while ((c = getopt(argc, argv, "i:lo:")) != -1) {
+               switch (c) {
+               case 'i':
+                       wf->setifname(wf, optarg);
+                       break;
+               case 'l':
+                       wf->print_fields(wf, stdout);
+                       return 0;
+               case 'o':
+                       wf->setfmt(wf, optarg);
+                       break;
+               default:
+                       errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] 
[interval]\n", argv[0]);
+                       /*NOTREACHED*/
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc > 0) {
+               u_long interval = strtoul(argv[0], NULL, 0);
+               int line, omask;
+
+               if (interval < 1)
+                       interval = 1;
+               signal(SIGALRM, catchalarm);
+               signalled = 0;
+               alarm(interval);
+       banner:
+               wf->print_header(wf, stdout);
+               line = 0;
+       loop:
+               if (line != 0) {
+                       wf->collect_cur(wf);
+                       wf->print_current(wf, stdout);
+                       wf->update_tot(wf);
+               } else {
+                       wf->collect_tot(wf);
+                       wf->print_total(wf, stdout);
+               }
+               fflush(stdout);
+               omask = sigblock(sigmask(SIGALRM));
+               if (!signalled)
+                       sigpause(0);
+               sigsetmask(omask);
+               signalled = 0;
+               alarm(interval);
+               line++;
+               if (line == 21)         /* XXX tty line count */
+                       goto banner;
+               else
+                       goto loop;
+               /*NOTREACHED*/
+       } else {
+               wf->collect_tot(wf);
+               wf->print_verbose(wf, stdout);
+       }
+       return 0;
+}

Added: head/tools/tools/mwl/mwlstats/mwlstats.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/mwlstats/mwlstats.c    Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,578 @@
+/*-
+ * Copyright (c) 2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * mwl statistics class.
+ */
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+#include "../../sys/net80211/ieee80211_ioctl.h"
+#include "../../sys/net80211/ieee80211_radiotap.h"
+
+/*
+ * Get Hardware Statistics.
+ */
+struct mwl_hal_hwstats {
+       uint32_t        TxRetrySuccesses;
+       uint32_t        TxMultipleRetrySuccesses;
+       uint32_t        TxFailures;
+       uint32_t        RTSSuccesses;
+       uint32_t        RTSFailures;
+       uint32_t        AckFailures;
+       uint32_t        RxDuplicateFrames;
+       uint32_t        FCSErrorCount;
+       uint32_t        TxWatchDogTimeouts;
+       uint32_t        RxOverflows;
+       uint32_t        RxFragErrors;
+       uint32_t        RxMemErrors;
+       uint32_t        PointerErrors;
+       uint32_t        TxUnderflows;
+       uint32_t        TxDone;
+       uint32_t        TxDoneBufTryPut;
+       uint32_t        TxDoneBufPut;
+       uint32_t        Wait4TxBuf;
+       uint32_t        TxAttempts;
+       uint32_t        TxSuccesses;
+       uint32_t        TxFragments;
+       uint32_t        TxMulticasts;
+       uint32_t        RxNonCtlPkts;
+       uint32_t        RxMulticasts;
+       uint32_t        RxUndecryptableFrames;
+       uint32_t        RxICVErrors;
+       uint32_t        RxExcludedFrames;
+};
+#include "../../../../sys/dev/mwl/if_mwlioctl.h"
+
+#include "mwlstats.h"
+
+#define        AFTER(prev)     ((prev)+1)
+
+static const struct fmt mwlstats[] = {
+#define        S_INPUT         0
+       { 8,    "input",        "input",        "total frames received" },
+#define        S_RX_MCAST      AFTER(S_INPUT)
+       { 7,    "rxmcast",      "rxmcast",      "rx multicast frames" },
+#define        S_RX_NONCTL     AFTER(S_RX_MCAST)
+       { 8,    "rxnonctl",     "rxnonctl"      "rx non control frames" },
+#define        S_RX_MGT        AFTER(S_RX_NONCTL)
+       { 5,    "rxmgt",        "rxmgt",        "rx management frames" },
+#define        S_RX_CTL        AFTER(S_RX_MGT)
+       { 5,    "rxctl",        "rxctl",        "rx control frames" },
+#define        S_OUTPUT        AFTER(S_RX_CTL)
+       { 8,    "output",       "output",       "total frames transmit" },
+#define        S_TX_MCAST      AFTER(S_OUTPUT)
+       { 7,    "txmcast",      "txmcast",      "tx multicast frames" },
+#define        S_TX_MGMT       AFTER(S_TX_MCAST)
+       { 5,    "txmgt",        "txmgt",        "tx management frames" },
+#define        S_TX_RETRY      AFTER(S_TX_MGMT)
+       { 7,    "txretry",      "txretry",      "tx success with 1 retry" },
+#define        S_TX_MRETRY     AFTER(S_TX_RETRY)
+       { 8,    "txmretry",     "txmretry",     "tx success with >1 retry" },
+#define        S_TX_RTSGOOD    AFTER(S_TX_MRETRY)
+       { 7,    "rtsgood",      "rtsgood",      "RTS tx success" },
+#define        S_TX_RTSBAD     AFTER(S_TX_RTSGOOD)
+       { 6,    "rtsbad",       "rtsbad",       "RTS tx failed" },
+#define        S_TX_NOACK      AFTER(S_TX_RTSBAD)
+       { 5,    "noack",        "noack",        "tx failed because no ACK was 
received" },
+#define        S_RX_DUPLICATE  AFTER(S_TX_NOACK)
+       { 5,    "rxdup",        "rxdup",        "rx discarded by f/w as dup" },
+#define        S_RX_FCS        AFTER(S_RX_DUPLICATE)
+       { 5,    "rxfcs",        "rxfcs",        "rx discarded by f/w for bad 
FCS" },
+#define        S_TX_WATCHDOG   AFTER(S_RX_FCS)
+       { 7,    "txwatch",      "txwatch",      "MAC tx hang (f/w recovery)" },
+#define        S_RX_OVERFLOW   AFTER(S_TX_WATCHDOG)
+       { 6,    "rxover",       "rxover",       "no f/w buffer for rx" },
+#define        S_RX_FRAGERROR  AFTER(S_RX_OVERFLOW)
+       { 6,    "rxfrag",       "rxfrag",       "rx failed in f/w due to 
defrag" },
+#define        S_RX_MEMERROR   AFTER(S_RX_FRAGERROR)
+       { 5,    "rxmem",        "rxmem",        "rx failed in f/w 'cuz out of 
of memory" },
+#define        S_PTRERROR      AFTER(S_RX_MEMERROR)
+       { 6,    "badptr",       "badptr",       "MAC internal pointer problem" 
},
+#define        S_TX_UNDERFLOW  AFTER(S_PTRERROR)
+       { 7,    "txunder",      "txunder",      "tx failed in f/w 'cuz of 
underflow" },
+#define        S_TX_DONE       AFTER(S_TX_UNDERFLOW)
+       { 6,    "txdone",       "txdone",       "MAC tx ops completed" },
+#define        S_TX_DONEBUFPUT AFTER(S_TX_DONE)
+       { 9,    "txdoneput",    "txdoneput",    "tx buffers returned by f/w to 
host" },
+#define        S_TX_WAIT4BUF   AFTER(S_TX_DONEBUFPUT)
+       { 6,    "txwait",       "txwait",       "no f/w buffers available when 
supplied a tx descriptor" },
+#define        S_TX_ATTEMPTS   AFTER(S_TX_WAIT4BUF)
+       { 5,    "txtry",        "txtry",        "tx descriptors processed by 
f/w" },
+#define        S_TX_SUCCESS    AFTER(S_TX_ATTEMPTS)
+       { 4,    "txok",         "txok",         "tx attempts successful" },
+#define        S_TX_FRAGS      AFTER(S_TX_SUCCESS)
+       { 6,    "txfrag",       "txfrag",       "tx attempts with 
fragmentation" },
+#define        S_RX_UNDECRYPT  AFTER(S_TX_FRAGS)
+       { 7,    "rxcrypt",      "rxcrypt",      "rx failed in f/w 'cuz decrypt 
failed" },
+#define        S_RX_ICVERROR   AFTER(S_RX_UNDECRYPT)
+       { 5,    "rxicv",        "rxicv",        "rx failed in f/w 'cuz ICV 
check" },
+#define        S_RX_EXCLUDE    AFTER(S_RX_ICVERROR)
+       { 8,    "rxfilter",     "rxfilter",     "rx frames filtered in f/w" },
+#define        S_TX_LINEAR     AFTER(S_RX_EXCLUDE)
+       { 5,    "txlinear",     "txlinear",     "tx linearized to cluster" },
+#define        S_TX_DISCARD    AFTER(S_TX_LINEAR)
+       { 5,    "txdisc",       "txdisc",       "tx frames discarded prior to 
association" },
+#define        S_TX_QSTOP      AFTER(S_TX_DISCARD)
+       { 5,    "qstop",        "qstop",        "tx stopped 'cuz no xmit 
buffer" },
+#define        S_TX_ENCAP      AFTER(S_TX_QSTOP)
+       { 5,    "txencode",     "txencode",     "tx encapsulation failed" },
+#define        S_TX_NOMBUF     AFTER(S_TX_ENCAP)
+       { 5,    "txnombuf",     "txnombuf",     "tx failed 'cuz mbuf allocation 
failed" },
+#define        S_TX_SHORTPRE   AFTER(S_TX_NOMBUF)
+       { 5,    "shpre",        "shpre",        "tx frames with short preamble" 
},
+#define        S_TX_NOHEADROOM AFTER(S_TX_SHORTPRE)
+       { 5,    "nohead",       "nohead",       "tx frames discarded for lack 
of headroom" },
+#define        S_TX_BADFRAMETYPE       AFTER(S_TX_NOHEADROOM)
+       { 5,    "badtxtype",    "badtxtype",    "tx frames discarded for 
invalid/unknown 802.11 frame type" },
+#define        S_RX_CRYPTO_ERR AFTER(S_TX_BADFRAMETYPE)
+       { 5,    "crypt",        "crypt",        "rx failed 'cuz decryption" },
+#define        S_RX_NOMBUF     AFTER(S_RX_CRYPTO_ERR)
+       { 5,    "rxnombuf",     "rxnombuf",     "rx setup failed 'cuz no mbuf" 
},
+#define        S_RX_TKIPMIC    AFTER(S_RX_NOMBUF)
+       { 5,    "rxtkipmic",    "rxtkipmic",    "rx failed 'cuz TKIP MIC error" 
},
+#define        S_RX_NODMABUF   AFTER(S_RX_TKIPMIC)
+       { 5,    "rxnodmabuf",   "rxnodmabuf",   "rx failed 'cuz no DMA buffer 
available" },
+#define        S_RX_DMABUFMISSING      AFTER(S_RX_NODMABUF)
+       { 5,    "rxdmabufmissing",      "rxdmabufmissing",      "rx descriptor 
with no DMA buffer attached" },
+#define        S_TX_NODATA     AFTER(S_RX_DMABUFMISSING)
+       { 5,    "txnodata",     "txnodata",     "tx discarded empty frame" },
+#define        S_TX_BUSDMA     AFTER(S_TX_NODATA)
+       { 5,    "txbusdma",     "txbusdma",     "tx failed for dma resources" },
+#define        S_RX_BUSDMA     AFTER(S_TX_BUSDMA)
+       { 5,    "rxbusdma",     "rxbusdma",     "rx setup failed for dma 
resources" },
+#define        S_AMPDU_NOSTREAM        AFTER(S_RX_BUSDMA)
+       { 5,    "ampdu_nostream","ampdu_nostream","ADDBA request failed 'cuz 
all BA streams in use" },
+#define        S_AMPDU_REJECT  AFTER(S_AMPDU_NOSTREAM)
+       { 5,    "ampdu_reject","ampdu_reject","ADDBA request failed 'cuz 
station already has one BA stream" },
+#define        S_ADDBA_NOSTREAM        AFTER(S_AMPDU_REJECT)
+       { 5,    "addba_nostream","addba_nostream","ADDBA response processed but 
no BA stream present" },
+#define        S_TX_TSO        AFTER(S_ADDBA_NOSTREAM)
+       { 8,    "txtso",        "tso",          "tx frames using TSO" },
+#define        S_TSO_BADETH    AFTER(S_TX_TSO)
+       { 5,    "tsoeth",       "tsoeth",       "TSO failed 'cuz ether header 
type not IPv4" },
+#define        S_TSO_NOHDR     AFTER(S_TSO_BADETH)
+       { 5,    "tsonohdr",     "tsonohdr",     "TSO failed 'cuz header not in 
first mbuf" },
+#define        S_TSO_BADSPLIT  AFTER(S_TSO_NOHDR)
+       { 5,    "tsobadsplit",  "tsobadsplit",  "TSO failed 'cuz payload split 
failed" },
+#define        S_BAWATCHDOG    AFTER(S_TSO_BADSPLIT)
+       { 5,    "bawatchdog",   "bawatchdog",   "BA watchdog interrupts" },
+#define        S_BAWATCHDOG_NOTFOUND   AFTER(S_BAWATCHDOG)
+       { 5,    "bawatchdog_notfound",  "bawatchdog_notfound",
+         "BA watchdog for unknown stream" },
+#define        S_BAWATCHDOG_EMPTY      AFTER(S_BAWATCHDOG_NOTFOUND)
+       { 5,    "bawatchdog_empty",     "bawatchdog_empty",
+         "BA watchdog on all streams but none found" },
+#define        S_BAWATCHDOG_FAILED     AFTER(S_BAWATCHDOG_EMPTY)
+       { 5,    "bawatchdog_failed",    "bawatchdog_failed",
+         "BA watchdog processing failed to get bitmap from f/w" },
+#define        S_RADARDETECT   AFTER(S_BAWATCHDOG_FAILED)
+       { 5,    "radardetect",  "radardetect",  "radar detect interrupts" },
+#define        S_RATE          AFTER(S_RADARDETECT)
+       { 4,    "rate",         "rate",         "rate of last transmit" },
+#define        S_TX_RSSI       AFTER(S_RATE)
+       { 4,    "arssi",        "arssi",        "rssi of last ack" },
+#define        S_RX_RSSI       AFTER(S_TX_RSSI)
+       { 4,    "rssi",         "rssi",         "avg recv rssi" },
+#define        S_RX_NOISE      AFTER(S_RX_RSSI)
+       { 5,    "noise",        "noise",        "rx noise floor" },
+#define        S_TX_SIGNAL     AFTER(S_RX_NOISE)
+       { 4,    "asignal",      "asig",         "signal of last ack (dBm)" },
+#define        S_RX_SIGNAL     AFTER(S_TX_SIGNAL)
+       { 4,    "signal",       "sig",          "avg recv signal (dBm)" },
+#define        S_ANT_TX0       AFTER(S_RX_SIGNAL)
+       { 8,    "tx0",          "ant0(tx)",     "frames tx on antenna 0" },
+#define        S_ANT_TX1       (S_RX_SIGNAL+2)
+       { 8,    "tx1",          "ant1(tx)",     "frames tx on antenna 1"  },
+#define        S_ANT_TX2       (S_RX_SIGNAL+3)
+       { 8,    "tx2",          "ant2(tx)",     "frames tx on antenna 2"  },
+#define        S_ANT_TX3       (S_RX_SIGNAL+4)
+       { 8,    "tx3",          "ant3(tx)",     "frames tx on antenna 3"  },
+#define        S_ANT_RX0       AFTER(S_ANT_TX3)
+       { 8,    "rx0",          "ant0(rx)",     "frames rx on antenna 0"  },
+#define        S_ANT_RX1       (S_ANT_TX3+2)
+       { 8,    "rx1",          "ant1(rx)",     "frames rx on antenna 1"   },
+#define        S_ANT_RX2       (S_ANT_TX3+3)
+       { 8,    "rx2",          "ant2(rx)",     "frames rx on antenna 2"   },
+#define        S_ANT_RX3       (S_ANT_TX3+4)
+       { 8,    "rx3",          "ant3(rx)",     "frames rx on antenna 3"   },
+};
+/* NB: this intentionally avoids per-antenna stats */
+#define        S_LAST  (S_RX_SIGNAL+1)
+
+struct mwlstatfoo_p {
+       struct mwlstatfoo base;
+       int s;
+       struct ifreq ifr;
+       struct mwl_stats cur;
+       struct mwl_stats total;
+};
+
+static void
+mwl_setifname(struct mwlstatfoo *wf0, const char *ifname)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) wf0;
+
+       strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
+}
+
+static void
+mwl_collect(struct mwlstatfoo_p *wf, struct mwl_stats *stats)
+{
+       wf->ifr.ifr_data = (caddr_t) stats;
+       if (ioctl(wf->s, SIOCGMVSTATS, &wf->ifr) < 0)
+               err(1, wf->ifr.ifr_name);
+}
+
+static void
+mwl_collect_cur(struct statfoo *sf)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf;
+
+       mwl_collect(wf, &wf->cur);
+}
+
+static void
+mwl_collect_tot(struct statfoo *sf)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf;
+
+       mwl_collect(wf, &wf->total);
+}
+
+static void
+mwl_update_tot(struct statfoo *sf)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf;
+
+       wf->total = wf->cur;
+}
+
+static void
+setrate(char b[], size_t bs, uint8_t rate)
+{
+       if (rate & IEEE80211_RATE_MCS)
+               snprintf(b, bs, "MCS%u", rate & IEEE80211_RATE_VAL);
+       else if (rate & 1)
+               snprintf(b, bs, "%u.5M", rate / 2);
+       else
+               snprintf(b, bs, "%uM", rate / 2);
+}
+
+static int
+mwl_get_curstat(struct statfoo *sf, int s, char b[], size_t bs)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf;
+#define        STAT(x) \
+       snprintf(b, bs, "%u", wf->cur.mst_##x - wf->total.mst_##x); return 1
+#define        HWSTAT(x) \
+       snprintf(b, bs, "%u", wf->cur.hw_stats.x - wf->total.hw_stats.x); 
return 1
+#define        RXANT(x) \
+       snprintf(b, bs, "%u", wf->cur.mst_ant_rx[x] - wf->total.mst_ant_rx[x]); 
return 1
+#define        TXANT(x) \
+       snprintf(b, bs, "%u", wf->cur.mst_ant_tx[x] - wf->total.mst_ant_tx[x]); 
return 1
+
+       switch (s) {
+       case S_INPUT:
+               snprintf(b, bs, "%lu", (u_long)(
+                   (wf->cur.mst_rx_packets - wf->total.mst_rx_packets)));
+               return 1;
+       case S_OUTPUT:
+               snprintf(b, bs, "%lu", (u_long)(
+                   wf->cur.mst_tx_packets - wf->total.mst_tx_packets));
+               return 1;
+       case S_RATE:
+               setrate(b, bs, wf->cur.mst_tx_rate);
+               return 1;
+       case S_TX_RETRY:        HWSTAT(TxRetrySuccesses);
+       case S_TX_MRETRY:       HWSTAT(TxMultipleRetrySuccesses);
+       case S_TX_RTSGOOD:      HWSTAT(RTSSuccesses);
+       case S_TX_RTSBAD:       HWSTAT(RTSFailures);
+       case S_TX_NOACK:        HWSTAT(AckFailures);
+       case S_RX_DUPLICATE:    HWSTAT(RxDuplicateFrames);
+       case S_RX_FCS:          HWSTAT(FCSErrorCount);
+       case S_TX_WATCHDOG:     HWSTAT(TxWatchDogTimeouts);
+       case S_RX_OVERFLOW:     HWSTAT(RxOverflows);
+       case S_RX_FRAGERROR:    HWSTAT(RxFragErrors);
+       case S_RX_MEMERROR:     HWSTAT(RxMemErrors);
+       case S_PTRERROR:        HWSTAT(PointerErrors);
+       case S_TX_UNDERFLOW:    HWSTAT(TxUnderflows);
+       case S_TX_DONE:         HWSTAT(TxDone);
+       case S_TX_DONEBUFPUT:   HWSTAT(TxDoneBufPut);
+       case S_TX_WAIT4BUF:     HWSTAT(Wait4TxBuf);
+       case S_TX_ATTEMPTS:     HWSTAT(TxAttempts);
+       case S_TX_SUCCESS:      HWSTAT(TxSuccesses);
+       case S_TX_FRAGS:        HWSTAT(TxFragments);
+       case S_TX_MCAST:        HWSTAT(TxMulticasts);
+       case S_RX_NONCTL:       HWSTAT(RxNonCtlPkts);
+       case S_RX_MCAST:        HWSTAT(RxMulticasts);
+       case S_RX_UNDECRYPT:    HWSTAT(RxUndecryptableFrames);
+       case S_RX_ICVERROR:     HWSTAT(RxICVErrors);
+       case S_RX_EXCLUDE:      HWSTAT(RxExcludedFrames);
+       case S_TX_MGMT:         STAT(tx_mgmt);
+       case S_TX_DISCARD:      STAT(tx_discard);
+       case S_TX_QSTOP:        STAT(tx_qstop);
+       case S_TX_ENCAP:        STAT(tx_encap);
+       case S_TX_NOMBUF:       STAT(tx_nombuf);
+       case S_TX_LINEAR:       STAT(tx_linear);
+       case S_TX_NODATA:       STAT(tx_nodata);
+       case S_TX_BUSDMA:       STAT(tx_busdma);
+       case S_TX_SHORTPRE:     STAT(tx_shortpre);
+       case S_TX_NOHEADROOM:   STAT(tx_noheadroom);
+       case S_TX_BADFRAMETYPE: STAT(tx_badframetype);
+       case S_RX_CRYPTO_ERR:   STAT(rx_crypto);
+       case S_RX_TKIPMIC:      STAT(rx_tkipmic);
+       case S_RX_NODMABUF:     STAT(rx_nodmabuf);
+       case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing);
+       case S_RX_NOMBUF:       STAT(rx_nombuf);
+       case S_RX_BUSDMA:       STAT(rx_busdma);
+       case S_AMPDU_NOSTREAM:  STAT(ampdu_nostream);
+       case S_AMPDU_REJECT:    STAT(ampdu_reject);
+       case S_ADDBA_NOSTREAM:  STAT(addba_nostream);
+       case S_TX_TSO:          STAT(tx_tso);
+       case S_TSO_BADETH:      STAT(tso_badeth);
+       case S_TSO_NOHDR:       STAT(tso_nohdr);
+       case S_TSO_BADSPLIT:    STAT(tso_badsplit);
+       case S_BAWATCHDOG:      STAT(bawatchdog);
+       case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound);
+       case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty);
+       case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed);
+       case S_RADARDETECT:     STAT(radardetect);
+       case S_RX_RSSI:
+               snprintf(b, bs, "%d", wf->cur.mst_rx_rssi);
+               return 1;
+       case S_ANT_TX0:         TXANT(0);
+       case S_ANT_TX1:         TXANT(1);
+       case S_ANT_TX2:         TXANT(2);
+       case S_ANT_TX3:         TXANT(3);
+       case S_ANT_RX0:         RXANT(0);
+       case S_ANT_RX1:         RXANT(1);
+       case S_ANT_RX2:         RXANT(2);
+       case S_ANT_RX3:         RXANT(3);
+       case S_RX_NOISE:
+               snprintf(b, bs, "%d", wf->cur.mst_rx_noise);
+               return 1;
+       case S_RX_SIGNAL:
+               snprintf(b, bs, "%d",
+                       wf->cur.mst_rx_rssi + wf->cur.mst_rx_noise);
+               return 1;
+       }
+       b[0] = '\0';
+       return 0;
+#undef RXANT
+#undef TXANT
+#undef HWSTAT
+#undef STAT
+}
+
+static int
+mwl_get_totstat(struct statfoo *sf, int s, char b[], size_t bs)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf;
+#define        STAT(x) \
+       snprintf(b, bs, "%u", wf->total.mst_##x); return 1
+#define        HWSTAT(x) \
+       snprintf(b, bs, "%u", wf->total.hw_stats.x); return 1
+#define        TXANT(x) \
+       snprintf(b, bs, "%u", wf->total.mst_ant_tx[x]); return 1
+#define        RXANT(x) \
+       snprintf(b, bs, "%u", wf->total.mst_ant_rx[x]); return 1
+
+       switch (s) {
+       case S_INPUT:
+               snprintf(b, bs, "%lu", (u_long)wf->total.mst_rx_packets);
+               return 1;
+       case S_OUTPUT:
+               snprintf(b, bs, "%lu", (u_long) wf->total.mst_tx_packets);
+               return 1;
+       case S_RATE:
+               setrate(b, bs, wf->total.mst_tx_rate);
+               return 1;
+       case S_TX_RETRY:        HWSTAT(TxRetrySuccesses);
+       case S_TX_MRETRY:       HWSTAT(TxMultipleRetrySuccesses);
+       case S_TX_RTSGOOD:      HWSTAT(RTSSuccesses);
+       case S_TX_RTSBAD:       HWSTAT(RTSFailures);
+       case S_TX_NOACK:        HWSTAT(AckFailures);
+       case S_RX_DUPLICATE:    HWSTAT(RxDuplicateFrames);
+       case S_RX_FCS:          HWSTAT(FCSErrorCount);
+       case S_TX_WATCHDOG:     HWSTAT(TxWatchDogTimeouts);
+       case S_RX_OVERFLOW:     HWSTAT(RxOverflows);
+       case S_RX_FRAGERROR:    HWSTAT(RxFragErrors);
+       case S_RX_MEMERROR:     HWSTAT(RxMemErrors);
+       case S_PTRERROR:        HWSTAT(PointerErrors);
+       case S_TX_UNDERFLOW:    HWSTAT(TxUnderflows);
+       case S_TX_DONE:         HWSTAT(TxDone);
+       case S_TX_DONEBUFPUT:   HWSTAT(TxDoneBufPut);
+       case S_TX_WAIT4BUF:     HWSTAT(Wait4TxBuf);
+       case S_TX_ATTEMPTS:     HWSTAT(TxAttempts);
+       case S_TX_SUCCESS:      HWSTAT(TxSuccesses);
+       case S_TX_FRAGS:        HWSTAT(TxFragments);
+       case S_TX_MCAST:        HWSTAT(TxMulticasts);
+       case S_RX_NONCTL:       HWSTAT(RxNonCtlPkts);
+       case S_RX_MCAST:        HWSTAT(RxMulticasts);
+       case S_RX_UNDECRYPT:    HWSTAT(RxUndecryptableFrames);
+       case S_RX_ICVERROR:     HWSTAT(RxICVErrors);
+       case S_RX_EXCLUDE:      HWSTAT(RxExcludedFrames);
+       case S_TX_MGMT:         STAT(tx_mgmt);
+       case S_TX_DISCARD:      STAT(tx_discard);
+       case S_TX_QSTOP:        STAT(tx_qstop);
+       case S_TX_ENCAP:        STAT(tx_encap);
+       case S_TX_NOMBUF:       STAT(tx_nombuf);
+       case S_TX_LINEAR:       STAT(tx_linear);
+       case S_TX_NODATA:       STAT(tx_nodata);
+       case S_TX_BUSDMA:       STAT(tx_busdma);
+       case S_TX_SHORTPRE:     STAT(tx_shortpre);
+       case S_TX_NOHEADROOM:   STAT(tx_noheadroom);
+       case S_TX_BADFRAMETYPE: STAT(tx_badframetype);
+       case S_RX_CRYPTO_ERR:   STAT(rx_crypto);
+       case S_RX_TKIPMIC:      STAT(rx_tkipmic);
+       case S_RX_NODMABUF:     STAT(rx_nodmabuf);
+       case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing);
+       case S_RX_NOMBUF:       STAT(rx_nombuf);
+       case S_RX_BUSDMA:       STAT(rx_busdma);
+       case S_AMPDU_NOSTREAM:  STAT(ampdu_nostream);
+       case S_AMPDU_REJECT:    STAT(ampdu_reject);
+       case S_ADDBA_NOSTREAM:  STAT(addba_nostream);
+       case S_TX_TSO:          STAT(tx_tso);
+       case S_TSO_BADETH:      STAT(tso_badeth);
+       case S_TSO_NOHDR:       STAT(tso_nohdr);
+       case S_TSO_BADSPLIT:    STAT(tso_badsplit);
+       case S_BAWATCHDOG:      STAT(bawatchdog);
+       case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound);
+       case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty);
+       case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed);
+       case S_RADARDETECT:     STAT(radardetect);
+       case S_RX_RSSI:
+               snprintf(b, bs, "%d", wf->total.mst_rx_rssi);
+               return 1;
+       case S_ANT_TX0:         TXANT(0);
+       case S_ANT_TX1:         TXANT(1);
+       case S_ANT_TX2:         TXANT(2);
+       case S_ANT_TX3:         TXANT(3);
+       case S_ANT_RX0:         RXANT(0);
+       case S_ANT_RX1:         RXANT(1);
+       case S_ANT_RX2:         RXANT(2);
+       case S_ANT_RX3:         RXANT(3);
+       case S_RX_NOISE:
+               snprintf(b, bs, "%d", wf->total.mst_rx_noise);
+               return 1;
+       case S_RX_SIGNAL:
+               snprintf(b, bs, "%d",
+                       wf->total.mst_rx_rssi + wf->total.mst_rx_noise);
+               return 1;
+       }
+       b[0] = '\0';
+       return 0;
+#undef RXANT
+#undef TXANT
+#undef HWSTAT
+#undef STAT
+}
+
+static void
+mwl_print_verbose(struct statfoo *sf, FILE *fd)
+{
+       struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf;
+       const struct fmt *f;
+       char s[32];
+       const char *indent;
+       int i, width;
+
+       width = 0;
+       for (i = 0; i < S_LAST; i++) {
+               f = &sf->stats[i];
+               if (f->width > width)
+                       width = f->width;
+       }
+       for (i = 0; i < S_LAST; i++) {
+               f = &sf->stats[i];
+               if (mwl_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) {
+                       indent = "";
+                       fprintf(fd, "%s%-*s %s\n", indent, width, s, f->desc);
+               }
+       }
+       fprintf(fd, "Antenna profile:\n");
+       for (i = 0; i < 4; i++)
+               if (wf->total.mst_ant_rx[i] || wf->total.mst_ant_tx[i])
+                       fprintf(fd, "[%u] tx %8u rx %8u\n", i,
+                               wf->total.mst_ant_tx[i],
+                               wf->total.mst_ant_rx[i]);
+}
+
+STATFOO_DEFINE_BOUNCE(mwlstatfoo)
+
+struct mwlstatfoo *
+mwlstats_new(const char *ifname, const char *fmtstring)
+{
+#define        N(a)    (sizeof(a) / sizeof(a[0]))
+       struct mwlstatfoo_p *wf;
+
+       wf = calloc(1, sizeof(struct mwlstatfoo_p));
+       if (wf != NULL) {
+               statfoo_init(&wf->base.base, "mwlstats", mwlstats, N(mwlstats));
+               /* override base methods */
+               wf->base.base.collect_cur = mwl_collect_cur;
+               wf->base.base.collect_tot = mwl_collect_tot;
+               wf->base.base.get_curstat = mwl_get_curstat;
+               wf->base.base.get_totstat = mwl_get_totstat;
+               wf->base.base.update_tot = mwl_update_tot;
+               wf->base.base.print_verbose = mwl_print_verbose;
+
+               /* setup bounce functions for public methods */
+               STATFOO_BOUNCE(wf, mwlstatfoo);
+
+               /* setup our public methods */
+               wf->base.setifname = mwl_setifname;
+#if 0
+               wf->base.setstamac = wlan_setstamac;
+#endif
+               wf->s = socket(AF_INET, SOCK_DGRAM, 0);
+               if (wf->s < 0)
+                       err(1, "socket");
+
+               mwl_setifname(&wf->base, ifname);
+               wf->base.setfmt(&wf->base, fmtstring);
+       }
+       return &wf->base;
+#undef N
+}

Added: head/tools/tools/mwl/mwlstats/mwlstats.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/tools/mwl/mwlstats/mwlstats.h    Mon Jun  1 18:27:16 2009        
(r193242)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to