1189702Ssam/*- 2189702Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3189702Ssam * All rights reserved. 4189702Ssam * 5189702Ssam * Redistribution and use in source and binary forms, with or without 6189702Ssam * modification, are permitted provided that the following conditions 7189702Ssam * are met: 8189702Ssam * 1. Redistributions of source code must retain the above copyright 9189702Ssam * notice, this list of conditions and the following disclaimer, 10189702Ssam * without modification. 11189702Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12189702Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13189702Ssam * redistribution must be conditioned upon including a substantially 14189702Ssam * similar Disclaimer requirement for further binary redistribution. 15189702Ssam * 16189702Ssam * NO WARRANTY 17189702Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18189702Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19189702Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20189702Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21189702Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22189702Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23189702Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24189702Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25189702Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26189702Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27189702Ssam * THE POSSIBILITY OF SUCH DAMAGES. 28189702Ssam * 29189702Ssam * $FreeBSD$ 30189702Ssam */ 31189702Ssam#include "diag.h" 32189702Ssam 33189702Ssam#include "ah.h" 34189702Ssam#include "ah_internal.h" 35189702Ssam#include "ah_decode.h" 36189702Ssam 37189702Ssam#include "dumpregs.h" 38189702Ssam 39189702Ssam#include <stdlib.h> 40217680Sadrian#include <string.h> 41217680Sadrian#include <err.h> 42189702Ssam#include <sys/file.h> 43189702Ssam#include <sys/stat.h> 44189702Ssam#include <sys/mman.h> 45189702Ssam 46189702Ssamtypedef struct { 47189702Ssam HAL_REVS revs; 48189702Ssam int chipnum; 49189702Ssam#define MAXREGS 5*1024 50189702Ssam struct dumpreg *regs[MAXREGS]; 51189702Ssam u_int nregs; 52189702Ssam} dumpregs_t; 53189702Ssamstatic dumpregs_t state; 54189702Ssam 55189702Ssamstatic void opdevice(const struct athregrec *r); 56189702Ssamstatic const char* opmark(FILE *, int, const struct athregrec *); 57189702Ssamstatic void oprw(FILE *fd, int recnum, struct athregrec *r); 58189702Ssam 59189702Ssamint 60189702Ssammain(int argc, char *argv[]) 61189702Ssam{ 62189702Ssam int fd, i, nrecs, same; 63189702Ssam struct stat sb; 64189702Ssam void *addr; 65189702Ssam const char *filename = "/tmp/ath_hal.log"; 66189702Ssam struct athregrec *rprev; 67189702Ssam 68189702Ssam if (argc > 1) 69189702Ssam filename = argv[1]; 70189702Ssam fd = open(filename, O_RDONLY); 71189702Ssam if (fd < 0) 72244962Sadrian err(1, "open: %s", filename); 73189702Ssam if (fstat(fd, &sb) < 0) 74189702Ssam err(1, "fstat"); 75189702Ssam addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0); 76189702Ssam if (addr == MAP_FAILED) 77189702Ssam err(1, "mmap"); 78189702Ssam nrecs = sb.st_size / sizeof (struct athregrec); 79189702Ssam printf("%u records", nrecs); 80189702Ssam rprev = NULL; 81189702Ssam same = 0; 82189702Ssam state.chipnum = 5210; 83189702Ssam for (i = 0; i < nrecs; i++) { 84189702Ssam struct athregrec *r = &((struct athregrec *) addr)[i]; 85189702Ssam if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) { 86189702Ssam same++; 87189702Ssam continue; 88189702Ssam } 89189702Ssam if (same) 90189702Ssam printf("\t\t+%u time%s", same, same == 1 ? "" : "s"); 91189702Ssam switch (r->op) { 92189702Ssam case OP_DEVICE: 93189702Ssam opdevice(r); 94189702Ssam break; 95189702Ssam case OP_READ: 96189702Ssam case OP_WRITE: 97189702Ssam oprw(stdout, i, r); 98189702Ssam break; 99189702Ssam case OP_MARK: 100189702Ssam opmark(stdout, i, r); 101189702Ssam break; 102189702Ssam } 103189702Ssam rprev = r; 104189702Ssam same = 0; 105189702Ssam } 106189702Ssam putchar('\n'); 107189702Ssam return 0; 108189702Ssam} 109189702Ssam 110189702Ssamstatic const char* 111189702Ssamopmark(FILE *fd, int i, const struct athregrec *r) 112189702Ssam{ 113189702Ssam fprintf(fd, "\n%05d: ", i); 114189702Ssam switch (r->reg) { 115189702Ssam case AH_MARK_RESET: 116189702Ssam fprintf(fd, "ar%uReset %s", state.chipnum, 117189702Ssam r->val ? "change channel" : "no channel change"); 118189702Ssam break; 119189702Ssam case AH_MARK_RESET_LINE: 120189702Ssam fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val); 121189702Ssam break; 122189702Ssam case AH_MARK_RESET_DONE: 123189702Ssam if (r->val) 124189702Ssam fprintf(fd, "ar%uReset (done), FAIL, error %u", 125189702Ssam state.chipnum, r->val); 126189702Ssam else 127189702Ssam fprintf(fd, "ar%uReset (done), OK", state.chipnum); 128189702Ssam break; 129189702Ssam case AH_MARK_CHIPRESET: 130202161Sgavin fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val); 131189702Ssam break; 132189702Ssam case AH_MARK_PERCAL: 133202161Sgavin fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val); 134189702Ssam break; 135189702Ssam case AH_MARK_SETCHANNEL: 136202161Sgavin fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val); 137189702Ssam break; 138189702Ssam case AH_MARK_ANI_RESET: 139189702Ssam switch (r->val) { 140189702Ssam case HAL_M_STA: 141189702Ssam fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum); 142189702Ssam break; 143189702Ssam case HAL_M_IBSS: 144189702Ssam fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum); 145189702Ssam break; 146189702Ssam case HAL_M_HOSTAP: 147189702Ssam fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum); 148189702Ssam break; 149189702Ssam case HAL_M_MONITOR: 150189702Ssam fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum); 151189702Ssam break; 152189702Ssam default: 153189702Ssam fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val); 154189702Ssam break; 155189702Ssam } 156189702Ssam break; 157189702Ssam case AH_MARK_ANI_POLL: 158189702Ssam fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val); 159189702Ssam break; 160189702Ssam case AH_MARK_ANI_CONTROL: 161189702Ssam switch (r->val) { 162189702Ssam case HAL_ANI_PRESENT: 163189702Ssam fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum); 164189702Ssam break; 165189702Ssam case HAL_ANI_NOISE_IMMUNITY_LEVEL: 166189702Ssam fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum); 167189702Ssam break; 168189702Ssam case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: 169189702Ssam fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum); 170189702Ssam break; 171189702Ssam case HAL_ANI_CCK_WEAK_SIGNAL_THR: 172189702Ssam fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum); 173189702Ssam break; 174189702Ssam case HAL_ANI_FIRSTEP_LEVEL: 175189702Ssam fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum); 176189702Ssam break; 177189702Ssam case HAL_ANI_SPUR_IMMUNITY_LEVEL: 178189702Ssam fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum); 179189702Ssam break; 180189702Ssam case HAL_ANI_MODE: 181189702Ssam fprintf(fd, "ar%uAniControl, MODE", state.chipnum); 182189702Ssam break; 183189702Ssam case HAL_ANI_PHYERR_RESET: 184189702Ssam fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum); 185189702Ssam break; 186189702Ssam default: 187189702Ssam fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val); 188189702Ssam break; 189189702Ssam } 190189702Ssam break; 191189702Ssam default: 192189702Ssam fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val); 193189702Ssam break; 194189702Ssam } 195269638Sadrian return (NULL); 196189702Ssam} 197189702Ssam 198189702Ssam#include "ah_devid.h" 199189702Ssam 200189702Ssamstatic void 201189702Ssamopdevice(const struct athregrec *r) 202189702Ssam{ 203189702Ssam switch (r->val) { 204189702Ssam case AR5210_PROD: 205189702Ssam case AR5210_DEFAULT: 206189702Ssam state.chipnum = 5210; 207189702Ssam state.revs.ah_macVersion = 1; 208189702Ssam state.revs.ah_macRev = 0; 209189702Ssam break; 210189702Ssam case AR5211_DEVID: 211189702Ssam case AR5311_DEVID: 212189702Ssam case AR5211_DEFAULT: 213189702Ssam case AR5211_FPGA11B: 214189702Ssam state.chipnum = 5211; 215189702Ssam state.revs.ah_macVersion = 2; 216189702Ssam state.revs.ah_macRev = 0; 217189702Ssam break; 218189702Ssam /* AR5212 */ 219189702Ssam case AR5212_DEFAULT: 220189702Ssam case AR5212_DEVID: 221189702Ssam case AR5212_FPGA: 222189702Ssam case AR5212_DEVID_IBM: 223189702Ssam case AR5212_AR5312_REV2: 224189702Ssam case AR5212_AR5312_REV7: 225189702Ssam case AR5212_AR2313_REV8: 226189702Ssam case AR5212_AR2315_REV6: 227189702Ssam case AR5212_AR2315_REV7: 228189702Ssam case AR5212_AR2317_REV1: 229189702Ssam case AR5212_AR2317_REV2: 230189702Ssam 231189702Ssam /* AR5212 compatible devid's also attach to 5212 */ 232189702Ssam case AR5212_DEVID_0014: 233189702Ssam case AR5212_DEVID_0015: 234189702Ssam case AR5212_DEVID_0016: 235189702Ssam case AR5212_DEVID_0017: 236189702Ssam case AR5212_DEVID_0018: 237189702Ssam case AR5212_DEVID_0019: 238189702Ssam case AR5212_AR2413: 239189702Ssam case AR5212_AR5413: 240189702Ssam case AR5212_AR5424: 241189702Ssam case AR5212_AR2417: 242189702Ssam case AR5212_DEVID_FF19: 243189702Ssam state.chipnum = 5212; 244189702Ssam state.revs.ah_macVersion = 4; 245189702Ssam state.revs.ah_macRev = 5; 246189702Ssam break; 247189702Ssam 248189702Ssam /* AR5213 */ 249189702Ssam case AR5213_SREV_1_0: 250189702Ssam case AR5213_SREV_REG: 251189702Ssam state.chipnum = 5213; 252189702Ssam state.revs.ah_macVersion = 5; 253189702Ssam state.revs.ah_macRev = 9; 254189702Ssam break; 255189702Ssam 256189702Ssam /* AR5416 compatible devid's */ 257189702Ssam case AR5416_DEVID_PCI: 258189702Ssam case AR5416_DEVID_PCIE: 259189702Ssam case AR9160_DEVID_PCI: 260189702Ssam case AR9280_DEVID_PCI: 261189702Ssam case AR9280_DEVID_PCIE: 262189702Ssam case AR9285_DEVID_PCIE: 263269638Sadrian case AR9287_DEVID_PCI: 264269638Sadrian case AR9287_DEVID_PCIE: 265269638Sadrian case AR9300_DEVID_AR9330: 266189702Ssam state.chipnum = 5416; 267189702Ssam state.revs.ah_macVersion = 13; 268189702Ssam state.revs.ah_macRev = 8; 269189702Ssam break; 270189702Ssam default: 271189702Ssam printf("Unknown device id 0x%x\n", r->val); 272189702Ssam exit(-1); 273189702Ssam } 274189702Ssam} 275189702Ssam 276189702Ssamstatic int 277189702Ssamregcompar(const void *a, const void *b) 278189702Ssam{ 279189702Ssam const struct dumpreg *ra = *(const struct dumpreg **)a; 280189702Ssam const struct dumpreg *rb = *(const struct dumpreg **)b; 281189702Ssam return ra->addr - rb->addr; 282189702Ssam} 283189702Ssam 284189702Ssamvoid 285189702Ssamregister_regs(struct dumpreg *chipregs, u_int nchipregs, 286189702Ssam int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 287189702Ssam{ 288189702Ssam const int existing_regs = state.nregs; 289189702Ssam int i, j; 290189702Ssam 291189702Ssam for (i = 0; i < nchipregs; i++) { 292189702Ssam struct dumpreg *nr = &chipregs[i]; 293189702Ssam if (nr->srevMin == 0) 294189702Ssam nr->srevMin = def_srev_min; 295189702Ssam if (nr->srevMax == 0) 296189702Ssam nr->srevMax = def_srev_max; 297189702Ssam if (nr->phyMin == 0) 298189702Ssam nr->phyMin = def_phy_min; 299189702Ssam if (nr->phyMax == 0) 300189702Ssam nr->phyMax = def_phy_max; 301189702Ssam for (j = 0; j < existing_regs; j++) { 302189702Ssam struct dumpreg *r = state.regs[j]; 303189702Ssam /* 304189702Ssam * Check if we can just expand the mac+phy 305189702Ssam * coverage for the existing entry. 306189702Ssam */ 307189702Ssam if (nr->addr == r->addr && 308189702Ssam (nr->name == r->name || 309244962Sadrian (nr->name != NULL && r->name != NULL && 310244962Sadrian strcmp(nr->name, r->name) == 0))) { 311189702Ssam if (nr->srevMin < r->srevMin && 312189702Ssam (r->srevMin <= nr->srevMax && 313189702Ssam nr->srevMax+1 <= r->srevMax)) { 314189702Ssam r->srevMin = nr->srevMin; 315189702Ssam goto skip; 316189702Ssam } 317189702Ssam if (nr->srevMax > r->srevMax && 318189702Ssam (r->srevMin <= nr->srevMin && 319189702Ssam nr->srevMin <= r->srevMax)) { 320189702Ssam r->srevMax = nr->srevMax; 321189702Ssam goto skip; 322189702Ssam } 323189702Ssam } 324189702Ssam if (r->addr > nr->addr) 325189702Ssam break; 326189702Ssam } 327189702Ssam /* 328189702Ssam * New item, add to the end, it'll be sorted below. 329189702Ssam */ 330189702Ssam if (state.nregs == MAXREGS) 331189702Ssam errx(-1, "too many registers; bump MAXREGS"); 332189702Ssam state.regs[state.nregs++] = nr; 333189702Ssam skip: 334189702Ssam ; 335189702Ssam } 336189702Ssam qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar); 337189702Ssam} 338189702Ssam 339189702Ssamvoid 340189702Ssamregister_keycache(u_int nslots, 341189702Ssam int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 342189702Ssam{ 343189702Ssam /* discard, no use */ 344189702Ssam} 345189702Ssam 346189702Ssamvoid 347189702Ssamregister_range(u_int brange, u_int erange, int type, 348189702Ssam int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 349189702Ssam{ 350189702Ssam /* discard, no use */ 351189702Ssam} 352189702Ssam 353189702Ssamstatic const struct dumpreg * 354189702Ssamfindreg(int reg) 355189702Ssam{ 356189702Ssam const HAL_REVS *revs = &state.revs; 357189702Ssam int i; 358189702Ssam 359189702Ssam for (i = 0; i < state.nregs; i++) { 360189702Ssam const struct dumpreg *dr = state.regs[i]; 361189702Ssam if (dr->addr == reg && 362189702Ssam MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev)) 363189702Ssam return dr; 364189702Ssam } 365189702Ssam return NULL; 366189702Ssam} 367189702Ssam 368189702Ssam/* XXX cheat, 5212 has a superset of the key table defs */ 369189702Ssam#include "ar5212/ar5212reg.h" 370189702Ssam#include "ar5212/ar5212phy.h" 371189702Ssam 372189702Ssam#define PWR_TABLE_SIZE 64 373189702Ssam 374189702Ssamstatic void 375189702Ssamoprw(FILE *fd, int recnum, struct athregrec *r) 376189702Ssam{ 377189702Ssam const struct dumpreg *dr; 378189702Ssam char buf[64]; 379189702Ssam const char* bits; 380189702Ssam int i; 381189702Ssam 382233887Sadrian fprintf(fd, "\n%05d: [%d] ", recnum, r->threadid); 383189702Ssam dr = findreg(r->reg); 384189702Ssam if (dr != NULL && dr->name != NULL) { 385189702Ssam snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg); 386189702Ssam bits = dr->bits; 387189702Ssam } else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) { 388189702Ssam snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)", 389189702Ssam ((r->reg - AR_KEYTABLE_0) >> 2) & 7, 390189702Ssam (r->reg - AR_KEYTABLE_0) >> 5, r->reg); 391189702Ssam bits = NULL; 392189702Ssam#if 0 393189702Ssam } else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) { 394189702Ssam snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)", 395189702Ssam (r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg); 396189702Ssam bits = NULL; 397189702Ssam#endif 398189702Ssam } else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) { 399189702Ssam snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)", 400189702Ssam (r->reg - AR_RATE_DURATION_0) >> 2, r->reg); 401189702Ssam bits = NULL; 402189702Ssam } else if (AR_PHY_BASE <= r->reg) { 403189702Ssam snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)", 404189702Ssam (r->reg - AR_PHY_BASE) >> 2, r->reg); 405189702Ssam bits = NULL; 406189702Ssam } else { 407189702Ssam snprintf(buf, sizeof (buf), "0x%x", r->reg); 408189702Ssam bits = NULL; 409189702Ssam } 410189702Ssam fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val); 411189702Ssam if (bits) { 412189702Ssam const char *p = bits; 413189702Ssam int tmp, n; 414189702Ssam 415189702Ssam for (tmp = 0, p++; *p;) { 416189702Ssam n = *p++; 417189702Ssam if (r->val & (1 << (n - 1))) { 418189702Ssam putc(tmp ? ',' : '<', fd); 419189702Ssam for (; (n = *p) > ' '; ++p) 420189702Ssam putc(n, fd); 421189702Ssam tmp = 1; 422189702Ssam } else 423189702Ssam for (; *p > ' '; ++p) 424189702Ssam continue; 425189702Ssam } 426189702Ssam if (tmp) 427189702Ssam putc('>', fd); 428189702Ssam } 429189702Ssam} 430