main.c revision 244962
1183724Ssos/*-
2230132Suqs * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3183724Ssos * All rights reserved.
4183724Ssos *
5183724Ssos * Redistribution and use in source and binary forms, with or without
6183724Ssos * modification, are permitted provided that the following conditions
7183724Ssos * are met:
8183724Ssos * 1. Redistributions of source code must retain the above copyright
9183724Ssos *    notice, this list of conditions and the following disclaimer,
10183724Ssos *    without modification.
11183724Ssos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12183724Ssos *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13183724Ssos *    redistribution must be conditioned upon including a substantially
14183724Ssos *    similar Disclaimer requirement for further binary redistribution.
15183724Ssos *
16183724Ssos * NO WARRANTY
17183724Ssos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18183724Ssos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19183724Ssos * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20183724Ssos * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21183724Ssos * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22183724Ssos * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23183724Ssos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24183724Ssos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25183724Ssos * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26183724Ssos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27183724Ssos * THE POSSIBILITY OF SUCH DAMAGES.
28183724Ssos *
29183724Ssos * $FreeBSD: head/tools/tools/ath/athdecode/main.c 244962 2013-01-02 18:09:30Z adrian $
30183724Ssos */
31183724Ssos#include "diag.h"
32183724Ssos
33183724Ssos#include "ah.h"
34183724Ssos#include "ah_internal.h"
35183724Ssos#include "ah_decode.h"
36183724Ssos
37183724Ssos#include "dumpregs.h"
38183724Ssos
39183724Ssos#include <stdlib.h>
40183724Ssos#include <string.h>
41183724Ssos#include <err.h>
42183724Ssos#include <sys/file.h>
43183724Ssos#include <sys/stat.h>
44183724Ssos#include <sys/mman.h>
45183724Ssos
46183724Ssostypedef struct {
47183724Ssos	HAL_REVS revs;
48183724Ssos	int chipnum;
49183724Ssos#define	MAXREGS	5*1024
50183724Ssos	struct dumpreg *regs[MAXREGS];
51183724Ssos	u_int nregs;
52183724Ssos} dumpregs_t;
53183724Ssosstatic	dumpregs_t state;
54188765Smav
55183724Ssosstatic void opdevice(const struct athregrec *r);
56200171Smavstatic const char* opmark(FILE *, int, const struct athregrec *);
57188765Smavstatic void oprw(FILE *fd, int recnum, struct athregrec *r);
58188769Smav
59183724Ssosint
60183724Ssosmain(int argc, char *argv[])
61200171Smav{
62183724Ssos	int fd, i, nrecs, same;
63183724Ssos	struct stat sb;
64183724Ssos	void *addr;
65183724Ssos	const char *filename = "/tmp/ath_hal.log";
66183724Ssos	struct athregrec *rprev;
67183724Ssos
68183724Ssos	if (argc > 1)
69183724Ssos		filename = argv[1];
70183724Ssos	fd = open(filename, O_RDONLY);
71183724Ssos	if (fd < 0)
72183724Ssos		err(1, "open: %s", filename);
73183724Ssos	if (fstat(fd, &sb) < 0)
74183724Ssos		err(1, "fstat");
75183724Ssos	addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0);
76183724Ssos	if (addr == MAP_FAILED)
77242625Sdim		err(1, "mmap");
78183724Ssos	nrecs = sb.st_size / sizeof (struct athregrec);
79183724Ssos	printf("%u records", nrecs);
80183724Ssos	rprev = NULL;
81183724Ssos	same = 0;
82183724Ssos	state.chipnum = 5210;
83183724Ssos	for (i = 0; i < nrecs; i++) {
84183724Ssos		struct athregrec *r = &((struct athregrec *) addr)[i];
85183724Ssos		if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) {
86183724Ssos			same++;
87183724Ssos			continue;
88183724Ssos		}
89183724Ssos		if (same)
90183724Ssos			printf("\t\t+%u time%s", same, same == 1 ? "" : "s");
91183724Ssos		switch (r->op) {
92183724Ssos		case OP_DEVICE:
93183724Ssos			opdevice(r);
94183724Ssos			break;
95183724Ssos		case OP_READ:
96183724Ssos		case OP_WRITE:
97183724Ssos			oprw(stdout, i, r);
98183724Ssos			break;
99183724Ssos		case OP_MARK:
100281140Smav			opmark(stdout, i, r);
101183724Ssos			break;
102183724Ssos		}
103183724Ssos		rprev = r;
104183724Ssos		same = 0;
105183724Ssos	}
106183724Ssos	putchar('\n');
107183724Ssos	return 0;
108183724Ssos}
109183724Ssos
110183724Ssosstatic const char*
111183724Ssosopmark(FILE *fd, int i, const struct athregrec *r)
112183724Ssos{
113183724Ssos	fprintf(fd, "\n%05d: ", i);
114183724Ssos	switch (r->reg) {
115183724Ssos	case AH_MARK_RESET:
116183724Ssos		fprintf(fd, "ar%uReset %s", state.chipnum,
117183724Ssos			r->val ? "change channel" : "no channel change");
118183724Ssos		break;
119183724Ssos	case AH_MARK_RESET_LINE:
120183724Ssos		fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val);
121183724Ssos		break;
122183724Ssos	case AH_MARK_RESET_DONE:
123183724Ssos		if (r->val)
124183724Ssos			fprintf(fd, "ar%uReset (done), FAIL, error %u",
125183724Ssos				state.chipnum, r->val);
126183724Ssos		else
127183724Ssos			fprintf(fd, "ar%uReset (done), OK", state.chipnum);
128183724Ssos		break;
129183724Ssos	case AH_MARK_CHIPRESET:
130183724Ssos		fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val);
131183724Ssos		break;
132183724Ssos	case AH_MARK_PERCAL:
133183724Ssos		fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val);
134183724Ssos		break;
135183724Ssos	case AH_MARK_SETCHANNEL:
136183724Ssos		fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val);
137183724Ssos		break;
138183724Ssos	case AH_MARK_ANI_RESET:
139183724Ssos		switch (r->val) {
140183724Ssos		case HAL_M_STA:
141183724Ssos			fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum);
142183724Ssos			break;
143183724Ssos		case HAL_M_IBSS:
144188769Smav			fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum);
145188765Smav			break;
146188769Smav		case HAL_M_HOSTAP:
147188769Smav			fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum);
148183724Ssos			break;
149183724Ssos		case HAL_M_MONITOR:
150183724Ssos			fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum);
151183724Ssos			break;
152200171Smav		default:
153183724Ssos			fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val);
154183724Ssos			break;
155183724Ssos		}
156183724Ssos		break;
157183724Ssos	case AH_MARK_ANI_POLL:
158183724Ssos		fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val);
159183724Ssos		break;
160183724Ssos	case AH_MARK_ANI_CONTROL:
161183724Ssos		switch (r->val) {
162183724Ssos		case HAL_ANI_PRESENT:
163183724Ssos			fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum);
164183724Ssos			break;
165183724Ssos		case HAL_ANI_NOISE_IMMUNITY_LEVEL:
166183724Ssos			fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum);
167188765Smav			break;
168188769Smav		case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
169183724Ssos			fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum);
170183724Ssos			break;
171183724Ssos		case HAL_ANI_CCK_WEAK_SIGNAL_THR:
172183724Ssos			fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum);
173183724Ssos			break;
174183724Ssos		case HAL_ANI_FIRSTEP_LEVEL:
175183724Ssos			fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum);
176188765Smav			break;
177183724Ssos		case HAL_ANI_SPUR_IMMUNITY_LEVEL:
178183724Ssos			fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum);
179183724Ssos			break;
180183724Ssos		case HAL_ANI_MODE:
181183724Ssos			fprintf(fd, "ar%uAniControl, MODE", state.chipnum);
182188765Smav			break;
183183724Ssos		case HAL_ANI_PHYERR_RESET:
184183724Ssos			fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum);
185183724Ssos			break;
186183724Ssos		default:
187183724Ssos			fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val);
188230627Smarius			break;
189230627Smarius		}
190183724Ssos		break;
191183724Ssos	default:
192183724Ssos		fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val);
193183724Ssos		break;
194183724Ssos	}
195183724Ssos	exit(0);
196183724Ssos}
197183724Ssos
198183724Ssos#include "ah_devid.h"
199183724Ssos
200183724Ssosstatic void
201183724Ssosopdevice(const struct athregrec *r)
202183724Ssos{
203183724Ssos	switch (r->val) {
204183724Ssos	case AR5210_PROD:
205183724Ssos	case AR5210_DEFAULT:
206183724Ssos		state.chipnum = 5210;
207183724Ssos		state.revs.ah_macVersion = 1;
208200171Smav		state.revs.ah_macRev = 0;
209200171Smav		break;
210183724Ssos	case AR5211_DEVID:
211200171Smav	case AR5311_DEVID:
212200171Smav	case AR5211_DEFAULT:
213200171Smav	case AR5211_FPGA11B:
214200171Smav		state.chipnum = 5211;
215183724Ssos		state.revs.ah_macVersion = 2;
216183724Ssos		state.revs.ah_macRev = 0;
217200171Smav		break;
218233282Smarius	/* AR5212 */
219233282Smarius	case AR5212_DEFAULT:
220233282Smarius	case AR5212_DEVID:
221233282Smarius	case AR5212_FPGA:
222233282Smarius	case AR5212_DEVID_IBM:
223183724Ssos	case AR5212_AR5312_REV2:
224200171Smav	case AR5212_AR5312_REV7:
225200171Smav	case AR5212_AR2313_REV8:
226200171Smav	case AR5212_AR2315_REV6:
227183724Ssos	case AR5212_AR2315_REV7:
228200171Smav	case AR5212_AR2317_REV1:
229200171Smav	case AR5212_AR2317_REV2:
230200171Smav
231200171Smav	/* AR5212 compatible devid's also attach to 5212 */
232200171Smav	case AR5212_DEVID_0014:
233200171Smav	case AR5212_DEVID_0015:
234200171Smav	case AR5212_DEVID_0016:
235200171Smav	case AR5212_DEVID_0017:
236200171Smav	case AR5212_DEVID_0018:
237183724Ssos	case AR5212_DEVID_0019:
238200171Smav	case AR5212_AR2413:
239200171Smav	case AR5212_AR5413:
240183724Ssos	case AR5212_AR5424:
241183724Ssos	case AR5212_AR2417:
242183724Ssos	case AR5212_DEVID_FF19:
243188765Smav		state.chipnum = 5212;
244183724Ssos		state.revs.ah_macVersion = 4;
245183724Ssos		state.revs.ah_macRev = 5;
246183724Ssos		break;
247183724Ssos
248183724Ssos	/* AR5213 */
249183724Ssos	case AR5213_SREV_1_0:
250183724Ssos	case AR5213_SREV_REG:
251183724Ssos		state.chipnum = 5213;
252183724Ssos		state.revs.ah_macVersion = 5;
253183724Ssos		state.revs.ah_macRev = 9;
254183724Ssos		break;
255183724Ssos
256183724Ssos	/* AR5416 compatible devid's  */
257183724Ssos	case AR5416_DEVID_PCI:
258183724Ssos	case AR5416_DEVID_PCIE:
259183724Ssos	case AR9160_DEVID_PCI:
260183724Ssos	case AR9280_DEVID_PCI:
261183724Ssos	case AR9280_DEVID_PCIE:
262183724Ssos	case AR9285_DEVID_PCIE:
263183724Ssos		state.chipnum = 5416;
264183724Ssos		state.revs.ah_macVersion = 13;
265183724Ssos		state.revs.ah_macRev = 8;
266183724Ssos		break;
267183724Ssos	default:
268183724Ssos		printf("Unknown device id 0x%x\n", r->val);
269183724Ssos		exit(-1);
270183724Ssos	}
271183724Ssos}
272183724Ssos
273183724Ssosstatic int
274200171Smavregcompar(const void *a, const void *b)
275212145Smav{
276183724Ssos	const struct dumpreg *ra = *(const struct dumpreg **)a;
277183724Ssos	const struct dumpreg *rb = *(const struct dumpreg **)b;
278183724Ssos	return ra->addr - rb->addr;
279183724Ssos}
280183724Ssos
281183724Ssosvoid
282183724Ssosregister_regs(struct dumpreg *chipregs, u_int nchipregs,
283183724Ssos	int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
284183724Ssos{
285183724Ssos	const int existing_regs = state.nregs;
286183724Ssos	int i, j;
287183724Ssos
288183724Ssos	for (i = 0; i < nchipregs; i++) {
289200171Smav		struct dumpreg *nr = &chipregs[i];
290200171Smav		if (nr->srevMin == 0)
291216013Smarius			nr->srevMin = def_srev_min;
292216013Smarius		if (nr->srevMax == 0)
293216013Smarius			nr->srevMax = def_srev_max;
294183724Ssos		if (nr->phyMin == 0)
295183724Ssos			nr->phyMin = def_phy_min;
296183724Ssos		if (nr->phyMax == 0)
297183724Ssos			nr->phyMax = def_phy_max;
298188769Smav		for (j = 0; j < existing_regs; j++) {
299188769Smav			struct dumpreg *r = state.regs[j];
300188769Smav			/*
301188769Smav			 * Check if we can just expand the mac+phy
302188769Smav			 * coverage for the existing entry.
303188769Smav			 */
304188769Smav			if (nr->addr == r->addr &&
305188769Smav			    (nr->name == r->name ||
306183724Ssos			     (nr->name != NULL && r->name != NULL &&
307183724Ssos			     strcmp(nr->name, r->name) == 0))) {
308183724Ssos				if (nr->srevMin < r->srevMin &&
309183724Ssos				    (r->srevMin <= nr->srevMax &&
310183724Ssos				     nr->srevMax+1 <= r->srevMax)) {
311183724Ssos					r->srevMin = nr->srevMin;
312183724Ssos					goto skip;
313183724Ssos				}
314183724Ssos				if (nr->srevMax > r->srevMax &&
315183724Ssos				    (r->srevMin <= nr->srevMin &&
316214016Smav				     nr->srevMin <= r->srevMax)) {
317183724Ssos					r->srevMax = nr->srevMax;
318183724Ssos					goto skip;
319183724Ssos				}
320183724Ssos			}
321183724Ssos			if (r->addr > nr->addr)
322183724Ssos				break;
323183724Ssos		}
324183724Ssos		/*
325183724Ssos		 * New item, add to the end, it'll be sorted below.
326183724Ssos		 */
327212146Smav		if (state.nregs == MAXREGS)
328209884Smav			errx(-1, "too many registers; bump MAXREGS");
329212146Smav		state.regs[state.nregs++] = nr;
330212146Smav	skip:
331209884Smav		;
332212146Smav	}
333212146Smav	qsort(state.regs, state.nregs, sizeof(struct dumpreg *), regcompar);
334212146Smav}
335212146Smav
336212146Smavvoid
337190581Smavregister_keycache(u_int nslots,
338183724Ssos	int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
339209884Smav{
340209884Smav	/* discard, no use */
341183724Ssos}
342183724Ssos
343200171Smavvoid
344200171Smavregister_range(u_int brange, u_int erange, int type,
345183724Ssos	int def_srev_min, int def_srev_max, int def_phy_min, int def_phy_max)
346200171Smav{
347200171Smav	/* discard, no use */
348200171Smav}
349200171Smav
350200171Smavstatic const struct dumpreg *
351200171Smavfindreg(int reg)
352200171Smav{
353200171Smav	const HAL_REVS *revs = &state.revs;
354200171Smav	int i;
355200171Smav
356200171Smav	for (i = 0; i < state.nregs; i++) {
357233282Smarius		const struct dumpreg *dr = state.regs[i];
358233282Smarius		if (dr->addr == reg &&
359233282Smarius		    MAC_MATCH(dr, revs->ah_macVersion, revs->ah_macRev))
360233282Smarius			return dr;
361233282Smarius	}
362183724Ssos	return NULL;
363200171Smav}
364183724Ssos
365200171Smav/* XXX cheat, 5212 has a superset of the key table defs */
366209872Smav#include "ar5212/ar5212reg.h"
367209872Smav#include "ar5212/ar5212phy.h"
368183724Ssos
369200171Smav#define PWR_TABLE_SIZE	64
370200171Smav
371200171Smavstatic void
372183724Ssosoprw(FILE *fd, int recnum, struct athregrec *r)
373200171Smav{
374200171Smav	const struct dumpreg *dr;
375200171Smav	char buf[64];
376200171Smav	const char* bits;
377200171Smav	int i;
378183724Ssos
379200171Smav	fprintf(fd, "\n%05d: [%d] ", recnum, r->threadid);
380200171Smav	dr = findreg(r->reg);
381200171Smav	if (dr != NULL && dr->name != NULL) {
382200171Smav		snprintf(buf, sizeof (buf), "AR_%s (0x%x)", dr->name, r->reg);
383200171Smav		bits = dr->bits;
384200171Smav	} else if (AR_KEYTABLE(0) <= r->reg && r->reg < AR_KEYTABLE(128)) {
385200171Smav		snprintf(buf, sizeof (buf), "AR_KEYTABLE%u(%u) (0x%x)",
386200171Smav			((r->reg - AR_KEYTABLE_0) >> 2) & 7,
387200171Smav			(r->reg - AR_KEYTABLE_0) >> 5, r->reg);
388200171Smav		bits = NULL;
389200171Smav#if 0
390200171Smav	} else if (AR_PHY_PCDAC_TX_POWER(0) <= r->reg && r->reg < AR_PHY_PCDAC_TX_POWER(PWR_TABLE_SIZE/2)) {
391200171Smav		snprintf(buf, sizeof (buf), "AR_PHY_PCDAC_TX_POWER(%u) (0x%x)",
392200171Smav			(r->reg - AR_PHY_PCDAC_TX_POWER_0) >> 2, r->reg);
393183724Ssos		bits = NULL;
394183724Ssos#endif
395183724Ssos	} else if (AR_RATE_DURATION(0) <= r->reg && r->reg < AR_RATE_DURATION(32)) {
396		snprintf(buf, sizeof (buf), "AR_RATE_DURATION(0x%x) (0x%x)",
397			(r->reg - AR_RATE_DURATION_0) >> 2, r->reg);
398		bits = NULL;
399	} else if (AR_PHY_BASE <= r->reg) {
400		snprintf(buf, sizeof (buf), "AR_PHY(%u) (0x%x)",
401			(r->reg - AR_PHY_BASE) >> 2, r->reg);
402		bits = NULL;
403	} else {
404		snprintf(buf, sizeof (buf), "0x%x", r->reg);
405		bits = NULL;
406	}
407	fprintf(fd, "%-30s %s 0x%x", buf, r->op ? "<=" : "=>", r->val);
408	if (bits) {
409		const char *p = bits;
410		int tmp, n;
411
412		for (tmp = 0, p++; *p;) {
413			n = *p++;
414			if (r->val & (1 << (n - 1))) {
415				putc(tmp ? ',' : '<', fd);
416				for (; (n = *p) > ' '; ++p)
417					putc(n, fd);
418				tmp = 1;
419			} else
420				for (; *p > ' '; ++p)
421					continue;
422		}
423		if (tmp)
424			putc('>', fd);
425	}
426}
427