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