1 /*-
2 * Copyright (c) 2002-2008 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 #include "diag.h"
30
31 #include "ah.h"
32 #include "ah_internal.h"
33 /* XXX cheat, 5212 has a superset of the key table defs */
34 #include "ar5212/ar5212reg.h"
35
36 #include "dumpregs.h"
37
38 #include <getopt.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <err.h>
43
44 #include "ctrl.h"
45
46 typedef struct {
47 HAL_REVS revs;
48 u_int32_t regdata[0xffff / sizeof(u_int32_t)];
49 #define MAXREGS 5*1024
50 struct dumpreg *regs[MAXREGS];
51 u_int nregs;
52 u_int show_names : 1,
53 show_addrs : 1;
54 } dumpregs_t;
55 static dumpregs_t state;
56
57 #undef OS_REG_READ
58 #define OS_REG_READ(ah, off) state.regdata[(off) >> 2]
59
60 static int ath_hal_anyregs(int what);
61 static int ath_hal_setupregs(struct ath_diag *atd, int what);
62 static u_int ath_hal_setupdiagregs(const HAL_REGRANGE regs[], u_int nr);
63 static void ath_hal_dumpregs(FILE *fd, int what);
64 static void ath_hal_dumprange(FILE *fd, u_int a, u_int b);
65 static void ath_hal_dumpkeycache(FILE *fd, int nkeys);
66 static void ath_hal_dumpint(FILE *fd, int what);
67 static void ath_hal_dumpqcu(FILE *fd, int what);
68 static void ath_hal_dumpdcu(FILE *fd, int what);
69 static void ath_hal_dumpbb(FILE *fd, int what);
70
71 static void
usage(void)72 usage(void)
73 {
74 fprintf(stderr, "usage: athregs [-i interface] [-abdkmqxz]\n");
75 fprintf(stderr, "-a display all registers\n");
76 fprintf(stderr, "-b display baseband registers\n");
77 fprintf(stderr, "-d display DCU registers\n");
78 fprintf(stderr, "-k display key cache registers\n");
79 fprintf(stderr, "-m display \"MAC\" registers (default)\n");
80 fprintf(stderr, "-q display QCU registers\n");
81 fprintf(stderr, "-x display XR registers\n");
82 fprintf(stderr, "-z display interrupt registers\n");
83 fprintf(stderr, "\n");
84 fprintf(stderr, "-A display register address\n");
85 fprintf(stderr, "-N suppress display of register name\n");
86 exit(-1);
87 }
88
89 int
main(int argc,char * argv[])90 main(int argc, char *argv[])
91 {
92 struct ath_diag atd;
93 const char *ifname;
94 u_int32_t *data;
95 u_int32_t *dp, *ep;
96 int what, c, i;
97 struct ath_driver_req req;
98
99 ath_driver_req_init(&req);
100
101 ifname = getenv("ATH");
102 if (!ifname)
103 ifname = ATH_DEFAULT;
104
105 what = 0;
106 state.show_addrs = 0;
107 state.show_names = 1;
108 while ((c = getopt(argc, argv, "i:aAbdkmNqxz")) != -1)
109 switch (c) {
110 case 'a':
111 what |= DUMP_ALL;
112 break;
113 case 'A':
114 state.show_addrs = 1;
115 break;
116 case 'b':
117 what |= DUMP_BASEBAND;
118 break;
119 case 'd':
120 what |= DUMP_DCU;
121 break;
122 case 'k':
123 what |= DUMP_KEYCACHE;
124 break;
125 case 'i':
126 ifname = optarg;
127 break;
128 case 'm':
129 what |= DUMP_BASIC;
130 break;
131 case 'N':
132 state.show_names = 0;
133 break;
134 case 'q':
135 what |= DUMP_QCU;
136 break;
137 case 'x':
138 what |= DUMP_XR;
139 break;
140 case 'z':
141 what |= DUMP_INTERRUPT;
142 break;
143 default:
144 usage();
145 /*NOTREACHED*/
146 }
147
148 /* Initialise the driver interface */
149 if (ath_driver_req_open(&req, ifname) < 0) {
150 exit(127);
151 }
152
153 /*
154 * Whilst we're doing the ath_diag pieces, we have to set this
155 * ourselves.
156 */
157 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
158
159 argc -= optind;
160 argv += optind;
161 if (what == 0)
162 what = DUMP_BASIC;
163
164 atd.ad_id = HAL_DIAG_REVS;
165 atd.ad_out_data = (caddr_t) &state.revs;
166 atd.ad_out_size = sizeof(state.revs);
167
168 if (ath_driver_req_fetch_diag(&req, SIOCGATHDIAG, &atd) < 0)
169 err(1, "%s", atd.ad_name);
170
171 if (ath_hal_setupregs(&atd, what) == 0)
172 errx(-1, "no registers are known for this part "
173 "(devid 0x%x mac %d.%d phy %d)", state.revs.ah_devid,
174 state.revs.ah_macVersion, state.revs.ah_macRev,
175 state.revs.ah_phyRev);
176
177 atd.ad_out_size = ath_hal_setupdiagregs((HAL_REGRANGE *) atd.ad_in_data,
178 atd.ad_in_size / sizeof(HAL_REGRANGE));
179 atd.ad_out_data = (caddr_t) malloc(atd.ad_out_size);
180 if (atd.ad_out_data == NULL) {
181 fprintf(stderr, "Cannot malloc output buffer, size %u\n",
182 atd.ad_out_size);
183 exit(-1);
184 }
185 atd.ad_id = HAL_DIAG_REGS | ATH_DIAG_IN | ATH_DIAG_DYN;
186
187 if (ath_driver_req_fetch_diag(&req, SIOCGATHDIAG, &atd) < 0)
188 err(1, "%s", atd.ad_name);
189
190 /*
191 * Expand register data into global space that can be
192 * indexed directly by register offset.
193 */
194 dp = (u_int32_t *)atd.ad_out_data;
195 ep = (u_int32_t *)(atd.ad_out_data + atd.ad_out_size);
196 while (dp < ep) {
197 u_int r = dp[0]; /* start of range */
198 u_int e = dp[1]; /* end of range */
199 dp++;
200 dp++;
201 /* convert offsets to indices */
202 r >>= 2; e >>= 2;
203 do {
204 if (dp >= ep) {
205 fprintf(stderr, "Warning, botched return data;"
206 "register at offset 0x%x not present\n",
207 r << 2);
208 break;
209 }
210 state.regdata[r++] = *dp++;
211 } while (r <= e);
212 }
213
214 if (what & DUMP_BASIC)
215 ath_hal_dumpregs(stdout, DUMP_BASIC);
216 if ((what & DUMP_INTERRUPT) && ath_hal_anyregs(DUMP_INTERRUPT)) {
217 if (what & DUMP_BASIC)
218 putchar('\n');
219 if (state.show_addrs)
220 ath_hal_dumpregs(stdout, DUMP_INTERRUPT);
221 else
222 ath_hal_dumpint(stdout, what);
223 }
224 if ((what & DUMP_QCU) && ath_hal_anyregs(DUMP_QCU)) {
225 if (what & (DUMP_BASIC|DUMP_INTERRUPT))
226 putchar('\n');
227 if (state.show_addrs)
228 ath_hal_dumpregs(stdout, DUMP_QCU);
229 else
230 ath_hal_dumpqcu(stdout, what);
231 }
232 if ((what & DUMP_DCU) && ath_hal_anyregs(DUMP_DCU)) {
233 if (what & (DUMP_BASIC|DUMP_INTERRUPT|DUMP_QCU))
234 putchar('\n');
235 if (state.show_addrs)
236 ath_hal_dumpregs(stdout, DUMP_DCU);
237 else
238 ath_hal_dumpdcu(stdout, what);
239 }
240 if (what & DUMP_KEYCACHE) {
241 if (state.show_addrs) {
242 if (what & (DUMP_BASIC|DUMP_INTERRUPT|DUMP_QCU|DUMP_DCU))
243 putchar('\n');
244 ath_hal_dumpregs(stdout, DUMP_KEYCACHE);
245 } else
246 ath_hal_dumpkeycache(stdout, 128);
247 }
248 if (what & DUMP_BASEBAND) {
249 if (what &~ DUMP_BASEBAND)
250 fprintf(stdout, "\n");
251 ath_hal_dumpbb(stdout, what);
252 }
253 ath_driver_req_close(&req);
254 return 0;
255 }
256
257 static int
regcompar(const void * a,const void * b)258 regcompar(const void *a, const void *b)
259 {
260 const struct dumpreg *ra = *(const struct dumpreg **)a;
261 const struct dumpreg *rb = *(const struct dumpreg **)b;
262 return ra->addr - rb->addr;
263 }
264
265 void
register_regs(struct dumpreg * chipregs,u_int nchipregs,int def_srev_min,int def_srev_max,int def_phy_min,int def_phy_max)266 register_regs(struct dumpreg *chipregs, u_int nchipregs,
267 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
268 {
269 const int existing_regs = state.nregs;
270 int i, j;
271
272 for (i = 0; i < nchipregs; i++) {
273 struct dumpreg *nr = &chipregs[i];
274 if (nr->srevMin == 0)
275 nr->srevMin = def_srev_min;
276 if (nr->srevMax == 0)
277 nr->srevMax = def_srev_max;
278 if (nr->phyMin == 0)
279 nr->phyMin = def_phy_min;
280 if (nr->phyMax == 0)
281 nr->phyMax = def_phy_max;
282 for (j = 0; j < existing_regs; j++) {
283 struct dumpreg *r = state.regs[j];
284 /*
285 * Check if we can just expand the mac+phy
286 * coverage for the existing entry.
287 */
288 if (nr->addr == r->addr &&
289 (nr->name == r->name ||
290 nr->name != NULL && r->name != NULL &&
291 strcmp(nr->name, r->name) == 0)) {
292 if (nr->srevMin < r->srevMin &&
293 (r->srevMin <= nr->srevMax &&
294 nr->srevMax+1 <= r->srevMax)) {
295 r->srevMin = nr->srevMin;
296 goto skip;
297 }
298 if (nr->srevMax > r->srevMax &&
299 (r->srevMin <= nr->srevMin &&
300 nr->srevMin <= r->srevMax)) {
301 r->srevMax = nr->srevMax;
302 goto skip;
303 }
304 }
305 if (r->addr > nr->addr)
306 break;
307 }
308 /*
309 * New item, add to the end, it'll be sorted below.
310 */
311 if (state.nregs == MAXREGS)
312 errx(-1, "too many registers; bump MAXREGS");
313 state.regs[state.nregs++] = nr;
314 skip:
315 ;
316 }
317 qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar);
318 }
319
320 void
register_keycache(u_int nslots,int def_srev_min,int def_srev_max,int def_phy_min,int def_phy_max)321 register_keycache(u_int nslots,
322 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
323 {
324 #define SET(r, a) do { \
325 r->addr = a; r->type = DUMP_KEYCACHE; r++; \
326 } while(0)
327 struct dumpreg *keyregs, *r;
328 int i;
329
330 keyregs = (struct dumpreg *) calloc(nslots, 8*sizeof(struct dumpreg));
331 if (keyregs == NULL)
332 errx(-1, "no space to %d keycache slots\n", nslots);
333 r = keyregs;
334 for (i = 0; i < nslots; i++) {
335 SET(r, AR_KEYTABLE_KEY0(i));
336 SET(r, AR_KEYTABLE_KEY1(i));
337 SET(r, AR_KEYTABLE_KEY2(i));
338 SET(r, AR_KEYTABLE_KEY3(i));
339 SET(r, AR_KEYTABLE_KEY4(i));
340 SET(r, AR_KEYTABLE_TYPE(i));
341 SET(r, AR_KEYTABLE_MAC0(i));
342 SET(r, AR_KEYTABLE_MAC1(i));
343 }
344 register_regs(keyregs, 8*nslots,
345 def_srev_min, def_srev_max, def_phy_min, def_phy_max);
346 #undef SET
347 }
348
349 void
register_range(u_int brange,u_int erange,int type,int def_srev_min,int def_srev_max,int def_phy_min,int def_phy_max)350 register_range(u_int brange, u_int erange, int type,
351 int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
352 {
353 struct dumpreg *bbregs, *r;
354 int i, nregs;
355
356 nregs = (erange - brange) / sizeof(uint32_t);
357 bbregs = (struct dumpreg *) calloc(nregs, sizeof(struct dumpreg));
358 if (bbregs == NULL)
359 errx(-1, "no space for %d register slots (type %d)\n",
360 nregs, type);
361 r = bbregs;
362 for (i = 0; i < nregs; i++) {
363 r->addr = brange + (i<<2);
364 r->type = type;
365 r++;
366 }
367 register_regs(bbregs, nregs,
368 def_srev_min, def_srev_max, def_phy_min, def_phy_max);
369 }
370
371 static __inline int
match(const struct dumpreg * dr,const HAL_REVS * revs)372 match(const struct dumpreg *dr, const HAL_REVS *revs)
373 {
374 if (!MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev))
375 return 0;
376 if ((dr->type & DUMP_BASEBAND) && !PHY_MATCH(dr, revs->ah_phyRev))
377 return 0;
378 return 1;
379 }
380
381 static int
ath_hal_anyregs(int what)382 ath_hal_anyregs(int what)
383 {
384 const HAL_REVS *revs = &state.revs;
385 int i;
386
387 for (i = 0; i < state.nregs; i++) {
388 const struct dumpreg *dr = state.regs[i];
389 if ((what & dr->type) && match(dr, revs))
390 return 1;
391 }
392 return 0;
393 }
394
395 static int
ath_hal_setupregs(struct ath_diag * atd,int what)396 ath_hal_setupregs(struct ath_diag *atd, int what)
397 {
398 const HAL_REVS *revs = &state.revs;
399 HAL_REGRANGE r;
400 size_t space = 0;
401 u_int8_t *cp;
402 int i, brun, erun;
403
404 brun = erun = -1;
405 for (i = 0; i < state.nregs; i++) {
406 const struct dumpreg *dr = state.regs[i];
407 if ((what & dr->type) && match(dr, revs)) {
408 if (erun + 4 != dr->addr) {
409 if (brun != -1)
410 space += sizeof(HAL_REGRANGE);
411 brun = erun = dr->addr;
412 } else
413 erun = dr->addr;
414 }
415 }
416 space += sizeof(HAL_REGRANGE);
417
418 atd->ad_in_data = (caddr_t) malloc(space);
419 if (atd->ad_in_data == NULL) {
420 fprintf(stderr, "Cannot malloc memory for registers!\n");
421 exit(-1);
422 }
423 atd->ad_in_size = space;
424 cp = (u_int8_t *) atd->ad_in_data;
425 brun = erun = -1;
426 for (i = 0; i < state.nregs; i++) {
427 const struct dumpreg *dr = state.regs[i];
428 if ((what & dr->type) && match(dr, revs)) {
429 if (erun + 4 != dr->addr) {
430 if (brun != -1) {
431 r.start = brun, r.end = erun;
432 memcpy(cp, &r, sizeof(r));
433 cp += sizeof(r);
434 }
435 brun = erun = dr->addr;
436 } else
437 erun = dr->addr;
438 }
439 }
440 if (brun != -1) {
441 r.start = brun, r.end = erun;
442 memcpy(cp, &r, sizeof(r));
443 cp += sizeof(r);
444 }
445 return space / sizeof(uint32_t);
446 }
447
448 static void
ath_hal_dumpregs(FILE * fd,int what)449 ath_hal_dumpregs(FILE *fd, int what)
450 {
451 const HAL_REVS *revs = &state.revs;
452 const char *sep = "";
453 int i, count, itemsperline;
454
455 count = 0;
456 itemsperline = 4;
457 if (state.show_names && state.show_addrs)
458 itemsperline--;
459 for (i = 0; i < state.nregs; i++) {
460 const struct dumpreg *dr = state.regs[i];
461 if ((what & dr->type) && match(dr, revs)) {
462 if (state.show_names && dr->name != NULL) {
463 fprintf(fd, "%s%-8s", sep, dr->name);
464 if (state.show_addrs)
465 fprintf(fd, " [%04x]", dr->addr);
466 } else
467 fprintf(fd, "%s%04x", sep, dr->addr);
468 fprintf(fd, " %08x", OS_REG_READ(ah, dr->addr));
469 sep = " ";
470 if ((++count % itemsperline) == 0)
471 sep = "\n";
472 }
473 }
474 if (count)
475 fprintf(fd, "\n");
476 }
477
478 static void
ath_hal_dumprange(FILE * fd,u_int a,u_int b)479 ath_hal_dumprange(FILE *fd, u_int a, u_int b)
480 {
481 u_int r;
482
483 for (r = a; r+16 <= b; r += 5*4)
484 fprintf(fd,
485 "%04x %08x %04x %08x %04x %08x %04x %08x %04x %08x\n"
486 , r, OS_REG_READ(ah, r)
487 , r+4, OS_REG_READ(ah, r+4)
488 , r+8, OS_REG_READ(ah, r+8)
489 , r+12, OS_REG_READ(ah, r+12)
490 , r+16, OS_REG_READ(ah, r+16)
491 );
492 switch (b-r) {
493 case 16:
494 fprintf(fd
495 , "%04x %08x %04x %08x %04x %08x %04x %08x\n"
496 , r, OS_REG_READ(ah, r)
497 , r+4, OS_REG_READ(ah, r+4)
498 , r+8, OS_REG_READ(ah, r+8)
499 , r+12, OS_REG_READ(ah, r+12)
500 );
501 break;
502 case 12:
503 fprintf(fd, "%04x %08x %04x %08x %04x %08x\n"
504 , r, OS_REG_READ(ah, r)
505 , r+4, OS_REG_READ(ah, r+4)
506 , r+8, OS_REG_READ(ah, r+8)
507 );
508 break;
509 case 8:
510 fprintf(fd, "%04x %08x %04x %08x\n"
511 , r, OS_REG_READ(ah, r)
512 , r+4, OS_REG_READ(ah, r+4)
513 );
514 break;
515 case 4:
516 fprintf(fd, "%04x %08x\n"
517 , r, OS_REG_READ(ah, r)
518 );
519 break;
520 }
521 }
522
523 static void
ath_hal_dumpint(FILE * fd,int what)524 ath_hal_dumpint(FILE *fd, int what)
525 {
526 int i;
527
528 /* Interrupt registers */
529 fprintf(fd, "IMR: %08x S0 %08x S1 %08x S2 %08x S3 %08x S4 %08x\n"
530 , OS_REG_READ(ah, AR_IMR)
531 , OS_REG_READ(ah, AR_IMR_S0)
532 , OS_REG_READ(ah, AR_IMR_S1)
533 , OS_REG_READ(ah, AR_IMR_S2)
534 , OS_REG_READ(ah, AR_IMR_S3)
535 , OS_REG_READ(ah, AR_IMR_S4)
536 );
537 fprintf(fd, "ISR: %08x S0 %08x S1 %08x S2 %08x S3 %08x S4 %08x\n"
538 , OS_REG_READ(ah, AR_ISR)
539 , OS_REG_READ(ah, AR_ISR_S0)
540 , OS_REG_READ(ah, AR_ISR_S1)
541 , OS_REG_READ(ah, AR_ISR_S2)
542 , OS_REG_READ(ah, AR_ISR_S3)
543 , OS_REG_READ(ah, AR_ISR_S4)
544 );
545 }
546
547 static void
ath_hal_dumpqcu(FILE * fd,int what)548 ath_hal_dumpqcu(FILE *fd, int what)
549 {
550 int i;
551
552 /* QCU registers */
553 fprintf(fd, "%-8s %08x %-8s %08x %-8s %08x\n"
554 , "Q_TXE", OS_REG_READ(ah, AR_Q_TXE)
555 , "Q_TXD", OS_REG_READ(ah, AR_Q_TXD)
556 , "Q_RDYTIMSHD", OS_REG_READ(ah, AR_Q_RDYTIMESHDN)
557 );
558 fprintf(fd, "Q_ONESHOTARM_SC %08x Q_ONESHOTARM_CC %08x\n"
559 , OS_REG_READ(ah, AR_Q_ONESHOTARM_SC)
560 , OS_REG_READ(ah, AR_Q_ONESHOTARM_CC)
561 );
562 for (i = 0; i < 10; i++)
563 fprintf(fd, "Q[%u] TXDP %08x CBR %08x RDYT %08x MISC %08x STS %08x\n"
564 , i
565 , OS_REG_READ(ah, AR_QTXDP(i))
566 , OS_REG_READ(ah, AR_QCBRCFG(i))
567 , OS_REG_READ(ah, AR_QRDYTIMECFG(i))
568 , OS_REG_READ(ah, AR_QMISC(i))
569 , OS_REG_READ(ah, AR_QSTS(i))
570 );
571 }
572
573 static void
ath_hal_dumpdcu(FILE * fd,int what)574 ath_hal_dumpdcu(FILE *fd, int what)
575 {
576 int i;
577
578 /* DCU registers */
579 for (i = 0; i < 10; i++)
580 fprintf(fd, "D[%u] MASK %08x IFS %08x RTRY %08x CHNT %08x MISC %06x\n"
581 , i
582 , OS_REG_READ(ah, AR_DQCUMASK(i))
583 , OS_REG_READ(ah, AR_DLCL_IFS(i))
584 , OS_REG_READ(ah, AR_DRETRY_LIMIT(i))
585 , OS_REG_READ(ah, AR_DCHNTIME(i))
586 , OS_REG_READ(ah, AR_DMISC(i))
587 );
588 }
589
590 static void
ath_hal_dumpbb(FILE * fd,int what)591 ath_hal_dumpbb(FILE *fd, int what)
592 {
593 const HAL_REVS *revs = &state.revs;
594 int i, brun, erun;
595
596 brun = erun = 0;
597 for (i = 0; i < state.nregs; i++) {
598 const struct dumpreg *dr = state.regs[i];
599 if (!match(dr, revs))
600 continue;
601 if (dr->type & DUMP_BASEBAND) {
602 if (brun == 0) {
603 brun = erun = dr->addr;
604 } else if (dr->addr == erun + sizeof(uint32_t)) {
605 erun = dr->addr;
606 } else {
607 ath_hal_dumprange(fd, brun, erun);
608 brun = erun = dr->addr;
609 }
610 } else {
611 if (brun != 0)
612 ath_hal_dumprange(fd, brun, erun);
613 brun = erun = 0;
614 }
615 }
616 if (brun != 0)
617 ath_hal_dumprange(fd, brun, erun);
618 }
619
620 static u_int
ath_hal_setupdiagregs(const HAL_REGRANGE regs[],u_int nr)621 ath_hal_setupdiagregs(const HAL_REGRANGE regs[], u_int nr)
622 {
623 u_int space;
624 int i;
625
626 space = 0;
627 for (i = 0; i < nr; i++) {
628 u_int n = sizeof(HAL_REGRANGE) + sizeof(u_int32_t); /* reg range + first */
629 if (regs[i].end) {
630 if (regs[i].end < regs[i].start) {
631 fprintf(stderr, "%s: bad register range, "
632 "end 0x%x < start 0x%x\n",
633 __func__, regs[i].end, regs[i].end);
634 exit(-1);
635 }
636 n += regs[i].end - regs[i].start;
637 }
638 space += n;
639 }
640 return space;
641 }
642
643 /*
644 * Format an Ethernet MAC for printing.
645 */
646 static const char*
ether_sprintf(const u_int8_t * mac)647 ether_sprintf(const u_int8_t *mac)
648 {
649 static char etherbuf[18];
650 snprintf(etherbuf, sizeof(etherbuf), "%02x:%02x:%02x:%02x:%02x:%02x",
651 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
652 return etherbuf;
653 }
654
655 #ifndef isclr
656 #define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
657 #define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
658 #define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
659 #define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
660 #endif
661
662 static void
ath_hal_dumpkeycache(FILE * fd,int nkeys)663 ath_hal_dumpkeycache(FILE *fd, int nkeys)
664 {
665 static const char *keytypenames[] = {
666 "WEP-40", /* AR_KEYTABLE_TYPE_40 */
667 "WEP-104", /* AR_KEYTABLE_TYPE_104 */
668 "#2",
669 "WEP-128", /* AR_KEYTABLE_TYPE_128 */
670 "TKIP", /* AR_KEYTABLE_TYPE_TKIP */
671 "AES-OCB", /* AR_KEYTABLE_TYPE_AES */
672 "AES-CCM", /* AR_KEYTABLE_TYPE_CCM */
673 "CLR", /* AR_KEYTABLE_TYPE_CLR */
674 };
675 int micEnabled = SREV(state.revs.ah_macVersion, state.revs.ah_macRev) < SREV(4,8) ? 0 :
676 OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_CRPT_MIC_ENABLE;
677 u_int8_t mac[IEEE80211_ADDR_LEN];
678 u_int8_t ismic[128/NBBY];
679 int entry;
680 int first = 1;
681
682 memset(ismic, 0, sizeof(ismic));
683 for (entry = 0; entry < nkeys; entry++) {
684 u_int32_t macLo, macHi, type;
685 u_int32_t key0, key1, key2, key3, key4;
686
687 macHi = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
688 if ((macHi & AR_KEYTABLE_VALID) == 0 && isclr(ismic, entry))
689 continue;
690 macLo = OS_REG_READ(ah, AR_KEYTABLE_MAC0(entry));
691 macHi <<= 1;
692 if (macLo & (1<<31))
693 macHi |= 1;
694 macLo <<= 1;
695 mac[4] = macHi & 0xff;
696 mac[5] = macHi >> 8;
697 mac[0] = macLo & 0xff;
698 mac[1] = macLo >> 8;
699 mac[2] = macLo >> 16;
700 mac[3] = macLo >> 24;
701 type = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry));
702 if ((type & 7) == AR_KEYTABLE_TYPE_TKIP && micEnabled)
703 setbit(ismic, entry+64);
704 key0 = OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry));
705 key1 = OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry));
706 key2 = OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry));
707 key3 = OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry));
708 key4 = OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry));
709 if (first) {
710 fprintf(fd, "\n");
711 first = 0;
712 }
713 fprintf(fd, "KEY[%03u] MAC %s %-7s %02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x\n"
714 , entry
715 , ether_sprintf(mac)
716 , isset(ismic, entry) ? "MIC" : keytypenames[type & 7]
717 , (key0 >> 0) & 0xff
718 , (key0 >> 8) & 0xff
719 , (key0 >> 16) & 0xff
720 , (key0 >> 24) & 0xff
721 , (key1 >> 0) & 0xff
722 , (key1 >> 8) & 0xff
723 , (key2 >> 0) & 0xff
724 , (key2 >> 8) & 0xff
725 , (key2 >> 16) & 0xff
726 , (key2 >> 24) & 0xff
727 , (key3 >> 0) & 0xff
728 , (key3 >> 8) & 0xff
729 , (key4 >> 0) & 0xff
730 , (key4 >> 8) & 0xff
731 , (key4 >> 16) & 0xff
732 , (key4 >> 24) & 0xff
733 );
734 }
735 }
736