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