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 $ */
3 /* $DragonFly: src/sys/dev/netif/awi/Attic/awi_wicfg.c,v 1.8 2004/07/27 14:25:56 joerg Exp $ */
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
9 * This code is derived from software contributed to The NetBSD Foundation
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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.
42 * WaveLAN compatible configuration support routines for the awi driver.
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
49 #include <sys/malloc.h>
51 #include <sys/socket.h>
52 #include <sys/errno.h>
53 #include <sys/sockio.h>
54 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)
57 #include <sys/device.h>
61 #include <net/if_dl.h>
62 #if defined(__DragonFly__) || defined(__FreeBSD__)
63 #include <net/ethernet.h>
64 #include <net/if_arp.h>
66 #include <net/if_ether.h>
68 #include <net/if_media.h>
69 #include <netproto/802_11/ieee80211.h>
70 #include <netproto/802_11/ieee80211_ioctl.h>
72 #include <machine/cpu.h>
73 #include <machine/bus.h>
74 #if defined(__DragonFly__) || defined(__FreeBSD__)
75 #include <machine/clock.h>
79 #include <dev/ic/am79c930reg.h>
80 #include <dev/ic/am79c930var.h>
81 #include <dev/ic/awireg.h>
82 #include <dev/ic/awivar.h>
84 #include <dev/pcmcia/if_wi_ieee.h> /* XXX */
86 #if defined(__DragonFly__) || defined(__FreeBSD__)
87 #include "am79c930reg.h"
88 #include "am79c930var.h"
90 #include <netproto/802_11/if_wavelan_ieee.h>
95 static int awi_cfgget (struct ifnet *ifp, u_long cmd, caddr_t data);
96 static int awi_cfgset (struct ifnet *ifp, u_long cmd, caddr_t data);
99 awi_wicfg(ifp, cmd, data)
105 struct thread *td = curthread;
109 error = awi_cfgget(ifp, cmd, data);
112 #if defined(__DragonFly__) || defined(__FreeBSD__)
113 error = suser(td); /* note: EPERM if no proc */
115 error = suser(curproc->p_ucred, &curproc->p_acflag);
119 error = awi_cfgset(ifp, cmd, data);
129 awi_cfgget(ifp, cmd, data)
134 int i, error, keylen;
136 struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
137 struct ifreq *ifr = (struct ifreq *)data;
138 struct wi_ltv_keys *keys;
142 struct wi_sigcache wsc;
145 struct thread *td = curthread;
147 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
150 switch (wreq.wi_type) {
151 case WI_RID_SERIALNO:
152 memcpy(wreq.wi_val, sc->sc_banner, AWI_BANNER_LEN);
153 wreq.wi_len = (AWI_BANNER_LEN + 1) / 2;
155 case WI_RID_NODENAME:
156 strcpy((char *)&wreq.wi_val[1], hostname);
157 wreq.wi_val[0] = strlen(hostname);
158 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
160 case WI_RID_OWN_SSID:
162 wreq.wi_val[0] = p[1];
163 memcpy(&wreq.wi_val[1], p + 2, p[1]);
164 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
166 case WI_RID_CURRENT_SSID:
167 if (ifp->if_flags & IFF_RUNNING) {
168 p = sc->sc_bss.essid;
169 wreq.wi_val[0] = p[1];
170 memcpy(&wreq.wi_val[1], p + 2, p[1]);
173 wreq.wi_val[1] = '\0';
175 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
177 case WI_RID_DESIRED_SSID:
178 p = sc->sc_mib_mac.aDesired_ESS_ID;
179 wreq.wi_val[0] = p[1];
180 memcpy(&wreq.wi_val[1], p + 2, p[1]);
181 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
183 case WI_RID_CURRENT_BSSID:
184 if (ifp->if_flags & IFF_RUNNING)
185 memcpy(wreq.wi_val, sc->sc_bss.bssid, ETHER_ADDR_LEN);
187 memset(wreq.wi_val, 0, ETHER_ADDR_LEN);
188 wreq.wi_len = ETHER_ADDR_LEN / 2;
190 case WI_RID_CHANNEL_LIST:
191 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
192 wreq.wi_val[0] = sc->sc_scan_min;
193 wreq.wi_val[1] = sc->sc_scan_max;
197 for (i = sc->sc_scan_min; i <= sc->sc_scan_max; i++)
198 wreq.wi_val[0] |= 1 << (i - 1);
202 case WI_RID_OWN_CHNL:
203 wreq.wi_val[0] = sc->sc_ownch;
206 case WI_RID_CURRENT_CHAN:
207 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
208 wreq.wi_val[0] = sc->sc_bss.pattern;
210 wreq.wi_val[0] = sc->sc_bss.chanset;
213 case WI_RID_COMMS_QUALITY:
214 wreq.wi_val[0] = 0; /* quality */
215 wreq.wi_val[1] = sc->sc_bss.rssi; /* signal */
216 wreq.wi_val[2] = 0; /* noise */
220 wreq.wi_val[0] = sc->sc_mib_mac.aPromiscuous_Enable;
223 case WI_RID_PORTTYPE:
224 if (sc->sc_mib_local.Network_Mode)
226 else if (!sc->sc_no_bssid)
232 case WI_RID_MAC_NODE:
233 memcpy(wreq.wi_val, sc->sc_mib_addr.aMAC_Address,
235 wreq.wi_len = ETHER_ADDR_LEN / 2;
238 case WI_RID_CUR_TX_RATE:
239 wreq.wi_val[0] = sc->sc_tx_rate / 10;
242 case WI_RID_RTS_THRESH:
243 wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aRTS_Threshold);
246 case WI_RID_CREATE_IBSS:
247 wreq.wi_val[0] = sc->sc_start_bss;
250 case WI_RID_SYSTEM_SCALE:
251 wreq.wi_val[0] = 1; /* low density ... not supported */
254 case WI_RID_PM_ENABLED:
255 wreq.wi_val[0] = sc->sc_mib_local.Power_Saving_Mode_Dis ? 0 : 1;
258 case WI_RID_MAX_SLEEP:
259 wreq.wi_val[0] = 0; /* not implemented */
262 case WI_RID_WEP_AVAIL:
266 case WI_RID_ENCRYPTION:
267 wreq.wi_val[0] = awi_wep_getalgo(sc);
270 case WI_RID_TX_CRYPT_KEY:
271 wreq.wi_val[0] = sc->sc_wep_defkid;
274 case WI_RID_DEFLT_CRYPT_KEYS:
275 keys = (struct wi_ltv_keys *)&wreq;
276 /* do not show keys to non-root user */
277 #if defined(__DragonFly__) || defined(__FreeBSD__)
278 error = suser(td); /* note: EPERM if no proc */
280 error = suser(curproc->p_ucred, &curproc->p_acflag);
283 memset(keys, 0, sizeof(*keys));
287 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
288 k = &keys->wi_keys[i];
289 keylen = sizeof(k->wi_keydat);
290 error = awi_wep_getkey(sc, i, k->wi_keydat, &keylen);
293 k->wi_keylen = keylen;
295 wreq.wi_len = sizeof(*keys) / 2;
297 case WI_RID_MAX_DATALEN:
298 wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aMax_Frame_Length);
301 case WI_RID_IFACE_STATS:
302 /* not implemented yet */
306 case WI_RID_READ_CACHE:
307 for (bp = TAILQ_FIRST(&sc->sc_scan), i = 0;
308 bp != NULL && i < MAXWICACHE;
309 bp = TAILQ_NEXT(bp, list), i++) {
310 memcpy(wsc.macsrc, bp->esrc, ETHER_ADDR_LEN);
312 memcpy(&wsc.ipsrc, bp->bssid, sizeof(wsc.ipsrc));
313 wsc.signal = bp->rssi;
316 memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
319 wreq.wi_len = sizeof(wsc) * i / 2;
328 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
334 awi_cfgset(ifp, cmd, data)
339 int i, error, rate, oregion;
341 struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
342 struct ifreq *ifr = (struct ifreq *)data;
343 struct wi_ltv_keys *keys;
347 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
350 if (wreq.wi_len-- < 1)
352 switch (wreq.wi_type) {
353 case WI_RID_SERIALNO:
354 case WI_RID_NODENAME:
357 case WI_RID_OWN_SSID:
358 if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
362 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
366 memset(sc->sc_ownssid, 0, AWI_ESS_ID_SIZE);
367 sc->sc_ownssid[0] = IEEE80211_ELEMID_SSID;
368 sc->sc_ownssid[1] = wreq.wi_val[0];
369 memcpy(&sc->sc_ownssid[2], &wreq.wi_val[1], wreq.wi_val[0]);
370 if (!sc->sc_mib_local.Network_Mode &&
371 !sc->sc_no_bssid && sc->sc_start_bss)
374 case WI_RID_CURRENT_SSID:
377 case WI_RID_DESIRED_SSID:
378 if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
382 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
386 memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
387 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
388 sc->sc_mib_mac.aDesired_ESS_ID[1] = wreq.wi_val[0];
389 memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], &wreq.wi_val[1],
391 if (sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid)
394 case WI_RID_CURRENT_BSSID:
397 case WI_RID_CHANNEL_LIST:
398 if (wreq.wi_len != 1) {
402 oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
403 if (wreq.wi_val[0] == oregion)
405 sc->sc_mib_phy.aCurrent_Reg_Domain = wreq.wi_val[0];
406 error = awi_init_region(sc);
408 sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
413 case WI_RID_OWN_CHNL:
414 if (wreq.wi_len != 1) {
418 if (wreq.wi_val[0] < sc->sc_scan_min ||
419 wreq.wi_val[0] > sc->sc_scan_max) {
423 sc->sc_ownch = wreq.wi_val[0];
424 if (!sc->sc_mib_local.Network_Mode)
427 case WI_RID_CURRENT_CHAN:
430 case WI_RID_COMMS_QUALITY:
434 if (wreq.wi_len != 1) {
438 if (ifp->if_flags & IFF_PROMISC) {
439 if (wreq.wi_val[0] == 0) {
440 ifp->if_flags &= ~IFF_PROMISC;
444 if (wreq.wi_val[0] != 0) {
445 ifp->if_flags |= IFF_PROMISC;
450 case WI_RID_PORTTYPE:
451 if (wreq.wi_len != 1) {
455 switch (wreq.wi_val[0]) {
457 sc->sc_mib_local.Network_Mode = 1;
462 sc->sc_mib_local.Network_Mode = 0;
467 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
471 sc->sc_mib_local.Network_Mode = 0;
480 case WI_RID_MAC_NODE:
481 /* XXX: should be implemented? */
485 if (wreq.wi_len != 1) {
489 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
490 switch (wreq.wi_val[0]) {
495 rate = wreq.wi_val[0] * 10;
503 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
504 rate = AWI_RATE_1MBIT;
505 for (i = 0; i < phy_rates[1]; i++) {
506 if (AWI_80211_RATE(phy_rates[2 + i]) > rate)
507 rate = AWI_80211_RATE(phy_rates[2 + i]);
517 for (i = 0; i < phy_rates[1]; i++) {
518 if (rate == AWI_80211_RATE(phy_rates[2 + i]))
521 if (i == phy_rates[1]) {
525 sc->sc_tx_rate = rate;
527 case WI_RID_CUR_TX_RATE:
530 case WI_RID_RTS_THRESH:
531 if (wreq.wi_len != 1) {
535 LE_WRITE_2(&sc->sc_mib_mac.aRTS_Threshold, wreq.wi_val[0]);
538 case WI_RID_CREATE_IBSS:
539 if (wreq.wi_len != 1) {
543 sc->sc_start_bss = wreq.wi_val[0] ? 1 : 0;
546 case WI_RID_SYSTEM_SCALE:
547 if (wreq.wi_len != 1) {
551 if (wreq.wi_val[0] != 1)
552 error = EINVAL; /* not supported */
554 case WI_RID_PM_ENABLED:
555 if (wreq.wi_len != 1) {
559 if (wreq.wi_val[0] != 0)
560 error = EINVAL; /* not implemented */
562 case WI_RID_MAX_SLEEP:
563 error = EINVAL; /* not implemented */
565 case WI_RID_WEP_AVAIL:
568 case WI_RID_ENCRYPTION:
569 if (wreq.wi_len != 1) {
573 error = awi_wep_setalgo(sc, wreq.wi_val[0]);
578 case WI_RID_TX_CRYPT_KEY:
579 if (wreq.wi_len != 1) {
583 if (wreq.wi_val[0] >= IEEE80211_WEP_NKID) {
587 sc->sc_wep_defkid = wreq.wi_val[1];
589 case WI_RID_DEFLT_CRYPT_KEYS:
590 if (wreq.wi_len != sizeof(*keys) / 2) {
594 keys = (struct wi_ltv_keys *)&wreq;
595 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
596 k = &keys->wi_keys[i];
597 error = awi_wep_setkey(sc, i, k->wi_keydat,
603 case WI_RID_MAX_DATALEN:
604 if (wreq.wi_len != 1) {
608 if (wreq.wi_val[0] < 350 || wreq.wi_val[0] > 2304) {
612 LE_WRITE_2(&sc->sc_mib_mac.aMax_Frame_Length, wreq.wi_val[0]);
614 case WI_RID_IFACE_STATS:
621 if (error == ENETRESET) {
622 if (sc->sc_enabled) {
624 error = awi_init(sc);