1185743Ssam/*- 2185743Ssam * Copyright (c) 2008 Sam Leffler, Errno Consulting 3185743Ssam * All rights reserved. 4185743Ssam * 5185743Ssam * Redistribution and use in source and binary forms, with or without 6185743Ssam * modification, are permitted provided that the following conditions 7185743Ssam * are met: 8185743Ssam * 1. Redistributions of source code must retain the above copyright 9185743Ssam * notice, this list of conditions and the following disclaimer, 10185743Ssam * without modification. 11185743Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12185743Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13185743Ssam * redistribution must be conditioned upon including a substantially 14185743Ssam * similar Disclaimer requirement for further binary redistribution. 15185743Ssam * 16185743Ssam * NO WARRANTY 17185743Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18185743Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19185743Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20185743Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21185743Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22185743Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23185743Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24185743Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25185743Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26185743Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27185743Ssam * THE POSSIBILITY OF SUCH DAMAGES. 28185743Ssam * 29185743Ssam * $FreeBSD$ 30185743Ssam */ 31185743Ssam#include "diag.h" 32185743Ssam 33185743Ssam#include "ah.h" 34185743Ssam#include "ah_internal.h" 35185743Ssam#include "ah_eeprom_v1.h" 36185743Ssam#include "ah_eeprom_v3.h" 37185743Ssam#include "ah_eeprom_v14.h" 38185743Ssam 39185743Ssam#define IS_VERS(op, v) (eeprom.ee_version op (v)) 40185743Ssam 41185743Ssam#include <getopt.h> 42185743Ssam#include <errno.h> 43185743Ssam#include <err.h> 44185743Ssam#include <stdlib.h> 45185743Ssam#include <string.h> 46217680Sadrian#include <ctype.h> 47185743Ssam 48185743Ssam#ifndef DIR_TEMPLATE 49185743Ssam#define DIR_TEMPLATE "/usr/local/libdata/athprom" 50185743Ssam#endif 51185743Ssam 52185743Ssamstruct ath_diag atd; 53185743Ssamint s; 54185743Ssamconst char *progname; 55185743Ssamunion { 56185743Ssam HAL_EEPROM legacy; /* format v3.x ... v5.x */ 57185743Ssam struct ar5416eeprom v14; /* 11n format v14.x ... */ 58185743Ssam} eep; 59185743Ssam#define eeprom eep.legacy 60185743Ssam#define eepromN eep.v14 61185743Ssam 62185743Ssamstatic void parseTemplate(FILE *ftemplate, FILE *fd); 63185743Ssamstatic uint16_t eeread(uint16_t); 64185743Ssamstatic void eewrite(uint16_t, uint16_t); 65185743Ssam 66185743Ssamstatic void 67185743Ssamusage() 68185743Ssam{ 69185743Ssam fprintf(stderr, "usage: %s [-i ifname] [-t pathname] [offset | offset=value]\n", progname); 70185743Ssam exit(-1); 71185743Ssam} 72185743Ssam 73185743Ssamstatic FILE * 74185743Ssamopentemplate(const char *dir) 75185743Ssam{ 76185743Ssam char filename[PATH_MAX]; 77185743Ssam FILE *fd; 78185743Ssam 79185743Ssam /* find the template using the eeprom version */ 80185743Ssam snprintf(filename, sizeof(filename), "%s/eeprom-%d.%d", 81185743Ssam dir, eeprom.ee_version >> 12, eeprom.ee_version & 0xfff); 82185743Ssam fd = fopen(filename, "r"); 83185743Ssam if (fd == NULL && errno == ENOENT) { 84185743Ssam /* retry with just the major version */ 85185743Ssam snprintf(filename, sizeof(filename), "%s/eeprom-%d", 86185743Ssam dir, eeprom.ee_version >> 12); 87185743Ssam fd = fopen(filename, "r"); 88185743Ssam if (fd != NULL) /* XXX verbose */ 89185743Ssam warnx("Using template file %s", filename); 90185743Ssam } 91185743Ssam return fd; 92185743Ssam} 93185743Ssam 94185743Ssamint 95185743Ssammain(int argc, char *argv[]) 96185743Ssam{ 97185743Ssam FILE *fd = NULL; 98185743Ssam const char *ifname; 99185743Ssam int c; 100185743Ssam 101185743Ssam s = socket(AF_INET, SOCK_DGRAM, 0); 102185743Ssam if (s < 0) 103185743Ssam err(1, "socket"); 104185743Ssam ifname = getenv("ATH"); 105185743Ssam if (!ifname) 106185743Ssam ifname = ATH_DEFAULT; 107185743Ssam 108185743Ssam progname = argv[0]; 109185743Ssam while ((c = getopt(argc, argv, "i:t:")) != -1) 110185743Ssam switch (c) { 111185743Ssam case 'i': 112185743Ssam ifname = optarg; 113185743Ssam break; 114185743Ssam case 't': 115185743Ssam fd = fopen(optarg, "r"); 116185743Ssam if (fd == NULL) 117185743Ssam err(-1, "Cannot open %s", optarg); 118185743Ssam break; 119185743Ssam default: 120185743Ssam usage(); 121185743Ssam /*NOTREACHED*/ 122185743Ssam } 123185743Ssam argc -= optind; 124185743Ssam argv += optind; 125185743Ssam 126185743Ssam strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); 127185743Ssam 128185743Ssam if (argc != 0) { 129185743Ssam for (; argc > 0; argc--, argv++) { 130185743Ssam uint16_t off, val, oval; 131185743Ssam char line[256]; 132185743Ssam char *cp; 133185743Ssam 134185743Ssam cp = strchr(argv[0], '='); 135185743Ssam if (cp != NULL) 136185743Ssam *cp = '\0'; 137185743Ssam off = (uint16_t) strtoul(argv[0], NULL, 0); 138185743Ssam if (off == 0 && errno == EINVAL) 139185743Ssam errx(1, "%s: invalid eeprom offset %s", 140185743Ssam progname, argv[0]); 141185743Ssam if (cp == NULL) { 142185743Ssam printf("%04x: %04x\n", off, eeread(off)); 143185743Ssam } else { 144185743Ssam val = (uint16_t) strtoul(cp+1, NULL, 0); 145185743Ssam if (val == 0 && errno == EINVAL) 146185743Ssam errx(1, "%s: invalid eeprom value %s", 147185743Ssam progname, cp+1); 148185743Ssam oval = eeread(off); 149185743Ssam printf("Write %04x: %04x = %04x? ", 150185743Ssam off, oval, val); 151185743Ssam fflush(stdout); 152185743Ssam if (fgets(line, sizeof(line), stdin) != NULL && 153185743Ssam line[0] == 'y') 154185743Ssam eewrite(off, val); 155185743Ssam } 156185743Ssam } 157185743Ssam } else { 158185743Ssam atd.ad_id = HAL_DIAG_EEPROM; 159185743Ssam atd.ad_out_data = (caddr_t) &eep; 160185743Ssam atd.ad_out_size = sizeof(eep); 161185743Ssam if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 162244964Sadrian err(1, "ioctl: %s", atd.ad_name); 163185743Ssam if (fd == NULL) { 164185743Ssam fd = opentemplate(DIR_TEMPLATE); 165185743Ssam if (fd == NULL) 166185743Ssam fd = opentemplate("."); 167185743Ssam if (fd == NULL) 168185743Ssam errx(-1, "Cannot locate template file for " 169185743Ssam "v%d.%d EEPROM", eeprom.ee_version >> 12, 170185743Ssam eeprom.ee_version & 0xfff); 171185743Ssam } 172185743Ssam parseTemplate(fd, stdout); 173185743Ssam fclose(fd); 174185743Ssam } 175185743Ssam return 0; 176185743Ssam} 177185743Ssam 178185743Ssamstatic u_int16_t 179185743Ssameeread(u_int16_t off) 180185743Ssam{ 181185743Ssam u_int16_t eedata; 182185743Ssam 183185743Ssam atd.ad_id = HAL_DIAG_EEREAD | ATH_DIAG_IN | ATH_DIAG_DYN; 184185743Ssam atd.ad_in_size = sizeof(off); 185185743Ssam atd.ad_in_data = (caddr_t) &off; 186185743Ssam atd.ad_out_size = sizeof(eedata); 187185743Ssam atd.ad_out_data = (caddr_t) &eedata; 188185743Ssam if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 189244964Sadrian err(1, "ioctl: %s", atd.ad_name); 190185743Ssam return eedata; 191185743Ssam} 192185743Ssam 193185743Ssamstatic void 194185743Ssameewrite(uint16_t off, uint16_t value) 195185743Ssam{ 196185743Ssam HAL_DIAG_EEVAL eeval; 197185743Ssam 198185743Ssam eeval.ee_off = off; 199185743Ssam eeval.ee_data = value; 200185743Ssam 201185743Ssam atd.ad_id = HAL_DIAG_EEWRITE | ATH_DIAG_IN; 202185743Ssam atd.ad_in_size = sizeof(eeval); 203185743Ssam atd.ad_in_data = (caddr_t) &eeval; 204185743Ssam atd.ad_out_size = 0; 205185743Ssam atd.ad_out_data = NULL; 206185743Ssam if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 207244964Sadrian err(1, "ioctl: %s", atd.ad_name); 208185743Ssam} 209185743Ssam 210185743Ssam#define MAXID 128 211185743Ssamint lineno; 212185743Ssamint bol; 213185743Ssamint curmode = -1; 214185743Ssamint curchan; 215185743Ssamint curpdgain; /* raw pdgain index */ 216185743Ssamint curlpdgain; /* logical pdgain index */ 217185743Ssamint curpcdac; 218185743Ssamint curctl; 219185743Ssamint numChannels; 220185743Ssamconst RAW_DATA_STRUCT_2413 *pRaw; 221185743Ssamconst TRGT_POWER_INFO *pPowerInfo; 222185743Ssamconst DATA_PER_CHANNEL *pDataPerChannel; 223185743Ssamconst EEPROM_POWER_EXPN_5112 *pExpnPower; 224185743Ssamint singleXpd; 225185743Ssam 226185743Ssamstatic int 227185743Ssamtoken(FILE *fd, char id[], int maxid, const char *what) 228185743Ssam{ 229185743Ssam int c, i; 230185743Ssam 231185743Ssam i = 0; 232185743Ssam for (;;) { 233185743Ssam c = getc(fd); 234185743Ssam if (c == EOF) 235185743Ssam return EOF; 236185743Ssam if (!isalnum(c) && c != '_') { 237185743Ssam ungetc(c, fd); 238185743Ssam break; 239185743Ssam } 240185743Ssam if (i == maxid-1) { 241185743Ssam warnx("line %d, %s too long", lineno, what); 242185743Ssam break; 243185743Ssam } 244185743Ssam id[i++] = c; 245185743Ssam } 246185743Ssam id[i] = '\0'; 247185743Ssam if (i != 0) 248185743Ssam bol = 0; 249185743Ssam return i; 250185743Ssam} 251185743Ssam 252185743Ssamstatic int 253185743Ssamskipto(FILE *fd, const char *what) 254185743Ssam{ 255185743Ssam char id[MAXID]; 256185743Ssam int c; 257185743Ssam 258185743Ssam for (;;) { 259185743Ssam c = getc(fd); 260185743Ssam if (c == EOF) 261185743Ssam goto bad; 262185743Ssam if (c == '.' && bol) { /* .directive */ 263185743Ssam if (token(fd, id, MAXID, ".directive") == EOF) 264185743Ssam goto bad; 265185743Ssam if (strcasecmp(id, what) == 0) 266185743Ssam break; 267185743Ssam continue; 268185743Ssam } 269185743Ssam if (c == '\\') { /* escape next character */ 270185743Ssam c = getc(fd); 271185743Ssam if (c == EOF) 272185743Ssam goto bad; 273185743Ssam } 274185743Ssam bol = (c == '\n'); 275185743Ssam if (bol) 276185743Ssam lineno++; 277185743Ssam } 278185743Ssam return 0; 279185743Ssambad: 280185743Ssam warnx("EOF with no matching .%s", what); 281185743Ssam return EOF; 282185743Ssam} 283185743Ssam 284185743Ssamstatic int 285185743Ssamskipws(FILE *fd) 286185743Ssam{ 287185743Ssam int c, i; 288185743Ssam 289185743Ssam i = 0; 290185743Ssam while ((c = getc(fd)) != EOF && isblank(c)) 291185743Ssam i++; 292185743Ssam if (c != EOF) 293185743Ssam ungetc(c, fd); 294185743Ssam if (i != 0) 295185743Ssam bol = 0; 296185743Ssam return 0; 297185743Ssam} 298185743Ssam 299185743Ssamstatic void 300185743Ssamsetmode(int mode) 301185743Ssam{ 302185743Ssam EEPROM_POWER_EXPN_5112 *exp; 303185743Ssam 304185743Ssam curmode = mode; 305185743Ssam curchan = -1; 306185743Ssam curctl = -1; 307185743Ssam curpdgain = -1; 308185743Ssam curlpdgain = -1; 309185743Ssam curpcdac = -1; 310185743Ssam switch (curmode) { 311185743Ssam case headerInfo11A: 312185743Ssam pPowerInfo = eeprom.ee_trgtPwr_11a; 313185743Ssam pDataPerChannel = eeprom.ee_dataPerChannel11a; 314185743Ssam break; 315185743Ssam case headerInfo11B: 316185743Ssam pPowerInfo = eeprom.ee_trgtPwr_11b; 317185743Ssam pDataPerChannel = eeprom.ee_dataPerChannel11b; 318185743Ssam break; 319185743Ssam case headerInfo11G: 320185743Ssam pPowerInfo = eeprom.ee_trgtPwr_11g; 321185743Ssam pDataPerChannel = eeprom.ee_dataPerChannel11g; 322185743Ssam break; 323185743Ssam } 324185743Ssam if (IS_VERS(<, AR_EEPROM_VER4_0)) /* nothing to do */ 325185743Ssam return; 326185743Ssam if (IS_VERS(<, AR_EEPROM_VER5_0)) { 327185743Ssam exp = &eeprom.ee_modePowerArray5112[curmode]; 328185743Ssam /* fetch indirect data*/ 329185743Ssam atd.ad_id = HAL_DIAG_EEPROM_EXP_11A+curmode; 330185743Ssam atd.ad_out_size = roundup( 331185743Ssam sizeof(u_int16_t) * exp->numChannels, sizeof(u_int32_t)) 332185743Ssam + sizeof(EXPN_DATA_PER_CHANNEL_5112) * exp->numChannels; 333185743Ssam atd.ad_out_data = (caddr_t) malloc(atd.ad_out_size); 334185743Ssam if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 335244964Sadrian err(1, "ioctl: %s", atd.ad_name); 336185743Ssam exp->pChannels = (void *) atd.ad_out_data; 337185743Ssam exp->pDataPerChannel = (void *)((char *)atd.ad_out_data + 338185743Ssam roundup(sizeof(u_int16_t) * exp->numChannels, sizeof(u_int32_t))); 339185743Ssam pExpnPower = exp; 340185743Ssam numChannels = pExpnPower->numChannels; 341185743Ssam if (exp->xpdMask != 0x9) { 342185743Ssam for (singleXpd = 0; singleXpd < NUM_XPD_PER_CHANNEL; singleXpd++) 343185743Ssam if (exp->xpdMask == (1<<singleXpd)) 344185743Ssam break; 345185743Ssam } else 346185743Ssam singleXpd = 0; 347185743Ssam } else if (IS_VERS(<, AR_EEPROM_VER14_2)) { 348185743Ssam pRaw = &eeprom.ee_rawDataset2413[curmode]; 349185743Ssam numChannels = pRaw->numChannels; 350185743Ssam } 351185743Ssam} 352185743Ssam 353185743Ssamint 354185743Ssamnextctl(int start) 355185743Ssam{ 356185743Ssam int i; 357185743Ssam 358185743Ssam for (i = start; i < eeprom.ee_numCtls && eeprom.ee_ctl[i]; i++) { 359185743Ssam switch (eeprom.ee_ctl[i] & 3) { 360185743Ssam case 0: case 3: 361185743Ssam if (curmode != headerInfo11A) 362185743Ssam continue; 363185743Ssam break; 364185743Ssam case 1: 365185743Ssam if (curmode != headerInfo11B) 366185743Ssam continue; 367185743Ssam break; 368185743Ssam case 2: 369185743Ssam if (curmode != headerInfo11G) 370185743Ssam continue; 371185743Ssam break; 372185743Ssam } 373185743Ssam return i; 374185743Ssam } 375185743Ssam return -1; 376185743Ssam} 377185743Ssam 378185743Ssamstatic void 379185743SsamprintAntennaControl(FILE *fd, int ant) 380185743Ssam{ 381185743Ssam fprintf(fd, "0x%02X", eeprom.ee_antennaControl[ant][curmode]); 382185743Ssam} 383185743Ssam 384185743Ssamstatic void 385185743SsamprintEdge(FILE *fd, int edge) 386185743Ssam{ 387185743Ssam const RD_EDGES_POWER *pRdEdgePwrInfo = 388185743Ssam &eeprom.ee_rdEdgesPower[curctl*NUM_EDGES]; 389185743Ssam 390185743Ssam if (pRdEdgePwrInfo[edge].rdEdge == 0) 391185743Ssam fprintf(fd, " -- "); 392185743Ssam else 393185743Ssam fprintf(fd, "%04d", pRdEdgePwrInfo[edge].rdEdge); 394185743Ssam} 395185743Ssam 396185743Ssamstatic void 397185743SsamprintEdgePower(FILE *fd, int edge) 398185743Ssam{ 399185743Ssam const RD_EDGES_POWER *pRdEdgePwrInfo = 400185743Ssam &eeprom.ee_rdEdgesPower[curctl*NUM_EDGES]; 401185743Ssam 402185743Ssam if (pRdEdgePwrInfo[edge].rdEdge == 0) 403185743Ssam fprintf(fd, " -- "); 404185743Ssam else 405185743Ssam fprintf(fd, "%2d.%d", 406185743Ssam pRdEdgePwrInfo[edge].twice_rdEdgePower / 2, 407185743Ssam (pRdEdgePwrInfo[edge].twice_rdEdgePower % 2) * 5); 408185743Ssam} 409185743Ssam 410185743Ssamstatic void 411185743SsamprintEdgeFlag(FILE *fd, int edge) 412185743Ssam{ 413185743Ssam const RD_EDGES_POWER *pRdEdgePwrInfo = 414185743Ssam &eeprom.ee_rdEdgesPower[curctl*NUM_EDGES]; 415185743Ssam 416185743Ssam if (pRdEdgePwrInfo[edge].rdEdge == 0) 417185743Ssam fprintf(fd, "--"); 418185743Ssam else 419185743Ssam fprintf(fd, " %1d", pRdEdgePwrInfo[edge].flag); 420185743Ssam} 421185743Ssam 422185743Ssamstatic int16_t 423185743SsamgetMaxPowerV5(const RAW_DATA_PER_CHANNEL_2413 *data) 424185743Ssam{ 425185743Ssam uint32_t i; 426185743Ssam uint16_t numVpd; 427185743Ssam 428185743Ssam for (i = 0; i < MAX_NUM_PDGAINS_PER_CHANNEL; i++) { 429185743Ssam numVpd = data->pDataPerPDGain[i].numVpd; 430185743Ssam if (numVpd > 0) 431185743Ssam return data->pDataPerPDGain[i].pwr_t4[numVpd-1]; 432185743Ssam } 433185743Ssam return 0; 434185743Ssam} 435185743Ssam 436185743Ssamstatic void 437185743SsamprintQuarterDbmPower(FILE *fd, int16_t power25dBm) 438185743Ssam{ 439185743Ssam fprintf(fd, "%2d.%02d", power25dBm / 4, (power25dBm % 4) * 25); 440185743Ssam} 441185743Ssam 442185743Ssamstatic void 443185743SsamprintHalfDbmPower(FILE *fd, int16_t power5dBm) 444185743Ssam{ 445185743Ssam fprintf(fd, "%2d.%d", power5dBm / 2, (power5dBm % 2) * 5); 446185743Ssam} 447185743Ssam 448185743Ssamstatic void 449185743SsamprintVpd(FILE *fd, int vpd) 450185743Ssam{ 451185743Ssam fprintf(fd, "[%3d]", vpd); 452185743Ssam} 453185743Ssam 454185743Ssamstatic void 455185743SsamprintPcdacValue(FILE *fd, int v) 456185743Ssam{ 457185743Ssam fprintf(fd, "%2d.%02d", v / EEP_SCALE, v % EEP_SCALE); 458185743Ssam} 459185743Ssam 460185743Ssamstatic void 461185743Ssamundef(const char *what) 462185743Ssam{ 463185743Ssam warnx("%s undefined for version %d.%d format EEPROM", what, 464185743Ssam eeprom.ee_version >> 12, eeprom.ee_version & 0xfff); 465185743Ssam} 466185743Ssam 467185743Ssamstatic int 468185743Ssampdgain(int lpdgain) 469185743Ssam{ 470185743Ssam uint32_t mask; 471185743Ssam int i, l = lpdgain; 472185743Ssam 473185743Ssam if (IS_VERS(<, AR_EEPROM_VER5_0)) 474185743Ssam mask = pExpnPower->xpdMask; 475185743Ssam else 476185743Ssam mask = pRaw->xpd_mask; 477185743Ssam for (i = 0; mask != 0; mask >>= 1, i++) 478185743Ssam if ((mask & 1) && l-- == 0) 479185743Ssam return i; 480185743Ssam warnx("can't find logical pdgain %d", lpdgain); 481185743Ssam return -1; 482185743Ssam} 483185743Ssam 484185743Ssam#define COUNTRY_ERD_FLAG 0x8000 485185743Ssam#define WORLDWIDE_ROAMING_FLAG 0x4000 486185743Ssam 487185743Ssamvoid 488185743Ssameevar(FILE *fd, const char *var) 489185743Ssam{ 490185743Ssam#define streq(a,b) (strcasecmp(a,b) == 0) 491185743Ssam#define strneq(a,b,n) (strncasecmp(a,b,n) == 0) 492185743Ssam if (streq(var, "mode")) { 493185743Ssam fprintf(fd, "%s", 494185743Ssam curmode == headerInfo11A ? "11a" : 495185743Ssam curmode == headerInfo11B ? "11b" : 496185743Ssam curmode == headerInfo11G ? "11g" : "???"); 497185743Ssam } else if (streq(var, "version")) { 498185743Ssam fprintf(fd, "%04x", eeprom.ee_version); 499185743Ssam } else if (streq(var, "V_major")) { 500185743Ssam fprintf(fd, "%2d", eeprom.ee_version >> 12); 501185743Ssam } else if (streq(var, "V_minor")) { 502185743Ssam fprintf(fd, "%2d", eeprom.ee_version & 0xfff); 503185743Ssam } else if (streq(var, "earStart")) { 504185743Ssam fprintf(fd, "%03x", eeprom.ee_earStart); 505185743Ssam } else if (streq(var, "tpStart")) { 506185743Ssam fprintf(fd, "%03x", eeprom.ee_targetPowersStart); 507185743Ssam } else if (streq(var, "eepMap")) { 508185743Ssam fprintf(fd, "%3d", eeprom.ee_eepMap); 509185743Ssam } else if (streq(var, "exist32KHzCrystal")) { 510185743Ssam fprintf(fd, "%3d", eeprom.ee_exist32kHzCrystal); 511185743Ssam } else if (streq(var, "eepMap2PowerCalStart")) { 512185743Ssam fprintf(fd , "%3d", eeprom.ee_eepMap2PowerCalStart); 513185743Ssam } else if (streq(var, "Amode")) { 514185743Ssam fprintf(fd , "%1d", eeprom.ee_Amode); 515185743Ssam } else if (streq(var, "Bmode")) { 516185743Ssam fprintf(fd , "%1d", eeprom.ee_Bmode); 517185743Ssam } else if (streq(var, "Gmode")) { 518185743Ssam fprintf(fd , "%1d", eeprom.ee_Gmode); 519185743Ssam } else if (streq(var, "regdomain")) { 520185743Ssam if ((eeprom.ee_regdomain & COUNTRY_ERD_FLAG) == 0) 521185743Ssam fprintf(fd, "%03X ", eeprom.ee_regdomain >> 15); 522185743Ssam else 523185743Ssam fprintf(fd, "%-3dC", eeprom.ee_regdomain & 0xfff); 524185743Ssam } else if (streq(var, "turbo2Disable")) { 525185743Ssam fprintf(fd, "%1d", eeprom.ee_turbo2Disable); 526185743Ssam } else if (streq(var, "turbo5Disable")) { 527185743Ssam fprintf(fd, "%1d", eeprom.ee_turbo5Disable); 528185743Ssam } else if (streq(var, "rfKill")) { 529185743Ssam fprintf(fd, "%1d", eeprom.ee_rfKill); 530185743Ssam } else if (streq(var, "disableXr5")) { 531185743Ssam fprintf(fd, "%1d", eeprom.ee_disableXr5); 532185743Ssam } else if (streq(var, "disableXr2")) { 533185743Ssam fprintf(fd, "%1d", eeprom.ee_disableXr2); 534185743Ssam } else if (streq(var, "turbo2WMaxPower5")) { 535185743Ssam fprintf(fd, "%2d", eeprom.ee_turbo2WMaxPower5); 536185743Ssam } else if (streq(var, "cckOfdmDelta")) { 537185743Ssam fprintf(fd, "%2d", eeprom.ee_cckOfdmPwrDelta); 538185743Ssam } else if (streq(var, "gainI")) { 539185743Ssam fprintf(fd, "%2d", eeprom.ee_gainI[curmode]); 540185743Ssam } else if (streq(var, "WWR")) { 541185743Ssam fprintf(fd, "%1x", 542185743Ssam (eeprom.ee_regdomain & WORLDWIDE_ROAMING_FLAG) != 0); 543185743Ssam } else if (streq(var, "falseDetectBackoff")) { 544185743Ssam fprintf(fd, "0x%02x", eeprom.ee_falseDetectBackoff[curmode]); 545185743Ssam } else if (streq(var, "deviceType")) { 546185743Ssam fprintf(fd, "%1x", eeprom.ee_deviceType); 547185743Ssam } else if (streq(var, "switchSettling")) { 548185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 549185743Ssam fprintf(fd, "0x%02x", eeprom.ee_switchSettling[curmode]); 550185743Ssam else 551185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].switchSettling); 552185743Ssam } else if (streq(var, "adcDesiredSize")) { 553185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 554185743Ssam fprintf(fd, "%2d", eeprom.ee_adcDesiredSize[curmode]); 555185743Ssam else 556185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].adcDesiredSize); 557185743Ssam } else if (streq(var, "xlnaGain")) { 558185743Ssam fprintf(fd, "0x%02x", eeprom.ee_xlnaGain[curmode]); 559185743Ssam } else if (streq(var, "txEndToXLNAOn")) { 560185743Ssam fprintf(fd, "0x%02x", eeprom.ee_txEndToXLNAOn[curmode]); 561185743Ssam } else if (streq(var, "thresh62")) { 562185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 563185743Ssam fprintf(fd, "0x%02x", eeprom.ee_thresh62[curmode]); 564185743Ssam else 565185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].thresh62); 566185743Ssam } else if (streq(var, "txEndToRxOn")) { 567185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].txEndToRxOn); 568185743Ssam } else if (streq(var, "txEndToXPAOff")) { 569185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 570185743Ssam fprintf(fd, "0x%02x", eeprom.ee_txEndToXPAOff[curmode]); 571185743Ssam else 572185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].txEndToXpaOff); 573185743Ssam } else if (streq(var, "txFrameToXPAOn")) { 574185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 575185743Ssam fprintf(fd, "0x%02x", eeprom.ee_txFrameToXPAOn[curmode]); 576185743Ssam else 577185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].txEndToRxOn); 578185743Ssam } else if (streq(var, "pgaDesiredSize")) { 579185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 580185743Ssam fprintf(fd, "%2d", eeprom.ee_pgaDesiredSize[curmode]); 581185743Ssam else 582185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].pgaDesiredSize); 583185743Ssam } else if (streq(var, "noiseFloorThresh")) { 584185743Ssam fprintf(fd, "%3d", eeprom.ee_noiseFloorThresh[curmode]); 585185743Ssam } else if (strneq(var, "noiseFloorThreshCh", 18)) { 586185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].noiseFloorThreshCh[atoi(var+18)]); 587185743Ssam } else if (strneq(var, "xlnaGainCh", 10)) { 588185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].xlnaGainCh[atoi(var+10)]); 589185743Ssam } else if (streq(var, "xgain")) { 590185743Ssam fprintf(fd, "0x%02x", eeprom.ee_xgain[curmode]); 591185743Ssam } else if (streq(var, "xpd")) { 592185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) 593185743Ssam fprintf(fd, "%1d", eeprom.ee_xpd[curmode]); 594185743Ssam else 595185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].xpd); 596185743Ssam } else if (streq(var, "txrxAtten")) { 597185743Ssam fprintf(fd, "0x%02x", eeprom.ee_txrxAtten[curmode]); 598185743Ssam } else if (streq(var, "capField")) { 599185743Ssam fprintf(fd, "0x%04X", eeprom.ee_capField); 600185743Ssam } else if (streq(var, "txrxAttenTurbo")) { 601185743Ssam fprintf(fd, "0x%02x", 602185743Ssam eeprom.ee_txrxAtten[curmode != headerInfo11A]); 603185743Ssam } else if (streq(var, "switchSettlingTurbo")) { 604185743Ssam fprintf(fd, "0x%02X", 605185743Ssam eeprom.ee_switchSettlingTurbo[curmode != headerInfo11A]); 606185743Ssam } else if (streq(var, "adcDesiredSizeTurbo")) { 607185743Ssam fprintf(fd, "%2d", 608185743Ssam eeprom.ee_adcDesiredSizeTurbo[curmode != headerInfo11A]); 609185743Ssam } else if (streq(var, "pgaDesiredSizeTurbo")) { 610185743Ssam fprintf(fd, "%2d", 611185743Ssam eeprom.ee_pgaDesiredSizeTurbo[curmode != headerInfo11A]); 612185743Ssam } else if (streq(var, "rxtxMarginTurbo")) { 613185743Ssam fprintf(fd, "0x%02x", 614185743Ssam eeprom.ee_rxtxMarginTurbo[curmode != headerInfo11A]); 615185743Ssam } else if (strneq(var, "antennaControl", 14)) { 616185743Ssam printAntennaControl(fd, atoi(var+14)); 617185743Ssam } else if (strneq(var, "antCtrlChain", 12)) { 618185743Ssam fprintf(fd, "0x%08X", 619185743Ssam eepromN.modalHeader[curmode].antCtrlChain[atoi(var+12)]); 620185743Ssam } else if (strneq(var, "antGainCh", 9)) { 621185743Ssam fprintf(fd, "%3d", 622185743Ssam eepromN.modalHeader[curmode].antennaGainCh[atoi(var+9)]); 623185743Ssam } else if (strneq(var, "txRxAttenCh", 11)) { 624185743Ssam fprintf(fd, "%3d", 625185743Ssam eepromN.modalHeader[curmode].txRxAttenCh[atoi(var+11)]); 626185743Ssam } else if (strneq(var, "rxTxMarginCh", 12)) { 627185743Ssam fprintf(fd, "%3d", 628185743Ssam eepromN.modalHeader[curmode].rxTxMarginCh[atoi(var+12)]); 629185743Ssam } else if (streq(var, "xpdGain")) { 630185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].xpdGain); 631185743Ssam } else if (strneq(var, "iqCalICh", 8)) { 632185743Ssam fprintf(fd, "%3d", 633185743Ssam eepromN.modalHeader[curmode].iqCalICh[atoi(var+8)]); 634185743Ssam } else if (strneq(var, "iqCalQCh", 8)) { 635185743Ssam fprintf(fd, "%3d", 636185743Ssam eepromN.modalHeader[curmode].iqCalQCh[atoi(var+8)]); 637185743Ssam } else if (streq(var, "pdGainOverlap")) { 638185743Ssam printHalfDbmPower(fd, eepromN.modalHeader[curmode].pdGainOverlap); 639185743Ssam } else if (streq(var, "ob1")) { 640185743Ssam fprintf(fd, "%1d", eeprom.ee_ob1); 641185743Ssam } else if (streq(var, "ob2")) { 642185743Ssam fprintf(fd, "%1d", eeprom.ee_ob2); 643185743Ssam } else if (streq(var, "ob3")) { 644185743Ssam fprintf(fd, "%1d", eeprom.ee_ob3); 645185743Ssam } else if (streq(var, "ob4")) { 646185743Ssam fprintf(fd, "%1d", eeprom.ee_ob4); 647185743Ssam } else if (streq(var, "db1")) { 648185743Ssam fprintf(fd, "%1d", eeprom.ee_db1); 649185743Ssam } else if (streq(var, "db2")) { 650185743Ssam fprintf(fd, "%1d", eeprom.ee_db2); 651185743Ssam } else if (streq(var, "db3")) { 652185743Ssam fprintf(fd, "%1d", eeprom.ee_db3); 653185743Ssam } else if (streq(var, "db4")) { 654185743Ssam fprintf(fd, "%1d", eeprom.ee_db4); 655185743Ssam } else if (streq(var, "obFor24")) { 656185743Ssam fprintf(fd, "%1d", eeprom.ee_obFor24); 657185743Ssam } else if (streq(var, "ob2GHz0")) { 658185743Ssam fprintf(fd, "%1d", eeprom.ee_ob2GHz[0]); 659185743Ssam } else if (streq(var, "dbFor24")) { 660185743Ssam fprintf(fd, "%1d", eeprom.ee_dbFor24); 661185743Ssam } else if (streq(var, "db2GHz0")) { 662185743Ssam fprintf(fd, "%1d", eeprom.ee_db2GHz[0]); 663185743Ssam } else if (streq(var, "obFor24g")) { 664185743Ssam fprintf(fd, "%1d", eeprom.ee_obFor24g); 665185743Ssam } else if (streq(var, "ob2GHz1")) { 666185743Ssam fprintf(fd, "%1d", eeprom.ee_ob2GHz[1]); 667185743Ssam } else if (streq(var, "dbFor24g")) { 668185743Ssam fprintf(fd, "%1d", eeprom.ee_dbFor24g); 669185743Ssam } else if (streq(var, "db2GHz1")) { 670185743Ssam fprintf(fd, "%1d", eeprom.ee_db2GHz[1]); 671185743Ssam } else if (streq(var, "ob")) { 672185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].ob); 673185743Ssam } else if (streq(var, "db")) { 674185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].db); 675185743Ssam } else if (streq(var, "xpaBiasLvl")) { 676185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].xpaBiasLvl); 677185743Ssam } else if (streq(var, "pwrDecreaseFor2Chain")) { 678185743Ssam printHalfDbmPower(fd, eepromN.modalHeader[curmode].pwrDecreaseFor2Chain); 679185743Ssam } else if (streq(var, "pwrDecreaseFor3Chain")) { 680185743Ssam printHalfDbmPower(fd, eepromN.modalHeader[curmode].pwrDecreaseFor3Chain); 681185743Ssam } else if (streq(var, "txFrameToDataStart")) { 682185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].txFrameToDataStart); 683185743Ssam } else if (streq(var, "txFrameToPaOn")) { 684185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].txFrameToPaOn); 685185743Ssam } else if (streq(var, "ht40PowerIncForPdadc")) { 686185743Ssam fprintf(fd, "%3d", eepromN.modalHeader[curmode].ht40PowerIncForPdadc); 687185743Ssam } else if (streq(var, "checksum")) { 688185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.checksum); 689185743Ssam } else if (streq(var, "length")) { 690185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.length); 691185743Ssam } else if (streq(var, "regDmn0")) { 692185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.regDmn[0]); 693185743Ssam } else if (streq(var, "regDmn1")) { 694185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.regDmn[1]); 695185743Ssam } else if (streq(var, "txMask")) { 696185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.txMask); 697185743Ssam } else if (streq(var, "rxMask")) { 698185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.rxMask); 699185743Ssam } else if (streq(var, "rfSilent")) { 700185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.rfSilent); 701185743Ssam } else if (streq(var, "btOptions")) { 702185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.blueToothOptions); 703185743Ssam } else if (streq(var, "deviceCap")) { 704185743Ssam fprintf(fd, "0x%04X", eepromN.baseEepHeader.deviceCap); 705185743Ssam } else if (strneq(var, "macaddr", 7)) { 706185743Ssam fprintf(fd, "%02X", 707185743Ssam eepromN.baseEepHeader.macAddr[atoi(var+7)]); 708185743Ssam } else if (streq(var, "opCapFlags")) { 709185743Ssam fprintf(fd, "0x%02X", eepromN.baseEepHeader.opCapFlags); 710185743Ssam } else if (streq(var, "eepMisc")) { 711185743Ssam fprintf(fd, "0x%02X", eepromN.baseEepHeader.eepMisc); 712185743Ssam } else if (strneq(var, "binBuildNumber", 14)) { 713185743Ssam fprintf(fd, "%3d", 714185743Ssam (eepromN.baseEepHeader.binBuildNumber >> (8*atoi(var+14))) 715185743Ssam & 0xff); 716185743Ssam } else if (strneq(var, "custData", 8)) { 717185743Ssam fprintf(fd, "%2.2X", eepromN.custData[atoi(var+8)]); 718185743Ssam } else if (streq(var, "xpd_mask")) { 719185743Ssam if (IS_VERS(<, AR_EEPROM_VER5_0)) 720185743Ssam fprintf(fd, "0x%02x", pExpnPower->xpdMask); 721185743Ssam else 722185743Ssam fprintf(fd, "0x%02x", pRaw->xpd_mask); 723185743Ssam } else if (streq(var, "numChannels")) { 724185743Ssam if (IS_VERS(<, AR_EEPROM_VER5_0)) 725185743Ssam fprintf(fd, "%2d", pExpnPower->numChannels); 726185743Ssam else 727185743Ssam fprintf(fd, "%2d", pRaw->numChannels); 728185743Ssam } else if (streq(var, "freq")) { 729185743Ssam if (IS_VERS(<, AR_EEPROM_VER5_0)) 730185743Ssam fprintf(fd, "%4d", pExpnPower->pChannels[curchan]); 731185743Ssam else 732185743Ssam fprintf(fd, "%4d", pRaw->pChannels[curchan]); 733185743Ssam } else if (streq(var, "maxpow")) { 734185743Ssam int16_t maxPower_t4; 735185743Ssam if (IS_VERS(<, AR_EEPROM_VER5_0)) { 736185743Ssam maxPower_t4 = pExpnPower->pDataPerChannel[curchan].maxPower_t4; 737185743Ssam } else { 738185743Ssam maxPower_t4 = pRaw->pDataPerChannel[curchan].maxPower_t4; 739185743Ssam if (maxPower_t4 == 0) 740185743Ssam maxPower_t4 = getMaxPowerV5(&pRaw->pDataPerChannel[curchan]); 741185743Ssam } 742185743Ssam printQuarterDbmPower(fd, maxPower_t4); 743185743Ssam } else if (streq(var, "pd_gain")) { 744185743Ssam fprintf(fd, "%4d", pRaw->pDataPerChannel[curchan]. 745185743Ssam pDataPerPDGain[curpdgain].pd_gain); 746185743Ssam } else if (strneq(var, "maxpwr", 6)) { 747185743Ssam int vpd = atoi(var+6); 748185743Ssam if (vpd < pRaw->pDataPerChannel[curchan].pDataPerPDGain[curpdgain].numVpd) 749185743Ssam printQuarterDbmPower(fd, pRaw->pDataPerChannel[curchan]. 750185743Ssam pDataPerPDGain[curpdgain].pwr_t4[vpd]); 751185743Ssam else 752185743Ssam fprintf(fd, " "); 753185743Ssam } else if (strneq(var, "pwr_t4_", 7)) { 754185743Ssam printQuarterDbmPower(fd, pExpnPower->pDataPerChannel[curchan]. 755185743Ssam pDataPerXPD[singleXpd].pwr_t4[atoi(var+7)]); 756185743Ssam } else if (strneq(var, "Vpd", 3)) { 757185743Ssam int vpd = atoi(var+3); 758185743Ssam if (vpd < pRaw->pDataPerChannel[curchan].pDataPerPDGain[curpdgain].numVpd) 759185743Ssam printVpd(fd, pRaw->pDataPerChannel[curchan]. 760185743Ssam pDataPerPDGain[curpdgain].Vpd[vpd]); 761185743Ssam else 762185743Ssam fprintf(fd, " "); 763185743Ssam } else if (streq(var, "CTL")) { 764185743Ssam fprintf(fd, "0x%2x", eeprom.ee_ctl[curctl] & 0xff); 765185743Ssam } else if (streq(var, "ctlType")) { 766185743Ssam static const char *ctlType[16] = { 767185743Ssam "11a base", "11b", "11g", "11a TURBO", "108g", 768185743Ssam "2GHT20", "5GHT20", "2GHT40", "5GHT40", 769185743Ssam "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf", 770185743Ssam }; 771185743Ssam fprintf(fd, "%8s", ctlType[eeprom.ee_ctl[curctl] & CTL_MODE_M]); 772185743Ssam } else if (streq(var, "ctlRD")) { 773185743Ssam static const char *ctlRD[8] = { 774185743Ssam "0x00", " FCC", "0x20", "ETSI", 775185743Ssam " MKK", "0x50", "0x60", "0x70" 776185743Ssam }; 777185743Ssam fprintf(fd, "%s", ctlRD[(eeprom.ee_ctl[curctl] >> 4) & 7]); 778185743Ssam } else if (strneq(var, "rdEdgePower", 11)) { 779185743Ssam printEdgePower(fd, atoi(var+11)); 780185743Ssam } else if (strneq(var, "rdEdgeFlag", 10)) { 781185743Ssam printEdgeFlag(fd, atoi(var+10)); 782185743Ssam } else if (strneq(var, "rdEdge", 6)) { 783185743Ssam printEdge(fd, atoi(var+6)); 784185743Ssam } else if (strneq(var, "testChannel", 11)) { 785185743Ssam fprintf(fd, "%4d", pPowerInfo[atoi(var+11)].testChannel); 786185743Ssam } else if (strneq(var, "pwr6_24_", 8)) { 787185743Ssam printHalfDbmPower(fd, pPowerInfo[atoi(var+8)].twicePwr6_24); 788185743Ssam } else if (strneq(var, "pwr36_", 6)) { 789185743Ssam printHalfDbmPower(fd, pPowerInfo[atoi(var+6)].twicePwr36); 790185743Ssam } else if (strneq(var, "pwr48_", 6)) { 791185743Ssam printHalfDbmPower(fd, pPowerInfo[atoi(var+6)].twicePwr48); 792185743Ssam } else if (strneq(var, "pwr54_", 6)) { 793185743Ssam printHalfDbmPower(fd, pPowerInfo[atoi(var+6)].twicePwr54); 794185743Ssam } else if (strneq(var, "channelValue", 12)) { 795185743Ssam fprintf(fd, "%4d", pDataPerChannel[atoi(var+12)].channelValue); 796185743Ssam } else if (strneq(var, "pcdacMin", 8)) { 797185743Ssam fprintf(fd, "%02d", pDataPerChannel[atoi(var+8)].pcdacMin); 798185743Ssam } else if (strneq(var, "pcdacMax", 8)) { 799185743Ssam fprintf(fd, "%02d", pDataPerChannel[atoi(var+8)].pcdacMax); 800185743Ssam } else if (strneq(var, "pcdac", 5)) { 801185743Ssam if (IS_VERS(<, AR_EEPROM_VER4_0)) { 802185743Ssam fprintf(fd, "%02d", pDataPerChannel[atoi(var+5)]. 803185743Ssam PcdacValues[curpcdac]); 804185743Ssam } else if (IS_VERS(<, AR_EEPROM_VER5_0)) { 805185743Ssam fprintf(fd, "%02d", 806185743Ssam pExpnPower->pDataPerChannel[curchan]. 807185743Ssam pDataPerXPD[singleXpd].pcdac[atoi(var+5)]); 808185743Ssam } else 809185743Ssam undef("pcdac"); 810185743Ssam } else if (strneq(var, "pwrValue", 8)) { 811185743Ssam printPcdacValue(fd, 812185743Ssam pDataPerChannel[atoi(var+8)].PwrValues[curpcdac]); 813185743Ssam } else if (streq(var, "singleXpd")) { 814185743Ssam fprintf(fd, "%2d", singleXpd); 815185743Ssam } else 816185743Ssam warnx("line %u, unknown EEPROM variable \"%s\"", lineno, var); 817185743Ssam#undef strneq 818185743Ssam#undef streq 819185743Ssam} 820185743Ssam 821185743Ssamstatic void 822185743Ssamifmode(FILE *ftemplate, const char *mode) 823185743Ssam{ 824185743Ssam if (strcasecmp(mode, "11a") == 0) { 825185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) { 826185743Ssam if (eeprom.ee_Amode) 827185743Ssam setmode(headerInfo11A); 828185743Ssam else 829185743Ssam skipto(ftemplate, "endmode"); 830185743Ssam return; 831185743Ssam } 832185743Ssam if (IS_VERS(>=, AR_EEPROM_VER14_2)) { 833185743Ssam if (eepromN.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) 834185743Ssam setmode(headerInfo11A); 835185743Ssam else 836185743Ssam skipto(ftemplate, "endmode"); 837185743Ssam return; 838185743Ssam } 839185743Ssam } else if (strcasecmp(mode, "11g") == 0) { 840185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) { 841185743Ssam if (eeprom.ee_Gmode) 842185743Ssam setmode(headerInfo11G); 843185743Ssam else 844185743Ssam skipto(ftemplate, "endmode"); 845185743Ssam return; 846185743Ssam } 847185743Ssam if (IS_VERS(>=, AR_EEPROM_VER14_2)) { 848185743Ssam if (eepromN.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) 849185743Ssam setmode(headerInfo11B); /* NB: 2.4GHz */ 850185743Ssam else 851185743Ssam skipto(ftemplate, "endmode"); 852185743Ssam return; 853185743Ssam } 854185743Ssam } else if (strcasecmp(mode, "11b") == 0) { 855185743Ssam if (IS_VERS(<, AR_EEPROM_VER14_2)) { 856185743Ssam if (eeprom.ee_Bmode) 857185743Ssam setmode(headerInfo11B); 858185743Ssam else 859185743Ssam skipto(ftemplate, "endmode"); 860185743Ssam return; 861185743Ssam } 862185743Ssam } 863185743Ssam warnx("line %d, unknown/unexpected mode \"%s\" ignored", 864185743Ssam lineno, mode); 865185743Ssam skipto(ftemplate, "endmode"); 866185743Ssam} 867185743Ssam 868185743Ssamstatic void 869185743SsamparseTemplate(FILE *ftemplate, FILE *fd) 870185743Ssam{ 871185743Ssam int c, i; 872185743Ssam char id[MAXID]; 873185743Ssam long forchan, forpdgain, forctl, forpcdac; 874185743Ssam 875185743Ssam lineno = 1; 876185743Ssam bol = 1; 877185743Ssam while ((c = getc(ftemplate)) != EOF) { 878185743Ssam if (c == '#') { /* comment */ 879185743Ssam skiptoeol: 880185743Ssam while ((c = getc(ftemplate)) != EOF && c != '\n') 881185743Ssam ; 882185743Ssam if (c == EOF) 883185743Ssam return; 884185743Ssam lineno++; 885185743Ssam bol = 1; 886185743Ssam continue; 887185743Ssam } 888185743Ssam if (c == '.' && bol) { /* .directive */ 889185743Ssam if (token(ftemplate, id, MAXID, ".directive") == EOF) 890185743Ssam return; 891185743Ssam /* process directive */ 892185743Ssam if (strcasecmp(id, "ifmode") == 0) { 893185743Ssam skipws(ftemplate); 894185743Ssam if (token(ftemplate, id, MAXID, "id") == EOF) 895185743Ssam return; 896185743Ssam ifmode(ftemplate, id); 897185743Ssam } else if (strcasecmp(id, "endmode") == 0) { 898185743Ssam /* XXX free malloc'd indirect data */ 899185743Ssam curmode = -1; /* NB: undefined */ 900185743Ssam } else if (strcasecmp(id, "forchan") == 0) { 901185743Ssam forchan = ftell(ftemplate) - sizeof("forchan"); 902185743Ssam if (curchan == -1) 903185743Ssam curchan = 0; 904185743Ssam } else if (strcasecmp(id, "endforchan") == 0) { 905185743Ssam if (++curchan < numChannels) 906185743Ssam fseek(ftemplate, forchan, SEEK_SET); 907185743Ssam else 908185743Ssam curchan = -1; 909185743Ssam } else if (strcasecmp(id, "ifpdgain") == 0) { 910185743Ssam skipws(ftemplate); 911185743Ssam if (token(ftemplate, id, MAXID, "pdgain") == EOF) 912185743Ssam return; 913185743Ssam curlpdgain = strtoul(id, NULL, 0); 914185743Ssam if (curlpdgain >= pRaw->pDataPerChannel[curchan].numPdGains) { 915185743Ssam skipto(ftemplate, "endpdgain"); 916185743Ssam curlpdgain = -1; 917185743Ssam } else 918185743Ssam curpdgain = pdgain(curlpdgain); 919185743Ssam } else if (strcasecmp(id, "endpdgain") == 0) { 920185743Ssam curlpdgain = curpdgain = -1; 921185743Ssam } else if (strcasecmp(id, "forpdgain") == 0) { 922185743Ssam forpdgain = ftell(ftemplate) - sizeof("forpdgain"); 923185743Ssam if (curlpdgain == -1) { 924185743Ssam skipws(ftemplate); 925185743Ssam if (token(ftemplate, id, MAXID, "pdgain") == EOF) 926185743Ssam return; 927185743Ssam curlpdgain = strtoul(id, NULL, 0); 928185743Ssam if (curlpdgain >= pRaw->pDataPerChannel[curchan].numPdGains) { 929185743Ssam skipto(ftemplate, "endforpdgain"); 930185743Ssam curlpdgain = -1; 931185743Ssam } else 932185743Ssam curpdgain = pdgain(curlpdgain); 933185743Ssam } 934185743Ssam } else if (strcasecmp(id, "endforpdgain") == 0) { 935185743Ssam if (++curpdgain < pRaw->pDataPerChannel[curchan].numPdGains) 936185743Ssam fseek(ftemplate, forpdgain, SEEK_SET); 937185743Ssam else 938185743Ssam curpdgain = -1; 939185743Ssam } else if (strcasecmp(id, "forpcdac") == 0) { 940185743Ssam forpcdac = ftell(ftemplate) - sizeof("forpcdac"); 941185743Ssam if (curpcdac == -1) 942185743Ssam curpcdac = 0; 943185743Ssam } else if (strcasecmp(id, "endforpcdac") == 0) { 944185743Ssam if (++curpcdac < pDataPerChannel[0].numPcdacValues) 945185743Ssam fseek(ftemplate, forpcdac, SEEK_SET); 946185743Ssam else 947185743Ssam curpcdac = -1; 948185743Ssam } else if (strcasecmp(id, "forctl") == 0) { 949185743Ssam forctl = ftell(ftemplate) - sizeof("forchan"); 950185743Ssam if (curctl == -1) 951185743Ssam curctl = nextctl(0); 952185743Ssam } else if (strcasecmp(id, "endforctl") == 0) { 953185743Ssam curctl = nextctl(curctl+1); 954185743Ssam if (curctl != -1) 955185743Ssam fseek(ftemplate, forctl, SEEK_SET); 956185743Ssam } else { 957185743Ssam warnx("line %d, unknown directive %s ignored", 958185743Ssam lineno, id); 959185743Ssam } 960185743Ssam goto skiptoeol; 961185743Ssam } 962185743Ssam if (c == '$') { /* $variable reference */ 963185743Ssam if (token(ftemplate, id, MAXID, "$var") == EOF) 964185743Ssam return; 965185743Ssam /* XXX not valid if variable depends on curmode */ 966185743Ssam eevar(fd, id); 967185743Ssam continue; 968185743Ssam } 969185743Ssam if (c == '\\') { /* escape next character */ 970185743Ssam c = getc(ftemplate); 971185743Ssam if (c == EOF) 972185743Ssam return; 973185743Ssam } 974185743Ssam fputc(c, fd); 975185743Ssam bol = (c == '\n'); 976185743Ssam if (bol) 977185743Ssam lineno++; 978185743Ssam } 979185743Ssam} 980