Date: Sun, 7 Dec 2008 19:17:34 +0000 (UTC) From: Sam Leffler <sam@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r185743 - in head/tools/tools/ath: . athdebug athkey athpow athprom athregs athstats common Message-ID: <200812071917.mB7JHYYJ033534@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812071917.mB7JHYYJ033534>