1185743Ssam/*- 2185743Ssam * Copyright (c) 2002-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/* XXX cheat, 5212 has a superset of the key table defs */ 36185743Ssam#include "ar5212/ar5212reg.h" 37185743Ssam 38185743Ssam#include "dumpregs.h" 39185743Ssam 40185743Ssam#include <getopt.h> 41185743Ssam#include <stdlib.h> 42185743Ssam#include <string.h> 43185743Ssam#include <ctype.h> 44217680Sadrian#include <err.h> 45185743Ssam 46185743Ssamtypedef struct { 47185743Ssam HAL_REVS revs; 48185743Ssam u_int32_t regdata[0xffff / sizeof(u_int32_t)]; 49185743Ssam#define MAXREGS 5*1024 50185743Ssam struct dumpreg *regs[MAXREGS]; 51185743Ssam u_int nregs; 52185743Ssam u_int show_names : 1, 53185743Ssam show_addrs : 1; 54185743Ssam} dumpregs_t; 55185743Ssamstatic dumpregs_t state; 56185743Ssam 57185743Ssam#undef OS_REG_READ 58185743Ssam#define OS_REG_READ(ah, off) state.regdata[(off) >> 2] 59185743Ssam 60185743Ssamstatic int ath_hal_anyregs(int what); 61185743Ssamstatic int ath_hal_setupregs(struct ath_diag *atd, int what); 62185743Ssamstatic u_int ath_hal_setupdiagregs(const HAL_REGRANGE regs[], u_int nr); 63185743Ssamstatic void ath_hal_dumpregs(FILE *fd, int what); 64185743Ssamstatic void ath_hal_dumprange(FILE *fd, u_int a, u_int b); 65185743Ssamstatic void ath_hal_dumpkeycache(FILE *fd, int nkeys); 66185743Ssamstatic void ath_hal_dumpint(FILE *fd, int what); 67185743Ssamstatic void ath_hal_dumpqcu(FILE *fd, int what); 68185743Ssamstatic void ath_hal_dumpdcu(FILE *fd, int what); 69185743Ssamstatic void ath_hal_dumpbb(FILE *fd, int what); 70185743Ssam 71185743Ssamstatic void 72185743Ssamusage(void) 73185743Ssam{ 74185743Ssam fprintf(stderr, "usage: athregs [-i interface] [-abdkmqxz]\n"); 75185743Ssam fprintf(stderr, "-a display all registers\n"); 76185743Ssam fprintf(stderr, "-b display baseband registers\n"); 77185743Ssam fprintf(stderr, "-d display DCU registers\n"); 78185743Ssam fprintf(stderr, "-k display key cache registers\n"); 79185743Ssam fprintf(stderr, "-m display \"MAC\" registers (default)\n"); 80185743Ssam fprintf(stderr, "-q display QCU registers\n"); 81185743Ssam fprintf(stderr, "-x display XR registers\n"); 82185743Ssam fprintf(stderr, "-z display interrupt registers\n"); 83185743Ssam fprintf(stderr, "\n"); 84185743Ssam fprintf(stderr, "-A display register address\n"); 85185743Ssam fprintf(stderr, "-N suppress display of register name\n"); 86185743Ssam exit(-1); 87185743Ssam} 88185743Ssam 89185743Ssamint 90185743Ssammain(int argc, char *argv[]) 91185743Ssam{ 92185743Ssam struct ath_diag atd; 93185743Ssam const char *ifname; 94185743Ssam u_int32_t *data; 95185743Ssam u_int32_t *dp, *ep; 96185743Ssam int what, c, s, i; 97185743Ssam 98185743Ssam s = socket(AF_INET, SOCK_DGRAM, 0); 99185743Ssam if (s < 0) 100185743Ssam err(1, "socket"); 101185743Ssam ifname = getenv("ATH"); 102185743Ssam if (!ifname) 103185743Ssam ifname = ATH_DEFAULT; 104185743Ssam 105185743Ssam what = 0; 106185743Ssam state.show_addrs = 0; 107185743Ssam state.show_names = 1; 108185743Ssam while ((c = getopt(argc, argv, "i:aAbdkmNqxz")) != -1) 109185743Ssam switch (c) { 110185743Ssam case 'a': 111185743Ssam what |= DUMP_ALL; 112185743Ssam break; 113185743Ssam case 'A': 114185743Ssam state.show_addrs = 1; 115185743Ssam break; 116185743Ssam case 'b': 117185743Ssam what |= DUMP_BASEBAND; 118185743Ssam break; 119185743Ssam case 'd': 120185743Ssam what |= DUMP_DCU; 121185743Ssam break; 122185743Ssam case 'k': 123185743Ssam what |= DUMP_KEYCACHE; 124185743Ssam break; 125185743Ssam case 'i': 126185743Ssam ifname = optarg; 127185743Ssam break; 128185743Ssam case 'm': 129185743Ssam what |= DUMP_BASIC; 130185743Ssam break; 131185743Ssam case 'N': 132185743Ssam state.show_names = 0; 133185743Ssam break; 134185743Ssam case 'q': 135185743Ssam what |= DUMP_QCU; 136185743Ssam break; 137185743Ssam case 'x': 138185743Ssam what |= DUMP_XR; 139185743Ssam break; 140185743Ssam case 'z': 141185743Ssam what |= DUMP_INTERRUPT; 142185743Ssam break; 143185743Ssam default: 144185743Ssam usage(); 145185743Ssam /*NOTREACHED*/ 146185743Ssam } 147185743Ssam strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); 148185743Ssam 149185743Ssam argc -= optind; 150185743Ssam argv += optind; 151185743Ssam if (what == 0) 152185743Ssam what = DUMP_BASIC; 153185743Ssam 154185743Ssam atd.ad_id = HAL_DIAG_REVS; 155185743Ssam atd.ad_out_data = (caddr_t) &state.revs; 156185743Ssam atd.ad_out_size = sizeof(state.revs); 157185743Ssam if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 158185743Ssam err(1, atd.ad_name); 159185743Ssam 160185743Ssam if (ath_hal_setupregs(&atd, what) == 0) 161185743Ssam errx(-1, "no registers are known for this part " 162185743Ssam "(devid 0x%x mac %d.%d phy %d)", state.revs.ah_devid, 163185743Ssam state.revs.ah_macVersion, state.revs.ah_macRev, 164185743Ssam state.revs.ah_phyRev); 165185743Ssam 166185743Ssam atd.ad_out_size = ath_hal_setupdiagregs((HAL_REGRANGE *) atd.ad_in_data, 167185743Ssam atd.ad_in_size / sizeof(HAL_REGRANGE)); 168185743Ssam atd.ad_out_data = (caddr_t) malloc(atd.ad_out_size); 169185743Ssam if (atd.ad_out_data == NULL) { 170185743Ssam fprintf(stderr, "Cannot malloc output buffer, size %u\n", 171185743Ssam atd.ad_out_size); 172185743Ssam exit(-1); 173185743Ssam } 174185743Ssam atd.ad_id = HAL_DIAG_REGS | ATH_DIAG_IN | ATH_DIAG_DYN; 175185743Ssam if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 176185743Ssam err(1, atd.ad_name); 177185743Ssam 178185743Ssam /* 179185743Ssam * Expand register data into global space that can be 180185743Ssam * indexed directly by register offset. 181185743Ssam */ 182185743Ssam dp = (u_int32_t *)atd.ad_out_data; 183185743Ssam ep = (u_int32_t *)(atd.ad_out_data + atd.ad_out_size); 184185743Ssam while (dp < ep) { 185185743Ssam u_int r = dp[0] >> 16; /* start of range */ 186185743Ssam u_int e = dp[0] & 0xffff; /* end of range */ 187185743Ssam dp++; 188185743Ssam /* convert offsets to indices */ 189185743Ssam r >>= 2; e >>= 2; 190185743Ssam do { 191185743Ssam if (dp >= ep) { 192185743Ssam fprintf(stderr, "Warning, botched return data;" 193185743Ssam "register at offset 0x%x not present\n", 194185743Ssam r << 2); 195185743Ssam break; 196185743Ssam } 197185743Ssam state.regdata[r++] = *dp++; 198185743Ssam } while (r <= e); 199185743Ssam } 200185743Ssam 201185743Ssam if (what & DUMP_BASIC) 202185743Ssam ath_hal_dumpregs(stdout, DUMP_BASIC); 203185743Ssam if ((what & DUMP_INTERRUPT) && ath_hal_anyregs(DUMP_INTERRUPT)) { 204185743Ssam if (what & DUMP_BASIC) 205185743Ssam putchar('\n'); 206185743Ssam if (state.show_addrs) 207185743Ssam ath_hal_dumpregs(stdout, DUMP_INTERRUPT); 208185743Ssam else 209185743Ssam ath_hal_dumpint(stdout, what); 210185743Ssam } 211185743Ssam if ((what & DUMP_QCU) && ath_hal_anyregs(DUMP_QCU)) { 212185743Ssam if (what & (DUMP_BASIC|DUMP_INTERRUPT)) 213185743Ssam putchar('\n'); 214185743Ssam if (state.show_addrs) 215185743Ssam ath_hal_dumpregs(stdout, DUMP_QCU); 216185743Ssam else 217185743Ssam ath_hal_dumpqcu(stdout, what); 218185743Ssam } 219185743Ssam if ((what & DUMP_DCU) && ath_hal_anyregs(DUMP_DCU)) { 220185743Ssam if (what & (DUMP_BASIC|DUMP_INTERRUPT|DUMP_QCU)) 221185743Ssam putchar('\n'); 222185743Ssam if (state.show_addrs) 223185743Ssam ath_hal_dumpregs(stdout, DUMP_DCU); 224185743Ssam else 225185743Ssam ath_hal_dumpdcu(stdout, what); 226185743Ssam } 227185743Ssam if (what & DUMP_KEYCACHE) { 228185743Ssam if (state.show_addrs) { 229185743Ssam if (what & (DUMP_BASIC|DUMP_INTERRUPT|DUMP_QCU|DUMP_DCU)) 230185743Ssam putchar('\n'); 231185743Ssam ath_hal_dumpregs(stdout, DUMP_KEYCACHE); 232185743Ssam } else 233185743Ssam ath_hal_dumpkeycache(stdout, 128); 234185743Ssam } 235185743Ssam if (what & DUMP_BASEBAND) { 236185743Ssam if (what &~ DUMP_BASEBAND) 237185743Ssam fprintf(stdout, "\n"); 238185743Ssam ath_hal_dumpbb(stdout, what); 239185743Ssam } 240185743Ssam return 0; 241185743Ssam} 242185743Ssam 243185743Ssamstatic int 244185743Ssamregcompar(const void *a, const void *b) 245185743Ssam{ 246185743Ssam const struct dumpreg *ra = *(const struct dumpreg **)a; 247185743Ssam const struct dumpreg *rb = *(const struct dumpreg **)b; 248185743Ssam return ra->addr - rb->addr; 249185743Ssam} 250185743Ssam 251185743Ssamvoid 252185743Ssamregister_regs(struct dumpreg *chipregs, u_int nchipregs, 253185743Ssam int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 254185743Ssam{ 255185743Ssam const int existing_regs = state.nregs; 256185743Ssam int i, j; 257185743Ssam 258185743Ssam for (i = 0; i < nchipregs; i++) { 259185743Ssam struct dumpreg *nr = &chipregs[i]; 260185743Ssam if (nr->srevMin == 0) 261185743Ssam nr->srevMin = def_srev_min; 262185743Ssam if (nr->srevMax == 0) 263185743Ssam nr->srevMax = def_srev_max; 264185743Ssam if (nr->phyMin == 0) 265185743Ssam nr->phyMin = def_phy_min; 266185743Ssam if (nr->phyMax == 0) 267185743Ssam nr->phyMax = def_phy_max; 268185743Ssam for (j = 0; j < existing_regs; j++) { 269185743Ssam struct dumpreg *r = state.regs[j]; 270185743Ssam /* 271185743Ssam * Check if we can just expand the mac+phy 272185743Ssam * coverage for the existing entry. 273185743Ssam */ 274185743Ssam if (nr->addr == r->addr && 275185743Ssam (nr->name == r->name || 276185743Ssam nr->name != NULL && r->name != NULL && 277185743Ssam strcmp(nr->name, r->name) == 0)) { 278185743Ssam if (nr->srevMin < r->srevMin && 279185743Ssam (r->srevMin <= nr->srevMax && 280185743Ssam nr->srevMax+1 <= r->srevMax)) { 281185743Ssam r->srevMin = nr->srevMin; 282185743Ssam goto skip; 283185743Ssam } 284185743Ssam if (nr->srevMax > r->srevMax && 285185743Ssam (r->srevMin <= nr->srevMin && 286185743Ssam nr->srevMin <= r->srevMax)) { 287185743Ssam r->srevMax = nr->srevMax; 288185743Ssam goto skip; 289185743Ssam } 290185743Ssam } 291185743Ssam if (r->addr > nr->addr) 292185743Ssam break; 293185743Ssam } 294185743Ssam /* 295185743Ssam * New item, add to the end, it'll be sorted below. 296185743Ssam */ 297185743Ssam if (state.nregs == MAXREGS) 298185743Ssam errx(-1, "too many registers; bump MAXREGS"); 299185743Ssam state.regs[state.nregs++] = nr; 300185743Ssam skip: 301185743Ssam ; 302185743Ssam } 303185743Ssam qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar); 304185743Ssam} 305185743Ssam 306185743Ssamvoid 307185743Ssamregister_keycache(u_int nslots, 308185743Ssam int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 309185743Ssam{ 310185743Ssam#define SET(r, a) do { \ 311185743Ssam r->addr = a; r->type = DUMP_KEYCACHE; r++; \ 312185743Ssam} while(0) 313185743Ssam struct dumpreg *keyregs, *r; 314185743Ssam int i; 315185743Ssam 316185743Ssam keyregs = (struct dumpreg *) calloc(nslots, 8*sizeof(struct dumpreg)); 317185743Ssam if (keyregs == NULL) 318185743Ssam errx(-1, "no space to %d keycache slots\n", nslots); 319185743Ssam r = keyregs; 320185743Ssam for (i = 0; i < nslots; i++) { 321185743Ssam SET(r, AR_KEYTABLE_KEY0(i)); 322185743Ssam SET(r, AR_KEYTABLE_KEY1(i)); 323185743Ssam SET(r, AR_KEYTABLE_KEY2(i)); 324185743Ssam SET(r, AR_KEYTABLE_KEY3(i)); 325185743Ssam SET(r, AR_KEYTABLE_KEY4(i)); 326185743Ssam SET(r, AR_KEYTABLE_TYPE(i)); 327185743Ssam SET(r, AR_KEYTABLE_MAC0(i)); 328185743Ssam SET(r, AR_KEYTABLE_MAC1(i)); 329185743Ssam } 330185743Ssam register_regs(keyregs, 8*nslots, 331185743Ssam def_srev_min, def_srev_max, def_phy_min, def_phy_max); 332185743Ssam#undef SET 333185743Ssam} 334185743Ssam 335185743Ssamvoid 336185743Ssamregister_range(u_int brange, u_int erange, int type, 337185743Ssam int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max) 338185743Ssam{ 339185743Ssam struct dumpreg *bbregs, *r; 340185743Ssam int i, nregs; 341185743Ssam 342185743Ssam nregs = (erange - brange) / sizeof(uint32_t); 343185743Ssam bbregs = (struct dumpreg *) calloc(nregs, sizeof(struct dumpreg)); 344185743Ssam if (bbregs == NULL) 345185743Ssam errx(-1, "no space for %d register slots (type %d)\n", 346185743Ssam nregs, type); 347185743Ssam r = bbregs; 348185743Ssam for (i = 0; i < nregs; i++) { 349185743Ssam r->addr = brange + (i<<2); 350185743Ssam r->type = type; 351185743Ssam r++; 352185743Ssam } 353185743Ssam register_regs(bbregs, nregs, 354185743Ssam def_srev_min, def_srev_max, def_phy_min, def_phy_max); 355185743Ssam} 356185743Ssam 357217680Sadrianstatic __inline int 358185743Ssammatch(const struct dumpreg *dr, const HAL_REVS *revs) 359185743Ssam{ 360185743Ssam if (!MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev)) 361185743Ssam return 0; 362185743Ssam if ((dr->type & DUMP_BASEBAND) && !PHY_MATCH(dr, revs->ah_phyRev)) 363185743Ssam return 0; 364185743Ssam return 1; 365185743Ssam} 366185743Ssam 367185743Ssamstatic int 368185743Ssamath_hal_anyregs(int what) 369185743Ssam{ 370185743Ssam const HAL_REVS *revs = &state.revs; 371185743Ssam int i; 372185743Ssam 373185743Ssam for (i = 0; i < state.nregs; i++) { 374185743Ssam const struct dumpreg *dr = state.regs[i]; 375185743Ssam if ((what & dr->type) && match(dr, revs)) 376185743Ssam return 1; 377185743Ssam } 378185743Ssam return 0; 379185743Ssam} 380185743Ssam 381185743Ssamstatic int 382185743Ssamath_hal_setupregs(struct ath_diag *atd, int what) 383185743Ssam{ 384185743Ssam const HAL_REVS *revs = &state.revs; 385185743Ssam HAL_REGRANGE r; 386185743Ssam size_t space = 0; 387185743Ssam u_int8_t *cp; 388185743Ssam int i, brun, erun; 389185743Ssam 390185743Ssam brun = erun = -1; 391185743Ssam for (i = 0; i < state.nregs; i++) { 392185743Ssam const struct dumpreg *dr = state.regs[i]; 393185743Ssam if ((what & dr->type) && match(dr, revs)) { 394185743Ssam if (erun + 4 != dr->addr) { 395185743Ssam if (brun != -1) 396185743Ssam space += sizeof(HAL_REGRANGE); 397185743Ssam brun = erun = dr->addr; 398185743Ssam } else 399185743Ssam erun = dr->addr; 400185743Ssam } 401185743Ssam } 402185743Ssam space += sizeof(HAL_REGRANGE); 403185743Ssam 404185743Ssam atd->ad_in_data = (caddr_t) malloc(space); 405185743Ssam if (atd->ad_in_data == NULL) { 406185743Ssam fprintf(stderr, "Cannot malloc memory for registers!\n"); 407185743Ssam exit(-1); 408185743Ssam } 409185743Ssam atd->ad_in_size = space; 410185743Ssam cp = (u_int8_t *) atd->ad_in_data; 411185743Ssam brun = erun = -1; 412185743Ssam for (i = 0; i < state.nregs; i++) { 413185743Ssam const struct dumpreg *dr = state.regs[i]; 414185743Ssam if ((what & dr->type) && match(dr, revs)) { 415185743Ssam if (erun + 4 != dr->addr) { 416185743Ssam if (brun != -1) { 417185743Ssam r.start = brun, r.end = erun; 418185743Ssam memcpy(cp, &r, sizeof(r)); 419185743Ssam cp += sizeof(r); 420185743Ssam } 421185743Ssam brun = erun = dr->addr; 422185743Ssam } else 423185743Ssam erun = dr->addr; 424185743Ssam } 425185743Ssam } 426185743Ssam if (brun != -1) { 427185743Ssam r.start = brun, r.end = erun; 428185743Ssam memcpy(cp, &r, sizeof(r)); 429185743Ssam cp += sizeof(r); 430185743Ssam } 431185743Ssam return space / sizeof(uint32_t); 432185743Ssam} 433185743Ssam 434185743Ssamstatic void 435185743Ssamath_hal_dumpregs(FILE *fd, int what) 436185743Ssam{ 437185743Ssam const HAL_REVS *revs = &state.revs; 438185743Ssam const char *sep = ""; 439185743Ssam int i, count, itemsperline; 440185743Ssam 441185743Ssam count = 0; 442185743Ssam itemsperline = 4; 443185743Ssam if (state.show_names && state.show_addrs) 444185743Ssam itemsperline--; 445185743Ssam for (i = 0; i < state.nregs; i++) { 446185743Ssam const struct dumpreg *dr = state.regs[i]; 447185743Ssam if ((what & dr->type) && match(dr, revs)) { 448185743Ssam if (state.show_names && dr->name != NULL) { 449185743Ssam fprintf(fd, "%s%-8s", sep, dr->name); 450185743Ssam if (state.show_addrs) 451185743Ssam fprintf(fd, " [%04x]", dr->addr); 452185743Ssam } else 453185743Ssam fprintf(fd, "%s%04x", sep, dr->addr); 454185743Ssam fprintf(fd, " %08x", OS_REG_READ(ah, dr->addr)); 455185743Ssam sep = " "; 456185743Ssam if ((++count % itemsperline) == 0) 457185743Ssam sep = "\n"; 458185743Ssam } 459185743Ssam } 460185743Ssam if (count) 461185743Ssam fprintf(fd, "\n"); 462185743Ssam} 463185743Ssam 464185743Ssamstatic void 465185743Ssamath_hal_dumprange(FILE *fd, u_int a, u_int b) 466185743Ssam{ 467185743Ssam u_int r; 468185743Ssam 469185743Ssam for (r = a; r+16 <= b; r += 5*4) 470185743Ssam fprintf(fd, 471185743Ssam "%04x %08x %04x %08x %04x %08x %04x %08x %04x %08x\n" 472185743Ssam , r, OS_REG_READ(ah, r) 473185743Ssam , r+4, OS_REG_READ(ah, r+4) 474185743Ssam , r+8, OS_REG_READ(ah, r+8) 475185743Ssam , r+12, OS_REG_READ(ah, r+12) 476185743Ssam , r+16, OS_REG_READ(ah, r+16) 477185743Ssam ); 478185743Ssam switch (b-r) { 479185743Ssam case 16: 480185743Ssam fprintf(fd 481185743Ssam , "%04x %08x %04x %08x %04x %08x %04x %08x\n" 482185743Ssam , r, OS_REG_READ(ah, r) 483185743Ssam , r+4, OS_REG_READ(ah, r+4) 484185743Ssam , r+8, OS_REG_READ(ah, r+8) 485185743Ssam , r+12, OS_REG_READ(ah, r+12) 486185743Ssam ); 487185743Ssam break; 488185743Ssam case 12: 489185743Ssam fprintf(fd, "%04x %08x %04x %08x %04x %08x\n" 490185743Ssam , r, OS_REG_READ(ah, r) 491185743Ssam , r+4, OS_REG_READ(ah, r+4) 492185743Ssam , r+8, OS_REG_READ(ah, r+8) 493185743Ssam ); 494185743Ssam break; 495185743Ssam case 8: 496185743Ssam fprintf(fd, "%04x %08x %04x %08x\n" 497185743Ssam , r, OS_REG_READ(ah, r) 498185743Ssam , r+4, OS_REG_READ(ah, r+4) 499185743Ssam ); 500185743Ssam break; 501185743Ssam case 4: 502185743Ssam fprintf(fd, "%04x %08x\n" 503185743Ssam , r, OS_REG_READ(ah, r) 504185743Ssam ); 505185743Ssam break; 506185743Ssam } 507185743Ssam} 508185743Ssam 509185743Ssamstatic void 510185743Ssamath_hal_dumpint(FILE *fd, int what) 511185743Ssam{ 512185743Ssam int i; 513185743Ssam 514185743Ssam /* Interrupt registers */ 515185743Ssam fprintf(fd, "IMR: %08x S0 %08x S1 %08x S2 %08x S3 %08x S4 %08x\n" 516185743Ssam , OS_REG_READ(ah, AR_IMR) 517185743Ssam , OS_REG_READ(ah, AR_IMR_S0) 518185743Ssam , OS_REG_READ(ah, AR_IMR_S1) 519185743Ssam , OS_REG_READ(ah, AR_IMR_S2) 520185743Ssam , OS_REG_READ(ah, AR_IMR_S3) 521185743Ssam , OS_REG_READ(ah, AR_IMR_S4) 522185743Ssam ); 523185743Ssam fprintf(fd, "ISR: %08x S0 %08x S1 %08x S2 %08x S3 %08x S4 %08x\n" 524185743Ssam , OS_REG_READ(ah, AR_ISR) 525185743Ssam , OS_REG_READ(ah, AR_ISR_S0) 526185743Ssam , OS_REG_READ(ah, AR_ISR_S1) 527185743Ssam , OS_REG_READ(ah, AR_ISR_S2) 528185743Ssam , OS_REG_READ(ah, AR_ISR_S3) 529185743Ssam , OS_REG_READ(ah, AR_ISR_S4) 530185743Ssam ); 531185743Ssam} 532185743Ssam 533185743Ssamstatic void 534185743Ssamath_hal_dumpqcu(FILE *fd, int what) 535185743Ssam{ 536185743Ssam int i; 537185743Ssam 538185743Ssam /* QCU registers */ 539185743Ssam fprintf(fd, "%-8s %08x %-8s %08x %-8s %08x\n" 540185743Ssam , "Q_TXE", OS_REG_READ(ah, AR_Q_TXE) 541185743Ssam , "Q_TXD", OS_REG_READ(ah, AR_Q_TXD) 542185743Ssam , "Q_RDYTIMSHD", OS_REG_READ(ah, AR_Q_RDYTIMESHDN) 543185743Ssam ); 544185743Ssam fprintf(fd, "Q_ONESHOTARM_SC %08x Q_ONESHOTARM_CC %08x\n" 545185743Ssam , OS_REG_READ(ah, AR_Q_ONESHOTARM_SC) 546185743Ssam , OS_REG_READ(ah, AR_Q_ONESHOTARM_CC) 547185743Ssam ); 548185743Ssam for (i = 0; i < 10; i++) 549185743Ssam fprintf(fd, "Q[%u] TXDP %08x CBR %08x RDYT %08x MISC %08x STS %08x\n" 550185743Ssam , i 551185743Ssam , OS_REG_READ(ah, AR_QTXDP(i)) 552185743Ssam , OS_REG_READ(ah, AR_QCBRCFG(i)) 553185743Ssam , OS_REG_READ(ah, AR_QRDYTIMECFG(i)) 554185743Ssam , OS_REG_READ(ah, AR_QMISC(i)) 555185743Ssam , OS_REG_READ(ah, AR_QSTS(i)) 556185743Ssam ); 557185743Ssam} 558185743Ssam 559185743Ssamstatic void 560185743Ssamath_hal_dumpdcu(FILE *fd, int what) 561185743Ssam{ 562185743Ssam int i; 563185743Ssam 564185743Ssam /* DCU registers */ 565185743Ssam for (i = 0; i < 10; i++) 566185743Ssam fprintf(fd, "D[%u] MASK %08x IFS %08x RTRY %08x CHNT %08x MISC %06x\n" 567185743Ssam , i 568185743Ssam , OS_REG_READ(ah, AR_DQCUMASK(i)) 569185743Ssam , OS_REG_READ(ah, AR_DLCL_IFS(i)) 570185743Ssam , OS_REG_READ(ah, AR_DRETRY_LIMIT(i)) 571185743Ssam , OS_REG_READ(ah, AR_DCHNTIME(i)) 572185743Ssam , OS_REG_READ(ah, AR_DMISC(i)) 573185743Ssam ); 574185743Ssam} 575185743Ssam 576185743Ssamstatic void 577185743Ssamath_hal_dumpbb(FILE *fd, int what) 578185743Ssam{ 579185743Ssam const HAL_REVS *revs = &state.revs; 580185743Ssam int i, brun, erun; 581185743Ssam 582185743Ssam brun = erun = 0; 583185743Ssam for (i = 0; i < state.nregs; i++) { 584185743Ssam const struct dumpreg *dr = state.regs[i]; 585185743Ssam if (!match(dr, revs)) 586185743Ssam continue; 587185743Ssam if (dr->type & DUMP_BASEBAND) { 588185743Ssam if (brun == 0) { 589185743Ssam brun = erun = dr->addr; 590185743Ssam } else if (dr->addr == erun + sizeof(uint32_t)) { 591185743Ssam erun = dr->addr; 592185743Ssam } else { 593185743Ssam ath_hal_dumprange(fd, brun, erun); 594185743Ssam brun = erun = dr->addr; 595185743Ssam } 596185743Ssam } else { 597185743Ssam if (brun != 0) 598185743Ssam ath_hal_dumprange(fd, brun, erun); 599185743Ssam brun = erun = 0; 600185743Ssam } 601185743Ssam } 602185743Ssam if (brun != 0) 603185743Ssam ath_hal_dumprange(fd, brun, erun); 604185743Ssam} 605185743Ssam 606185743Ssamstatic u_int 607185743Ssamath_hal_setupdiagregs(const HAL_REGRANGE regs[], u_int nr) 608185743Ssam{ 609185743Ssam u_int space; 610185743Ssam int i; 611185743Ssam 612185743Ssam space = 0; 613185743Ssam for (i = 0; i < nr; i++) { 614185743Ssam u_int n = 2 * sizeof(u_int32_t); /* reg range + first */ 615185743Ssam if (regs[i].end) { 616185743Ssam if (regs[i].end < regs[i].start) { 617185743Ssam fprintf(stderr, "%s: bad register range, " 618185743Ssam "end 0x%x < start 0x%x\n", 619185743Ssam __func__, regs[i].end, regs[i].end); 620185743Ssam exit(-1); 621185743Ssam } 622185743Ssam n += regs[i].end - regs[i].start; 623185743Ssam } 624185743Ssam space += n; 625185743Ssam } 626185743Ssam return space; 627185743Ssam} 628185743Ssam 629185743Ssam/* 630185743Ssam * Format an Ethernet MAC for printing. 631185743Ssam */ 632185743Ssamstatic const char* 633185743Ssamether_sprintf(const u_int8_t *mac) 634185743Ssam{ 635185743Ssam static char etherbuf[18]; 636185743Ssam snprintf(etherbuf, sizeof(etherbuf), "%02x:%02x:%02x:%02x:%02x:%02x", 637185743Ssam mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 638185743Ssam return etherbuf; 639185743Ssam} 640185743Ssam 641185743Ssam#ifndef isclr 642185743Ssam#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) 643185743Ssam#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) 644185743Ssam#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) 645185743Ssam#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) 646185743Ssam#endif 647185743Ssam 648185743Ssamstatic void 649185743Ssamath_hal_dumpkeycache(FILE *fd, int nkeys) 650185743Ssam{ 651185743Ssam static const char *keytypenames[] = { 652185743Ssam "WEP-40", /* AR_KEYTABLE_TYPE_40 */ 653185743Ssam "WEP-104", /* AR_KEYTABLE_TYPE_104 */ 654185743Ssam "#2", 655185743Ssam "WEP-128", /* AR_KEYTABLE_TYPE_128 */ 656185743Ssam "TKIP", /* AR_KEYTABLE_TYPE_TKIP */ 657185743Ssam "AES-OCB", /* AR_KEYTABLE_TYPE_AES */ 658185743Ssam "AES-CCM", /* AR_KEYTABLE_TYPE_CCM */ 659185743Ssam "CLR", /* AR_KEYTABLE_TYPE_CLR */ 660185743Ssam }; 661185743Ssam int micEnabled = SREV(state.revs.ah_macVersion, state.revs.ah_macRev) < SREV(4,8) ? 0 : 662185743Ssam OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_CRPT_MIC_ENABLE; 663185743Ssam u_int8_t mac[IEEE80211_ADDR_LEN]; 664185743Ssam u_int8_t ismic[128/NBBY]; 665185743Ssam int entry; 666185743Ssam int first = 1; 667185743Ssam 668185743Ssam memset(ismic, 0, sizeof(ismic)); 669185743Ssam for (entry = 0; entry < nkeys; entry++) { 670185743Ssam u_int32_t macLo, macHi, type; 671185743Ssam u_int32_t key0, key1, key2, key3, key4; 672185743Ssam 673185743Ssam macHi = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); 674185743Ssam if ((macHi & AR_KEYTABLE_VALID) == 0 && isclr(ismic, entry)) 675185743Ssam continue; 676185743Ssam macLo = OS_REG_READ(ah, AR_KEYTABLE_MAC0(entry)); 677185743Ssam macHi <<= 1; 678185743Ssam if (macLo & (1<<31)) 679185743Ssam macHi |= 1; 680185743Ssam macLo <<= 1; 681185743Ssam mac[4] = macHi & 0xff; 682185743Ssam mac[5] = macHi >> 8; 683185743Ssam mac[0] = macLo & 0xff; 684185743Ssam mac[1] = macLo >> 8; 685185743Ssam mac[2] = macLo >> 16; 686185743Ssam mac[3] = macLo >> 24; 687185743Ssam type = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)); 688185743Ssam if ((type & 7) == AR_KEYTABLE_TYPE_TKIP && micEnabled) 689185743Ssam setbit(ismic, entry+64); 690185743Ssam key0 = OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)); 691185743Ssam key1 = OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)); 692185743Ssam key2 = OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)); 693185743Ssam key3 = OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)); 694185743Ssam key4 = OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)); 695185743Ssam if (first) { 696185743Ssam fprintf(fd, "\n"); 697185743Ssam first = 0; 698185743Ssam } 699185743Ssam fprintf(fd, "KEY[%03u] MAC %s %-7s %02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x\n" 700185743Ssam , entry 701185743Ssam , ether_sprintf(mac) 702185743Ssam , isset(ismic, entry) ? "MIC" : keytypenames[type & 7] 703185743Ssam , (key0 >> 0) & 0xff 704185743Ssam , (key0 >> 8) & 0xff 705185743Ssam , (key0 >> 16) & 0xff 706185743Ssam , (key0 >> 24) & 0xff 707185743Ssam , (key1 >> 0) & 0xff 708185743Ssam , (key1 >> 8) & 0xff 709185743Ssam , (key2 >> 0) & 0xff 710185743Ssam , (key2 >> 8) & 0xff 711185743Ssam , (key2 >> 16) & 0xff 712185743Ssam , (key2 >> 24) & 0xff 713185743Ssam , (key3 >> 0) & 0xff 714185743Ssam , (key3 >> 8) & 0xff 715185743Ssam , (key4 >> 0) & 0xff 716185743Ssam , (key4 >> 8) & 0xff 717185743Ssam , (key4 >> 16) & 0xff 718185743Ssam , (key4 >> 24) & 0xff 719185743Ssam ); 720185743Ssam } 721185743Ssam} 722