main.c revision 217680
1254721Semaste/*-
2254721Semaste * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3353358Sdim * All rights reserved.
4353358Sdim *
5353358Sdim * Redistribution and use in source and binary forms, with or without
6254721Semaste * modification, are permitted provided that the following conditions
7254721Semaste * are met:
8254721Semaste * 1. Redistributions of source code must retain the above copyright
9254721Semaste *    notice, this list of conditions and the following disclaimer,
10254721Semaste *    without modification.
11344779Sdim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12296417Sdim *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13254721Semaste *    redistribution must be conditioned upon including a substantially
14254721Semaste *    similar Disclaimer requirement for further binary redistribution.
15344779Sdim *
16344779Sdim * NO WARRANTY
17344779Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18344779Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19254721Semaste * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20344779Sdim * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21344779Sdim * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22344779Sdim * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23321369Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24344779Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25344779Sdim * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26321369Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27254721Semaste * THE POSSIBILITY OF SUCH DAMAGES.
28254721Semaste *
29314564Sdim * $FreeBSD: head/tools/tools/ath/athdecode/main.c 217680 2011-01-21 02:53:32Z adrian $
30314564Sdim */
31353358Sdim#include "diag.h"
32314564Sdim
33314564Sdim#include "ah.h"
34314564Sdim#include "ah_internal.h"
35314564Sdim#include "ah_decode.h"
36314564Sdim
37314564Sdim#include "dumpregs.h"
38314564Sdim
39314564Sdim#include <stdlib.h>
40314564Sdim#include <string.h>
41314564Sdim#include <err.h>
42314564Sdim#include <sys/file.h>
43314564Sdim#include <sys/stat.h>
44254721Semaste#include <sys/mman.h>
45254721Semaste
46314564Sdimtypedef struct {
47254721Semaste	HAL_REVS revs;
48314564Sdim	int chipnum;
49314564Sdim#define	MAXREGS	5*1024
50254721Semaste	struct dumpreg *regs[MAXREGS];
51254721Semaste	u_int nregs;
52314564Sdim} dumpregs_t;
53344779Sdimstatic	dumpregs_t state;
54344779Sdim
55314564Sdimstatic void opdevice(const struct athregrec *r);
56254721Semastestatic const char* opmark(FILE *, int, const struct athregrec *);
57254721Semastestatic void oprw(FILE *fd, int recnum, struct athregrec *r);
58314564Sdim
59314564Sdimint
60314564Sdimmain(int argc, char *argv[])
61314564Sdim{
62314564Sdim	int fd, i, nrecs, same;
63314564Sdim	struct stat sb;
64314564Sdim	void *addr;
65314564Sdim	const char *filename = "/tmp/ath_hal.log";
66314564Sdim	struct athregrec *rprev;
67276479Sdim
68314564Sdim	if (argc > 1)
69276479Sdim		filename = argv[1];
70276479Sdim	fd = open(filename, O_RDONLY);
71314564Sdim	if (fd < 0)
72314564Sdim		err(1, filename);
73314564Sdim	if (fstat(fd, &sb) < 0)
74314564Sdim		err(1, "fstat");
75314564Sdim	addr = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE|MAP_NOCORE, fd, 0);
76314564Sdim	if (addr == MAP_FAILED)
77254721Semaste		err(1, "mmap");
78254721Semaste	nrecs = sb.st_size / sizeof (struct athregrec);
79314564Sdim	printf("%u records", nrecs);
80314564Sdim	rprev = NULL;
81314564Sdim	same = 0;
82314564Sdim	state.chipnum = 5210;
83254721Semaste	for (i = 0; i < nrecs; i++) {
84254721Semaste		struct athregrec *r = &((struct athregrec *) addr)[i];
85314564Sdim		if (rprev && bcmp(r, rprev, sizeof (*r)) == 0) {
86314564Sdim			same++;
87314564Sdim			continue;
88314564Sdim		}
89276479Sdim		if (same)
90276479Sdim			printf("\t\t+%u time%s", same, same == 1 ? "" : "s");
91314564Sdim		switch (r->op) {
92314564Sdim		case OP_DEVICE:
93314564Sdim			opdevice(r);
94314564Sdim			break;
95314564Sdim		case OP_READ:
96314564Sdim		case OP_WRITE:
97314564Sdim			oprw(stdout, i, r);
98314564Sdim			break;
99296417Sdim		case OP_MARK:
100314564Sdim			opmark(stdout, i, r);
101314564Sdim			break;
102314564Sdim		}
103314564Sdim		rprev = r;
104314564Sdim		same = 0;
105314564Sdim	}
106314564Sdim	putchar('\n');
107314564Sdim	return 0;
108288943Sdim}
109288943Sdim
110314564Sdimstatic const char*
111314564Sdimopmark(FILE *fd, int i, const struct athregrec *r)
112314564Sdim{
113314564Sdim	fprintf(fd, "\n%05d: ", i);
114314564Sdim	switch (r->reg) {
115314564Sdim	case AH_MARK_RESET:
116314564Sdim		fprintf(fd, "ar%uReset %s", state.chipnum,
117254721Semaste			r->val ? "change channel" : "no channel change");
118314564Sdim		break;
119314564Sdim	case AH_MARK_RESET_LINE:
120314564Sdim		fprintf(fd, "ar%u_reset.c; line %u", state.chipnum, r->val);
121314564Sdim		break;
122314564Sdim	case AH_MARK_RESET_DONE:
123314564Sdim		if (r->val)
124314564Sdim			fprintf(fd, "ar%uReset (done), FAIL, error %u",
125314564Sdim				state.chipnum, r->val);
126344779Sdim		else
127314564Sdim			fprintf(fd, "ar%uReset (done), OK", state.chipnum);
128314564Sdim		break;
129314564Sdim	case AH_MARK_CHIPRESET:
130314564Sdim		fprintf(fd, "ar%uChipReset, channel %u MHz", state.chipnum, r->val);
131314564Sdim		break;
132314564Sdim	case AH_MARK_PERCAL:
133314564Sdim		fprintf(fd, "ar%uPerCalibration, channel %u MHz", state.chipnum, r->val);
134314564Sdim		break;
135314564Sdim	case AH_MARK_SETCHANNEL:
136314564Sdim		fprintf(fd, "ar%uSetChannel, channel %u MHz", state.chipnum, r->val);
137314564Sdim		break;
138314564Sdim	case AH_MARK_ANI_RESET:
139314564Sdim		switch (r->val) {
140314564Sdim		case HAL_M_STA:
141314564Sdim			fprintf(fd, "ar%uAniReset, HAL_M_STA", state.chipnum);
142314564Sdim			break;
143314564Sdim		case HAL_M_IBSS:
144344779Sdim			fprintf(fd, "ar%uAniReset, HAL_M_IBSS", state.chipnum);
145314564Sdim			break;
146254721Semaste		case HAL_M_HOSTAP:
147314564Sdim			fprintf(fd, "ar%uAniReset, HAL_M_HOSTAP", state.chipnum);
148314564Sdim			break;
149314564Sdim		case HAL_M_MONITOR:
150314564Sdim			fprintf(fd, "ar%uAniReset, HAL_M_MONITOR", state.chipnum);
151314564Sdim			break;
152314564Sdim		default:
153314564Sdim			fprintf(fd, "ar%uAniReset, opmode %u", state.chipnum, r->val);
154314564Sdim			break;
155314564Sdim		}
156314564Sdim		break;
157314564Sdim	case AH_MARK_ANI_POLL:
158314564Sdim		fprintf(fd, "ar%uAniPoll, listenTime %u", state.chipnum, r->val);
159314564Sdim		break;
160314564Sdim	case AH_MARK_ANI_CONTROL:
161314564Sdim		switch (r->val) {
162254721Semaste		case HAL_ANI_PRESENT:
163314564Sdim			fprintf(fd, "ar%uAniControl, PRESENT", state.chipnum);
164314564Sdim			break;
165314564Sdim		case HAL_ANI_NOISE_IMMUNITY_LEVEL:
166314564Sdim			fprintf(fd, "ar%uAniControl, NOISE_IMMUNITY", state.chipnum);
167314564Sdim			break;
168314564Sdim		case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
169314564Sdim			fprintf(fd, "ar%uAniControl, OFDM_WEAK_SIGNAL", state.chipnum);
170314564Sdim			break;
171314564Sdim		case HAL_ANI_CCK_WEAK_SIGNAL_THR:
172314564Sdim			fprintf(fd, "ar%uAniControl, CCK_WEAK_SIGNAL", state.chipnum);
173314564Sdim			break;
174314564Sdim		case HAL_ANI_FIRSTEP_LEVEL:
175341825Sdim			fprintf(fd, "ar%uAniControl, FIRSTEP_LEVEL", state.chipnum);
176341825Sdim			break;
177314564Sdim		case HAL_ANI_SPUR_IMMUNITY_LEVEL:
178360784Sdim			fprintf(fd, "ar%uAniControl, SPUR_IMMUNITY", state.chipnum);
179360784Sdim			break;
180360784Sdim		case HAL_ANI_MODE:
181360784Sdim			fprintf(fd, "ar%uAniControl, MODE", state.chipnum);
182360784Sdim			break;
183360784Sdim		case HAL_ANI_PHYERR_RESET:
184360784Sdim			fprintf(fd, "ar%uAniControl, PHYERR_RESET", state.chipnum);
185360784Sdim			break;
186360784Sdim		default:
187360784Sdim			fprintf(fd, "ar%uAniControl, cmd %u", state.chipnum, r->val);
188360784Sdim			break;
189360784Sdim		}
190360784Sdim		break;
191360784Sdim	default:
192360784Sdim		fprintf(fd, "mark #%u value %u/0x%x", r->reg, r->val, r->val);
193360784Sdim		break;
194360784Sdim	}
195360784Sdim}
196360784Sdim
197360784Sdim#include "ah_devid.h"
198360784Sdim
199360784Sdimstatic void
200360784Sdimopdevice(const struct athregrec *r)
201360784Sdim{
202314564Sdim	switch (r->val) {
203314564Sdim	case AR5210_PROD:
204314564Sdim	case AR5210_DEFAULT:
205314564Sdim		state.chipnum = 5210;
206314564Sdim		state.revs.ah_macVersion = 1;
207314564Sdim		state.revs.ah_macRev = 0;
208314564Sdim		break;
209314564Sdim	case AR5211_DEVID:
210314564Sdim	case AR5311_DEVID:
211314564Sdim	case AR5211_DEFAULT:
212314564Sdim	case AR5211_FPGA11B:
213314564Sdim		state.chipnum = 5211;
214314564Sdim		state.revs.ah_macVersion = 2;
215314564Sdim		state.revs.ah_macRev = 0;
216314564Sdim		break;
217314564Sdim	/* AR5212 */
218314564Sdim	case AR5212_DEFAULT:
219314564Sdim	case AR5212_DEVID:
220254721Semaste	case AR5212_FPGA:
221314564Sdim	case AR5212_DEVID_IBM:
222314564Sdim	case AR5212_AR5312_REV2:
223314564Sdim	case AR5212_AR5312_REV7:
224314564Sdim	case AR5212_AR2313_REV8:
225314564Sdim	case AR5212_AR2315_REV6:
226314564Sdim	case AR5212_AR2315_REV7:
227314564Sdim	case AR5212_AR2317_REV1:
228344779Sdim	case AR5212_AR2317_REV2:
229344779Sdim
230360784Sdim	/* AR5212 compatible devid's also attach to 5212 */
231314564Sdim	case AR5212_DEVID_0014:
232314564Sdim	case AR5212_DEVID_0015:
233314564Sdim	case AR5212_DEVID_0016:
234314564Sdim	case AR5212_DEVID_0017:
235314564Sdim	case AR5212_DEVID_0018:
236314564Sdim	case AR5212_DEVID_0019:
237314564Sdim	case AR5212_AR2413:
238314564Sdim	case AR5212_AR5413:
239254721Semaste	case AR5212_AR5424:
240314564Sdim	case AR5212_AR2417:
241314564Sdim	case AR5212_DEVID_FF19:
242314564Sdim		state.chipnum = 5212;
243314564Sdim		state.revs.ah_macVersion = 4;
244314564Sdim		state.revs.ah_macRev = 5;
245254721Semaste		break;
246254721Semaste
247314564Sdim	/* AR5213 */
248314564Sdim	case AR5213_SREV_1_0:
249314564Sdim	case AR5213_SREV_REG:
250314564Sdim		state.chipnum = 5213;
251314564Sdim		state.revs.ah_macVersion = 5;
252254721Semaste		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
272static int
273regcompar(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
280void
281register_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
335void
336register_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
342void
343register_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
349static const struct dumpreg *
350findreg(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
370static void
371oprw(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}
426