Broadcom SDK and wireless driver: another attempt to update to ver. 5.10.147.0
[tomato.git] / release / src-rt / et / linux / et.c
blob10a3734938a4f2d5ae81eb8d5bebdc1b3f843d88
1 /*
2 * et driver ioctl swiss army knife command.
4 * Copyright (C) 2009, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: et.c,v 1.9.130.4 2009/07/17 03:09:33 Exp $
15 #include <stdio.h>
17 #include <sys/param.h>
18 #include <sys/ioctl.h>
19 #include <sys/socket.h>
20 #include <sys/sysctl.h>
21 #include <sys/time.h>
22 #include <net/if.h>
23 #include <netinet/in.h>
24 #include <typedefs.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <etioctl.h>
30 #include <proto/ethernet.h>
32 typedef u_int64_t u64;
33 typedef u_int32_t u32;
34 typedef u_int16_t u16;
35 typedef u_int8_t u8;
36 #include <linux/types.h>
37 #include <linux/sockios.h>
38 #include <linux/ethtool.h>
40 static void usage(char *av0);
41 static void syserr(char *s);
42 static void et_find(int s, struct ifreq *ifr);
43 static int et_check(int s, struct ifreq *ifr);
47 char buf[16 * 1024];
49 #define VECLEN 5
51 int
52 main(int ac, char *av[])
54 char *interface = NULL;
55 struct ifreq ifr;
56 char *endptr;
57 int arg;
58 int vecarg[VECLEN];
59 int s;
60 static int optind;
61 et_var_t var;
63 if (ac < 2)
64 usage(av[0]);
66 optind = 1;
68 if (av[1][0] == '-') {
69 if ((av[1][1] != 'a') && (av[1][1] != 'i'))
70 usage(av[0]);
71 if (ac < 4)
72 usage(av[0]);
73 interface = av[2];
74 optind += 2;
77 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
78 syserr("socket");
80 if (interface)
81 strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name));
82 else
83 et_find(s, &ifr);
85 if (!*ifr.ifr_name) {
86 fprintf(stderr, "et interface not found\n");
87 exit(1);
90 if (strcmp(av[optind], "up") == 0) {
91 if (ioctl(s, SIOCSETCUP, (caddr_t)&ifr) < 0)
92 syserr("etcup");
93 } else if (strcmp(av[optind], "down") == 0) {
94 if (ioctl(s, SIOCSETCDOWN, (caddr_t)&ifr) < 0)
95 syserr("etcdown");
96 } else if (strcmp(av[optind], "loop") == 0) {
97 if (optind >= (ac -1))
98 usage(av[0]);
99 arg = atoi(av[optind + 1]);
100 ifr.ifr_data = (caddr_t) &arg;
101 if (ioctl(s, SIOCSETCLOOP, (caddr_t)&ifr) < 0)
102 syserr("etcloop");
103 } else if (strcmp(av[optind], "dump") == 0) {
104 ifr.ifr_data = buf;
105 if (ioctl(s, SIOCGETCDUMP, (caddr_t)&ifr) < 0)
106 syserr("etcdump");
107 printf("%s\n", buf);
108 } else if (strcmp(av[optind], "msglevel") == 0) {
109 if (optind >= (ac -1))
110 usage(av[0]);
111 arg = strtol(av[optind + 1], &endptr, 0);
112 ifr.ifr_data = (caddr_t) &arg;
113 if (ioctl(s, SIOCSETCSETMSGLEVEL, (caddr_t)&ifr) < 0)
114 syserr("etcsetmsglevel");
115 } else if (strcmp(av[optind], "promisc") == 0) {
116 if (optind >= (ac -1))
117 usage(av[0]);
118 arg = atoi(av[optind + 1]);
119 ifr.ifr_data = (caddr_t) &arg;
120 if (ioctl(s, SIOCSETCPROMISC, (caddr_t)&ifr) < 0)
121 syserr("etcpromisc");
122 } else if (strcmp(av[optind], "qos") == 0) {
123 if (optind >= (ac -1))
124 usage(av[0]);
125 arg = atoi(av[optind + 1]);
126 ifr.ifr_data = (caddr_t) &arg;
127 if (ioctl(s, SIOCSETCQOS, (caddr_t)&ifr) < 0)
128 syserr("etcqos");
129 } else if (strcmp(av[optind], "speed") == 0) {
130 if (optind >= (ac -1))
131 usage(av[0]);
132 if (strcmp(av[optind+1], "auto") == 0)
133 arg = -1;
134 else if (strcmp(av[optind+1], "10half") == 0)
135 arg = 0;
136 else if (strcmp(av[optind+1], "10full") == 0)
137 arg = 1;
138 else if (strcmp(av[optind+1], "100half") == 0)
139 arg = 2;
140 else if (strcmp(av[optind+1], "100full") == 0)
141 arg = 3;
142 else if (strcmp(av[optind+1], "1000full") == 0)
143 arg = 5;
144 else
145 usage(av[0]);
147 ifr.ifr_data = (caddr_t) &arg;
148 if (ioctl(s, SIOCSETCSPEED, (caddr_t)&ifr) < 0)
149 syserr("etcspeed");
151 else if (strcmp(av[optind], "phyrd") == 0) {
152 int cmd = -1;
154 if ((ac < (optind + 2)) || (ac > (optind + 3))) {
155 usage(av[0]);
156 } else if (ac == (optind + 3)) {
157 /* PHY address provided */
158 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
159 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
160 cmd = SIOCGETCPHYRD2;
161 } else {
162 /* "My" PHY address implied */
163 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
164 cmd = SIOCGETCPHYRD;
166 ifr.ifr_data = (caddr_t) vecarg;
167 if (ioctl(s, cmd, (caddr_t)&ifr) < 0)
168 syserr("etcphyrd");
170 printf("0x%04x\n", vecarg[1]);
171 } else if (strcmp(av[optind], "phywr") == 0) {
172 int cmd = -1;
174 if ((ac < (optind + 3)) || (ac > (optind + 4))) {
175 usage(av[0]);
176 } else if (ac == (optind + 4)) {
177 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
178 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
179 vecarg[1] = strtoul(av[optind + 3], NULL, 0);
180 cmd = SIOCSETCPHYWR2;
181 } else {
182 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
183 vecarg[1] = strtoul(av[optind + 2], NULL, 0);
184 cmd = SIOCSETCPHYWR;
186 ifr.ifr_data = (caddr_t) vecarg;
187 if (ioctl(s, cmd, (caddr_t)&ifr) < 0)
188 syserr("etcphywr");
189 } else if (strcmp(av[optind], "robord") == 0) {
190 if (ac != (optind + 3))
191 usage(av[0]);
193 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
194 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
196 ifr.ifr_data = (caddr_t) vecarg;
197 if (ioctl(s, SIOCGETCROBORD, (caddr_t)&ifr) < 0)
198 syserr("etcrobord");
200 printf("0x%04x\n", vecarg[1]);
201 } else if (strcmp(av[optind], "robowr") == 0) {
202 if (ac != (optind + 4))
203 usage(av[0]);
205 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
206 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
207 vecarg[1] = strtoul(av[optind + 3], NULL, 0);
209 ifr.ifr_data = (caddr_t) vecarg;
210 if (ioctl(s, SIOCSETCROBOWR, (caddr_t)&ifr) < 0)
211 syserr("etcrobowr");
212 } else {
213 if (strcmp(av[optind], "switch_mode") == 0) {
214 int all = 0;
216 /* GET case */
217 if (ac == (optind + 1)) {
218 var.set = 0;
219 vecarg[0] = VECLEN;
220 all = 1;
221 } else if (ac == (optind + 2)) {
222 var.set = 0;
223 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
224 all = (int)(vecarg[0] == VECLEN);
225 } else {
226 if (ac != (optind + 3))
227 usage(av[0]);
229 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
230 vecarg[1] = strtoul(av[optind + 2], NULL, 0);
231 if (vecarg[1] > 3)
232 usage(av[0]);
234 var.set = 1;
237 var.len = VECLEN * sizeof(int);
238 var.cmd = IOV_ET_POWER_SAVE_MODE;
239 var.buf = &vecarg;
241 ifr.ifr_data = (caddr_t) &var;
242 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
243 syserr("etcswitchmode");
245 if (!var.set) {
246 if (all)
247 printf("phy power save mode for all phys:"
248 " %d %d %d %d %d \n",
249 vecarg[0], vecarg[1], vecarg[2],
250 vecarg[3], vecarg[4]);
251 else
252 printf("phy power save mode for phy %d mode %d\n",
253 vecarg[0], vecarg[1]);
255 } else {
256 usage(av[0]);
260 return (0);
263 static void
264 usage(char *av0)
266 fprintf(stderr, "usage: %s [ [ -a | -i ] interface ] and one of:\n"
267 "\tup\n"
268 "\tdown\n"
269 "\tloop <0 or 1>\n"
270 "\tdump\n"
271 "\tmsglevel <bitvec> (error=1, trace=2, prhdr=4, prpkt=8)\n"
272 "\tpromisc <0 or 1>\n"
273 "\tqos <0 or 1>\n"
274 "\tspeed <auto, 10half, 10full, 100half, 100full, 1000full>\n"
275 "\tphyrd [<phyaddr>] <reg>\n"
276 "\tphywr [<phyaddr>] <reg> <val>\n"
277 "\trobord <page> <reg>\n"
278 "\trobowr <page> <reg> <val>\n"
279 "\tswitch_mode <phy> <mode> (mode 0, 1, 2, 3)\n"
281 av0);
282 exit(1);
285 static void
286 et_find(int s, struct ifreq *ifr)
288 char proc_net_dev[] = "/proc/net/dev";
289 FILE *fp;
290 char buf[512], *c, *name;
292 ifr->ifr_name[0] = '\0';
294 /* eat first two lines */
295 if (!(fp = fopen(proc_net_dev, "r")) ||
296 !fgets(buf, sizeof(buf), fp) ||
297 !fgets(buf, sizeof(buf), fp))
298 return;
300 while (fgets(buf, sizeof(buf), fp)) {
301 c = buf;
302 while (isspace(*c))
303 c++;
304 if (!(name = strsep(&c, ":")))
305 continue;
306 strncpy(ifr->ifr_name, name, IFNAMSIZ);
307 if (et_check(s, ifr) == 0)
308 break;
309 ifr->ifr_name[0] = '\0';
312 fclose(fp);
315 static int
316 et_check(int s, struct ifreq *ifr)
318 struct ethtool_drvinfo info;
320 memset(&info, 0, sizeof(info));
321 info.cmd = ETHTOOL_GDRVINFO;
322 ifr->ifr_data = (caddr_t)&info;
323 if (ioctl(s, SIOCETHTOOL, (caddr_t)ifr) < 0) {
324 /* print a good diagnostic if not superuser */
325 if (errno == EPERM)
326 syserr("siocethtool");
327 return (-1);
330 if (!strncmp(info.driver, "et", 2))
331 return (0);
332 else if (!strncmp(info.driver, "bcm57", 5))
333 return (0);
335 return (-1);
338 static void
339 syserr(char *s)
341 perror(s);
342 exit(1);