3 * Michael Smith. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY Michael Smith AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/usr.sbin/wlconfig/wlconfig.c,v 1.8.2.2 2001/07/19 05:24:10 kris Exp $
27 * $DragonFly: src/usr.sbin/wlconfig/wlconfig.c,v 1.3 2005/12/05 01:23:23 swildner Exp $
33 * utility to read out and change various WAVELAN parameters.
34 * Currently supports NWID and IRQ values.
36 * The NWID is used by 2 or more wavelan controllers to determine
37 * if packets should be received or not. It is a filter that
38 * is roughly analogous to the "channel" setting with a garage
39 * door controller. Two companies side by side with wavelan devices
40 * that could actually hear each other can use different NWIDs
41 * and ignore packets. In truth however, the air space is shared,
42 * and the NWID is a virtual filter.
44 * In the current set of wavelan drivers, ioctls changed only
45 * the runtime radio modem registers which act in a manner analogous
46 * to an ethernet transceiver. The ioctls do not change the
47 * stored nvram PSA (or parameter storage area). At boot, the PSA
48 * values are stored in the radio modem. Thus when the
49 * system reboots it will restore the wavelan NWID to the value
50 * stored in the PSA. The NCR/ATT dos utilities must be used to
51 * change the initial NWID values in the PSA. The wlconfig utility
52 * may be used to set a different NWID at runtime; this is only
53 * permitted while the interface is up and running.
55 * By contrast, the IRQ value can only be changed while the
56 * Wavelan card is down and unconfigured, and it will remain
57 * disabled after an IRQ change until reboot.
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <sys/ioctl.h>
65 #include <machine/if_wl_wavelan.h>
68 #include <netinet/in.h>
69 #include <netinet/if_ether.h>
78 /* translate IRQ bit to number */
79 /* array for maping irq numbers to values for the irq parameter register */
80 static int irqvals
[16] = {
81 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
85 static int w_sigitems
; /* count of valid items */
86 static struct w_sigcache wsc
[MAXCACHEITEMS
];
93 for(irq
= 0; irq
< 16; irq
++)
94 if(irqvals
[irq
] == irqval
)
99 char *compat_type
[] = {
104 "PCCARD or 1/2 size AT, 915MHz or 2.4GHz"
108 "915MHz/see WaveModem",
119 ** Given a pointer to a PSA structure, print it out
122 print_psa(u_char
*psa
, int currnwid
)
127 ** Work out what sort of board we have
129 if (psa
[0] == 0x14) {
130 printf("Board type : Microchannel\n");
133 printf("Board type : PCCARD\n");
135 printf("Board type : ISA");
139 printf(" (DEC OEM)");
141 printf("Base address options : 0x300, 0x%02x0, 0x%02x0, 0x%02x0\n",
142 (int)psa
[1], (int)psa
[2], (int)psa
[3]);
143 printf("Waitstates : %d\n",psa
[7] & 0xf);
144 printf("Bus mode : %s\n",(psa
[7] & 0x10) ? "EISA" : "ISA");
145 printf("IRQ : %d\n",wlirq(psa
[8]));
148 printf("Default MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n",
149 psa
[0x10],psa
[0x11],psa
[0x12],psa
[0x13],psa
[0x14],psa
[0x15]);
150 printf("Soft MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n",
151 psa
[0x16],psa
[0x17],psa
[0x18],psa
[0x19],psa
[0x1a],psa
[0x1b]);
152 printf("Current MAC address : %s\n",(psa
[0x1c] & 0x1) ? "Soft" : "Default");
153 printf("Adapter compatibility : ");
155 printf("%s\n",compat_type
[psa
[0x1d]]);
159 printf("Threshold preset : %d\n",psa
[0x1e]);
160 printf("Call code required : %s\n",(psa
[0x1f] & 0x1) ? "YES" : "NO");
162 printf("Call code : 0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
163 psa
[0x30],psa
[0x31],psa
[0x32],psa
[0x33],psa
[0x34],psa
[0x35],psa
[0x36],psa
[0x37]);
164 printf("Subband : %s\n",subband
[psa
[0x20] & 0xf]);
165 printf("Quality threshold : %d\n",psa
[0x21]);
166 printf("Hardware version : %d (%s)\n",psa
[0x22],psa
[0x22] ? "Rel3" : "Rel1/Rel2");
167 printf("Network ID enable : %s\n",(psa
[0x25] & 0x1) ? "YES" : "NO");
168 if (psa
[0x25] & 0x1) {
169 nwid
= (psa
[0x23] << 8) + psa
[0x24];
170 printf("NWID : 0x%04x\n",nwid
);
171 if (nwid
!= currnwid
) {
172 printf("Current NWID : 0x%04x\n",currnwid
);
175 printf("Datalink security : %s\n",(psa
[0x26] & 0x1) ? "YES" : "NO");
176 if (psa
[0x26] & 0x1) {
177 printf("Encryption key : ");
178 if (psa
[0x27] == 0) {
181 printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
182 psa
[0x27],psa
[0x28],psa
[0x29],psa
[0x2a],psa
[0x2b],psa
[0x2c],psa
[0x2d],psa
[0x2e]);
185 printf("Databus width : %d (%s)\n",
186 (psa
[0x2f] & 0x1) ? 16 : 8, (psa
[0x2f] & 0x80) ? "fixed" : "variable");
187 printf("Configuration state : %sconfigured\n",(psa
[0x38] & 0x1) ? "" : "un");
188 printf("CRC-16 : 0x%02x%02x\n",psa
[0x3e],psa
[0x3d]);
189 printf("CRC status : ");
207 fprintf(stderr
,"usage: wlconfig ifname [param value ...]\n");
213 get_cache(int sd
, struct ifreq
*ifr
)
215 /* get the cache count */
216 if (ioctl(sd
, SIOCGWLCITEM
, (caddr_t
)ifr
))
217 err(1, "SIOCGWLCITEM - get cache count");
218 w_sigitems
= (int) ifr
->ifr_data
;
220 ifr
->ifr_data
= (caddr_t
) &wsc
;
222 if (ioctl(sd
, SIOCGWLCACHE
, (caddr_t
)ifr
))
223 err(1, "SIOCGWLCACHE - get cache count");
227 scale_value(int value
, int max
)
229 double dmax
= (double) max
;
232 return((value
/dmax
) * 100);
236 dump_cache(int rawFlag
)
239 int signal
, silence
, quality
;
242 printf("signal range 0..63: silence 0..63: quality 0..15\n");
244 printf("signal range 0..100: silence 0..100: quality 0..100\n");
246 /* after you read it, loop through structure,i.e. wsc
249 for(i
= 0; i
< w_sigitems
; i
++) {
250 printf("[%d:%d]>\n", i
+1, w_sigitems
);
251 printf("\tip: %d.%d.%d.%d,",((wsc
[i
].ipsrc
>> 0) & 0xff),
252 ((wsc
[i
].ipsrc
>> 8) & 0xff),
253 ((wsc
[i
].ipsrc
>> 16) & 0xff),
254 ((wsc
[i
].ipsrc
>> 24) & 0xff));
255 printf(" mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
256 wsc
[i
].macsrc
[0]&0xff,
257 wsc
[i
].macsrc
[1]&0xff,
258 wsc
[i
].macsrc
[2]&0xff,
259 wsc
[i
].macsrc
[3]&0xff,
260 wsc
[i
].macsrc
[4]&0xff,
261 wsc
[i
].macsrc
[5]&0xff);
263 signal
= wsc
[i
].signal
;
264 silence
= wsc
[i
].silence
;
265 quality
= wsc
[i
].quality
;
268 signal
= scale_value(wsc
[i
].signal
, 63);
269 silence
= scale_value(wsc
[i
].silence
, 63);
270 quality
= scale_value(wsc
[i
].quality
, 15);
272 printf("\tsignal: %d, silence: %d, quality: %d, ",
276 printf("snr: %d\n", signal
- silence
);
280 #define raw_cache() dump_cache(1)
281 #define scale_cache() dump_cache(0)
284 main(int argc
, char *argv
[])
290 char *cp
, *param
, *value
;
291 struct ether_addr
*ea
;
295 if ((argc
< 2) || (argc
% 2))
299 sd
= socket(AF_INET
, SOCK_DGRAM
, 0);
302 strncpy(ifr
.ifr_name
, argv
[1], sizeof(ifr
.ifr_name
));
303 ifr
.ifr_addr
.sa_family
= AF_INET
;
306 ifr
.ifr_data
= (caddr_t
)psabuf
;
307 if (ioctl(sd
, SIOCGWLPSA
, (caddr_t
)&ifr
))
310 /* get the current NWID */
311 if (ioctl(sd
, SIOCGWLCNWID
, (caddr_t
)&ifr
))
313 currnwid
= (int)ifr
.ifr_data
;
315 /* just dump and exit? */
317 print_psa(psabuf
, currnwid
);
321 /* loop reading arg pairs */
322 for (argind
= 2; argind
< argc
; argind
+= 2) {
324 param
= argv
[argind
];
325 value
= argv
[argind
+1];
329 if (!strcasecmp(param
,"currnwid")) { /* set current NWID */
330 val
= strtol(value
,&cp
,0);
331 if ((val
< 0) || (val
> 0xffff) || (cp
== value
))
332 errx(1,"bad NWID '%s'",value
);
334 ifr
.ifr_data
= (caddr_t
)val
;
335 if (ioctl(sd
, SIOCSWLCNWID
, (caddr_t
)&ifr
))
336 err(1,"set NWID (interface not up?)");
340 if (!strcasecmp(param
,"irq")) {
341 val
= strtol(value
,&cp
,0);
343 if ((val
== 0) || (cp
== value
))
344 errx(1,"bad IRQ '%s'",value
);
345 psabuf
[WLPSA_IRQNO
] = (u_char
)val
;
350 if (!strcasecmp(param
,"mac")) {
351 if ((ea
= ether_aton(value
)) == NULL
)
352 errx(1,"bad ethernet address '%s'",value
);
353 for (i
= 0; i
< 6; i
++)
354 psabuf
[WLPSA_LOCALMAC
+ i
] = ea
->octet
[i
];
359 if (!strcasecmp(param
,"macsel")) {
360 if (!strcasecmp(value
,"local")) {
361 psabuf
[WLPSA_MACSEL
] |= 0x1;
365 if (!strcasecmp(value
,"universal")) {
366 psabuf
[WLPSA_MACSEL
] &= ~0x1;
370 errx(1,"bad macsel value '%s'",value
);
373 if (!strcasecmp(param
,"nwid")) {
374 val
= strtol(value
,&cp
,0);
375 if ((val
< 0) || (val
> 0xffff) || (cp
== value
))
376 errx(1,"bad NWID '%s'",value
);
377 psabuf
[WLPSA_NWID
] = (val
>> 8) & 0xff;
378 psabuf
[WLPSA_NWID
+1] = val
& 0xff;
382 if (!strcasecmp(param
,"cache")) {
386 if (!strcasecmp(value
,"raw")) {
393 else if (!strcasecmp(value
,"scale")) {
400 else if (!strcasecmp(value
,"zero")) {
401 if (ioctl(sd
, SIOCDWLCACHE
, (caddr_t
)&ifr
))
405 errx(1,"unknown value '%s'", value
);
407 errx(1,"unknown parameter '%s'",param
);
410 ifr
.ifr_data
= (caddr_t
)psabuf
;
411 if (ioctl(sd
, SIOCSWLPSA
, (caddr_t
)&ifr
))