proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / dev / netif / awi / awi_wicfg.c
CommitLineData
984263bc
MD
1/* $NetBSD: awi_wicfg.c,v 1.3 2000/07/06 17:22:25 onoe Exp $ */
2/* $FreeBSD: src/sys/dev/awi/awi_wicfg.c,v 1.3.2.2 2002/06/18 08:06:15 jhay Exp $ */
dadab5e9 3/* $DragonFly: src/sys/dev/netif/awi/Attic/awi_wicfg.c,v 1.4 2003/06/25 03:55:46 dillon Exp $ */
984263bc
MD
4
5/*
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Atsushi Onoe.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41/*
42 * WaveLAN compatible configuration support routines for the awi driver.
43 */
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/kernel.h>
48#include <sys/mbuf.h>
49#include <sys/malloc.h>
50#include <sys/proc.h>
51#include <sys/socket.h>
52#include <sys/errno.h>
53#include <sys/sockio.h>
54#if defined(__FreeBSD__) && __FreeBSD__ >= 4
55#include <sys/bus.h>
56#else
57#include <sys/device.h>
58#endif
59
60#include <net/if.h>
61#include <net/if_dl.h>
62#ifdef __FreeBSD__
63#include <net/ethernet.h>
64#include <net/if_arp.h>
65#else
66#include <net/if_ether.h>
67#endif
68#include <net/if_media.h>
69#include <net/if_ieee80211.h>
70
71#include <machine/cpu.h>
72#include <machine/bus.h>
73#ifdef __FreeBSD__
74#include <machine/clock.h>
75#endif
76
77#ifdef __NetBSD__
78#include <dev/ic/am79c930reg.h>
79#include <dev/ic/am79c930var.h>
80#include <dev/ic/awireg.h>
81#include <dev/ic/awivar.h>
82
83#include <dev/pcmcia/if_wi_ieee.h> /* XXX */
84#endif
85#ifdef __FreeBSD__
86#include <dev/awi/am79c930reg.h>
87#include <dev/awi/am79c930var.h>
88
89#undef _KERNEL /* XXX */
90#include <dev/wi/if_wavelan_ieee.h> /* XXX */
91#define _KERNEL /* XXX */
92#include <dev/awi/awireg.h>
93#include <dev/awi/awivar.h>
94#endif
95
96static int awi_cfgget __P((struct ifnet *ifp, u_long cmd, caddr_t data));
97static int awi_cfgset __P((struct ifnet *ifp, u_long cmd, caddr_t data));
98
99int
100awi_wicfg(ifp, cmd, data)
101 struct ifnet *ifp;
102 u_long cmd;
103 caddr_t data;
104{
105 int error;
dadab5e9 106 struct thread *td = curthread;
984263bc
MD
107
108 switch (cmd) {
109 case SIOCGWAVELAN:
110 error = awi_cfgget(ifp, cmd, data);
111 break;
112 case SIOCSWAVELAN:
113#ifdef __FreeBSD__
dadab5e9 114 error = suser(td); /* note: EPERM if no proc */
984263bc
MD
115#else
116 error = suser(curproc->p_ucred, &curproc->p_acflag);
117#endif
118 if (error)
119 break;
120 error = awi_cfgset(ifp, cmd, data);
121 break;
122 default:
123 error = EINVAL;
124 break;
125 }
126 return error;
127}
128
129static int
130awi_cfgget(ifp, cmd, data)
131 struct ifnet *ifp;
132 u_long cmd;
133 caddr_t data;
134{
135 int i, error, keylen;
136 char *p;
137 struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
138 struct ifreq *ifr = (struct ifreq *)data;
139 struct wi_ltv_keys *keys;
140 struct wi_key *k;
141 struct wi_req wreq;
142#ifdef WICACHE
143 struct wi_sigcache wsc;
144 struct awi_bss *bp;
145#endif /* WICACHE */
dadab5e9 146 struct thread *td = curthread;
984263bc
MD
147
148 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
149 if (error)
150 return error;
151 switch (wreq.wi_type) {
152 case WI_RID_SERIALNO:
153 memcpy(wreq.wi_val, sc->sc_banner, AWI_BANNER_LEN);
154 wreq.wi_len = (AWI_BANNER_LEN + 1) / 2;
155 break;
156 case WI_RID_NODENAME:
157 strcpy((char *)&wreq.wi_val[1], hostname);
158 wreq.wi_val[0] = strlen(hostname);
159 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
160 break;
161 case WI_RID_OWN_SSID:
162 p = sc->sc_ownssid;
163 wreq.wi_val[0] = p[1];
164 memcpy(&wreq.wi_val[1], p + 2, p[1]);
165 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
166 break;
167 case WI_RID_CURRENT_SSID:
168 if (ifp->if_flags & IFF_RUNNING) {
169 p = sc->sc_bss.essid;
170 wreq.wi_val[0] = p[1];
171 memcpy(&wreq.wi_val[1], p + 2, p[1]);
172 } else {
173 wreq.wi_val[0] = 0;
174 wreq.wi_val[1] = '\0';
175 }
176 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
177 break;
178 case WI_RID_DESIRED_SSID:
179 p = sc->sc_mib_mac.aDesired_ESS_ID;
180 wreq.wi_val[0] = p[1];
181 memcpy(&wreq.wi_val[1], p + 2, p[1]);
182 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
183 break;
184 case WI_RID_CURRENT_BSSID:
185 if (ifp->if_flags & IFF_RUNNING)
186 memcpy(wreq.wi_val, sc->sc_bss.bssid, ETHER_ADDR_LEN);
187 else
188 memset(wreq.wi_val, 0, ETHER_ADDR_LEN);
189 wreq.wi_len = ETHER_ADDR_LEN / 2;
190 break;
191 case WI_RID_CHANNEL_LIST:
192 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
193 wreq.wi_val[0] = sc->sc_scan_min;
194 wreq.wi_val[1] = sc->sc_scan_max;
195 wreq.wi_len = 2;
196 } else {
197 wreq.wi_val[0] = 0;
198 for (i = sc->sc_scan_min; i <= sc->sc_scan_max; i++)
199 wreq.wi_val[0] |= 1 << (i - 1);
200 wreq.wi_len = 1;
201 }
202 break;
203 case WI_RID_OWN_CHNL:
204 wreq.wi_val[0] = sc->sc_ownch;
205 wreq.wi_len = 1;
206 break;
207 case WI_RID_CURRENT_CHAN:
208 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
209 wreq.wi_val[0] = sc->sc_bss.pattern;
210 else
211 wreq.wi_val[0] = sc->sc_bss.chanset;
212 wreq.wi_len = 1;
213 break;
214 case WI_RID_COMMS_QUALITY:
215 wreq.wi_val[0] = 0; /* quality */
216 wreq.wi_val[1] = sc->sc_bss.rssi; /* signal */
217 wreq.wi_val[2] = 0; /* noise */
218 wreq.wi_len = 3;
219 break;
220 case WI_RID_PROMISC:
221 wreq.wi_val[0] = sc->sc_mib_mac.aPromiscuous_Enable;
222 wreq.wi_len = 1;
223 break;
224 case WI_RID_PORTTYPE:
225 if (sc->sc_mib_local.Network_Mode)
226 wreq.wi_val[0] = 1;
227 else if (!sc->sc_no_bssid)
228 wreq.wi_val[0] = 2;
229 else
230 wreq.wi_val[0] = 3;
231 wreq.wi_len = 1;
232 break;
233 case WI_RID_MAC_NODE:
234 memcpy(wreq.wi_val, sc->sc_mib_addr.aMAC_Address,
235 ETHER_ADDR_LEN);
236 wreq.wi_len = ETHER_ADDR_LEN / 2;
237 break;
238 case WI_RID_TX_RATE:
239 case WI_RID_CUR_TX_RATE:
240 wreq.wi_val[0] = sc->sc_tx_rate / 10;
241 wreq.wi_len = 1;
242 break;
243 case WI_RID_RTS_THRESH:
244 wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aRTS_Threshold);
245 wreq.wi_len = 1;
246 break;
247 case WI_RID_CREATE_IBSS:
248 wreq.wi_val[0] = sc->sc_start_bss;
249 wreq.wi_len = 1;
250 break;
251 case WI_RID_SYSTEM_SCALE:
252 wreq.wi_val[0] = 1; /* low density ... not supported */
253 wreq.wi_len = 1;
254 break;
255 case WI_RID_PM_ENABLED:
256 wreq.wi_val[0] = sc->sc_mib_local.Power_Saving_Mode_Dis ? 0 : 1;
257 wreq.wi_len = 1;
258 break;
259 case WI_RID_MAX_SLEEP:
260 wreq.wi_val[0] = 0; /* not implemented */
261 wreq.wi_len = 1;
262 break;
263 case WI_RID_WEP_AVAIL:
264 wreq.wi_val[0] = 1;
265 wreq.wi_len = 1;
266 break;
267 case WI_RID_ENCRYPTION:
268 wreq.wi_val[0] = awi_wep_getalgo(sc);
269 wreq.wi_len = 1;
270 break;
271 case WI_RID_TX_CRYPT_KEY:
272 wreq.wi_val[0] = sc->sc_wep_defkid;
273 wreq.wi_len = 1;
274 break;
275 case WI_RID_DEFLT_CRYPT_KEYS:
276 keys = (struct wi_ltv_keys *)&wreq;
277 /* do not show keys to non-root user */
278#ifdef __FreeBSD__
dadab5e9 279 error = suser(td); /* note: EPERM if no proc */
984263bc
MD
280#else
281 error = suser(curproc->p_ucred, &curproc->p_acflag);
282#endif
283 if (error) {
284 memset(keys, 0, sizeof(*keys));
285 error = 0;
286 break;
287 }
288 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
289 k = &keys->wi_keys[i];
290 keylen = sizeof(k->wi_keydat);
291 error = awi_wep_getkey(sc, i, k->wi_keydat, &keylen);
292 if (error)
293 break;
294 k->wi_keylen = keylen;
295 }
296 wreq.wi_len = sizeof(*keys) / 2;
297 break;
298 case WI_RID_MAX_DATALEN:
299 wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aMax_Frame_Length);
300 wreq.wi_len = 1;
301 break;
302 case WI_RID_IFACE_STATS:
303 /* not implemented yet */
304 wreq.wi_len = 0;
305 break;
306#ifdef WICACHE
307 case WI_RID_READ_CACHE:
308 for (bp = TAILQ_FIRST(&sc->sc_scan), i = 0;
309 bp != NULL && i < MAXWICACHE;
310 bp = TAILQ_NEXT(bp, list), i++) {
311 memcpy(wsc.macsrc, bp->esrc, ETHER_ADDR_LEN);
312 /*XXX*/
313 memcpy(&wsc.ipsrc, bp->bssid, sizeof(wsc.ipsrc));
314 wsc.signal = bp->rssi;
315 wsc.noise = 0;
316 wsc.quality = 0;
317 memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
318 &wsc, sizeof(wsc));
319 }
320 wreq.wi_len = sizeof(wsc) * i / 2;
321 break;
322#endif /* WICACHE */
323 default:
324 error = EINVAL;
325 break;
326 }
327 if (error == 0) {
328 wreq.wi_len++;
329 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
330 }
331 return error;
332}
333
334static int
335awi_cfgset(ifp, cmd, data)
336 struct ifnet *ifp;
337 u_long cmd;
338 caddr_t data;
339{
340 int i, error, rate, oregion;
341 u_int8_t *phy_rates;
342 struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
343 struct ifreq *ifr = (struct ifreq *)data;
344 struct wi_ltv_keys *keys;
345 struct wi_key *k;
346 struct wi_req wreq;
347
348 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
349 if (error)
350 return error;
351 if (wreq.wi_len-- < 1)
352 return EINVAL;
353 switch (wreq.wi_type) {
354 case WI_RID_SERIALNO:
355 case WI_RID_NODENAME:
356 error = EPERM;
357 break;
358 case WI_RID_OWN_SSID:
359 if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
360 error = EINVAL;
361 break;
362 }
363 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
364 error = EINVAL;
365 break;
366 }
367 memset(sc->sc_ownssid, 0, AWI_ESS_ID_SIZE);
368 sc->sc_ownssid[0] = IEEE80211_ELEMID_SSID;
369 sc->sc_ownssid[1] = wreq.wi_val[0];
370 memcpy(&sc->sc_ownssid[2], &wreq.wi_val[1], wreq.wi_val[0]);
371 if (!sc->sc_mib_local.Network_Mode &&
372 !sc->sc_no_bssid && sc->sc_start_bss)
373 error = ENETRESET;
374 break;
375 case WI_RID_CURRENT_SSID:
376 error = EPERM;
377 break;
378 case WI_RID_DESIRED_SSID:
379 if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
380 error = EINVAL;
381 break;
382 }
383 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
384 error = EINVAL;
385 break;
386 }
387 memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
388 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
389 sc->sc_mib_mac.aDesired_ESS_ID[1] = wreq.wi_val[0];
390 memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], &wreq.wi_val[1],
391 wreq.wi_val[0]);
392 if (sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid)
393 error = ENETRESET;
394 break;
395 case WI_RID_CURRENT_BSSID:
396 error = EPERM;
397 break;
398 case WI_RID_CHANNEL_LIST:
399 if (wreq.wi_len != 1) {
400 error = EINVAL;
401 break;
402 }
403 oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
404 if (wreq.wi_val[0] == oregion)
405 break;
406 sc->sc_mib_phy.aCurrent_Reg_Domain = wreq.wi_val[0];
407 error = awi_init_region(sc);
408 if (error) {
409 sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
410 break;
411 }
412 error = ENETRESET;
413 break;
414 case WI_RID_OWN_CHNL:
415 if (wreq.wi_len != 1) {
416 error = EINVAL;
417 break;
418 }
419 if (wreq.wi_val[0] < sc->sc_scan_min ||
420 wreq.wi_val[0] > sc->sc_scan_max) {
421 error = EINVAL;
422 break;
423 }
424 sc->sc_ownch = wreq.wi_val[0];
425 if (!sc->sc_mib_local.Network_Mode)
426 error = ENETRESET;
427 break;
428 case WI_RID_CURRENT_CHAN:
429 error = EPERM;
430 break;
431 case WI_RID_COMMS_QUALITY:
432 error = EPERM;
433 break;
434 case WI_RID_PROMISC:
435 if (wreq.wi_len != 1) {
436 error = EINVAL;
437 break;
438 }
439 if (ifp->if_flags & IFF_PROMISC) {
440 if (wreq.wi_val[0] == 0) {
441 ifp->if_flags &= ~IFF_PROMISC;
442 error = ENETRESET;
443 }
444 } else {
445 if (wreq.wi_val[0] != 0) {
446 ifp->if_flags |= IFF_PROMISC;
447 error = ENETRESET;
448 }
449 }
450 break;
451 case WI_RID_PORTTYPE:
452 if (wreq.wi_len != 1) {
453 error = EINVAL;
454 break;
455 }
456 switch (wreq.wi_val[0]) {
457 case 1:
458 sc->sc_mib_local.Network_Mode = 1;
459 sc->sc_no_bssid = 0;
460 error = ENETRESET;
461 break;
462 case 2:
463 sc->sc_mib_local.Network_Mode = 0;
464 sc->sc_no_bssid = 0;
465 error = ENETRESET;
466 break;
467 case 3:
468 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
469 error = EINVAL;
470 break;
471 }
472 sc->sc_mib_local.Network_Mode = 0;
473 sc->sc_no_bssid = 1;
474 error = ENETRESET;
475 break;
476 default:
477 error = EINVAL;
478 break;
479 }
480 break;
481 case WI_RID_MAC_NODE:
482 /* XXX: should be implemented? */
483 error = EPERM;
484 break;
485 case WI_RID_TX_RATE:
486 if (wreq.wi_len != 1) {
487 error = EINVAL;
488 break;
489 }
490 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
491 switch (wreq.wi_val[0]) {
492 case 1:
493 case 2:
494 case 5:
495 case 11:
496 rate = wreq.wi_val[0] * 10;
497 if (rate == 50)
498 rate += 5; /*XXX*/
499 break;
500 case 3:
501 case 6:
502 case 7:
503 /* auto rate */
504 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
505 rate = AWI_RATE_1MBIT;
506 for (i = 0; i < phy_rates[1]; i++) {
507 if (AWI_80211_RATE(phy_rates[2 + i]) > rate)
508 rate = AWI_80211_RATE(phy_rates[2 + i]);
509 }
510 break;
511 default:
512 rate = 0;
513 error = EINVAL;
514 break;
515 }
516 if (error)
517 break;
518 for (i = 0; i < phy_rates[1]; i++) {
519 if (rate == AWI_80211_RATE(phy_rates[2 + i]))
520 break;
521 }
522 if (i == phy_rates[1]) {
523 error = EINVAL;
524 break;
525 }
526 sc->sc_tx_rate = rate;
527 break;
528 case WI_RID_CUR_TX_RATE:
529 error = EPERM;
530 break;
531 case WI_RID_RTS_THRESH:
532 if (wreq.wi_len != 1) {
533 error = EINVAL;
534 break;
535 }
536 LE_WRITE_2(&sc->sc_mib_mac.aRTS_Threshold, wreq.wi_val[0]);
537 error = ENETRESET;
538 break;
539 case WI_RID_CREATE_IBSS:
540 if (wreq.wi_len != 1) {
541 error = EINVAL;
542 break;
543 }
544 sc->sc_start_bss = wreq.wi_val[0] ? 1 : 0;
545 error = ENETRESET;
546 break;
547 case WI_RID_SYSTEM_SCALE:
548 if (wreq.wi_len != 1) {
549 error = EINVAL;
550 break;
551 }
552 if (wreq.wi_val[0] != 1)
553 error = EINVAL; /* not supported */
554 break;
555 case WI_RID_PM_ENABLED:
556 if (wreq.wi_len != 1) {
557 error = EINVAL;
558 break;
559 }
560 if (wreq.wi_val[0] != 0)
561 error = EINVAL; /* not implemented */
562 break;
563 case WI_RID_MAX_SLEEP:
564 error = EINVAL; /* not implemented */
565 break;
566 case WI_RID_WEP_AVAIL:
567 error = EPERM;
568 break;
569 case WI_RID_ENCRYPTION:
570 if (wreq.wi_len != 1) {
571 error = EINVAL;
572 break;
573 }
574 error = awi_wep_setalgo(sc, wreq.wi_val[0]);
575 if (error)
576 break;
577 error = ENETRESET;
578 break;
579 case WI_RID_TX_CRYPT_KEY:
580 if (wreq.wi_len != 1) {
581 error = EINVAL;
582 break;
583 }
584 if (wreq.wi_val[0] >= IEEE80211_WEP_NKID) {
585 error = EINVAL;
586 break;
587 }
588 sc->sc_wep_defkid = wreq.wi_val[1];
589 break;
590 case WI_RID_DEFLT_CRYPT_KEYS:
591 if (wreq.wi_len != sizeof(*keys) / 2) {
592 error = EINVAL;
593 break;
594 }
595 keys = (struct wi_ltv_keys *)&wreq;
596 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
597 k = &keys->wi_keys[i];
598 error = awi_wep_setkey(sc, i, k->wi_keydat,
599 k->wi_keylen);
600 if (error)
601 break;
602 }
603 break;
604 case WI_RID_MAX_DATALEN:
605 if (wreq.wi_len != 1) {
606 error = EINVAL;
607 break;
608 }
609 if (wreq.wi_val[0] < 350 || wreq.wi_val[0] > 2304) {
610 error = EINVAL;
611 break;
612 }
613 LE_WRITE_2(&sc->sc_mib_mac.aMax_Frame_Length, wreq.wi_val[0]);
614 break;
615 case WI_RID_IFACE_STATS:
616 error = EPERM;
617 break;
618 default:
619 error = EINVAL;
620 break;
621 }
622 if (error == ENETRESET) {
623 if (sc->sc_enabled) {
624 awi_stop(sc);
625 error = awi_init(sc);
626 } else
627 error = 0;
628 }
629 return error;
630}