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, MERCHANTIBILITY 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$ 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 <string.h> 41 #include <err.h> 42 #include <sys/file.h> 43 #include <sys/stat.h> 44 #include <sys/mman.h> 45 46 typedef struct { 47 HAL_REVS revs; 48 int chipnum; 49 #define MAXREGS 5*1024 50 struct dumpreg *regs[MAXREGS]; 51 u_int nregs; 52 } dumpregs_t; 53 static dumpregs_t state; 54 55 static void opdevice(const struct athregrec *r); 56 static const char* opmark(FILE *, int, const struct athregrec *); 57 static void oprw(FILE *fd, int recnum, struct athregrec *r); 58 59 int 60 main(int argc, char *argv[]) 61 { 62 int fd, i, nrecs, same; 63 struct stat sb; 64 void *addr; 65 const char *filename = "/tmp/ath_hal.log"; 66 struct athregrec *rprev; 67 68 if (argc > 1) 69 filename = argv[1]; 70 fd = open(filename, O_RDONLY); 71 if (fd < 0) 72 err(1, "open: %s", filename); 73 if (fstat(fd, &sb) < 0) 74 err(1, "fstat"); 75 addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0); 76 if (addr == MAP_FAILED) 77 err(1, "mmap"); 78 nrecs = sb.st_size / sizeof (struct athregrec); 79 printf("%u records", nrecs); 80 rprev = NULL; 81 same = 0; 82 state.chipnum = 5210; 83 for (i = 0; i < nrecs; i++) { 84 struct athregrec *r = &((struct athregrec *) addr)[i]; 85 if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) { 86 same++; 87 continue; 88 } 89 if (same) 90 printf("\t\t+%u time%s", same, same == 1 ? "" : "s"); 91 switch (r->op) { 92 case OP_DEVICE: 93 opdevice(r); 94 break; 95 case OP_READ: 96 case OP_WRITE: 97 oprw(stdout, i, r); 98 break; 99 case OP_MARK: 100 opmark(stdout, i, r); 101 break; 102 } 103 rprev = r; 104 same = 0; 105 } 106 putchar('\n'); 107 return 0; 108 } 109 110 static const char* 111 opmark(FILE *fd, int i, const struct athregrec *r) 112 { 113 fprintf(fd, "\n%05d: ", i); 114 switch (r->reg) { 115 case AH_MARK_RESET: 116 fprintf(fd, "ar%uReset %s", state.chipnum, 117 r->val ? "change channel" : "no channel change"); 118 break; 119 case AH_MARK_RESET_LINE: 120 fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val); 121 break; 122 case AH_MARK_RESET_DONE: 123 if (r->val) 124 fprintf(fd, "ar%uReset (done), FAIL, error %u", 125 state.chipnum, r->val); 126 else 127 fprintf(fd, "ar%uReset (done), OK", state.chipnum); 128 break; 129 case AH_MARK_CHIPRESET: 130 fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val); 131 break; 132 case AH_MARK_PERCAL: 133 fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val); 134 break; 135 case AH_MARK_SETCHANNEL: 136 fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val); 137 break; 138 case AH_MARK_ANI_RESET: 139 switch (r->val) { 140 case HAL_M_STA: 141 fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum); 142 break; 143 case HAL_M_IBSS: 144 fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum); 145 break; 146 case HAL_M_HOSTAP: 147 fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum); 148 break; 149 case HAL_M_MONITOR: 150 fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum); 151 break; 152 default: 153 fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val); 154 break; 155 } 156 break; 157 case AH_MARK_ANI_POLL: 158 fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val); 159 break; 160 case AH_MARK_ANI_CONTROL: 161 switch (r->val) { 162 case HAL_ANI_PRESENT: 163 fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum); 164 break; 165 case HAL_ANI_NOISE_IMMUNITY_LEVEL: 166 fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum); 167 break; 168 case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: 169 fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum); 170 break; 171 case HAL_ANI_CCK_WEAK_SIGNAL_THR: 172 fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum); 173 break; 174 case HAL_ANI_FIRSTEP_LEVEL: 175 fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum); 176 break; 177 case HAL_ANI_SPUR_IMMUNITY_LEVEL: 178 fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum); 179 break; 180 case HAL_ANI_MODE: 181 fprintf(fd, "ar%uAniControl, MODE", state.chipnum); 182 break; 183 case HAL_ANI_PHYERR_RESET: 184 fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum); 185 break; 186 default: 187 fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val); 188 break; 189 } 190 break; 191 default: 192 fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val); 193 break; 194 } 195 return (NULL); 196 } 197 198 #include "ah_devid.h" 199 200 static void 201 opdevice(const struct athregrec *r) 202 { 203 switch (r->val) { 204 case AR5210_PROD: 205 case AR5210_DEFAULT: 206 state.chipnum = 5210; 207 state.revs.ah_macVersion = 1; 208 state.revs.ah_macRev = 0; 209 break; 210 case AR5211_DEVID: 211 case AR5311_DEVID: 212 case AR5211_DEFAULT: 213 case AR5211_FPGA11B: 214 state.chipnum = 5211; 215 state.revs.ah_macVersion = 2; 216 state.revs.ah_macRev = 0; 217 break; 218 /* AR5212 */ 219 case AR5212_DEFAULT: 220 case AR5212_DEVID: 221 case AR5212_FPGA: 222 case AR5212_DEVID_IBM: 223 case AR5212_AR5312_REV2: 224 case AR5212_AR5312_REV7: 225 case AR5212_AR2313_REV8: 226 case AR5212_AR2315_REV6: 227 case AR5212_AR2315_REV7: 228 case AR5212_AR2317_REV1: 229 case AR5212_AR2317_REV2: 230 231 /* AR5212 compatible devid's also attach to 5212 */ 232 case AR5212_DEVID_0014: 233 case AR5212_DEVID_0015: 234 case AR5212_DEVID_0016: 235 case AR5212_DEVID_0017: 236 case AR5212_DEVID_0018: 237 case AR5212_DEVID_0019: 238 case AR5212_AR2413: 239 case AR5212_AR5413: 240 case AR5212_AR5424: 241 case AR5212_AR2417: 242 case AR5212_DEVID_FF19: 243 state.chipnum = 5212; 244 state.revs.ah_macVersion = 4; 245 state.revs.ah_macRev = 5; 246 break; 247 248 /* AR5213 */ 249 case AR5213_SREV_1_0: 250 case AR5213_SREV_REG: 251 state.chipnum = 5213; 252 state.revs.ah_macVersion = 5; 253 state.revs.ah_macRev = 9; 254 break; 255 256 /* AR5416 compatible devid's */ 257 case AR5416_DEVID_PCI: 258 case AR5416_DEVID_PCIE: 259 case AR9160_DEVID_PCI: 260 case AR9280_DEVID_PCI: 261 case AR9280_DEVID_PCIE: 262 case AR9285_DEVID_PCIE: 263 case AR9287_DEVID_PCI: 264 case AR9287_DEVID_PCIE: 265 case AR9300_DEVID_AR9330: 266 state.chipnum = 5416; 267 state.revs.ah_macVersion = 13; 268 state.revs.ah_macRev = 8; 269 break; 270 default: 271 printf("Unknown device id 0x%x\n", r->val); 272 exit(-1); 273 } 274 } 275 276 static int 277 regcompar(const void *a, const void *b) 278 { 279 const struct dumpreg *ra = *(const struct dumpreg **)a; 280 const struct dumpreg *rb = *(const struct dumpreg **)b; 281 return ra->addr - rb->addr; 282 } 283 284 void 285 register_regs(struct dumpreg *chipregs, u_int nchipregs, 286 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 287 { 288 const int existing_regs = state.nregs; 289 int i, j; 290 291 for (i = 0; i < nchipregs; i++) { 292 struct dumpreg *nr = &chipregs[i]; 293 if (nr->srevMin == 0) 294 nr->srevMin = def_srev_min; 295 if (nr->srevMax == 0) 296 nr->srevMax = def_srev_max; 297 if (nr->phyMin == 0) 298 nr->phyMin = def_phy_min; 299 if (nr->phyMax == 0) 300 nr->phyMax = def_phy_max; 301 for (j = 0; j < existing_regs; j++) { 302 struct dumpreg *r = state.regs[j]; 303 /* 304 * Check if we can just expand the mac+phy 305 * coverage for the existing entry. 306 */ 307 if (nr->addr == r->addr && 308 (nr->name == r->name || 309 (nr->name != NULL && r->name != NULL && 310 strcmp(nr->name, r->name) == 0))) { 311 if (nr->srevMin < r->srevMin && 312 (r->srevMin <= nr->srevMax && 313 nr->srevMax+1 <= r->srevMax)) { 314 r->srevMin = nr->srevMin; 315 goto skip; 316 } 317 if (nr->srevMax > r->srevMax && 318 (r->srevMin <= nr->srevMin && 319 nr->srevMin <= r->srevMax)) { 320 r->srevMax = nr->srevMax; 321 goto skip; 322 } 323 } 324 if (r->addr > nr->addr) 325 break; 326 } 327 /* 328 * New item, add to the end, it'll be sorted below. 329 */ 330 if (state.nregs == MAXREGS) 331 errx(-1, "too many registers; bump MAXREGS"); 332 state.regs[state.nregs++] = nr; 333 skip: 334 ; 335 } 336 qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar); 337 } 338 339 void 340 register_keycache(u_int nslots, 341 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 342 { 343 /* discard, no use */ 344 } 345 346 void 347 register_range(u_int brange, u_int erange, int type, 348 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 349 { 350 /* discard, no use */ 351 } 352 353 static const struct dumpreg * 354 findreg(int reg) 355 { 356 const HAL_REVS *revs = &state.revs; 357 int i; 358 359 for (i = 0; i < state.nregs; i++) { 360 const struct dumpreg *dr = state.regs[i]; 361 if (dr->addr == reg && 362 MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev)) 363 return dr; 364 } 365 return NULL; 366 } 367 368 /* XXX cheat, 5212 has a superset of the key table defs */ 369 #include "ar5212/ar5212reg.h" 370 #include "ar5212/ar5212phy.h" 371 372 #define PWR_TABLE_SIZE 64 373 374 static void 375 oprw(FILE *fd, int recnum, struct athregrec *r) 376 { 377 const struct dumpreg *dr; 378 char buf[64]; 379 const char* bits; 380 int i; 381 382 fprintf(fd, "\n%05d: [%d] ", recnum, r->threadid); 383 dr = findreg(r->reg); 384 if (dr != NULL && dr->name != NULL) { 385 snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg); 386 bits = dr->bits; 387 } else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) { 388 snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)", 389 ((r->reg - AR_KEYTABLE_0) >> 2) & 7, 390 (r->reg - AR_KEYTABLE_0) >> 5, r->reg); 391 bits = NULL; 392 #if 0 393 } else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) { 394 snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)", 395 (r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg); 396 bits = NULL; 397 #endif 398 } else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) { 399 snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)", 400 (r->reg - AR_RATE_DURATION_0) >> 2, r->reg); 401 bits = NULL; 402 } else if (AR_PHY_BASE <= r->reg) { 403 snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)", 404 (r->reg - AR_PHY_BASE) >> 2, r->reg); 405 bits = NULL; 406 } else { 407 snprintf(buf, sizeof (buf), "0x%x", r->reg); 408 bits = NULL; 409 } 410 fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val); 411 if (bits) { 412 const char *p = bits; 413 int tmp, n; 414 415 for (tmp = 0, p++; *p;) { 416 n = *p++; 417 if (r->val & (1 << (n - 1))) { 418 putc(tmp ? ',' : '<', fd); 419 for (; (n = *p) > ' '; ++p) 420 putc(n, fd); 421 tmp = 1; 422 } else 423 for (; *p > ' '; ++p) 424 continue; 425 } 426 if (tmp) 427 putc('>', fd); 428 } 429 } 430