1 /*- 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD: src/tools/tools/ath/athdecode/main.c,v 1.2 2010/01/12 17:59:58 gavin Exp $ 30 */ 31 #include "diag.h" 32 33 #include "ah.h" 34 #include "ah_internal.h" 35 #include "ah_decode.h" 36 37 #include "dumpregs.h" 38 39 #include <stdlib.h> 40 #include <sys/file.h> 41 #include <sys/stat.h> 42 #include <sys/mman.h> 43 44 typedef struct { 45 HAL_REVS revs; 46 int chipnum; 47 #define MAXREGS 5*1024 48 struct dumpreg *regs[MAXREGS]; 49 u_int nregs; 50 } dumpregs_t; 51 static dumpregs_t state; 52 53 static void opdevice(const struct athregrec *r); 54 static const char* opmark(FILE *, int, const struct athregrec *); 55 static void oprw(FILE *fd, int recnum, struct athregrec *r); 56 57 int 58 main(int argc, char *argv[]) 59 { 60 int fd, i, nrecs, same; 61 struct stat sb; 62 void *addr; 63 const char *filename = "/tmp/ath_hal.log"; 64 struct athregrec *rprev; 65 66 if (argc > 1) 67 filename = argv[1]; 68 fd = open(filename, O_RDONLY); 69 if (fd < 0) 70 err(1, filename); 71 if (fstat(fd, &sb) < 0) 72 err(1, "fstat"); 73 addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0); 74 if (addr == MAP_FAILED) 75 err(1, "mmap"); 76 nrecs = sb.st_size / sizeof (struct athregrec); 77 printf("%u records", nrecs); 78 rprev = NULL; 79 same = 0; 80 state.chipnum = 5210; 81 for (i = 0; i < nrecs; i++) { 82 struct athregrec *r = &((struct athregrec *) addr)[i]; 83 if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) { 84 same++; 85 continue; 86 } 87 if (same) 88 printf("\t\t+%u time%s", same, same == 1 ? "" : "s"); 89 switch (r->op) { 90 case OP_DEVICE: 91 opdevice(r); 92 break; 93 case OP_READ: 94 case OP_WRITE: 95 oprw(stdout, i, r); 96 break; 97 case OP_MARK: 98 opmark(stdout, i, r); 99 break; 100 } 101 rprev = r; 102 same = 0; 103 } 104 putchar('\n'); 105 return 0; 106 } 107 108 static const char* 109 opmark(FILE *fd, int i, const struct athregrec *r) 110 { 111 fprintf(fd, "\n%05d: ", i); 112 switch (r->reg) { 113 case AH_MARK_RESET: 114 fprintf(fd, "ar%uReset %s", state.chipnum, 115 r->val ? "change channel" : "no channel change"); 116 break; 117 case AH_MARK_RESET_LINE: 118 fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val); 119 break; 120 case AH_MARK_RESET_DONE: 121 if (r->val) 122 fprintf(fd, "ar%uReset (done), FAIL, error %u", 123 state.chipnum, r->val); 124 else 125 fprintf(fd, "ar%uReset (done), OK", state.chipnum); 126 break; 127 case AH_MARK_CHIPRESET: 128 fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val); 129 break; 130 case AH_MARK_PERCAL: 131 fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val); 132 break; 133 case AH_MARK_SETCHANNEL: 134 fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val); 135 break; 136 case AH_MARK_ANI_RESET: 137 switch (r->val) { 138 case HAL_M_STA: 139 fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum); 140 break; 141 case HAL_M_IBSS: 142 fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum); 143 break; 144 case HAL_M_HOSTAP: 145 fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum); 146 break; 147 case HAL_M_MONITOR: 148 fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum); 149 break; 150 default: 151 fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val); 152 break; 153 } 154 break; 155 case AH_MARK_ANI_POLL: 156 fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val); 157 break; 158 case AH_MARK_ANI_CONTROL: 159 switch (r->val) { 160 case HAL_ANI_PRESENT: 161 fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum); 162 break; 163 case HAL_ANI_NOISE_IMMUNITY_LEVEL: 164 fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum); 165 break; 166 case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: 167 fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum); 168 break; 169 case HAL_ANI_CCK_WEAK_SIGNAL_THR: 170 fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum); 171 break; 172 case HAL_ANI_FIRSTEP_LEVEL: 173 fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum); 174 break; 175 case HAL_ANI_SPUR_IMMUNITY_LEVEL: 176 fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum); 177 break; 178 case HAL_ANI_MODE: 179 fprintf(fd, "ar%uAniControl, MODE", state.chipnum); 180 break; 181 case HAL_ANI_PHYERR_RESET: 182 fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum); 183 break; 184 default: 185 fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val); 186 break; 187 } 188 break; 189 default: 190 fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val); 191 break; 192 } 193 } 194 195 #include "ah_devid.h" 196 197 static void 198 opdevice(const struct athregrec *r) 199 { 200 switch (r->val) { 201 case AR5210_PROD: 202 case AR5210_DEFAULT: 203 state.chipnum = 5210; 204 state.revs.ah_macVersion = 1; 205 state.revs.ah_macRev = 0; 206 break; 207 case AR5211_DEVID: 208 case AR5311_DEVID: 209 case AR5211_DEFAULT: 210 case AR5211_FPGA11B: 211 state.chipnum = 5211; 212 state.revs.ah_macVersion = 2; 213 state.revs.ah_macRev = 0; 214 break; 215 /* AR5212 */ 216 case AR5212_DEFAULT: 217 case AR5212_DEVID: 218 case AR5212_FPGA: 219 case AR5212_DEVID_IBM: 220 case AR5212_AR5312_REV2: 221 case AR5212_AR5312_REV7: 222 case AR5212_AR2313_REV8: 223 case AR5212_AR2315_REV6: 224 case AR5212_AR2315_REV7: 225 case AR5212_AR2317_REV1: 226 case AR5212_AR2317_REV2: 227 228 /* AR5212 compatible devid's also attach to 5212 */ 229 case AR5212_DEVID_0014: 230 case AR5212_DEVID_0015: 231 case AR5212_DEVID_0016: 232 case AR5212_DEVID_0017: 233 case AR5212_DEVID_0018: 234 case AR5212_DEVID_0019: 235 case AR5212_AR2413: 236 case AR5212_AR5413: 237 case AR5212_AR5424: 238 case AR5212_AR2417: 239 case AR5212_DEVID_FF19: 240 state.chipnum = 5212; 241 state.revs.ah_macVersion = 4; 242 state.revs.ah_macRev = 5; 243 break; 244 245 /* AR5213 */ 246 case AR5213_SREV_1_0: 247 case AR5213_SREV_REG: 248 state.chipnum = 5213; 249 state.revs.ah_macVersion = 5; 250 state.revs.ah_macRev = 9; 251 break; 252 253 /* AR5416 compatible devid's */ 254 case AR5416_DEVID_PCI: 255 case AR5416_DEVID_PCIE: 256 case AR9160_DEVID_PCI: 257 case AR9280_DEVID_PCI: 258 case AR9280_DEVID_PCIE: 259 case AR9285_DEVID_PCIE: 260 state.chipnum = 5416; 261 state.revs.ah_macVersion = 13; 262 state.revs.ah_macRev = 8; 263 break; 264 default: 265 printf("Unknown device id 0x%x\n", r->val); 266 exit(-1); 267 } 268 } 269 270 static int 271 regcompar(const void *a, const void *b) 272 { 273 const struct dumpreg *ra = *(const struct dumpreg **)a; 274 const struct dumpreg *rb = *(const struct dumpreg **)b; 275 return ra->addr - rb->addr; 276 } 277 278 void 279 register_regs(struct dumpreg *chipregs, u_int nchipregs, 280 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 281 { 282 const int existing_regs = state.nregs; 283 int i, j; 284 285 for (i = 0; i < nchipregs; i++) { 286 struct dumpreg *nr = &chipregs[i]; 287 if (nr->srevMin == 0) 288 nr->srevMin = def_srev_min; 289 if (nr->srevMax == 0) 290 nr->srevMax = def_srev_max; 291 if (nr->phyMin == 0) 292 nr->phyMin = def_phy_min; 293 if (nr->phyMax == 0) 294 nr->phyMax = def_phy_max; 295 for (j = 0; j < existing_regs; j++) { 296 struct dumpreg *r = state.regs[j]; 297 /* 298 * Check if we can just expand the mac+phy 299 * coverage for the existing entry. 300 */ 301 if (nr->addr == r->addr && 302 (nr->name == r->name || 303 nr->name != NULL && r->name != NULL && 304 strcmp(nr->name, r->name) == 0)) { 305 if (nr->srevMin < r->srevMin && 306 (r->srevMin <= nr->srevMax && 307 nr->srevMax+1 <= r->srevMax)) { 308 r->srevMin = nr->srevMin; 309 goto skip; 310 } 311 if (nr->srevMax > r->srevMax && 312 (r->srevMin <= nr->srevMin && 313 nr->srevMin <= r->srevMax)) { 314 r->srevMax = nr->srevMax; 315 goto skip; 316 } 317 } 318 if (r->addr > nr->addr) 319 break; 320 } 321 /* 322 * New item, add to the end, it'll be sorted below. 323 */ 324 if (state.nregs == MAXREGS) 325 errx(-1, "too many registers; bump MAXREGS"); 326 state.regs[state.nregs++] = nr; 327 skip: 328 ; 329 } 330 qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar); 331 } 332 333 void 334 register_keycache(u_int nslots, 335 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 336 { 337 /* discard, no use */ 338 } 339 340 void 341 register_range(u_int brange, u_int erange, int type, 342 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 343 { 344 /* discard, no use */ 345 } 346 347 static const struct dumpreg * 348 findreg(int reg) 349 { 350 const HAL_REVS *revs = &state.revs; 351 int i; 352 353 for (i = 0; i < state.nregs; i++) { 354 const struct dumpreg *dr = state.regs[i]; 355 if (dr->addr == reg && 356 MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev)) 357 return dr; 358 } 359 return NULL; 360 } 361 362 /* XXX cheat, 5212 has a superset of the key table defs */ 363 #include "ar5212/ar5212reg.h" 364 #include "ar5212/ar5212phy.h" 365 366 #define PWR_TABLE_SIZE 64 367 368 static void 369 oprw(FILE *fd, int recnum, struct athregrec *r) 370 { 371 const struct dumpreg *dr; 372 char buf[64]; 373 const char* bits; 374 int i; 375 376 fprintf(fd, "\n%05d: ", recnum); 377 dr = findreg(r->reg); 378 if (dr != NULL && dr->name != NULL) { 379 snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg); 380 bits = dr->bits; 381 } else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) { 382 snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)", 383 ((r->reg - AR_KEYTABLE_0) >> 2) & 7, 384 (r->reg - AR_KEYTABLE_0) >> 5, r->reg); 385 bits = NULL; 386 #if 0 387 } else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) { 388 snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)", 389 (r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg); 390 bits = NULL; 391 #endif 392 } else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) { 393 snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)", 394 (r->reg - AR_RATE_DURATION_0) >> 2, r->reg); 395 bits = NULL; 396 } else if (AR_PHY_BASE <= r->reg) { 397 snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)", 398 (r->reg - AR_PHY_BASE) >> 2, r->reg); 399 bits = NULL; 400 } else { 401 snprintf(buf, sizeof (buf), "0x%x", r->reg); 402 bits = NULL; 403 } 404 fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val); 405 if (bits) { 406 const char *p = bits; 407 int tmp, n; 408 409 for (tmp = 0, p++; *p;) { 410 n = *p++; 411 if (r->val & (1 << (n - 1))) { 412 putc(tmp ? ',' : '<', fd); 413 for (; (n = *p) > ' '; ++p) 414 putc(n, fd); 415 tmp = 1; 416 } else 417 for (; *p > ' '; ++p) 418 continue; 419 } 420 if (tmp) 421 putc('>', fd); 422 } 423 } 424