xref: /freebsd/tools/tools/mwl/mwldebug/mwldebug.c (revision c697fb7f)
1 /*-
2  * Copyright (c) 2007 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 
32 /*
33  * mwldebug [-i interface] flags
34  * (default interface is mwl0).
35  */
36 
37 #include <sys/param.h>
38 #include <sys/file.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
41 #include <sys/sysctl.h>
42 
43 #include <ctype.h>
44 #include <err.h>
45 #include <getopt.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 
50 const char *progname;
51 
52 enum {
53 	MWL_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
54 	MWL_DEBUG_XMIT_DESC	= 0x00000002,	/* xmit descriptors */
55 	MWL_DEBUG_RECV		= 0x00000004,	/* basic recv operation */
56 	MWL_DEBUG_RECV_DESC	= 0x00000008,	/* recv descriptors */
57 	MWL_DEBUG_RESET		= 0x00000010,	/* reset processing */
58 	MWL_DEBUG_BEACON 	= 0x00000020,	/* beacon handling */
59 	MWL_DEBUG_INTR		= 0x00000040,	/* ISR */
60 	MWL_DEBUG_TX_PROC	= 0x00000080,	/* tx ISR proc */
61 	MWL_DEBUG_RX_PROC	= 0x00000100,	/* rx ISR proc */
62 	MWL_DEBUG_KEYCACHE	= 0x00000200,	/* key cache management */
63 	MWL_DEBUG_STATE		= 0x00000400,	/* 802.11 state transitions */
64 	MWL_DEBUG_NODE		= 0x00000800,	/* node management */
65 	MWL_DEBUG_RECV_ALL	= 0x00001000,	/* trace all frames (beacons) */
66 	MWL_DEBUG_TSO		= 0x00002000,	/* TSO processing */
67 	MWL_DEBUG_AMPDU		= 0x00004000,	/* BA stream handling */
68 	MWL_DEBUG_ANY		= 0xffffffff
69 };
70 
71 static struct {
72 	const char	*name;
73 	u_int		bit;
74 } flags[] = {
75 	{ "xmit",	MWL_DEBUG_XMIT },
76 	{ "xmit_desc",	MWL_DEBUG_XMIT_DESC },
77 	{ "recv",	MWL_DEBUG_RECV },
78 	{ "recv_desc",	MWL_DEBUG_RECV_DESC },
79 	{ "reset",	MWL_DEBUG_RESET },
80 	{ "beacon",	MWL_DEBUG_BEACON },
81 	{ "intr",	MWL_DEBUG_INTR },
82 	{ "xmit_proc",	MWL_DEBUG_TX_PROC },
83 	{ "recv_proc",	MWL_DEBUG_RX_PROC },
84 	{ "keycache",	MWL_DEBUG_KEYCACHE },
85 	{ "state",	MWL_DEBUG_STATE },
86 	{ "node",	MWL_DEBUG_NODE },
87 	{ "recv_all",	MWL_DEBUG_RECV_ALL },
88 	{ "tso",	MWL_DEBUG_TSO },
89 	{ "ampdu",	MWL_DEBUG_AMPDU },
90 	/* XXX these are a hack; there should be a separate sysctl knob */
91 	{ "hal",	0x02000000 },		/* cmd-completion processing */
92 	{ "hal2",	0x01000000 },		/* cmd submission processing */
93 	{ "halhang",	0x04000000 },		/* disable fw hang stuff */
94 };
95 
96 static u_int
97 getflag(const char *name, int len)
98 {
99 	int i;
100 
101 	for (i = 0; i < nitems(flags); i++)
102 		if (strncasecmp(flags[i].name, name, len) == 0)
103 			return flags[i].bit;
104 	return 0;
105 }
106 
107 #if 0
108 static const char *
109 getflagname(u_int flag)
110 {
111 	int i;
112 
113 	for (i = 0; i < nitems(flags); i++)
114 		if (flags[i].bit == flag)
115 			return flags[i].name;
116 	return "???";
117 }
118 #endif
119 
120 static void
121 usage(void)
122 {
123 	int i;
124 
125 	fprintf(stderr, "usage: %s [-i device] [flags]\n", progname);
126 	fprintf(stderr, "where flags are:\n");
127 	for (i = 0; i < nitems(flags); i++)
128 		printf("%s\n", flags[i].name);
129 	exit(-1);
130 }
131 
132 int
133 main(int argc, char *argv[])
134 {
135 	const char *ifname = "mwl0";
136 	const char *cp, *tp;
137 	const char *sep;
138 	int c, op, i;
139 	u_int32_t debug, ndebug;
140 	size_t debuglen;
141 	char oid[256];
142 
143 	progname = argv[0];
144 	if (argc > 1) {
145 		if (strcmp(argv[1], "-i") == 0) {
146 			if (argc < 2)
147 				errx(1, "missing interface name for -i option");
148 			ifname = argv[2];
149 			if (strncmp(ifname, "mv", 2) != 0)
150 				errx(2, "huh, this is for mv devices?");
151 			argc -= 2, argv += 2;
152 		} else if (strcmp(argv[1], "-?") == 0)
153 			usage();
154 	}
155 
156 	snprintf(oid, sizeof(oid), "dev.mwl.%s.debug", ifname+3);
157 	debuglen = sizeof(debug);
158 	if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0)
159 		err(1, "sysctl-get(%s)", oid);
160 	ndebug = debug;
161 	for (; argc > 1; argc--, argv++) {
162 		cp = argv[1];
163 		do {
164 			u_int bit;
165 
166 			if (*cp == '-') {
167 				cp++;
168 				op = -1;
169 			} else if (*cp == '+') {
170 				cp++;
171 				op = 1;
172 			} else
173 				op = 0;
174 			for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';)
175 				tp++;
176 			bit = getflag(cp, tp-cp);
177 			if (op < 0)
178 				ndebug &= ~bit;
179 			else if (op > 0)
180 				ndebug |= bit;
181 			else {
182 				if (bit == 0) {
183 					c = *cp;
184 					if (isdigit(c))
185 						bit = strtoul(cp, NULL, 0);
186 					else
187 						errx(1, "unknown flag %.*s",
188 							(int)(tp-cp), cp);
189 				}
190 				ndebug = bit;
191 			}
192 		} while (*(cp = tp) != '\0');
193 	}
194 	if (debug != ndebug) {
195 		printf("%s: 0x%x => ", oid, debug);
196 		if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0)
197 			err(1, "sysctl-set(%s)", oid);
198 		printf("0x%x", ndebug);
199 		debug = ndebug;
200 	} else
201 		printf("%s: 0x%x", oid, debug);
202 	sep = "<";
203 	for (i = 0; i < nitems(flags); i++)
204 		if (debug & flags[i].bit) {
205 			printf("%s%s", sep, flags[i].name);
206 			sep = ",";
207 		}
208 	printf("%s\n", *sep != '<' ? ">" : "");
209 	return 0;
210 }
211