main.c revision 217680
1254721Semaste/*- 2254721Semaste * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3353358Sdim * All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6254721Semaste * modification, are permitted provided that the following conditions 7254721Semaste * are met: 8254721Semaste * 1. Redistributions of source code must retain the above copyright 9254721Semaste * notice, this list of conditions and the following disclaimer, 10254721Semaste * without modification. 11344779Sdim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12296417Sdim * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13254721Semaste * redistribution must be conditioned upon including a substantially 14254721Semaste * similar Disclaimer requirement for further binary redistribution. 15344779Sdim * 16344779Sdim * NO WARRANTY 17344779Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18344779Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19254721Semaste * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20344779Sdim * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21344779Sdim * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22344779Sdim * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23321369Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24344779Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25344779Sdim * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26321369Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27254721Semaste * THE POSSIBILITY OF SUCH DAMAGES. 28254721Semaste * 29314564Sdim * $FreeBSD: head/tools/tools/ath/athdecode/main.c 217680 2011-01-21 02:53:32Z adrian $ 30314564Sdim */ 31353358Sdim#include "diag.h" 32314564Sdim 33314564Sdim#include "ah.h" 34314564Sdim#include "ah_internal.h" 35314564Sdim#include "ah_decode.h" 36314564Sdim 37314564Sdim#include "dumpregs.h" 38314564Sdim 39314564Sdim#include <stdlib.h> 40314564Sdim#include <string.h> 41314564Sdim#include <err.h> 42314564Sdim#include <sys/file.h> 43314564Sdim#include <sys/stat.h> 44254721Semaste#include <sys/mman.h> 45254721Semaste 46314564Sdimtypedef struct { 47254721Semaste HAL_REVS revs; 48314564Sdim int chipnum; 49314564Sdim#define MAXREGS 5*1024 50254721Semaste struct dumpreg *regs[MAXREGS]; 51254721Semaste u_int nregs; 52314564Sdim} dumpregs_t; 53344779Sdimstatic dumpregs_t state; 54344779Sdim 55314564Sdimstatic void opdevice(const struct athregrec *r); 56254721Semastestatic const char* opmark(FILE *, int, const struct athregrec *); 57254721Semastestatic void oprw(FILE *fd, int recnum, struct athregrec *r); 58314564Sdim 59314564Sdimint 60314564Sdimmain(int argc, char *argv[]) 61314564Sdim{ 62314564Sdim int fd, i, nrecs, same; 63314564Sdim struct stat sb; 64314564Sdim void *addr; 65314564Sdim const char *filename = "/tmp/ath_hal.log"; 66314564Sdim struct athregrec *rprev; 67276479Sdim 68314564Sdim if (argc > 1) 69276479Sdim filename = argv[1]; 70276479Sdim fd = open(filename, O_RDONLY); 71314564Sdim if (fd < 0) 72314564Sdim err(1, filename); 73314564Sdim if (fstat(fd, &sb) < 0) 74314564Sdim err(1, "fstat"); 75314564Sdim addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0); 76314564Sdim if (addr == MAP_FAILED) 77254721Semaste err(1, "mmap"); 78254721Semaste nrecs = sb.st_size / sizeof (struct athregrec); 79314564Sdim printf("%u records", nrecs); 80314564Sdim rprev = NULL; 81314564Sdim same = 0; 82314564Sdim state.chipnum = 5210; 83254721Semaste for (i = 0; i < nrecs; i++) { 84254721Semaste struct athregrec *r = &((struct athregrec *) addr)[i]; 85314564Sdim if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) { 86314564Sdim same++; 87314564Sdim continue; 88314564Sdim } 89276479Sdim if (same) 90276479Sdim printf("\t\t+%u time%s", same, same == 1 ? "" : "s"); 91314564Sdim switch (r->op) { 92314564Sdim case OP_DEVICE: 93314564Sdim opdevice(r); 94314564Sdim break; 95314564Sdim case OP_READ: 96314564Sdim case OP_WRITE: 97314564Sdim oprw(stdout, i, r); 98314564Sdim break; 99296417Sdim case OP_MARK: 100314564Sdim opmark(stdout, i, r); 101314564Sdim break; 102314564Sdim } 103314564Sdim rprev = r; 104314564Sdim same = 0; 105314564Sdim } 106314564Sdim putchar('\n'); 107314564Sdim return 0; 108288943Sdim} 109288943Sdim 110314564Sdimstatic const char* 111314564Sdimopmark(FILE *fd, int i, const struct athregrec *r) 112314564Sdim{ 113314564Sdim fprintf(fd, "\n%05d: ", i); 114314564Sdim switch (r->reg) { 115314564Sdim case AH_MARK_RESET: 116314564Sdim fprintf(fd, "ar%uReset %s", state.chipnum, 117254721Semaste r->val ? "change channel" : "no channel change"); 118314564Sdim break; 119314564Sdim case AH_MARK_RESET_LINE: 120314564Sdim fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val); 121314564Sdim break; 122314564Sdim case AH_MARK_RESET_DONE: 123314564Sdim if (r->val) 124314564Sdim fprintf(fd, "ar%uReset (done), FAIL, error %u", 125314564Sdim state.chipnum, r->val); 126344779Sdim else 127314564Sdim fprintf(fd, "ar%uReset (done), OK", state.chipnum); 128314564Sdim break; 129314564Sdim case AH_MARK_CHIPRESET: 130314564Sdim fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val); 131314564Sdim break; 132314564Sdim case AH_MARK_PERCAL: 133314564Sdim fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val); 134314564Sdim break; 135314564Sdim case AH_MARK_SETCHANNEL: 136314564Sdim fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val); 137314564Sdim break; 138314564Sdim case AH_MARK_ANI_RESET: 139314564Sdim switch (r->val) { 140314564Sdim case HAL_M_STA: 141314564Sdim fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum); 142314564Sdim break; 143314564Sdim case HAL_M_IBSS: 144344779Sdim fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum); 145314564Sdim break; 146254721Semaste case HAL_M_HOSTAP: 147314564Sdim fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum); 148314564Sdim break; 149314564Sdim case HAL_M_MONITOR: 150314564Sdim fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum); 151314564Sdim break; 152314564Sdim default: 153314564Sdim fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val); 154314564Sdim break; 155314564Sdim } 156314564Sdim break; 157314564Sdim case AH_MARK_ANI_POLL: 158314564Sdim fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val); 159314564Sdim break; 160314564Sdim case AH_MARK_ANI_CONTROL: 161314564Sdim switch (r->val) { 162254721Semaste case HAL_ANI_PRESENT: 163314564Sdim fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum); 164314564Sdim break; 165314564Sdim case HAL_ANI_NOISE_IMMUNITY_LEVEL: 166314564Sdim fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum); 167314564Sdim break; 168314564Sdim case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: 169314564Sdim fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum); 170314564Sdim break; 171314564Sdim case HAL_ANI_CCK_WEAK_SIGNAL_THR: 172314564Sdim fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum); 173314564Sdim break; 174314564Sdim case HAL_ANI_FIRSTEP_LEVEL: 175341825Sdim fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum); 176341825Sdim break; 177314564Sdim case HAL_ANI_SPUR_IMMUNITY_LEVEL: 178360784Sdim fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum); 179360784Sdim break; 180360784Sdim case HAL_ANI_MODE: 181360784Sdim fprintf(fd, "ar%uAniControl, MODE", state.chipnum); 182360784Sdim break; 183360784Sdim case HAL_ANI_PHYERR_RESET: 184360784Sdim fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum); 185360784Sdim break; 186360784Sdim default: 187360784Sdim fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val); 188360784Sdim break; 189360784Sdim } 190360784Sdim break; 191360784Sdim default: 192360784Sdim fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val); 193360784Sdim break; 194360784Sdim } 195360784Sdim} 196360784Sdim 197360784Sdim#include "ah_devid.h" 198360784Sdim 199360784Sdimstatic void 200360784Sdimopdevice(const struct athregrec *r) 201360784Sdim{ 202314564Sdim switch (r->val) { 203314564Sdim case AR5210_PROD: 204314564Sdim case AR5210_DEFAULT: 205314564Sdim state.chipnum = 5210; 206314564Sdim state.revs.ah_macVersion = 1; 207314564Sdim state.revs.ah_macRev = 0; 208314564Sdim break; 209314564Sdim case AR5211_DEVID: 210314564Sdim case AR5311_DEVID: 211314564Sdim case AR5211_DEFAULT: 212314564Sdim case AR5211_FPGA11B: 213314564Sdim state.chipnum = 5211; 214314564Sdim state.revs.ah_macVersion = 2; 215314564Sdim state.revs.ah_macRev = 0; 216314564Sdim break; 217314564Sdim /* AR5212 */ 218314564Sdim case AR5212_DEFAULT: 219314564Sdim case AR5212_DEVID: 220254721Semaste case AR5212_FPGA: 221314564Sdim case AR5212_DEVID_IBM: 222314564Sdim case AR5212_AR5312_REV2: 223314564Sdim case AR5212_AR5312_REV7: 224314564Sdim case AR5212_AR2313_REV8: 225314564Sdim case AR5212_AR2315_REV6: 226314564Sdim case AR5212_AR2315_REV7: 227314564Sdim case AR5212_AR2317_REV1: 228344779Sdim case AR5212_AR2317_REV2: 229344779Sdim 230360784Sdim /* AR5212 compatible devid's also attach to 5212 */ 231314564Sdim case AR5212_DEVID_0014: 232314564Sdim case AR5212_DEVID_0015: 233314564Sdim case AR5212_DEVID_0016: 234314564Sdim case AR5212_DEVID_0017: 235314564Sdim case AR5212_DEVID_0018: 236314564Sdim case AR5212_DEVID_0019: 237314564Sdim case AR5212_AR2413: 238314564Sdim case AR5212_AR5413: 239254721Semaste case AR5212_AR5424: 240314564Sdim case AR5212_AR2417: 241314564Sdim case AR5212_DEVID_FF19: 242314564Sdim state.chipnum = 5212; 243314564Sdim state.revs.ah_macVersion = 4; 244314564Sdim state.revs.ah_macRev = 5; 245254721Semaste break; 246254721Semaste 247314564Sdim /* AR5213 */ 248314564Sdim case AR5213_SREV_1_0: 249314564Sdim case AR5213_SREV_REG: 250314564Sdim state.chipnum = 5213; 251314564Sdim state.revs.ah_macVersion = 5; 252254721Semaste state.revs.ah_macRev = 9; 253 break; 254 255 /* AR5416 compatible devid's */ 256 case AR5416_DEVID_PCI: 257 case AR5416_DEVID_PCIE: 258 case AR9160_DEVID_PCI: 259 case AR9280_DEVID_PCI: 260 case AR9280_DEVID_PCIE: 261 case AR9285_DEVID_PCIE: 262 state.chipnum = 5416; 263 state.revs.ah_macVersion = 13; 264 state.revs.ah_macRev = 8; 265 break; 266 default: 267 printf("Unknown device id 0x%x\n", r->val); 268 exit(-1); 269 } 270} 271 272static int 273regcompar(const void *a, const void *b) 274{ 275 const struct dumpreg *ra = *(const struct dumpreg **)a; 276 const struct dumpreg *rb = *(const struct dumpreg **)b; 277 return ra->addr - rb->addr; 278} 279 280void 281register_regs(struct dumpreg *chipregs, u_int nchipregs, 282 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 283{ 284 const int existing_regs = state.nregs; 285 int i, j; 286 287 for (i = 0; i < nchipregs; i++) { 288 struct dumpreg *nr = &chipregs[i]; 289 if (nr->srevMin == 0) 290 nr->srevMin = def_srev_min; 291 if (nr->srevMax == 0) 292 nr->srevMax = def_srev_max; 293 if (nr->phyMin == 0) 294 nr->phyMin = def_phy_min; 295 if (nr->phyMax == 0) 296 nr->phyMax = def_phy_max; 297 for (j = 0; j < existing_regs; j++) { 298 struct dumpreg *r = state.regs[j]; 299 /* 300 * Check if we can just expand the mac+phy 301 * coverage for the existing entry. 302 */ 303 if (nr->addr == r->addr && 304 (nr->name == r->name || 305 nr->name != NULL && r->name != NULL && 306 strcmp(nr->name, r->name) == 0)) { 307 if (nr->srevMin < r->srevMin && 308 (r->srevMin <= nr->srevMax && 309 nr->srevMax+1 <= r->srevMax)) { 310 r->srevMin = nr->srevMin; 311 goto skip; 312 } 313 if (nr->srevMax > r->srevMax && 314 (r->srevMin <= nr->srevMin && 315 nr->srevMin <= r->srevMax)) { 316 r->srevMax = nr->srevMax; 317 goto skip; 318 } 319 } 320 if (r->addr > nr->addr) 321 break; 322 } 323 /* 324 * New item, add to the end, it'll be sorted below. 325 */ 326 if (state.nregs == MAXREGS) 327 errx(-1, "too many registers; bump MAXREGS"); 328 state.regs[state.nregs++] = nr; 329 skip: 330 ; 331 } 332 qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar); 333} 334 335void 336register_keycache(u_int nslots, 337 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 338{ 339 /* discard, no use */ 340} 341 342void 343register_range(u_int brange, u_int erange, int type, 344 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 345{ 346 /* discard, no use */ 347} 348 349static const struct dumpreg * 350findreg(int reg) 351{ 352 const HAL_REVS *revs = &state.revs; 353 int i; 354 355 for (i = 0; i < state.nregs; i++) { 356 const struct dumpreg *dr = state.regs[i]; 357 if (dr->addr == reg && 358 MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev)) 359 return dr; 360 } 361 return NULL; 362} 363 364/* XXX cheat, 5212 has a superset of the key table defs */ 365#include "ar5212/ar5212reg.h" 366#include "ar5212/ar5212phy.h" 367 368#define PWR_TABLE_SIZE 64 369 370static void 371oprw(FILE *fd, int recnum, struct athregrec *r) 372{ 373 const struct dumpreg *dr; 374 char buf[64]; 375 const char* bits; 376 int i; 377 378 fprintf(fd, "\n%05d: ", recnum); 379 dr = findreg(r->reg); 380 if (dr != NULL && dr->name != NULL) { 381 snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg); 382 bits = dr->bits; 383 } else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) { 384 snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)", 385 ((r->reg - AR_KEYTABLE_0) >> 2) & 7, 386 (r->reg - AR_KEYTABLE_0) >> 5, r->reg); 387 bits = NULL; 388#if 0 389 } else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) { 390 snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)", 391 (r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg); 392 bits = NULL; 393#endif 394 } else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) { 395 snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)", 396 (r->reg - AR_RATE_DURATION_0) >> 2, r->reg); 397 bits = NULL; 398 } else if (AR_PHY_BASE <= r->reg) { 399 snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)", 400 (r->reg - AR_PHY_BASE) >> 2, r->reg); 401 bits = NULL; 402 } else { 403 snprintf(buf, sizeof (buf), "0x%x", r->reg); 404 bits = NULL; 405 } 406 fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val); 407 if (bits) { 408 const char *p = bits; 409 int tmp, n; 410 411 for (tmp = 0, p++; *p;) { 412 n = *p++; 413 if (r->val & (1 << (n - 1))) { 414 putc(tmp ? ',' : '<', fd); 415 for (; (n = *p) > ' '; ++p) 416 putc(n, fd); 417 tmp = 1; 418 } else 419 for (; *p > ' '; ++p) 420 continue; 421 } 422 if (tmp) 423 putc('>', fd); 424 } 425} 426