svn commit: r185743 - in head/tools/tools/ath: . athdebug athkey
athpow athprom athregs athstats common
Sam Leffler
sam at FreeBSD.org
Sun Dec 7 11:17:35 PST 2008
Author: sam
Date: Sun Dec 7 19:17:33 2008
New Revision: 185743
URL: http://svn.freebsd.org/changeset/base/185743
Log:
bring in diagnostic tools that are useful now that we have hal source code
Added:
head/tools/tools/ath/Makefile.inc (contents, props changed)
head/tools/tools/ath/athkey/
head/tools/tools/ath/athkey/Makefile (contents, props changed)
head/tools/tools/ath/athkey/athkey.c (contents, props changed)
head/tools/tools/ath/athpow/
head/tools/tools/ath/athpow/Makefile (contents, props changed)
head/tools/tools/ath/athpow/athpow.c (contents, props changed)
head/tools/tools/ath/athprom/
head/tools/tools/ath/athprom/Makefile (contents, props changed)
head/tools/tools/ath/athprom/athprom.c (contents, props changed)
head/tools/tools/ath/athprom/eeprom-14 (contents, props changed)
head/tools/tools/ath/athprom/eeprom-3 (contents, props changed)
head/tools/tools/ath/athprom/eeprom-4 (contents, props changed)
head/tools/tools/ath/athprom/eeprom-5 (contents, props changed)
head/tools/tools/ath/athregs/
head/tools/tools/ath/athregs/Makefile (contents, props changed)
head/tools/tools/ath/athregs/dumpregs.c (contents, props changed)
head/tools/tools/ath/athregs/dumpregs.h (contents, props changed)
head/tools/tools/ath/athregs/dumpregs_5210.c (contents, props changed)
head/tools/tools/ath/athregs/dumpregs_5211.c (contents, props changed)
head/tools/tools/ath/athregs/dumpregs_5212.c (contents, props changed)
head/tools/tools/ath/athregs/dumpregs_5416.c (contents, props changed)
head/tools/tools/ath/common/
head/tools/tools/ath/common/ah_osdep.h (contents, props changed)
head/tools/tools/ath/common/diag.h (contents, props changed)
Modified:
head/tools/tools/ath/Makefile
head/tools/tools/ath/athdebug/Makefile
head/tools/tools/ath/athstats/Makefile
Modified: head/tools/tools/ath/Makefile
==============================================================================
--- head/tools/tools/ath/Makefile Sun Dec 7 18:45:30 2008 (r185742)
+++ head/tools/tools/ath/Makefile Sun Dec 7 19:17:33 2008 (r185743)
@@ -1,5 +1,5 @@
# $FreeBSD$
-SUBDIR= athstats athdebug
+SUBDIR= athdebug athkey athprom athregs athstats
.include <bsd.subdir.mk>
Added: head/tools/tools/ath/Makefile.inc
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/Makefile.inc Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+BINDIR= /usr/local/bin
+NO_MAN=
+
+ATH_DEFAULT= ath0
+
+CFLAGS+=-DATH_DEFAULT='"${ATH_DEFAULT}"'
+CFLAGS+=-I../common
+CFLAGS+=-I../../../../sys/dev/ath
+CFLAGS+=-I../../../../sys/dev/ath/ath_hal
Modified: head/tools/tools/ath/athdebug/Makefile
==============================================================================
--- head/tools/tools/ath/athdebug/Makefile Sun Dec 7 18:45:30 2008 (r185742)
+++ head/tools/tools/ath/athdebug/Makefile Sun Dec 7 19:17:33 2008 (r185743)
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= athdebug
-BINDIR= /usr/local/bin
-NO_MAN=
+
+.include <../Makefile.inc>
.include <bsd.prog.mk>
Added: head/tools/tools/ath/athkey/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/athkey/Makefile Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= athkey
+
+.include <../Makefile.inc>
+
+.include <bsd.prog.mk>
Added: head/tools/tools/ath/athkey/athkey.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/athkey/athkey.c Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2002-2008 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$
+ */
+
+#include "diag.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <err.h>
+#include <ctype.h>
+#include <getopt.h>
+
+const char *progname;
+
+static int
+toint(int c)
+{
+ return isdigit(c) ? c - '0' : isupper(c) ? c - 'A' + 10 : c - 'a' + 10;
+}
+
+static int
+getdata(const char *arg, u_int8_t *data, size_t maxlen)
+{
+ const char *cp = arg;
+ int len;
+
+ if (cp[0] == '0' && (cp[1] == 'x' || cp[1] == 'X'))
+ cp += 2;
+ len = 0;
+ while (*cp) {
+ int b0, b1;
+ if (cp[0] == ':' || cp[0] == '-' || cp[0] == '.') {
+ cp++;
+ continue;
+ }
+ if (!isxdigit(cp[0])) {
+ fprintf(stderr, "%s: invalid data value %c (not hex)\n",
+ progname, cp[0]);
+ exit(-1);
+ }
+ b0 = toint(cp[0]);
+ if (cp[1] != '\0') {
+ if (!isxdigit(cp[1])) {
+ fprintf(stderr, "%s: invalid data value %c "
+ "(not hex)\n", progname, cp[1]);
+ exit(-1);
+ }
+ b1 = toint(cp[1]);
+ cp += 2;
+ } else { /* fake up 0<n> */
+ b1 = b0, b0 = 0;
+ cp += 1;
+ }
+ if (len > maxlen) {
+ fprintf(stderr,
+ "%s: too much data in %s, max %u bytes\n",
+ progname, arg, maxlen);
+ }
+ data[len++] = (b0<<4) | b1;
+ }
+ return len;
+}
+
+/* XXX this assumes 5212 key types are common to 5211 and 5210 */
+
+static int
+getcipher(const char *name)
+{
+#define streq(a,b) (strcasecmp(a,b) == 0)
+
+ if (streq(name, "wep"))
+ return HAL_CIPHER_WEP;
+ if (streq(name, "tkip"))
+ return HAL_CIPHER_TKIP;
+ if (streq(name, "aes-ocb") || streq(name, "ocb"))
+ return HAL_CIPHER_AES_OCB;
+ if (streq(name, "aes-ccm") || streq(name, "ccm") ||
+ streq(name, "aes"))
+ return HAL_CIPHER_AES_CCM;
+ if (streq(name, "ckip"))
+ return HAL_CIPHER_CKIP;
+ if (streq(name, "none") || streq(name, "clr"))
+ return HAL_CIPHER_CLR;
+
+ fprintf(stderr, "%s: unknown cipher %s\n", progname, name);
+ exit(-1);
+#undef streq
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-i device] keyix cipher keyval [mac]\n",
+ progname);
+ exit(-1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *ifname;
+ struct ath_diag atd;
+ HAL_DIAG_KEYVAL setkey;
+ const char *cp;
+ int s, c;
+ u_int16_t keyix;
+ int op = HAL_DIAG_SETKEY;
+ int xor = 0;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ err(1, "socket");
+ ifname = getenv("ATH");
+ if (!ifname)
+ ifname = ATH_DEFAULT;
+
+ progname = argv[0];
+ while ((c = getopt(argc, argv, "di:x")) != -1)
+ switch (c) {
+ case 'd':
+ op = HAL_DIAG_RESETKEY;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'x':
+ xor = 1;
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc < 1)
+ usage();
+
+ keyix = (u_int16_t) atoi(argv[0]);
+ if (keyix > 127)
+ errx(-1, "%s: invalid key index %s, must be [0..127]",
+ progname, argv[0]);
+ strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
+ atd.ad_id = op | ATH_DIAG_IN | ATH_DIAG_DYN;
+ atd.ad_out_data = NULL;
+ atd.ad_out_size = 0;
+ switch (op) {
+ case HAL_DIAG_RESETKEY:
+ atd.ad_in_data = (caddr_t) &keyix;
+ atd.ad_in_size = sizeof(u_int16_t);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ return 0;
+ case HAL_DIAG_SETKEY:
+ if (argc != 3 && argc != 4)
+ usage();
+ memset(&setkey, 0, sizeof(setkey));
+ setkey.dk_keyix = keyix;
+ setkey.dk_xor = xor;
+ setkey.dk_keyval.kv_type = getcipher(argv[1]);
+ setkey.dk_keyval.kv_len = getdata(argv[2],
+ setkey.dk_keyval.kv_val, sizeof(setkey.dk_keyval.kv_val));
+ /* XXX MIC */
+ if (argc == 4)
+ (void) getdata(argv[3], setkey.dk_mac,
+ IEEE80211_ADDR_LEN);
+ atd.ad_in_data = (caddr_t) &setkey;
+ atd.ad_in_size = sizeof(setkey);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ return 0;
+ }
+ return -1;
+}
Added: head/tools/tools/ath/athpow/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/athpow/Makefile Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= athpow
+
+.include <../Makefile.inc>
+
+.include <bsd.prog.mk>
Added: head/tools/tools/ath/athpow/athpow.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/athpow/athpow.c Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2002-2008 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$
+ */
+#include "diag.h"
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_eeprom.h"
+#include "ah_eeprom_v1.h"
+#include "ah_eeprom_v3.h"
+#include "ah_eeprom_v14.h"
+#include "ar5212/ar5212reg.h"
+#define IS_5112(ah) \
+ (((ah)->ah_analog5GhzRev&0xf0) >= AR_RAD5112_SREV_MAJOR \
+ && ((ah)->ah_analog5GhzRev&0xf0) < AR_RAD2316_SREV_MAJOR )
+#define IS_2316(ah) \
+ ((ah)->ah_macVersion == AR_SREV_2415)
+#define IS_2413(ah) \
+ ((ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah))
+#define IS_5424(ah) \
+ ((ah)->ah_macVersion == AR_SREV_5424 || \
+ ((ah)->ah_macVersion == AR_SREV_5413 && \
+ (ah)->ah_macRev <= AR_SREV_D2PLUS_MS))
+#define IS_5413(ah) \
+ ((ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah))
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+static void printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n);
+static void printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n);
+static void printRevs(FILE *fd, const HAL_REVS *revs);
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [-v] [-i dev]\n", progname);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int s, i, verbose = 0, c;
+ struct ath_diag atd;
+ const char *ifname;
+ HAL_REVS revs;
+ u_int16_t pcdacTable[MAX(PWR_TABLE_SIZE,PWR_TABLE_SIZE_2413)];
+ u_int16_t ratesArray[16];
+ u_int nrates, npcdac;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ err(1, "socket");
+ ifname = getenv("ATH");
+ if (!ifname)
+ ifname = ATH_DEFAULT;
+ while ((c = getopt(argc, argv, "i:v")) != -1)
+ switch (c) {
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
+
+ atd.ad_id = HAL_DIAG_REVS;
+ atd.ad_out_data = (caddr_t) &revs;
+ atd.ad_out_size = sizeof(revs);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+
+ if (verbose)
+ printRevs(stdout, &revs);
+
+ atd.ad_id = HAL_DIAG_TXRATES;
+ atd.ad_out_data = (caddr_t) ratesArray;
+ atd.ad_out_size = sizeof(ratesArray);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ nrates = sizeof(ratesArray) / sizeof(u_int16_t);
+
+ atd.ad_id = HAL_DIAG_PCDAC;
+ atd.ad_out_data = (caddr_t) pcdacTable;
+ atd.ad_out_size = sizeof(pcdacTable);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ if (IS_2413(&revs) || IS_5413(&revs))
+ npcdac = PWR_TABLE_SIZE_2413;
+ else
+ npcdac = PWR_TABLE_SIZE;
+
+ printf("PCDAC table:\n");
+ printPcdacTable(stdout, pcdacTable, npcdac);
+
+ printf("Power per rate table:\n");
+ printPowerPerRate(stdout, ratesArray, nrates);
+
+ return 0;
+}
+
+static void
+printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n)
+{
+ int i, halfRates = n/2;
+
+ for (i = 0; i < halfRates; i += 2)
+ fprintf(fd, "[%2u] %04x %04x [%2u] %04x %04x\n",
+ i, pcdac[2*i + 1], pcdac[2*i],
+ i+1, pcdac[2*(i+1) + 1], pcdac[2*(i+1)]);
+}
+
+static void
+printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n)
+{
+ const char *rateString[] = {
+ " 6mb OFDM", " 9mb OFDM", "12mb OFDM", "18mb OFDM",
+ "24mb OFDM", "36mb OFDM", "48mb OFDM", "54mb OFDM",
+ "1L CCK ", "2L CCK ", "2S CCK ", "5.5L CCK ",
+ "5.5S CCK ", "11L CCK ", "11S CCK ", "XR "
+ };
+ int i, halfRates = n/2;
+
+ for (i = 0; i < halfRates; i++)
+ fprintf(fd, " %s %3d.%1d dBm | %s %3d.%1d dBm\n",
+ rateString[i], ratesArray[i]/2,
+ (ratesArray[i] %2) * 5,
+ rateString[i + halfRates],
+ ratesArray[i + halfRates]/2,
+ (ratesArray[i + halfRates] %2) *5);
+}
+
+static void
+printRevs(FILE *fd, const HAL_REVS *revs)
+{
+ const char *rfbackend;
+
+ fprintf(fd, "PCI device id 0x%x subvendor id 0x%x\n",
+ revs->ah_devid, revs->ah_subvendorid);
+ fprintf(fd, "mac %d.%d phy %d.%d"
+ , revs->ah_macVersion, revs->ah_macRev
+ , revs->ah_phyRev >> 4, revs->ah_phyRev & 0xf
+ );
+ rfbackend = IS_5413(revs) ? "5413" :
+ IS_2413(revs) ? "2413" :
+ IS_5112(revs) ? "5112" :
+ "5111";
+ if (revs->ah_analog5GhzRev && revs->ah_analog2GhzRev)
+ fprintf(fd, " 5ghz radio %d.%d 2ghz radio %d.%d (%s)\n"
+ , revs->ah_analog5GhzRev >> 4
+ , revs->ah_analog5GhzRev & 0xf
+ , revs->ah_analog2GhzRev >> 4
+ , revs->ah_analog2GhzRev & 0xf
+ , rfbackend
+ );
+ else
+ fprintf(fd, " radio %d.%d (%s)\n"
+ , revs->ah_analog5GhzRev >> 4
+ , revs->ah_analog5GhzRev & 0xf
+ , rfbackend
+ );
+}
Added: head/tools/tools/ath/athprom/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/athprom/Makefile Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+PROG= athprom
+
+.include <../Makefile.inc>
+
+TEMPLATEDIR= /usr/local/libdata/athprom
+TEXTMODE?= 444
+
+CFLAGS+=-DDIR_TEMPLATE='"${TEMPLATEDIR}"'
+
+beforeinstall:
+ mkdir -p ${DESTDIR}${TEMPLATEDIR}
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \
+ ${.CURDIR}/eeprom-* ${DESTDIR}${TEMPLATEDIR}/
+
+.include <bsd.prog.mk>
Added: head/tools/tools/ath/athprom/athprom.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/tools/tools/ath/athprom/athprom.c Sun Dec 7 19:17:33 2008 (r185743)
@@ -0,0 +1,978 @@
+/*-
+ * Copyright (c) 2008 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$
+ */
+#include "diag.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_eeprom_v1.h"
+#include "ah_eeprom_v3.h"
+#include "ah_eeprom_v14.h"
+
+#define IS_VERS(op, v) (eeprom.ee_version op (v))
+
+#include <getopt.h>
+#include <errno.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef DIR_TEMPLATE
+#define DIR_TEMPLATE "/usr/local/libdata/athprom"
+#endif
+
+struct ath_diag atd;
+int s;
+const char *progname;
+union {
+ HAL_EEPROM legacy; /* format v3.x ... v5.x */
+ struct ar5416eeprom v14; /* 11n format v14.x ... */
+} eep;
+#define eeprom eep.legacy
+#define eepromN eep.v14
+
+static void parseTemplate(FILE *ftemplate, FILE *fd);
+static uint16_t eeread(uint16_t);
+static void eewrite(uint16_t, uint16_t);
+
+static void
+usage()
+{
+ fprintf(stderr, "usage: %s [-i ifname] [-t pathname] [offset | offset=value]\n", progname);
+ exit(-1);
+}
+
+static FILE *
+opentemplate(const char *dir)
+{
+ char filename[PATH_MAX];
+ FILE *fd;
+
+ /* find the template using the eeprom version */
+ snprintf(filename, sizeof(filename), "%s/eeprom-%d.%d",
+ dir, eeprom.ee_version >> 12, eeprom.ee_version & 0xfff);
+ fd = fopen(filename, "r");
+ if (fd == NULL && errno == ENOENT) {
+ /* retry with just the major version */
+ snprintf(filename, sizeof(filename), "%s/eeprom-%d",
+ dir, eeprom.ee_version >> 12);
+ fd = fopen(filename, "r");
+ if (fd != NULL) /* XXX verbose */
+ warnx("Using template file %s", filename);
+ }
+ return fd;
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fd = NULL;
+ const char *ifname;
+ int c;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ err(1, "socket");
+ ifname = getenv("ATH");
+ if (!ifname)
+ ifname = ATH_DEFAULT;
+
+ progname = argv[0];
+ while ((c = getopt(argc, argv, "i:t:")) != -1)
+ switch (c) {
+ case 'i':
+ ifname = optarg;
+ break;
+ case 't':
+ fd = fopen(optarg, "r");
+ if (fd == NULL)
+ err(-1, "Cannot open %s", optarg);
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ argc -= optind;
+ argv += optind;
+
+ strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
+
+ if (argc != 0) {
+ for (; argc > 0; argc--, argv++) {
+ uint16_t off, val, oval;
+ char line[256];
+ char *cp;
+
+ cp = strchr(argv[0], '=');
+ if (cp != NULL)
+ *cp = '\0';
+ off = (uint16_t) strtoul(argv[0], NULL, 0);
+ if (off == 0 && errno == EINVAL)
+ errx(1, "%s: invalid eeprom offset %s",
+ progname, argv[0]);
+ if (cp == NULL) {
+ printf("%04x: %04x\n", off, eeread(off));
+ } else {
+ val = (uint16_t) strtoul(cp+1, NULL, 0);
+ if (val == 0 && errno == EINVAL)
+ errx(1, "%s: invalid eeprom value %s",
+ progname, cp+1);
+ oval = eeread(off);
+ printf("Write %04x: %04x = %04x? ",
+ off, oval, val);
+ fflush(stdout);
+ if (fgets(line, sizeof(line), stdin) != NULL &&
+ line[0] == 'y')
+ eewrite(off, val);
+ }
+ }
+ } else {
+ atd.ad_id = HAL_DIAG_EEPROM;
+ atd.ad_out_data = (caddr_t) &eep;
+ atd.ad_out_size = sizeof(eep);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ if (fd == NULL) {
+ fd = opentemplate(DIR_TEMPLATE);
+ if (fd == NULL)
+ fd = opentemplate(".");
+ if (fd == NULL)
+ errx(-1, "Cannot locate template file for "
+ "v%d.%d EEPROM", eeprom.ee_version >> 12,
+ eeprom.ee_version & 0xfff);
+ }
+ parseTemplate(fd, stdout);
+ fclose(fd);
+ }
+ return 0;
+}
+
+static u_int16_t
+eeread(u_int16_t off)
+{
+ u_int16_t eedata;
+
+ atd.ad_id = HAL_DIAG_EEREAD | ATH_DIAG_IN | ATH_DIAG_DYN;
+ atd.ad_in_size = sizeof(off);
+ atd.ad_in_data = (caddr_t) &off;
+ atd.ad_out_size = sizeof(eedata);
+ atd.ad_out_data = (caddr_t) &eedata;
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ return eedata;
+}
+
+static void
+eewrite(uint16_t off, uint16_t value)
+{
+ HAL_DIAG_EEVAL eeval;
+
+ eeval.ee_off = off;
+ eeval.ee_data = value;
+
+ atd.ad_id = HAL_DIAG_EEWRITE | ATH_DIAG_IN;
+ atd.ad_in_size = sizeof(eeval);
+ atd.ad_in_data = (caddr_t) &eeval;
+ atd.ad_out_size = 0;
+ atd.ad_out_data = NULL;
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+}
+
+#define MAXID 128
+int lineno;
+int bol;
+int curmode = -1;
+int curchan;
+int curpdgain; /* raw pdgain index */
+int curlpdgain; /* logical pdgain index */
+int curpcdac;
+int curctl;
+int numChannels;
+const RAW_DATA_STRUCT_2413 *pRaw;
+const TRGT_POWER_INFO *pPowerInfo;
+const DATA_PER_CHANNEL *pDataPerChannel;
+const EEPROM_POWER_EXPN_5112 *pExpnPower;
+int singleXpd;
+
+static int
+token(FILE *fd, char id[], int maxid, const char *what)
+{
+ int c, i;
+
+ i = 0;
+ for (;;) {
+ c = getc(fd);
+ if (c == EOF)
+ return EOF;
+ if (!isalnum(c) && c != '_') {
+ ungetc(c, fd);
+ break;
+ }
+ if (i == maxid-1) {
+ warnx("line %d, %s too long", lineno, what);
+ break;
+ }
+ id[i++] = c;
+ }
+ id[i] = '\0';
+ if (i != 0)
+ bol = 0;
+ return i;
+}
+
+static int
+skipto(FILE *fd, const char *what)
+{
+ char id[MAXID];
+ int c;
+
+ for (;;) {
+ c = getc(fd);
+ if (c == EOF)
+ goto bad;
+ if (c == '.' && bol) { /* .directive */
+ if (token(fd, id, MAXID, ".directive") == EOF)
+ goto bad;
+ if (strcasecmp(id, what) == 0)
+ break;
+ continue;
+ }
+ if (c == '\\') { /* escape next character */
+ c = getc(fd);
+ if (c == EOF)
+ goto bad;
+ }
+ bol = (c == '\n');
+ if (bol)
+ lineno++;
+ }
+ return 0;
+bad:
+ warnx("EOF with no matching .%s", what);
+ return EOF;
+}
+
+static int
+skipws(FILE *fd)
+{
+ int c, i;
+
+ i = 0;
+ while ((c = getc(fd)) != EOF && isblank(c))
+ i++;
+ if (c != EOF)
+ ungetc(c, fd);
+ if (i != 0)
+ bol = 0;
+ return 0;
+}
+
+static void
+setmode(int mode)
+{
+ EEPROM_POWER_EXPN_5112 *exp;
+
+ curmode = mode;
+ curchan = -1;
+ curctl = -1;
+ curpdgain = -1;
+ curlpdgain = -1;
+ curpcdac = -1;
+ switch (curmode) {
+ case headerInfo11A:
+ pPowerInfo = eeprom.ee_trgtPwr_11a;
+ pDataPerChannel = eeprom.ee_dataPerChannel11a;
+ break;
+ case headerInfo11B:
+ pPowerInfo = eeprom.ee_trgtPwr_11b;
+ pDataPerChannel = eeprom.ee_dataPerChannel11b;
+ break;
+ case headerInfo11G:
+ pPowerInfo = eeprom.ee_trgtPwr_11g;
+ pDataPerChannel = eeprom.ee_dataPerChannel11g;
+ break;
+ }
+ if (IS_VERS(<, AR_EEPROM_VER4_0)) /* nothing to do */
+ return;
+ if (IS_VERS(<, AR_EEPROM_VER5_0)) {
+ exp = &eeprom.ee_modePowerArray5112[curmode];
+ /* fetch indirect data*/
+ atd.ad_id = HAL_DIAG_EEPROM_EXP_11A+curmode;
+ atd.ad_out_size = roundup(
+ sizeof(u_int16_t) * exp->numChannels, sizeof(u_int32_t))
+ + sizeof(EXPN_DATA_PER_CHANNEL_5112) * exp->numChannels;
+ atd.ad_out_data = (caddr_t) malloc(atd.ad_out_size);
+ if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
+ err(1, atd.ad_name);
+ exp->pChannels = (void *) atd.ad_out_data;
+ exp->pDataPerChannel = (void *)((char *)atd.ad_out_data +
+ roundup(sizeof(u_int16_t) * exp->numChannels, sizeof(u_int32_t)));
+ pExpnPower = exp;
+ numChannels = pExpnPower->numChannels;
+ if (exp->xpdMask != 0x9) {
+ for (singleXpd = 0; singleXpd < NUM_XPD_PER_CHANNEL; singleXpd++)
+ if (exp->xpdMask == (1<<singleXpd))
+ break;
+ } else
+ singleXpd = 0;
+ } else if (IS_VERS(<, AR_EEPROM_VER14_2)) {
+ pRaw = &eeprom.ee_rawDataset2413[curmode];
+ numChannels = pRaw->numChannels;
+ }
+}
+
+int
+nextctl(int start)
+{
+ int i;
+
+ for (i = start; i < eeprom.ee_numCtls && eeprom.ee_ctl[i]; i++) {
+ switch (eeprom.ee_ctl[i] & 3) {
+ case 0: case 3:
+ if (curmode != headerInfo11A)
+ continue;
+ break;
+ case 1:
+ if (curmode != headerInfo11B)
+ continue;
+ break;
+ case 2:
+ if (curmode != headerInfo11G)
+ continue;
+ break;
+ }
+ return i;
+ }
+ return -1;
+}
+
+static void
+printAntennaControl(FILE *fd, int ant)
+{
+ fprintf(fd, "0x%02X", eeprom.ee_antennaControl[ant][curmode]);
+}
+
+static void
+printEdge(FILE *fd, int edge)
+{
+ const RD_EDGES_POWER *pRdEdgePwrInfo =
+ &eeprom.ee_rdEdgesPower[curctl*NUM_EDGES];
+
+ if (pRdEdgePwrInfo[edge].rdEdge == 0)
+ fprintf(fd, " -- ");
+ else
+ fprintf(fd, "%04d", pRdEdgePwrInfo[edge].rdEdge);
+}
+
+static void
+printEdgePower(FILE *fd, int edge)
+{
+ const RD_EDGES_POWER *pRdEdgePwrInfo =
+ &eeprom.ee_rdEdgesPower[curctl*NUM_EDGES];
+
+ if (pRdEdgePwrInfo[edge].rdEdge == 0)
+ fprintf(fd, " -- ");
+ else
+ fprintf(fd, "%2d.%d",
+ pRdEdgePwrInfo[edge].twice_rdEdgePower / 2,
+ (pRdEdgePwrInfo[edge].twice_rdEdgePower % 2) * 5);
+}
+
+static void
+printEdgeFlag(FILE *fd, int edge)
+{
+ const RD_EDGES_POWER *pRdEdgePwrInfo =
+ &eeprom.ee_rdEdgesPower[curctl*NUM_EDGES];
+
+ if (pRdEdgePwrInfo[edge].rdEdge == 0)
+ fprintf(fd, "--");
+ else
+ fprintf(fd, " %1d", pRdEdgePwrInfo[edge].flag);
+}
+
+static int16_t
+getMaxPowerV5(const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+ uint32_t i;
+ uint16_t numVpd;
+
+ for (i = 0; i < MAX_NUM_PDGAINS_PER_CHANNEL; i++) {
+ numVpd = data->pDataPerPDGain[i].numVpd;
+ if (numVpd > 0)
+ return data->pDataPerPDGain[i].pwr_t4[numVpd-1];
+ }
+ return 0;
+}
+
+static void
+printQuarterDbmPower(FILE *fd, int16_t power25dBm)
+{
+ fprintf(fd, "%2d.%02d", power25dBm / 4, (power25dBm % 4) * 25);
+}
+
+static void
+printHalfDbmPower(FILE *fd, int16_t power5dBm)
+{
+ fprintf(fd, "%2d.%d", power5dBm / 2, (power5dBm % 2) * 5);
+}
+
+static void
+printVpd(FILE *fd, int vpd)
+{
+ fprintf(fd, "[%3d]", vpd);
+}
+
+static void
+printPcdacValue(FILE *fd, int v)
+{
+ fprintf(fd, "%2d.%02d", v / EEP_SCALE, v % EEP_SCALE);
+}
+
+static void
+undef(const char *what)
+{
+ warnx("%s undefined for version %d.%d format EEPROM", what,
+ eeprom.ee_version >> 12, eeprom.ee_version & 0xfff);
+}
+
+static int
+pdgain(int lpdgain)
+{
+ uint32_t mask;
+ int i, l = lpdgain;
+
+ if (IS_VERS(<, AR_EEPROM_VER5_0))
+ mask = pExpnPower->xpdMask;
+ else
+ mask = pRaw->xpd_mask;
+ for (i = 0; mask != 0; mask >>= 1, i++)
+ if ((mask & 1) && l-- == 0)
+ return i;
+ warnx("can't find logical pdgain %d", lpdgain);
+ return -1;
+}
+
+#define COUNTRY_ERD_FLAG 0x8000
+#define WORLDWIDE_ROAMING_FLAG 0x4000
+
+void
+eevar(FILE *fd, const char *var)
+{
+#define streq(a,b) (strcasecmp(a,b) == 0)
+#define strneq(a,b,n) (strncasecmp(a,b,n) == 0)
+ if (streq(var, "mode")) {
+ fprintf(fd, "%s",
+ curmode == headerInfo11A ? "11a" :
+ curmode == headerInfo11B ? "11b" :
+ curmode == headerInfo11G ? "11g" : "???");
+ } else if (streq(var, "version")) {
+ fprintf(fd, "%04x", eeprom.ee_version);
+ } else if (streq(var, "V_major")) {
+ fprintf(fd, "%2d", eeprom.ee_version >> 12);
+ } else if (streq(var, "V_minor")) {
+ fprintf(fd, "%2d", eeprom.ee_version & 0xfff);
+ } else if (streq(var, "earStart")) {
+ fprintf(fd, "%03x", eeprom.ee_earStart);
+ } else if (streq(var, "tpStart")) {
+ fprintf(fd, "%03x", eeprom.ee_targetPowersStart);
+ } else if (streq(var, "eepMap")) {
+ fprintf(fd, "%3d", eeprom.ee_eepMap);
+ } else if (streq(var, "exist32KHzCrystal")) {
+ fprintf(fd, "%3d", eeprom.ee_exist32kHzCrystal);
+ } else if (streq(var, "eepMap2PowerCalStart")) {
+ fprintf(fd , "%3d", eeprom.ee_eepMap2PowerCalStart);
+ } else if (streq(var, "Amode")) {
+ fprintf(fd , "%1d", eeprom.ee_Amode);
+ } else if (streq(var, "Bmode")) {
+ fprintf(fd , "%1d", eeprom.ee_Bmode);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list