]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/ath/athregs/dumpregs.c
Upgrade to Bzip2 version 1.0.7.
[FreeBSD/FreeBSD.git] / tools / tools / ath / athregs / dumpregs.c
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 }