]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/tools/ath/athdecode/main.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / tools / ath / athdecode / main.c
1 /*-
2  * Copyright (c) 2002-2009 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 #include "ah_decode.h"
36
37 #include "dumpregs.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <err.h>
42 #include <sys/file.h>
43 #include <sys/stat.h>
44 #include <sys/mman.h>
45
46 typedef struct {
47         HAL_REVS revs;
48         int chipnum;
49 #define MAXREGS 5*1024
50         struct dumpreg *regs[MAXREGS];
51         u_int nregs;
52 } dumpregs_t;
53 static  dumpregs_t state;
54
55 static void opdevice(const struct athregrec *r);
56 static const char* opmark(FILE *, int, const struct athregrec *);
57 static void oprw(FILE *fd, int recnum, struct athregrec *r);
58
59 int
60 main(int argc, char *argv[])
61 {
62         int fd, i, nrecs, same;
63         struct stat sb;
64         void *addr;
65         const char *filename = "/tmp/ath_hal.log";
66         struct athregrec *rprev;
67
68         if (argc > 1)
69                 filename = argv[1];
70         fd = open(filename, O_RDONLY);
71         if (fd < 0)
72                 err(1, filename);
73         if (fstat(fd, &sb) < 0)
74                 err(1, "fstat");
75         addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0);
76         if (addr == MAP_FAILED)
77                 err(1, "mmap");
78         nrecs = sb.st_size / sizeof (struct athregrec);
79         printf("%u records", nrecs);
80         rprev = NULL;
81         same = 0;
82         state.chipnum = 5210;
83         for (i = 0; i < nrecs; i++) {
84                 struct athregrec *r = &((struct athregrec *) addr)[i];
85                 if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) {
86                         same++;
87                         continue;
88                 }
89                 if (same)
90                         printf("\t\t+%u time%s", same, same == 1 ? "" : "s");
91                 switch (r->op) {
92                 case OP_DEVICE:
93                         opdevice(r);
94                         break;
95                 case OP_READ:
96                 case OP_WRITE:
97                         oprw(stdout, i, r);
98                         break;
99                 case OP_MARK:
100                         opmark(stdout, i, r);
101                         break;
102                 }
103                 rprev = r;
104                 same = 0;
105         }
106         putchar('\n');
107         return 0;
108 }
109
110 static const char*
111 opmark(FILE *fd, int i, const struct athregrec *r)
112 {
113         fprintf(fd, "\n%05d: ", i);
114         switch (r->reg) {
115         case AH_MARK_RESET:
116                 fprintf(fd, "ar%uReset %s", state.chipnum,
117                         r->val ? "change channel" : "no channel change");
118                 break;
119         case AH_MARK_RESET_LINE:
120                 fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val);
121                 break;
122         case AH_MARK_RESET_DONE:
123                 if (r->val)
124                         fprintf(fd, "ar%uReset (done), FAIL, error %u",
125                                 state.chipnum, r->val);
126                 else
127                         fprintf(fd, "ar%uReset (done), OK", state.chipnum);
128                 break;
129         case AH_MARK_CHIPRESET:
130                 fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val);
131                 break;
132         case AH_MARK_PERCAL:
133                 fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val);
134                 break;
135         case AH_MARK_SETCHANNEL:
136                 fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val);
137                 break;
138         case AH_MARK_ANI_RESET:
139                 switch (r->val) {
140                 case HAL_M_STA:
141                         fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum);
142                         break;
143                 case HAL_M_IBSS:
144                         fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum);
145                         break;
146                 case HAL_M_HOSTAP:
147                         fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum);
148                         break;
149                 case HAL_M_MONITOR:
150                         fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum);
151                         break;
152                 default:
153                         fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val);
154                         break;
155                 }
156                 break;
157         case AH_MARK_ANI_POLL:
158                 fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val);
159                 break;
160         case AH_MARK_ANI_CONTROL:
161                 switch (r->val) {
162                 case HAL_ANI_PRESENT:
163                         fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum);
164                         break;
165                 case HAL_ANI_NOISE_IMMUNITY_LEVEL:
166                         fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum);
167                         break;
168                 case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
169                         fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum);
170                         break;
171                 case HAL_ANI_CCK_WEAK_SIGNAL_THR:
172                         fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum);
173                         break;
174                 case HAL_ANI_FIRSTEP_LEVEL:
175                         fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum);
176                         break;
177                 case HAL_ANI_SPUR_IMMUNITY_LEVEL:
178                         fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum);
179                         break;
180                 case HAL_ANI_MODE:
181                         fprintf(fd, "ar%uAniControl, MODE", state.chipnum);
182                         break;
183                 case HAL_ANI_PHYERR_RESET:
184                         fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum);
185                         break;
186                 default:
187                         fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val);
188                         break;
189                 }
190                 break;
191         default:
192                 fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val);
193                 break;
194         }
195 }
196
197 #include "ah_devid.h"
198
199 static void
200 opdevice(const struct athregrec *r)
201 {
202         switch (r->val) {
203         case AR5210_PROD:
204         case AR5210_DEFAULT:
205                 state.chipnum = 5210;
206                 state.revs.ah_macVersion = 1;
207                 state.revs.ah_macRev = 0;
208                 break;
209         case AR5211_DEVID:
210         case AR5311_DEVID:
211         case AR5211_DEFAULT:
212         case AR5211_FPGA11B:
213                 state.chipnum = 5211;
214                 state.revs.ah_macVersion = 2;
215                 state.revs.ah_macRev = 0;
216                 break;
217         /* AR5212 */
218         case AR5212_DEFAULT:
219         case AR5212_DEVID:
220         case AR5212_FPGA:
221         case AR5212_DEVID_IBM:
222         case AR5212_AR5312_REV2:
223         case AR5212_AR5312_REV7:
224         case AR5212_AR2313_REV8:
225         case AR5212_AR2315_REV6:
226         case AR5212_AR2315_REV7:
227         case AR5212_AR2317_REV1:
228         case AR5212_AR2317_REV2:
229
230         /* AR5212 compatible devid's also attach to 5212 */
231         case AR5212_DEVID_0014:
232         case AR5212_DEVID_0015:
233         case AR5212_DEVID_0016:
234         case AR5212_DEVID_0017:
235         case AR5212_DEVID_0018:
236         case AR5212_DEVID_0019:
237         case AR5212_AR2413:
238         case AR5212_AR5413:
239         case AR5212_AR5424:
240         case AR5212_AR2417:
241         case AR5212_DEVID_FF19:
242                 state.chipnum = 5212;
243                 state.revs.ah_macVersion = 4;
244                 state.revs.ah_macRev = 5;
245                 break;
246
247         /* AR5213 */
248         case AR5213_SREV_1_0:
249         case AR5213_SREV_REG:
250                 state.chipnum = 5213;
251                 state.revs.ah_macVersion = 5;
252                 state.revs.ah_macRev = 9;
253                 break;
254
255         /* AR5416 compatible devid's  */
256         case AR5416_DEVID_PCI:
257         case AR5416_DEVID_PCIE:
258         case AR9160_DEVID_PCI:
259         case AR9280_DEVID_PCI:
260         case AR9280_DEVID_PCIE:
261         case AR9285_DEVID_PCIE:
262                 state.chipnum = 5416;
263                 state.revs.ah_macVersion = 13;
264                 state.revs.ah_macRev = 8;
265                 break;
266         default:
267                 printf("Unknown device id 0x%x\n", r->val);
268                 exit(-1);
269         }
270 }
271
272 static int
273 regcompar(const void *a, const void *b)
274 {
275         const struct dumpreg *ra = *(const struct dumpreg **)a;
276         const struct dumpreg *rb = *(const struct dumpreg **)b;
277         return ra->addr - rb->addr;
278 }
279
280 void
281 register_regs(struct dumpreg *chipregs, u_int nchipregs,
282         int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
283 {
284         const int existing_regs = state.nregs;
285         int i, j;
286
287         for (i = 0; i < nchipregs; i++) {
288                 struct dumpreg *nr = &chipregs[i];
289                 if (nr->srevMin == 0)
290                         nr->srevMin = def_srev_min;
291                 if (nr->srevMax == 0)
292                         nr->srevMax = def_srev_max;
293                 if (nr->phyMin == 0)
294                         nr->phyMin = def_phy_min;
295                 if (nr->phyMax == 0)
296                         nr->phyMax = def_phy_max;
297                 for (j = 0; j < existing_regs; j++) {
298                         struct dumpreg *r = state.regs[j];
299                         /*
300                          * Check if we can just expand the mac+phy
301                          * coverage for the existing entry.
302                          */
303                         if (nr->addr == r->addr &&
304                             (nr->name == r->name ||
305                              nr->name != NULL && r->name != NULL &&
306                              strcmp(nr->name, r->name) == 0)) {
307                                 if (nr->srevMin < r->srevMin &&
308                                     (r->srevMin <= nr->srevMax &&
309                                      nr->srevMax+1 <= r->srevMax)) {
310                                         r->srevMin = nr->srevMin;
311                                         goto skip;
312                                 }
313                                 if (nr->srevMax > r->srevMax &&
314                                     (r->srevMin <= nr->srevMin &&
315                                      nr->srevMin <= r->srevMax)) {
316                                         r->srevMax = nr->srevMax;
317                                         goto skip;
318                                 }
319                         }
320                         if (r->addr > nr->addr)
321                                 break;
322                 }
323                 /*
324                  * New item, add to the end, it'll be sorted below.
325                  */
326                 if (state.nregs == MAXREGS)
327                         errx(-1, "too many registers; bump MAXREGS");
328                 state.regs[state.nregs++] = nr;
329         skip:
330                 ;
331         }
332         qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar);
333 }
334
335 void
336 register_keycache(u_int nslots,
337         int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
338 {
339         /* discard, no use */
340 }
341
342 void
343 register_range(u_int brange, u_int erange, int type,
344         int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
345 {
346         /* discard, no use */
347 }
348
349 static const struct dumpreg *
350 findreg(int reg)
351 {
352         const HAL_REVS *revs = &state.revs;
353         int i;
354
355         for (i = 0; i < state.nregs; i++) {
356                 const struct dumpreg *dr = state.regs[i];
357                 if (dr->addr == reg &&
358                     MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev))
359                         return dr;
360         }
361         return NULL;
362 }
363
364 /* XXX cheat, 5212 has a superset of the key table defs */
365 #include "ar5212/ar5212reg.h"
366 #include "ar5212/ar5212phy.h"
367
368 #define PWR_TABLE_SIZE  64
369
370 static void
371 oprw(FILE *fd, int recnum, struct athregrec *r)
372 {
373         const struct dumpreg *dr;
374         char buf[64];
375         const char* bits;
376         int i;
377
378         fprintf(fd, "\n%05d: ", recnum);
379         dr = findreg(r->reg);
380         if (dr != NULL && dr->name != NULL) {
381                 snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg);
382                 bits = dr->bits;
383         } else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) {
384                 snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)",
385                         ((r->reg - AR_KEYTABLE_0) >> 2) & 7,
386                         (r->reg - AR_KEYTABLE_0) >> 5, r->reg);
387                 bits = NULL;
388 #if 0
389         } else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) {
390                 snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)",
391                         (r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg);
392                 bits = NULL;
393 #endif
394         } else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) {
395                 snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)",
396                         (r->reg - AR_RATE_DURATION_0) >> 2, r->reg);
397                 bits = NULL;
398         } else if (AR_PHY_BASE <= r->reg) {
399                 snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)",
400                         (r->reg - AR_PHY_BASE) >> 2, r->reg);
401                 bits = NULL;
402         } else {
403                 snprintf(buf, sizeof (buf), "0x%x", r->reg);
404                 bits = NULL;
405         }
406         fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val);
407         if (bits) {
408                 const char *p = bits;
409                 int tmp, n;
410
411                 for (tmp = 0, p++; *p;) {
412                         n = *p++;
413                         if (r->val & (1 << (n - 1))) {
414                                 putc(tmp ? ',' : '<', fd);
415                                 for (; (n = *p) > ' '; ++p)
416                                         putc(n, fd);
417                                 tmp = 1;
418                         } else
419                                 for (; *p > ' '; ++p)
420                                         continue;
421                 }
422                 if (tmp)
423                         putc('>', fd);
424         }
425 }