xref: /freebsd/tools/tools/ath/athdecode/main.c (revision b3e76948)
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 #include "diag.h"
30 
31 #include "ah.h"
32 #include "ah_internal.h"
33 #include "ah_decode.h"
34 
35 #include "dumpregs.h"
36 
37 #include <stdlib.h>
38 #include <string.h>
39 #include <err.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
main(int argc,char * argv[])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, "open: %s", 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*
opmark(FILE * fd,int i,const struct athregrec * r)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 	return (NULL);
194 }
195 
196 #include "ah_devid.h"
197 
198 static void
opdevice(const struct athregrec * r)199 opdevice(const struct athregrec *r)
200 {
201 	switch (r->val) {
202 	case AR5210_PROD:
203 	case AR5210_DEFAULT:
204 		state.chipnum = 5210;
205 		state.revs.ah_macVersion = 1;
206 		state.revs.ah_macRev = 0;
207 		break;
208 	case AR5211_DEVID:
209 	case AR5311_DEVID:
210 	case AR5211_DEFAULT:
211 	case AR5211_FPGA11B:
212 		state.chipnum = 5211;
213 		state.revs.ah_macVersion = 2;
214 		state.revs.ah_macRev = 0;
215 		break;
216 	/* AR5212 */
217 	case AR5212_DEFAULT:
218 	case AR5212_DEVID:
219 	case AR5212_FPGA:
220 	case AR5212_DEVID_IBM:
221 	case AR5212_AR5312_REV2:
222 	case AR5212_AR5312_REV7:
223 	case AR5212_AR2313_REV8:
224 	case AR5212_AR2315_REV6:
225 	case AR5212_AR2315_REV7:
226 	case AR5212_AR2317_REV1:
227 	case AR5212_AR2317_REV2:
228 
229 	/* AR5212 compatible devid's also attach to 5212 */
230 	case AR5212_DEVID_0014:
231 	case AR5212_DEVID_0015:
232 	case AR5212_DEVID_0016:
233 	case AR5212_DEVID_0017:
234 	case AR5212_DEVID_0018:
235 	case AR5212_DEVID_0019:
236 	case AR5212_AR2413:
237 	case AR5212_AR5413:
238 	case AR5212_AR5424:
239 	case AR5212_AR2417:
240 	case AR5212_DEVID_FF19:
241 		state.chipnum = 5212;
242 		state.revs.ah_macVersion = 4;
243 		state.revs.ah_macRev = 5;
244 		break;
245 
246 	/* AR5213 */
247 	case AR5213_SREV_1_0:
248 	case AR5213_SREV_REG:
249 		state.chipnum = 5213;
250 		state.revs.ah_macVersion = 5;
251 		state.revs.ah_macRev = 9;
252 		break;
253 
254 	/* AR5416 compatible devid's  */
255 	case AR5416_DEVID_PCI:
256 	case AR5416_DEVID_PCIE:
257 	case AR9160_DEVID_PCI:
258 	case AR9280_DEVID_PCI:
259 	case AR9280_DEVID_PCIE:
260 	case AR9285_DEVID_PCIE:
261 	case AR9287_DEVID_PCI:
262 	case AR9287_DEVID_PCIE:
263 	case AR9300_DEVID_AR9330:
264 		state.chipnum = 5416;
265 		state.revs.ah_macVersion = 13;
266 		state.revs.ah_macRev = 8;
267 		break;
268 	default:
269 		printf("Unknown device id 0x%x\n", r->val);
270 		exit(-1);
271 	}
272 }
273 
274 static int
regcompar(const void * a,const void * b)275 regcompar(const void *a, const void *b)
276 {
277 	const struct dumpreg *ra = *(const struct dumpreg **)a;
278 	const struct dumpreg *rb = *(const struct dumpreg **)b;
279 	return ra->addr - rb->addr;
280 }
281 
282 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)283 register_regs(struct dumpreg *chipregs, u_int nchipregs,
284 	int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
285 {
286 	const int existing_regs = state.nregs;
287 	int i, j;
288 
289 	for (i = 0; i < nchipregs; i++) {
290 		struct dumpreg *nr = &chipregs[i];
291 		if (nr->srevMin == 0)
292 			nr->srevMin = def_srev_min;
293 		if (nr->srevMax == 0)
294 			nr->srevMax = def_srev_max;
295 		if (nr->phyMin == 0)
296 			nr->phyMin = def_phy_min;
297 		if (nr->phyMax == 0)
298 			nr->phyMax = def_phy_max;
299 		for (j = 0; j < existing_regs; j++) {
300 			struct dumpreg *r = state.regs[j];
301 			/*
302 			 * Check if we can just expand the mac+phy
303 			 * coverage for the existing entry.
304 			 */
305 			if (nr->addr == r->addr &&
306 			    (nr->name == r->name ||
307 			     (nr->name != NULL && r->name != NULL &&
308 			     strcmp(nr->name, r->name) == 0))) {
309 				if (nr->srevMin < r->srevMin &&
310 				    (r->srevMin <= nr->srevMax &&
311 				     nr->srevMax+1 <= r->srevMax)) {
312 					r->srevMin = nr->srevMin;
313 					goto skip;
314 				}
315 				if (nr->srevMax > r->srevMax &&
316 				    (r->srevMin <= nr->srevMin &&
317 				     nr->srevMin <= r->srevMax)) {
318 					r->srevMax = nr->srevMax;
319 					goto skip;
320 				}
321 			}
322 			if (r->addr > nr->addr)
323 				break;
324 		}
325 		/*
326 		 * New item, add to the end, it'll be sorted below.
327 		 */
328 		if (state.nregs == MAXREGS)
329 			errx(-1, "too many registers; bump MAXREGS");
330 		state.regs[state.nregs++] = nr;
331 	skip:
332 		;
333 	}
334 	qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar);
335 }
336 
337 void
register_keycache(u_int nslots,int def_srev_min,int def_srev_max,int def_phy_min,int def_phy_max)338 register_keycache(u_int nslots,
339 	int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
340 {
341 	/* discard, no use */
342 }
343 
344 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)345 register_range(u_int brange, u_int erange, int type,
346 	int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
347 {
348 	/* discard, no use */
349 }
350 
351 static const struct dumpreg *
findreg(int reg)352 findreg(int reg)
353 {
354 	const HAL_REVS *revs = &state.revs;
355 	int i;
356 
357 	for (i = 0; i < state.nregs; i++) {
358 		const struct dumpreg *dr = state.regs[i];
359 		if (dr->addr == reg &&
360 		    MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev))
361 			return dr;
362 	}
363 	return NULL;
364 }
365 
366 /* XXX cheat, 5212 has a superset of the key table defs */
367 #include "ar5212/ar5212reg.h"
368 #include "ar5212/ar5212phy.h"
369 
370 #define PWR_TABLE_SIZE	64
371 
372 static void
oprw(FILE * fd,int recnum,struct athregrec * r)373 oprw(FILE *fd, int recnum, struct athregrec *r)
374 {
375 	const struct dumpreg *dr;
376 	char buf[64];
377 	const char* bits;
378 	int i;
379 
380 	fprintf(fd, "\n%05d: [%d] ", recnum, r->threadid);
381 	dr = findreg(r->reg);
382 	if (dr != NULL && dr->name != NULL) {
383 		snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg);
384 		bits = dr->bits;
385 	} else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) {
386 		snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)",
387 			((r->reg - AR_KEYTABLE_0) >> 2) & 7,
388 			(r->reg - AR_KEYTABLE_0) >> 5, r->reg);
389 		bits = NULL;
390 #if 0
391 	} else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) {
392 		snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)",
393 			(r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg);
394 		bits = NULL;
395 #endif
396 	} else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) {
397 		snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)",
398 			(r->reg - AR_RATE_DURATION_0) >> 2, r->reg);
399 		bits = NULL;
400 	} else if (AR_PHY_BASE <= r->reg) {
401 		snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)",
402 			(r->reg - AR_PHY_BASE) >> 2, r->reg);
403 		bits = NULL;
404 	} else {
405 		snprintf(buf, sizeof (buf), "0x%x", r->reg);
406 		bits = NULL;
407 	}
408 	fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val);
409 	if (bits) {
410 		const char *p = bits;
411 		int tmp, n;
412 
413 		for (tmp = 0, p++; *p;) {
414 			n = *p++;
415 			if (r->val & (1 << (n - 1))) {
416 				putc(tmp ? ',' : '<', fd);
417 				for (; (n = *p) > ' '; ++p)
418 					putc(n, fd);
419 				tmp = 1;
420 			} else
421 				for (; *p > ' '; ++p)
422 					continue;
423 		}
424 		if (tmp)
425 			putc('>', fd);
426 	}
427 }
428