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