Remove compatiblity code.
[dragonfly.git] / sys / dev / netif / awi / awi_wicfg.c
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.9 2005/06/13 20:25:56 joerg Exp $ */
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 #include <sys/bus.h>
55
56 #include <net/if.h>
57 #include <net/if_dl.h>
58 #include <net/ethernet.h>
59 #include <net/if_arp.h>
60 #include <net/if_media.h>
61 #include <netproto/802_11/ieee80211.h>
62 #include <netproto/802_11/ieee80211_ioctl.h>
63
64 #include <machine/cpu.h>
65 #include <machine/bus.h>
66
67 #include <dev/netif/awi/am79c930reg.h>
68 #include <dev/netif/awi/am79c930var.h>
69
70 #include <netproto/802_11/if_wavelan_ieee.h>
71 #include <dev/netif/awi/awireg.h>
72 #include <dev/netif/awi/awivar.h>
73
74 static int awi_cfgget (struct ifnet *ifp, u_long cmd, caddr_t data);
75 static int awi_cfgset (struct ifnet *ifp, u_long cmd, caddr_t data);
76
77 int
78 awi_wicfg(ifp, cmd, data)
79         struct ifnet *ifp;
80         u_long cmd;
81         caddr_t data;
82 {
83         int error;
84         struct thread *td = curthread;
85
86         switch (cmd) {
87         case SIOCGWAVELAN:
88                 error = awi_cfgget(ifp, cmd, data);
89                 break;
90         case SIOCSWAVELAN:
91                 error = suser(td);      /* note: EPERM if no proc */
92                 if (error)
93                         break;
94                 error = awi_cfgset(ifp, cmd, data);
95                 break;
96         default:
97                 error = EINVAL;
98                 break;
99         }
100         return error;
101 }
102
103 static int
104 awi_cfgget(ifp, cmd, data)
105         struct ifnet *ifp;
106         u_long cmd;
107         caddr_t data;
108 {
109         int i, error, keylen;
110         char *p;
111         struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
112         struct ifreq *ifr = (struct ifreq *)data;
113         struct wi_ltv_keys *keys;
114         struct wi_key *k;
115         struct wi_req wreq;
116 #ifdef WICACHE
117         struct wi_sigcache wsc;
118         struct awi_bss *bp;
119 #endif /* WICACHE */
120         struct thread *td = curthread;
121
122         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
123         if (error)
124                 return error;
125         switch (wreq.wi_type) {
126         case WI_RID_SERIALNO:
127                 memcpy(wreq.wi_val, sc->sc_banner, AWI_BANNER_LEN);
128                 wreq.wi_len = (AWI_BANNER_LEN + 1) / 2;
129                 break;
130         case WI_RID_NODENAME:
131                 strcpy((char *)&wreq.wi_val[1], hostname);
132                 wreq.wi_val[0] = strlen(hostname);
133                 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
134                 break;
135         case WI_RID_OWN_SSID:
136                 p = sc->sc_ownssid;
137                 wreq.wi_val[0] = p[1];
138                 memcpy(&wreq.wi_val[1], p + 2, p[1]);
139                 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
140                 break;
141         case WI_RID_CURRENT_SSID:
142                 if (ifp->if_flags & IFF_RUNNING) {
143                         p = sc->sc_bss.essid;
144                         wreq.wi_val[0] = p[1];
145                         memcpy(&wreq.wi_val[1], p + 2, p[1]);
146                 } else {
147                         wreq.wi_val[0] = 0;
148                         wreq.wi_val[1] = '\0';
149                 }
150                 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
151                 break;
152         case WI_RID_DESIRED_SSID:
153                 p = sc->sc_mib_mac.aDesired_ESS_ID;
154                 wreq.wi_val[0] = p[1];
155                 memcpy(&wreq.wi_val[1], p + 2, p[1]);
156                 wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
157                 break;
158         case WI_RID_CURRENT_BSSID:
159                 if (ifp->if_flags & IFF_RUNNING)
160                         memcpy(wreq.wi_val, sc->sc_bss.bssid, ETHER_ADDR_LEN);
161                 else
162                         memset(wreq.wi_val, 0, ETHER_ADDR_LEN);
163                 wreq.wi_len = ETHER_ADDR_LEN / 2;
164                 break;
165         case WI_RID_CHANNEL_LIST:
166                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
167                         wreq.wi_val[0] = sc->sc_scan_min;
168                         wreq.wi_val[1] = sc->sc_scan_max;
169                         wreq.wi_len = 2;
170                 } else {
171                         wreq.wi_val[0] = 0;
172                         for (i = sc->sc_scan_min; i <= sc->sc_scan_max; i++)
173                                 wreq.wi_val[0] |= 1 << (i - 1);
174                         wreq.wi_len = 1;
175                 }
176                 break;
177         case WI_RID_OWN_CHNL:
178                 wreq.wi_val[0] = sc->sc_ownch;
179                 wreq.wi_len = 1;
180                 break;
181         case WI_RID_CURRENT_CHAN:
182                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
183                         wreq.wi_val[0] = sc->sc_bss.pattern;
184                 else
185                         wreq.wi_val[0] = sc->sc_bss.chanset;
186                 wreq.wi_len = 1;
187                 break;
188         case WI_RID_COMMS_QUALITY:
189                 wreq.wi_val[0] = 0;                     /* quality */
190                 wreq.wi_val[1] = sc->sc_bss.rssi;       /* signal */
191                 wreq.wi_val[2] = 0;                     /* noise */
192                 wreq.wi_len = 3;
193                 break;
194         case WI_RID_PROMISC:
195                 wreq.wi_val[0] = sc->sc_mib_mac.aPromiscuous_Enable;
196                 wreq.wi_len = 1;
197                 break;
198         case WI_RID_PORTTYPE:
199                 if (sc->sc_mib_local.Network_Mode)
200                         wreq.wi_val[0] = 1;
201                 else if (!sc->sc_no_bssid)
202                         wreq.wi_val[0] = 2;
203                 else
204                         wreq.wi_val[0] = 3;
205                 wreq.wi_len = 1;
206                 break;
207         case WI_RID_MAC_NODE:
208                 memcpy(wreq.wi_val, sc->sc_mib_addr.aMAC_Address,
209                     ETHER_ADDR_LEN);
210                 wreq.wi_len = ETHER_ADDR_LEN / 2;
211                 break;
212         case WI_RID_TX_RATE:
213         case WI_RID_CUR_TX_RATE:
214                 wreq.wi_val[0] = sc->sc_tx_rate / 10;
215                 wreq.wi_len = 1;
216                 break;
217         case WI_RID_RTS_THRESH:
218                 wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aRTS_Threshold);
219                 wreq.wi_len = 1;
220                 break;
221         case WI_RID_CREATE_IBSS:
222                 wreq.wi_val[0] = sc->sc_start_bss;
223                 wreq.wi_len = 1;
224                 break;
225         case WI_RID_SYSTEM_SCALE:
226                 wreq.wi_val[0] = 1;     /* low density ... not supported */
227                 wreq.wi_len = 1;
228                 break;
229         case WI_RID_PM_ENABLED:
230                 wreq.wi_val[0] = sc->sc_mib_local.Power_Saving_Mode_Dis ? 0 : 1;
231                 wreq.wi_len = 1;
232                 break;
233         case WI_RID_MAX_SLEEP:
234                 wreq.wi_val[0] = 0;     /* not implemented */
235                 wreq.wi_len = 1;
236                 break;
237         case WI_RID_WEP_AVAIL:
238                 wreq.wi_val[0] = 1;
239                 wreq.wi_len = 1;
240                 break;
241         case WI_RID_ENCRYPTION:
242                 wreq.wi_val[0] = awi_wep_getalgo(sc);
243                 wreq.wi_len = 1;
244                 break;
245         case WI_RID_TX_CRYPT_KEY:
246                 wreq.wi_val[0] = sc->sc_wep_defkid;
247                 wreq.wi_len = 1;
248                 break;
249         case WI_RID_DEFLT_CRYPT_KEYS:
250                 keys = (struct wi_ltv_keys *)&wreq;
251                 /* do not show keys to non-root user */
252                 error = suser(td);      /* note: EPERM if no proc */
253                 if (error) {
254                         memset(keys, 0, sizeof(*keys));
255                         error = 0;
256                         break;
257                 }
258                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
259                         k = &keys->wi_keys[i];
260                         keylen = sizeof(k->wi_keydat);
261                         error = awi_wep_getkey(sc, i, k->wi_keydat, &keylen);
262                         if (error)
263                                 break;
264                         k->wi_keylen = keylen;
265                 }
266                 wreq.wi_len = sizeof(*keys) / 2;
267                 break;
268         case WI_RID_MAX_DATALEN:
269                 wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aMax_Frame_Length);
270                 wreq.wi_len = 1;
271                 break;
272         case WI_RID_IFACE_STATS:
273                 /* not implemented yet */
274                 wreq.wi_len = 0;
275                 break;
276 #ifdef WICACHE
277         case WI_RID_READ_CACHE:
278                 for (bp = TAILQ_FIRST(&sc->sc_scan), i = 0;
279                     bp != NULL && i < MAXWICACHE;
280                     bp = TAILQ_NEXT(bp, list), i++) {
281                         memcpy(wsc.macsrc, bp->esrc, ETHER_ADDR_LEN);
282                         /*XXX*/
283                         memcpy(&wsc.ipsrc, bp->bssid, sizeof(wsc.ipsrc));
284                         wsc.signal = bp->rssi;
285                         wsc.noise = 0;
286                         wsc.quality = 0;
287                         memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
288                             &wsc, sizeof(wsc));
289                 }
290                 wreq.wi_len = sizeof(wsc) * i / 2;
291                 break;
292 #endif /* WICACHE */
293         default:
294                 error = EINVAL;
295                 break;
296         }
297         if (error == 0) {
298                 wreq.wi_len++;
299                 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
300         }
301         return error;
302 }
303
304 static int
305 awi_cfgset(ifp, cmd, data)
306         struct ifnet *ifp;
307         u_long cmd;
308         caddr_t data;
309 {
310         int i, error, rate, oregion;
311         u_int8_t *phy_rates;
312         struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
313         struct ifreq *ifr = (struct ifreq *)data;
314         struct wi_ltv_keys *keys;
315         struct wi_key *k;
316         struct wi_req wreq;
317
318         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
319         if (error)
320                 return error;
321         if (wreq.wi_len-- < 1)
322                 return EINVAL;
323         switch (wreq.wi_type) {
324         case WI_RID_SERIALNO:
325         case WI_RID_NODENAME:
326                 error = EPERM;
327                 break;
328         case WI_RID_OWN_SSID:
329                 if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
330                         error = EINVAL;
331                         break;
332                 }
333                 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
334                         error = EINVAL;
335                         break;
336                 }
337                 memset(sc->sc_ownssid, 0, AWI_ESS_ID_SIZE);
338                 sc->sc_ownssid[0] = IEEE80211_ELEMID_SSID;
339                 sc->sc_ownssid[1] = wreq.wi_val[0];
340                 memcpy(&sc->sc_ownssid[2], &wreq.wi_val[1], wreq.wi_val[0]);
341                 if (!sc->sc_mib_local.Network_Mode &&
342                     !sc->sc_no_bssid && sc->sc_start_bss)
343                         error = ENETRESET;
344                 break;
345         case WI_RID_CURRENT_SSID:
346                 error = EPERM;
347                 break;
348         case WI_RID_DESIRED_SSID:
349                 if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
350                         error = EINVAL;
351                         break;
352                 }
353                 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
354                         error = EINVAL;
355                         break;
356                 }
357                 memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
358                 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
359                 sc->sc_mib_mac.aDesired_ESS_ID[1] = wreq.wi_val[0];
360                 memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], &wreq.wi_val[1],
361                     wreq.wi_val[0]);
362                 if (sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid)
363                         error = ENETRESET;
364                 break;
365         case WI_RID_CURRENT_BSSID:
366                 error = EPERM;
367                 break;
368         case WI_RID_CHANNEL_LIST:
369                 if (wreq.wi_len != 1) {
370                         error = EINVAL;
371                         break;
372                 }
373                 oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
374                 if (wreq.wi_val[0] == oregion)
375                         break;
376                 sc->sc_mib_phy.aCurrent_Reg_Domain = wreq.wi_val[0];
377                 error = awi_init_region(sc);
378                 if (error) {
379                         sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
380                         break;
381                 }
382                 error = ENETRESET;
383                 break;
384         case WI_RID_OWN_CHNL:
385                 if (wreq.wi_len != 1) {
386                         error = EINVAL;
387                         break;
388                 }
389                 if (wreq.wi_val[0] < sc->sc_scan_min ||
390                     wreq.wi_val[0] > sc->sc_scan_max) {
391                         error = EINVAL;
392                         break;
393                 }
394                 sc->sc_ownch = wreq.wi_val[0];
395                 if (!sc->sc_mib_local.Network_Mode)
396                         error = ENETRESET;
397                 break;
398         case WI_RID_CURRENT_CHAN:
399                 error = EPERM;
400                 break;
401         case WI_RID_COMMS_QUALITY:
402                 error = EPERM;
403                 break;
404         case WI_RID_PROMISC:
405                 if (wreq.wi_len != 1) {
406                         error = EINVAL;
407                         break;
408                 }
409                 if (ifp->if_flags & IFF_PROMISC) {
410                         if (wreq.wi_val[0] == 0) {
411                                 ifp->if_flags &= ~IFF_PROMISC;
412                                 error = ENETRESET;
413                         }
414                 } else {
415                         if (wreq.wi_val[0] != 0) {
416                                 ifp->if_flags |= IFF_PROMISC;
417                                 error = ENETRESET;
418                         }
419                 }
420                 break;
421         case WI_RID_PORTTYPE:
422                 if (wreq.wi_len != 1) {
423                         error = EINVAL;
424                         break;
425                 }
426                 switch (wreq.wi_val[0]) {
427                 case 1:
428                         sc->sc_mib_local.Network_Mode = 1;
429                         sc->sc_no_bssid = 0;
430                         error = ENETRESET;
431                         break;
432                 case 2:
433                         sc->sc_mib_local.Network_Mode = 0;
434                         sc->sc_no_bssid = 0;
435                         error = ENETRESET;
436                         break;
437                 case 3:
438                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
439                                 error = EINVAL;
440                                 break;
441                         }
442                         sc->sc_mib_local.Network_Mode = 0;
443                         sc->sc_no_bssid = 1;
444                         error = ENETRESET;
445                         break;
446                 default:
447                         error = EINVAL;
448                         break;
449                 }
450                 break;
451         case WI_RID_MAC_NODE:
452                 /* XXX: should be implemented? */
453                 error = EPERM;
454                 break;
455         case WI_RID_TX_RATE:
456                 if (wreq.wi_len != 1) {
457                         error = EINVAL;
458                         break;
459                 }
460                 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
461                 switch (wreq.wi_val[0]) {
462                 case 1:
463                 case 2:
464                 case 5:
465                 case 11:
466                         rate = wreq.wi_val[0] * 10;
467                         if (rate == 50)
468                                 rate += 5;      /*XXX*/
469                         break;
470                 case 3:
471                 case 6:
472                 case 7:
473                         /* auto rate */
474                         phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
475                         rate = AWI_RATE_1MBIT;
476                         for (i = 0; i < phy_rates[1]; i++) {
477                                 if (AWI_80211_RATE(phy_rates[2 + i]) > rate)
478                                         rate = AWI_80211_RATE(phy_rates[2 + i]);
479                         }
480                         break;
481                 default:
482                         rate = 0;
483                         error = EINVAL;
484                         break;
485                 }
486                 if (error)
487                         break;
488                 for (i = 0; i < phy_rates[1]; i++) {
489                         if (rate == AWI_80211_RATE(phy_rates[2 + i]))
490                                 break;
491                 }
492                 if (i == phy_rates[1]) {
493                         error = EINVAL;
494                         break;
495                 }
496                 sc->sc_tx_rate = rate;
497                 break;
498         case WI_RID_CUR_TX_RATE:
499                 error = EPERM;
500                 break;
501         case WI_RID_RTS_THRESH:
502                 if (wreq.wi_len != 1) {
503                         error = EINVAL;
504                         break;
505                 }
506                 LE_WRITE_2(&sc->sc_mib_mac.aRTS_Threshold, wreq.wi_val[0]);
507                 error = ENETRESET;
508                 break;
509         case WI_RID_CREATE_IBSS:
510                 if (wreq.wi_len != 1) {
511                         error = EINVAL;
512                         break;
513                 }
514                 sc->sc_start_bss = wreq.wi_val[0] ? 1 : 0;
515                 error = ENETRESET;
516                 break;
517         case WI_RID_SYSTEM_SCALE:
518                 if (wreq.wi_len != 1) {
519                         error = EINVAL;
520                         break;
521                 }
522                 if (wreq.wi_val[0] != 1)
523                         error = EINVAL;         /* not supported */
524                 break;
525         case WI_RID_PM_ENABLED:
526                 if (wreq.wi_len != 1) {
527                         error = EINVAL;
528                         break;
529                 }
530                 if (wreq.wi_val[0] != 0)
531                         error = EINVAL;         /* not implemented */
532                 break;
533         case WI_RID_MAX_SLEEP:
534                 error = EINVAL;         /* not implemented */
535                 break;
536         case WI_RID_WEP_AVAIL:
537                 error = EPERM;
538                 break;
539         case WI_RID_ENCRYPTION:
540                 if (wreq.wi_len != 1) {
541                         error = EINVAL;
542                         break;
543                 }
544                 error = awi_wep_setalgo(sc, wreq.wi_val[0]);
545                 if (error)
546                         break;
547                 error = ENETRESET;
548                 break;
549         case WI_RID_TX_CRYPT_KEY:
550                 if (wreq.wi_len != 1) {
551                         error = EINVAL;
552                         break;
553                 }
554                 if (wreq.wi_val[0] >= IEEE80211_WEP_NKID) {
555                         error = EINVAL;
556                         break;
557                 }
558                 sc->sc_wep_defkid = wreq.wi_val[1];
559                 break;
560         case WI_RID_DEFLT_CRYPT_KEYS:
561                 if (wreq.wi_len != sizeof(*keys) / 2) {
562                         error = EINVAL;
563                         break;
564                 }
565                 keys = (struct wi_ltv_keys *)&wreq;
566                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
567                         k = &keys->wi_keys[i];
568                         error = awi_wep_setkey(sc, i, k->wi_keydat,
569                             k->wi_keylen);
570                         if (error)
571                                 break;
572                 }
573                 break;
574         case WI_RID_MAX_DATALEN:
575                 if (wreq.wi_len != 1) {
576                         error = EINVAL;
577                         break;
578                 }
579                 if (wreq.wi_val[0] < 350 || wreq.wi_val[0] > 2304) {
580                         error = EINVAL;
581                         break;
582                 }
583                 LE_WRITE_2(&sc->sc_mib_mac.aMax_Frame_Length, wreq.wi_val[0]);
584                 break;
585         case WI_RID_IFACE_STATS:
586                 error = EPERM;
587                 break;
588         default:
589                 error = EINVAL;
590                 break;
591         }
592         if (error == ENETRESET) {
593                 if (sc->sc_enabled) {
594                         awi_stop(sc);
595                         error = awi_init(sc);
596                 } else
597                         error = 0;
598         }
599         return error;
600 }