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