goldfish: R.I.P.
[openwrt.git] / target / linux / s3c24xx / files-2.6.30 / drivers / ar6000 / ar6000 / wireless_ext.c
1 /*
2  *
3  * Copyright (c) 2004-2007 Atheros Communications Inc.
4  * All rights reserved.
5  *
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation;
10  *
11  *  Software distributed under the License is distributed on an "AS
12  *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13  *  implied. See the License for the specific language governing
14  *  rights and limitations under the License.
15  *
16  *
17  *
18  */
19
20 #include "ar6000_drv.h"
21
22 static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
23 static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
24 extern unsigned int wmitimeout;
25 extern A_WAITQUEUE_HEAD arEvent;
26 extern wait_queue_head_t ar6000_scan_queue;
27
28 /*
29  * Encode a WPA or RSN information element as a custom
30  * element using the hostap format.
31  */
32 static u_int
33 encode_ie(void *buf, size_t bufsize,
34     const u_int8_t *ie, size_t ielen,
35     const char *leader, size_t leader_len)
36 {
37     u_int8_t *p;
38     int i;
39
40     if (bufsize < leader_len)
41         return 0;
42     p = buf;
43     memcpy(p, leader, leader_len);
44     bufsize -= leader_len;
45     p += leader_len;
46     for (i = 0; i < ielen && bufsize > 2; i++)
47         p += sprintf(p, "%02x", ie[i]);
48     return (i == ielen ? p - (u_int8_t *)buf : 0);
49 }
50
51 void
52 ar6000_scan_node(void *arg, bss_t *ni)
53 {
54     struct iw_event iwe;
55 #if WIRELESS_EXT > 14
56     char buf[64*2 + 30];
57 #endif
58     struct ar_giwscan_param *param;
59     A_CHAR *current_ev;
60     A_CHAR *end_buf;
61     struct ieee80211_common_ie  *cie;
62         struct iw_request_info info;
63
64         info.cmd = 0;
65         info.flags = 0;
66
67     param = (struct ar_giwscan_param *)arg;
68
69     if (param->current_ev >= param->end_buf) {
70         return;
71     }
72     if ((param->firstPass == TRUE) &&
73         ((ni->ni_cie.ie_wpa == NULL) && (ni->ni_cie.ie_rsn == NULL))) {
74         /*
75          * Only forward wpa bss's in first pass
76          */
77         return;
78     }
79
80      if ((param->firstPass == FALSE) &&
81         ((ni->ni_cie.ie_wpa != NULL) || (ni->ni_cie.ie_rsn != NULL))) {
82         /*
83          * Only forward non-wpa bss's in 2nd pass
84          */
85         return;
86     }
87
88     current_ev = param->current_ev;
89     end_buf = param->end_buf;
90
91     cie = &ni->ni_cie;
92
93     A_MEMZERO(&iwe, sizeof(iwe));
94     iwe.cmd = SIOCGIWAP;
95     iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
96     A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
97     current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
98                                       IW_EV_ADDR_LEN);
99
100     A_MEMZERO(&iwe, sizeof(iwe));
101     iwe.cmd = SIOCGIWESSID;
102     iwe.u.data.flags = 1;
103     iwe.u.data.length = cie->ie_ssid[1];
104     current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
105                                       &cie->ie_ssid[2]);
106
107     if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
108         A_MEMZERO(&iwe, sizeof(iwe));
109         iwe.cmd = SIOCGIWMODE;
110         iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
111                 IW_MODE_MASTER : IW_MODE_ADHOC;
112         current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
113                                           IW_EV_UINT_LEN);
114     }
115
116     A_MEMZERO(&iwe, sizeof(iwe));
117     iwe.cmd = SIOCGIWFREQ;
118     iwe.u.freq.m = cie->ie_chan * 100000;
119     iwe.u.freq.e = 1;
120     current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
121                                       IW_EV_FREQ_LEN);
122
123     A_MEMZERO(&iwe, sizeof(iwe));
124     iwe.cmd = IWEVQUAL;
125     ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
126     current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
127                                       IW_EV_QUAL_LEN);
128
129     A_MEMZERO(&iwe, sizeof(iwe));
130     iwe.cmd = SIOCGIWENCODE;
131     if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
132         iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
133     } else {
134         iwe.u.data.flags = IW_ENCODE_DISABLED;
135     }
136     iwe.u.data.length = 0;
137     current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, "");
138
139     A_MEMZERO(&iwe, sizeof(iwe));
140     iwe.cmd = IWEVCUSTOM;
141     snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
142     iwe.u.data.length = strlen(buf);
143     current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, buf);
144
145     if (cie->ie_wpa != NULL) {
146         static const char wpa_leader[] = "wpa_ie=";
147
148         A_MEMZERO(&iwe, sizeof(iwe));
149         iwe.cmd = IWEVCUSTOM;
150         iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
151                                       cie->ie_wpa[1]+2,
152                                       wpa_leader, sizeof(wpa_leader)-1);
153
154         if (iwe.u.data.length != 0) {
155             current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
156                                                                            buf);
157         }
158     }
159
160     if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
161         static const char rsn_leader[] = "rsn_ie=";
162
163         A_MEMZERO(&iwe, sizeof(iwe));
164         iwe.cmd = IWEVCUSTOM;
165         iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
166                                       cie->ie_rsn[1]+2,
167                                       rsn_leader, sizeof(rsn_leader)-1);
168
169         if (iwe.u.data.length != 0) {
170             current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
171                                                                            buf);
172         }
173     }
174
175     if (cie->ie_wmm != NULL) {
176         static const char wmm_leader[] = "wmm_ie=";
177
178         A_MEMZERO(&iwe, sizeof(iwe));
179         iwe.cmd = IWEVCUSTOM;
180         iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
181                                       cie->ie_wmm[1]+2,
182                                       wmm_leader, sizeof(wmm_leader)-1);
183         if (iwe.u.data.length != 0) {
184             current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
185                                                                            buf);
186         }
187     }
188
189     if (cie->ie_ath != NULL) {
190         static const char ath_leader[] = "ath_ie=";
191
192         A_MEMZERO(&iwe, sizeof(iwe));
193         iwe.cmd = IWEVCUSTOM;
194         iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
195                                       cie->ie_ath[1]+2,
196                                       ath_leader, sizeof(ath_leader)-1);
197         if (iwe.u.data.length != 0) {
198             current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
199                                                                            buf);
200         }
201     }
202
203     param->current_ev = current_ev;
204 }
205
206 int
207 ar6000_ioctl_giwscan(struct net_device *dev,
208             struct iw_request_info *info,
209             struct iw_point *data, char *extra)
210 {
211     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
212     struct ar_giwscan_param param;
213     int i;
214
215     if (ar->arWlanState == WLAN_DISABLED) {
216         return -EIO;
217     }
218
219     if (ar->arWmiReady == FALSE) {
220         return -EIO;
221     }
222
223     param.current_ev = extra;
224     param.end_buf = extra + IW_SCAN_MAX_DATA;
225     param.firstPass = TRUE;
226
227     /*
228      * Do two passes to insure WPA scan candidates
229      * are sorted to the front.  This is a hack to deal with
230      * the wireless extensions capping scan results at
231      * IW_SCAN_MAX_DATA bytes.  In densely populated environments
232      * it's easy to overflow this buffer (especially with WPA/RSN
233      * information elements).  Note this sorting hack does not
234      * guarantee we won't overflow anyway.
235      */
236     for (i = 0; i < 2; i++) {
237         /*
238          * Translate data to WE format.
239          */
240         wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
241         param.firstPass = FALSE;
242         if (param.current_ev >= param.end_buf) {
243             data->length = param.current_ev - extra;
244             return -E2BIG;
245         }
246     }
247
248     data->length = param.current_ev - extra;
249     return 0;
250 }
251
252 extern int reconnect_flag;
253 /* SIOCSIWESSID */
254 static int
255 ar6000_ioctl_siwessid(struct net_device *dev,
256                      struct iw_request_info *info,
257                      struct iw_point *data, char *ssid)
258 {
259     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
260     A_STATUS status;
261     A_UINT8     arNetworkType;
262
263     if (ar->arWlanState == WLAN_DISABLED) {
264         return -EIO;
265     }
266
267     if (ar->arWmiReady == FALSE) {
268         return -EIO;
269     }
270
271     /*
272      * iwconfig passes a string with length excluding any trailing NUL.
273      * FIXME: we should be able to set an ESSID of 32 bytes, yet things fall
274      * over badly if we do. So we limit the ESSID to 31 bytes.
275      */
276     if (data->flags && (!data->length || data->length >= sizeof(ar->arSsid))) {
277         /*
278          * ssid is invalid
279          */
280         return -EINVAL;
281     }
282     /* Added for bug 25178, return an IOCTL error instead of target returning
283        Illegal parameter error when either the BSSID or channel is missing
284        and we cannot scan during connect.
285      */
286     if (data->flags) {
287         if (ar->arSkipScan == TRUE &&
288             (ar->arChannelHint == 0 ||
289              (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
290               !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
291         {
292             return -EINVAL;
293         }
294     }
295
296     if (down_interruptible(&ar->arSem)) {
297         return -ERESTARTSYS;
298     }
299
300     if (ar->arTxPending[WMI_CONTROL_PRI]) {
301         /*
302          * sleep until the command queue drains
303          */
304         wait_event_interruptible_timeout(arEvent,
305             ar->arTxPending[WMI_CONTROL_PRI] == 0, wmitimeout * HZ);
306         if (signal_pending(current)) {
307             return -EINTR;
308         }
309     }
310
311     if (!data->flags) {
312         arNetworkType = ar->arNetworkType;
313         ar6000_init_profile_info(ar);
314         ar->arNetworkType = arNetworkType;
315     }
316
317     /*
318      * The original logic here prevented a disconnect if issuing an "essid off"
319      * if no ESSID was set, presumably to prevent sending multiple disconnects
320      * to the WMI.
321      *
322      * Unfortunately, this also meant that no disconnect was sent when we were
323      * already connected, but the profile has been changed since (which also
324      * clears the ESSID as a reminder that the WMI needs updating.)
325      *
326      * The "1 ||" makes sure we always disconnect or reconnect. The WMI doesn't
327      * seem to mind being sent multiple disconnects.
328      */
329     if (1 || (ar->arSsidLen) || (!data->flags))
330     {
331         if ((!data->flags) ||
332             (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
333             (ar->arSsidLen != (data->length)))
334         {
335             /*
336              * SSID set previously or essid off has been issued.
337              *
338              * Disconnect Command is issued in two cases after wmi is ready
339              * (1) ssid is different from the previous setting
340              * (2) essid off has been issued
341              *
342              */
343             if (ar->arWmiReady == TRUE) {
344                 reconnect_flag = 0;
345                 status = wmi_disconnect_cmd(ar->arWmi);
346                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
347                 ar->arSsidLen = 0;
348                 if (ar->arSkipScan == FALSE) {
349                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
350                 }
351                 if (!data->flags) {
352                     up(&ar->arSem);
353                     return 0;
354                 }
355             } else {
356                  up(&ar->arSem);
357             }
358         }
359         else
360         {
361             /*
362              * SSID is same, so we assume profile hasn't changed.
363              * If the interface is up and wmi is ready, we issue
364              * a reconnect cmd. Issue a reconnect only we are already
365              * connected.
366              */
367             if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
368             {
369                 reconnect_flag = TRUE;
370                 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
371                                            ar->arChannelHint);
372                 up(&ar->arSem);
373                 if (status != A_OK) {
374                     return -EIO;
375                 }
376                 return 0;
377             }
378             else{
379                 /*
380                  * Dont return if connect is pending.
381                  */
382                 if(!(ar->arConnectPending)) {
383                     up(&ar->arSem);
384                     return 0;
385                 }
386             }
387         }
388     }
389
390     ar->arSsidLen = data->length;
391     A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
392
393     /* The ssid length check prevents second "essid off" from the user,
394        to be treated as a connect cmd. The second "essid off" is ignored.
395     */
396     if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) )
397     {
398         AR6000_SPIN_LOCK(&ar->arLock, 0);
399         if (SHARED_AUTH == ar->arDot11AuthMode) {
400             ar6000_install_static_wep_keys(ar);
401         }
402         AR_DEBUG_PRINTF("Connect called with authmode %d dot11 auth %d"\
403                         " PW crypto %d PW crypto Len %d GRP crypto %d"\
404                         " GRP crypto Len %d\n",
405                         ar->arAuthMode, ar->arDot11AuthMode,
406                         ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
407                         ar->arGroupCrypto, ar->arGroupCryptoLen);
408         reconnect_flag = 0;
409         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
410         status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
411                                  ar->arDot11AuthMode, ar->arAuthMode,
412                                  ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
413                                  ar->arGroupCrypto,ar->arGroupCryptoLen,
414                                  ar->arSsidLen, ar->arSsid,
415                                  ar->arReqBssid, ar->arChannelHint,
416                                  ar->arConnectCtrlFlags);
417
418
419         up(&ar->arSem);
420
421         if (status != A_OK) {
422             return -EIO;
423         }
424         ar->arConnectPending = TRUE;
425     }else{
426       up(&ar->arSem);
427     }
428     return 0;
429 }
430
431 /* SIOCGIWESSID */
432 static int
433 ar6000_ioctl_giwessid(struct net_device *dev,
434                      struct iw_request_info *info,
435                      struct iw_point *data, char *essid)
436 {
437     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
438
439     if (ar->arWlanState == WLAN_DISABLED) {
440         return -EIO;
441     }
442
443     data->flags = 1;
444     data->length = ar->arSsidLen;
445     A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
446
447     return 0;
448 }
449
450
451 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
452 {
453     A_UINT8 index;
454     A_UINT8 keyUsage;
455
456     for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
457         if (ar->arWepKeyList[index].arKeyLen) {
458             keyUsage = GROUP_USAGE;
459             if (index == ar->arDefTxKeyIndex) {
460                 keyUsage |= TX_USAGE;
461             }
462             wmi_addKey_cmd(ar->arWmi,
463                            index,
464                            WEP_CRYPT,
465                            keyUsage,
466                            ar->arWepKeyList[index].arKeyLen,
467                            NULL,
468                            ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL,
469                            NO_SYNC_WMIFLAG);
470         }
471     }
472 }
473
474 int
475 ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
476              void *w, char *extra)
477 {
478     return 0;
479 }
480
481 int
482 ar6000_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
483              void *w, char *extra)
484 {
485     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
486     struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
487
488     if ((ar->arWmiReady == FALSE) || (ar->arConnected != TRUE))
489                 return -EIO;
490
491     switch (mlme->im_op) {
492         case IEEE80211_MLME_DISASSOC:
493         case IEEE80211_MLME_DEAUTH:
494             /* Not Supported */
495             break;
496         default:
497             break;
498     }
499     return 0;
500 }
501
502
503 int
504 ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info,
505              void *w, char *extra)
506 {
507     return -EIO;            /* for now */
508 }
509
510 int
511 ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info,
512              void *w, char *extra)
513 {
514     return -EIO;            /* for now */
515 }
516
517 int ar6000_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
518                           struct iw_point *data, char *extra)
519 {
520         /* The target generates the WPA/RSN IE */
521         return 0;
522 }
523
524 int
525 ar6000_ioctl_setauthalg(struct net_device *dev, struct iw_request_info *info,
526              void *w, char *extra)
527 {
528     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
529     struct ieee80211req_authalg *req = (struct ieee80211req_authalg *)extra;
530     int ret = 0;
531
532
533     AR6000_SPIN_LOCK(&ar->arLock, 0);
534
535     if (req->auth_alg == AUTH_ALG_OPEN_SYSTEM) {
536         ar->arDot11AuthMode  = OPEN_AUTH;
537     } else if (req->auth_alg == AUTH_ALG_LEAP) {
538         ar->arDot11AuthMode   = LEAP_AUTH;
539         ar->arPairwiseCrypto  = WEP_CRYPT;
540         ar->arGroupCrypto     = WEP_CRYPT;
541     } else {
542         ret = -EIO;
543     }
544
545     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
546
547     return ret;
548 }
549 static int
550 ar6000_ioctl_addpmkid(struct net_device *dev, struct iw_request_info *info,
551              void *w, char *extra)
552 {
553     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
554     struct ieee80211req_addpmkid  *req = (struct ieee80211req_addpmkid *)extra;
555     A_STATUS status;
556
557     if (ar->arWlanState == WLAN_DISABLED) {
558         return -EIO;
559     }
560
561     AR_DEBUG_PRINTF("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
562                     req->pi_bssid[0], req->pi_bssid[1], req->pi_bssid[2],
563                     req->pi_bssid[3], req->pi_bssid[4], req->pi_bssid[5],
564                     req->pi_enable);
565
566     status = wmi_setPmkid_cmd(ar->arWmi, req->pi_bssid, req->pi_pmkid,
567                               req->pi_enable);
568
569     if (status != A_OK) {
570         return -EIO;
571     }
572
573     return 0;
574 }
575
576 /*
577  * SIOCSIWRATE
578  */
579 int
580 ar6000_ioctl_siwrate(struct net_device *dev,
581             struct iw_request_info *info,
582             struct iw_param *rrq, char *extra)
583 {
584     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
585     A_UINT32  kbps;
586
587     if (rrq->fixed) {
588         kbps = rrq->value / 1000;           /* rrq->value is in bps */
589     } else {
590         kbps = -1;                          /* -1 indicates auto rate */
591     }
592     if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL)
593     {
594         AR_DEBUG_PRINTF("BitRate is not Valid %d\n", kbps);
595         return -EINVAL;
596     }
597     ar->arBitRate = kbps;
598     if(ar->arWmiReady == TRUE)
599     {
600         if (wmi_set_bitrate_cmd(ar->arWmi, kbps) != A_OK) {
601             return -EINVAL;
602         }
603     }
604     return 0;
605 }
606
607 /*
608  * SIOCGIWRATE
609  */
610 int
611 ar6000_ioctl_giwrate(struct net_device *dev,
612             struct iw_request_info *info,
613             struct iw_param *rrq, char *extra)
614 {
615     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
616     int ret = 0;
617
618     if (down_interruptible(&ar->arSem)) {
619         return -ERESTARTSYS;
620     }
621     if(ar->arWmiReady == TRUE)
622     {
623         ar->arBitRate = 0xFFFF;
624         if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
625             up(&ar->arSem);
626             return -EIO;
627         }
628         wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
629         if (signal_pending(current)) {
630             ret = -EINTR;
631         }
632     }
633     /* If the interface is down or wmi is not ready or the target is not
634        connected - return the value stored in the device structure */
635     if (!ret) {
636         if (ar->arBitRate == -1) {
637             rrq->fixed = TRUE;
638             rrq->value = 0;
639         } else {
640             rrq->value = ar->arBitRate * 1000;
641         }
642     }
643
644     up(&ar->arSem);
645
646     return ret;
647 }
648
649 /*
650  * SIOCSIWTXPOW
651  */
652 static int
653 ar6000_ioctl_siwtxpow(struct net_device *dev,
654              struct iw_request_info *info,
655              struct iw_param *rrq, char *extra)
656 {
657     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
658     A_UINT8 dbM;
659
660     if (ar->arWlanState == WLAN_DISABLED) {
661         return -EIO;
662     }
663
664     if (ar->arRadioSwitch == WLAN_ENABLED
665         && rrq->disabled) {
666             if (wmi_switch_radio(ar->arWmi, WLAN_DISABLED) < 0)
667                     return -EIO;
668             ar->arRadioSwitch = WLAN_DISABLED;
669     } else if (ar->arRadioSwitch == WLAN_DISABLED
670                && !rrq->disabled) {
671             if (wmi_switch_radio(ar->arWmi, WLAN_ENABLED) < 0)
672                     return -EIO;
673             ar->arRadioSwitch = WLAN_ENABLED;
674     }
675
676     if (rrq->fixed) {
677         if (rrq->flags != IW_TXPOW_DBM) {
678             return -EOPNOTSUPP;
679         }
680         ar->arTxPwr= dbM = rrq->value;
681         ar->arTxPwrSet = TRUE;
682     } else {
683         ar->arTxPwr = dbM = 0;
684         ar->arTxPwrSet = FALSE;
685     }
686     if(ar->arWmiReady == TRUE)
687     {
688         AR_DEBUG_PRINTF("Set tx pwr cmd %d dbM\n", dbM);
689         wmi_set_txPwr_cmd(ar->arWmi, dbM);
690     }
691     return 0;
692 }
693
694 /*
695  * SIOCGIWTXPOW
696  */
697 int
698 ar6000_ioctl_giwtxpow(struct net_device *dev,
699             struct iw_request_info *info,
700             struct iw_param *rrq, char *extra)
701 {
702     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
703     int ret = 0;
704
705     if (ar->arWlanState == WLAN_DISABLED) {
706         return -EIO;
707     }
708
709     if (ar->arRadioSwitch == WLAN_DISABLED) {
710             rrq->disabled = 1;
711             return 0;
712     }
713
714     if (down_interruptible(&ar->arSem)) {
715         return -ERESTARTSYS;
716     }
717     if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
718     {
719         ar->arTxPwr = 0;
720
721         if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
722             up(&ar->arSem);
723             return -EIO;
724         }
725
726         wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
727
728         if (signal_pending(current)) {
729             ret = -EINTR;
730          }
731     }
732    /* If the interace is down or wmi is not ready or target is not connected
733       then return value stored in the device structure */
734
735     if (!ret) {
736          if (ar->arTxPwrSet == TRUE) {
737             rrq->fixed = TRUE;
738         }
739         rrq->value = ar->arTxPwr;
740         rrq->flags = IW_TXPOW_DBM;
741     }
742
743     up(&ar->arSem);
744
745     return ret;
746 }
747
748 /*
749  * SIOCSIWRETRY
750  * since iwconfig only provides us with one max retry value, we use it
751  * to apply to data frames of the BE traffic class.
752  */
753 static int
754 ar6000_ioctl_siwretry(struct net_device *dev,
755              struct iw_request_info *info,
756              struct iw_param *rrq, char *extra)
757 {
758     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
759
760     if (ar->arWlanState == WLAN_DISABLED) {
761         return -EIO;
762     }
763
764     if (rrq->disabled) {
765         return -EOPNOTSUPP;
766     }
767
768     if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
769         return -EOPNOTSUPP;
770     }
771
772     if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
773             return - EINVAL;
774     }
775     if(ar->arWmiReady == TRUE)
776     {
777         if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
778                                      rrq->value, 0) != A_OK){
779             return -EINVAL;
780         }
781     }
782     ar->arMaxRetries = rrq->value;
783     return 0;
784 }
785
786 /*
787  * SIOCGIWRETRY
788  */
789 static int
790 ar6000_ioctl_giwretry(struct net_device *dev,
791              struct iw_request_info *info,
792              struct iw_param *rrq, char *extra)
793 {
794     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
795
796     if (ar->arWlanState == WLAN_DISABLED) {
797         return -EIO;
798     }
799
800     rrq->disabled = 0;
801     switch (rrq->flags & IW_RETRY_TYPE) {
802     case IW_RETRY_LIFETIME:
803         return -EOPNOTSUPP;
804         break;
805     case IW_RETRY_LIMIT:
806         rrq->flags = IW_RETRY_LIMIT;
807         switch (rrq->flags & IW_RETRY_MODIFIER) {
808         case IW_RETRY_MIN:
809             rrq->flags |= IW_RETRY_MIN;
810             rrq->value = WMI_MIN_RETRIES;
811             break;
812         case IW_RETRY_MAX:
813             rrq->flags |= IW_RETRY_MAX;
814             rrq->value = ar->arMaxRetries;
815             break;
816         }
817         break;
818     }
819     return 0;
820 }
821
822 /*
823  * SIOCSIWENCODE
824  */
825 static int
826 ar6000_ioctl_siwencode(struct net_device *dev,
827               struct iw_request_info *info,
828               struct iw_point *erq, char *keybuf)
829 {
830     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
831     int index;
832     A_INT32 auth = ar->arDot11AuthMode;
833
834     if (ar->arWlanState == WLAN_DISABLED) {
835         return -EIO;
836     }
837
838     index = erq->flags & IW_ENCODE_INDEX;
839
840     if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
841                   ((index - 1) > WMI_MAX_KEY_INDEX)))
842     {
843         return -EIO;
844     }
845
846     if (erq->flags & IW_ENCODE_DISABLED) {
847         /*
848          * Encryption disabled
849          */
850         if (index) {
851             /*
852              * If key index was specified then clear the specified key
853              */
854             index--;
855             A_MEMZERO(ar->arWepKeyList[index].arKey,
856                       sizeof(ar->arWepKeyList[index].arKey));
857             ar->arWepKeyList[index].arKeyLen = 0;
858         }
859         ar->arDot11AuthMode       = OPEN_AUTH;
860         ar->arPairwiseCrypto      = NONE_CRYPT;
861         ar->arGroupCrypto         = NONE_CRYPT;
862         ar->arAuthMode            = NONE_AUTH;
863     } else {
864         /*
865          * Enabling WEP encryption
866          */
867         if (index) {
868             index--;                /* keyindex is off base 1 in iwconfig */
869         }
870
871         if (erq->flags & IW_ENCODE_OPEN) {
872             auth = OPEN_AUTH;
873         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
874             auth = SHARED_AUTH;
875         }
876
877         if (erq->length) {
878             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
879                 return -EIO;
880             }
881
882             A_MEMZERO(ar->arWepKeyList[index].arKey,
883                       sizeof(ar->arWepKeyList[index].arKey));
884             A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
885             ar->arWepKeyList[index].arKeyLen = erq->length;
886         } else {
887             if (ar->arWepKeyList[index].arKeyLen == 0) {
888                 return -EIO;
889             }
890             ar->arDefTxKeyIndex = index;
891         }
892
893         ar->arPairwiseCrypto      = WEP_CRYPT;
894         ar->arGroupCrypto         = WEP_CRYPT;
895         ar->arDot11AuthMode       = auth;
896         ar->arAuthMode            = NONE_AUTH;
897     }
898
899     /*
900      * profile has changed.  Erase ssid to signal change
901      */
902     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
903     ar->arSsidLen = 0;
904
905     return 0;
906 }
907
908 static int
909 ar6000_ioctl_giwencode(struct net_device *dev,
910               struct iw_request_info *info,
911               struct iw_point *erq, char *key)
912 {
913     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
914     A_UINT8 keyIndex;
915     struct ar_wep_key *wk;
916
917     if (ar->arWlanState == WLAN_DISABLED) {
918         return -EIO;
919     }
920
921     if (ar->arPairwiseCrypto == NONE_CRYPT) {
922         erq->length = 0;
923         erq->flags = IW_ENCODE_DISABLED;
924     } else {
925         /* get the keyIndex */
926         keyIndex = erq->flags & IW_ENCODE_INDEX;
927         if (0 == keyIndex) {
928             keyIndex = ar->arDefTxKeyIndex;
929         } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
930                    (keyIndex - 1 > WMI_MAX_KEY_INDEX))
931         {
932             keyIndex = WMI_MIN_KEY_INDEX;
933         } else {
934             keyIndex--;
935         }
936         erq->flags = keyIndex + 1;
937         erq->flags |= IW_ENCODE_ENABLED;
938         wk = &ar->arWepKeyList[keyIndex];
939         if (erq->length > wk->arKeyLen) {
940             erq->length = wk->arKeyLen;
941         }
942         if (wk->arKeyLen) {
943             A_MEMCPY(key, wk->arKey, erq->length);
944         }
945         if (ar->arDot11AuthMode == OPEN_AUTH) {
946             erq->flags |= IW_ENCODE_OPEN;
947         } else if (ar->arDot11AuthMode == SHARED_AUTH) {
948             erq->flags |= IW_ENCODE_RESTRICTED;
949         }
950     }
951
952     return 0;
953 }
954
955 static int ar6000_ioctl_siwpower(struct net_device *dev,
956                                  struct iw_request_info *info,
957                                  union iwreq_data *wrqu, char *extra)
958 {
959         AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
960         WMI_POWER_MODE power_mode;
961
962         if (wrqu->power.disabled)
963                 power_mode = MAX_PERF_POWER;
964         else
965                 power_mode = REC_POWER;
966
967         if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
968                 return -EIO;
969
970         return 0;
971 }
972
973 static int ar6000_ioctl_giwpower(struct net_device *dev,
974                                  struct iw_request_info *info,
975                                  union iwreq_data *wrqu, char *extra)
976 {
977         AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
978
979         /*
980          * FIXME:
981          * https://docs.openmoko.org/trac/ticket/2267
982          * When starting wpa_supplicant the kernel oopses.
983          * The following condition avoids the oops.
984          * Remove this comment to bless this solution.
985          */
986         if (ar->arWlanState == WLAN_DISABLED || ar->arWmiReady == FALSE)
987                 return -EIO;
988
989         return wmi_get_power_mode_cmd(ar->arWmi);
990 }
991
992 static int ar6000_ioctl_siwgenie(struct net_device *dev,
993                                  struct iw_request_info *info,
994                                  struct iw_point *dwrq,
995                                  char *extra)
996 {
997         /* The target does that for us */
998         return 0;
999 }
1000
1001 static int ar6000_ioctl_giwgenie(struct net_device *dev,
1002                                  struct iw_request_info *info,
1003                                  struct iw_point *dwrq,
1004                                  char *extra)
1005 {
1006         return 0;
1007 }
1008
1009 static int ar6000_ioctl_siwauth(struct net_device *dev,
1010                                 struct iw_request_info *info,
1011                                 struct iw_param *param,
1012                                 char *extra)
1013 {
1014         AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1015         int reset = 0;
1016
1017         switch (param->flags & IW_AUTH_INDEX) {
1018         case IW_AUTH_WPA_VERSION:
1019                 if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
1020                         ar->arAuthMode = NONE_AUTH;
1021                 }
1022                 if (param->value & IW_AUTH_WPA_VERSION_WPA) {
1023                         ar->arAuthMode = WPA_AUTH;
1024                 }
1025                 if (param->value & IW_AUTH_WPA_VERSION_WPA2) {
1026                         ar->arAuthMode = WPA2_AUTH;
1027                 }
1028
1029                 reset = 1;
1030                 break;
1031         case IW_AUTH_CIPHER_PAIRWISE:
1032                 if (param->value & IW_AUTH_CIPHER_NONE) {
1033                         ar->arPairwiseCrypto = NONE_CRYPT;
1034                 }
1035                 if (param->value & IW_AUTH_CIPHER_WEP40) {
1036                         ar->arPairwiseCrypto = WEP_CRYPT;
1037                 }
1038                 if (param->value & IW_AUTH_CIPHER_TKIP) {
1039                         ar->arPairwiseCrypto = TKIP_CRYPT;
1040                 }
1041                 if (param->value & IW_AUTH_CIPHER_CCMP) {
1042                         ar->arPairwiseCrypto = AES_CRYPT;
1043                 }
1044
1045                 reset = 1;
1046                 break;
1047         case IW_AUTH_CIPHER_GROUP:
1048                 if (param->value & IW_AUTH_CIPHER_NONE) {
1049                         ar->arGroupCrypto = NONE_CRYPT;
1050                 }
1051                 if (param->value & IW_AUTH_CIPHER_WEP40) {
1052                         ar->arGroupCrypto = WEP_CRYPT;
1053                 }
1054                 if (param->value & IW_AUTH_CIPHER_TKIP) {
1055                         ar->arGroupCrypto = TKIP_CRYPT;
1056                 }
1057                 if (param->value & IW_AUTH_CIPHER_CCMP) {
1058                         ar->arGroupCrypto = AES_CRYPT;
1059                 }
1060
1061                 reset = 1;
1062                 break;
1063         case IW_AUTH_KEY_MGMT:
1064                 if (param->value & IW_AUTH_KEY_MGMT_PSK) {
1065                         if (ar->arAuthMode == WPA_AUTH) {
1066                                 ar->arAuthMode = WPA_PSK_AUTH;
1067                         } else if (ar->arAuthMode == WPA2_AUTH) {
1068                                 ar->arAuthMode = WPA2_PSK_AUTH;
1069                         }
1070
1071                         reset = 1;
1072                 }
1073                 break;
1074
1075         case IW_AUTH_TKIP_COUNTERMEASURES:
1076                 if (ar->arWmiReady == FALSE) {
1077                         return -EIO;
1078                 }
1079                 wmi_set_tkip_countermeasures_cmd(ar->arWmi, param->value);
1080                 break;
1081
1082         case IW_AUTH_DROP_UNENCRYPTED:
1083                 break;
1084
1085         case IW_AUTH_80211_AUTH_ALG:
1086                 if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1087                         ar->arDot11AuthMode  = OPEN_AUTH;
1088                 }
1089                 if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1090                         ar->arDot11AuthMode  = SHARED_AUTH;
1091                 }
1092                 if (param->value & IW_AUTH_ALG_LEAP) {
1093                         ar->arDot11AuthMode   = LEAP_AUTH;
1094                         ar->arPairwiseCrypto  = WEP_CRYPT;
1095                         ar->arGroupCrypto     = WEP_CRYPT;
1096                 }
1097
1098                 reset = 1;
1099                 break;
1100
1101         case IW_AUTH_WPA_ENABLED:
1102                 reset = 1;
1103                 break;
1104
1105         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1106                 break;
1107
1108         case IW_AUTH_PRIVACY_INVOKED:
1109                 break;
1110
1111         default:
1112                 printk("%s(): Unknown flag 0x%x\n", __FUNCTION__, param->flags);
1113                 return -EOPNOTSUPP;
1114         }
1115
1116         if (reset) {
1117                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1118                 ar->arSsidLen = 0;
1119         }
1120
1121         return 0;
1122 }
1123
1124 static int ar6000_ioctl_giwauth(struct net_device *dev,
1125                                 struct iw_request_info *info,
1126                                 struct iw_param *dwrq,
1127                                 char *extra)
1128 {
1129         return 0;
1130 }
1131
1132 static int ar6000_ioctl_siwencodeext(struct net_device *dev,
1133                                      struct iw_request_info *info,
1134                                      union iwreq_data *wrqu,
1135                                      char *extra)
1136 {
1137         AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1138         struct iw_point *encoding = &wrqu->encoding;
1139         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1140         int alg = ext->alg, idx;
1141
1142         if (ar->arWlanState == WLAN_DISABLED) {
1143                 return -EIO;
1144         }
1145
1146         /* Determine and validate the key index */
1147         idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
1148         if (idx) {
1149                 if (idx < 0 || idx > 3)
1150                         return -EINVAL;
1151         }
1152
1153         if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
1154                 struct ieee80211req_key ik;
1155                 KEY_USAGE key_usage;
1156                 CRYPTO_TYPE key_type = NONE_CRYPT;
1157                 int status;
1158
1159                 ar->user_saved_keys.keyOk = FALSE;
1160
1161                 if (alg == IW_ENCODE_ALG_TKIP) {
1162                         key_type = TKIP_CRYPT;
1163                         ik.ik_type = IEEE80211_CIPHER_TKIP;
1164                 } else {
1165                         key_type = AES_CRYPT;
1166                         ik.ik_type = IEEE80211_CIPHER_AES_CCM;
1167                 }
1168
1169                 ik.ik_keyix = idx;
1170                 ik.ik_keylen = ext->key_len;
1171                 ik.ik_flags = IEEE80211_KEY_RECV;
1172                 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1173                         ik.ik_flags |= IEEE80211_KEY_XMIT
1174                                 | IEEE80211_KEY_DEFAULT;
1175                 }
1176
1177                 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1178                         memcpy(&ik.ik_keyrsc, ext->rx_seq, 8);
1179                 }
1180
1181                 memcpy(ik.ik_keydata, ext->key, ext->key_len);
1182
1183                 ar->user_saved_keys.keyType = key_type;
1184                 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1185                         key_usage = GROUP_USAGE;
1186                         memset(ik.ik_macaddr, 0, ETH_ALEN);
1187                         memcpy(&ar->user_saved_keys.bcast_ik, &ik,
1188                                sizeof(struct ieee80211req_key));
1189                 } else {
1190                         key_usage = PAIRWISE_USAGE;
1191                         memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
1192                         memcpy(&ar->user_saved_keys.ucast_ik, &ik,
1193                                sizeof(struct ieee80211req_key));
1194                 }
1195
1196                 status = wmi_addKey_cmd(ar->arWmi, ik.ik_keyix, key_type,
1197                                         key_usage, ik.ik_keylen,
1198                                         (A_UINT8 *)&ik.ik_keyrsc,
1199                                         ik.ik_keydata,
1200                                         KEY_OP_INIT_VAL, SYNC_BEFORE_WMIFLAG);
1201
1202                 if (status < 0)
1203                         return -EIO;
1204
1205                 ar->user_saved_keys.keyOk = TRUE;
1206
1207                 return 0;
1208
1209         } else {
1210                 /* WEP falls back to SIWENCODE */
1211                 return -EOPNOTSUPP;
1212         }
1213
1214         return 0;
1215 }
1216
1217
1218 static int ar6000_ioctl_giwencodeext(struct net_device *dev,
1219                                      struct iw_request_info *info,
1220                                      struct iw_point *dwrq,
1221                                      char *extra)
1222 {
1223         return 0;
1224 }
1225
1226
1227 static int
1228 ar6000_ioctl_setparam(struct net_device *dev,
1229                       struct iw_request_info *info,
1230                       void *erq, char *extra)
1231 {
1232     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1233     int *i = (int *)extra;
1234     int param = i[0];
1235     int value = i[1];
1236     int ret = 0;
1237     A_BOOL profChanged = FALSE;
1238
1239     if (ar->arWlanState == WLAN_DISABLED) {
1240         return -EIO;
1241     }
1242
1243     switch (param) {
1244         case IEEE80211_PARAM_WPA:
1245             switch (value) {
1246                 case WPA_MODE_WPA1:
1247                     ar->arAuthMode = WPA_AUTH;
1248                     profChanged    = TRUE;
1249                     break;
1250                 case WPA_MODE_WPA2:
1251                     ar->arAuthMode = WPA2_AUTH;
1252                     profChanged    = TRUE;
1253                     break;
1254                 case WPA_MODE_NONE:
1255                     ar->arAuthMode = NONE_AUTH;
1256                     profChanged    = TRUE;
1257                     break;
1258             default:
1259                     printk("IEEE80211_PARAM_WPA: Unknown value %d\n", value);
1260             }
1261             break;
1262         case IEEE80211_PARAM_AUTHMODE:
1263             switch(value) {
1264                 case IEEE80211_AUTH_WPA_PSK:
1265                     if (WPA_AUTH == ar->arAuthMode) {
1266                         ar->arAuthMode = WPA_PSK_AUTH;
1267                         profChanged    = TRUE;
1268                     } else if (WPA2_AUTH == ar->arAuthMode) {
1269                         ar->arAuthMode = WPA2_PSK_AUTH;
1270                         profChanged    = TRUE;
1271                     } else {
1272                         AR_DEBUG_PRINTF("Error -  Setting PSK mode when WPA "\
1273                                         "param was set to %d\n",
1274                                         ar->arAuthMode);
1275                         ret = -1;
1276                     }
1277                     break;
1278                 case IEEE80211_AUTH_WPA_CCKM:
1279                     if (WPA2_AUTH == ar->arAuthMode) {
1280                         ar->arAuthMode = WPA2_AUTH_CCKM;
1281                     } else {
1282                         ar->arAuthMode = WPA_AUTH_CCKM;
1283                     }
1284                     break;
1285                 default:
1286                     break;
1287             }
1288             break;
1289         case IEEE80211_PARAM_UCASTCIPHER:
1290             switch (value) {
1291                 case IEEE80211_CIPHER_AES_CCM:
1292                     ar->arPairwiseCrypto = AES_CRYPT;
1293                     profChanged          = TRUE;
1294                     break;
1295                 case IEEE80211_CIPHER_TKIP:
1296                     ar->arPairwiseCrypto = TKIP_CRYPT;
1297                     profChanged          = TRUE;
1298                     break;
1299                 case IEEE80211_CIPHER_WEP:
1300                     ar->arPairwiseCrypto = WEP_CRYPT;
1301                     profChanged          = TRUE;
1302                     break;
1303                 case IEEE80211_CIPHER_NONE:
1304                     ar->arPairwiseCrypto = NONE_CRYPT;
1305                     profChanged          = TRUE;
1306                     break;
1307             }
1308             break;
1309         case IEEE80211_PARAM_UCASTKEYLEN:
1310             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1311                 ret = -EIO;
1312             } else {
1313                 ar->arPairwiseCryptoLen = value;
1314             }
1315             break;
1316         case IEEE80211_PARAM_MCASTCIPHER:
1317             switch (value) {
1318                 case IEEE80211_CIPHER_AES_CCM:
1319                     ar->arGroupCrypto = AES_CRYPT;
1320                     profChanged       = TRUE;
1321                     break;
1322                 case IEEE80211_CIPHER_TKIP:
1323                     ar->arGroupCrypto = TKIP_CRYPT;
1324                     profChanged       = TRUE;
1325                     break;
1326                 case IEEE80211_CIPHER_WEP:
1327                     ar->arGroupCrypto = WEP_CRYPT;
1328                     profChanged       = TRUE;
1329                     break;
1330                 case IEEE80211_CIPHER_NONE:
1331                     ar->arGroupCrypto = NONE_CRYPT;
1332                     profChanged       = TRUE;
1333                     break;
1334             }
1335             break;
1336         case IEEE80211_PARAM_MCASTKEYLEN:
1337             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1338                 ret = -EIO;
1339             } else {
1340                 ar->arGroupCryptoLen = value;
1341             }
1342             break;
1343         case IEEE80211_PARAM_COUNTERMEASURES:
1344             if (ar->arWmiReady == FALSE) {
1345                 return -EIO;
1346             }
1347             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1348             break;
1349         default:
1350             break;
1351     }
1352
1353     if (profChanged == TRUE) {
1354         /*
1355          * profile has changed.  Erase ssid to signal change
1356          */
1357         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1358         ar->arSsidLen = 0;
1359     }
1360
1361     return ret;
1362 }
1363
1364 int
1365 ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
1366             void *w, char *extra)
1367 {
1368     return -EIO;            /* for now */
1369 }
1370
1371 int
1372 ar6000_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
1373                     void *w, char *extra)
1374 {
1375     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1376     struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
1377     KEY_USAGE keyUsage;
1378     A_STATUS status;
1379     CRYPTO_TYPE keyType = NONE_CRYPT;
1380
1381     if (ar->arWlanState == WLAN_DISABLED) {
1382         return -EIO;
1383     }
1384
1385     ar->user_saved_keys.keyOk = FALSE;
1386
1387     if ( 0 == memcmp(ik->ik_macaddr, "\x00\x00\x00\x00\x00\x00",
1388                      IEEE80211_ADDR_LEN)) {
1389         keyUsage = GROUP_USAGE;
1390         A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik,
1391                  sizeof(struct ieee80211req_key));
1392     } else {
1393         keyUsage = PAIRWISE_USAGE;
1394         A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik,
1395                  sizeof(struct ieee80211req_key));
1396     }
1397
1398     switch (ik->ik_type) {
1399         case IEEE80211_CIPHER_WEP:
1400             keyType = WEP_CRYPT;
1401             break;
1402         case IEEE80211_CIPHER_TKIP:
1403             keyType = TKIP_CRYPT;
1404             break;
1405         case IEEE80211_CIPHER_AES_CCM:
1406             keyType = AES_CRYPT;
1407             break;
1408         default:
1409             break;
1410     }
1411     ar->user_saved_keys.keyType = keyType;
1412
1413     if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) {
1414         if (NONE_CRYPT == keyType) {
1415             return -EIO;
1416         }
1417
1418         status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
1419                                 ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
1420                                 ik->ik_keydata, KEY_OP_INIT_VAL,
1421                                 SYNC_BEFORE_WMIFLAG);
1422
1423         if (status != A_OK) {
1424             return -EIO;
1425         }
1426     } else {
1427         status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata);
1428     }
1429
1430     ar->user_saved_keys.keyOk = TRUE;
1431
1432     return 0;
1433 }
1434
1435
1436 /*
1437  * SIOCGIWNAME
1438  */
1439 int
1440 ar6000_ioctl_giwname(struct net_device *dev,
1441            struct iw_request_info *info,
1442            char *name, char *extra)
1443 {
1444     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1445
1446     if (ar->arWlanState == WLAN_DISABLED) {
1447         return -EIO;
1448     }
1449
1450     switch (ar->arPhyCapability) {
1451     case (WMI_11A_CAPABILITY):
1452         strncpy(name, "AR6000 802.11a", IFNAMSIZ);
1453         break;
1454     case (WMI_11G_CAPABILITY):
1455         strncpy(name, "AR6000 802.11g", IFNAMSIZ);
1456         break;
1457     case (WMI_11AG_CAPABILITY):
1458         strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
1459         break;
1460     default:
1461         strncpy(name, "AR6000 802.11", IFNAMSIZ);
1462         break;
1463     }
1464
1465     return 0;
1466 }
1467
1468 /*
1469  * SIOCSIWFREQ
1470  */
1471 int
1472 ar6000_ioctl_siwfreq(struct net_device *dev,
1473             struct iw_request_info *info,
1474             struct iw_freq *freq, char *extra)
1475 {
1476     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1477
1478     if (ar->arWlanState == WLAN_DISABLED) {
1479         return -EIO;
1480     }
1481
1482     /*
1483      * We support limiting the channels via wmiconfig.
1484      *
1485      * We use this command to configure the channel hint for the connect cmd
1486      * so it is possible the target will end up connecting to a different
1487      * channel.
1488      */
1489     if (freq->e > 1) {
1490         return -EINVAL;
1491     } else if (freq->e == 1) {
1492         ar->arChannelHint = freq->m / 100000;
1493     } else {
1494         ar->arChannelHint = wlan_ieee2freq(freq->m);
1495     }
1496
1497     A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
1498     return 0;
1499 }
1500
1501 /*
1502  * SIOCGIWFREQ
1503  */
1504 int
1505 ar6000_ioctl_giwfreq(struct net_device *dev,
1506                 struct iw_request_info *info,
1507                 struct iw_freq *freq, char *extra)
1508 {
1509     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1510
1511     if (ar->arWlanState == WLAN_DISABLED) {
1512         return -EIO;
1513     }
1514
1515     if (ar->arConnected != TRUE) {
1516         return -EINVAL;
1517     }
1518
1519     freq->m = ar->arBssChannel * 100000;
1520     freq->e = 1;
1521
1522     return 0;
1523 }
1524
1525 /*
1526  * SIOCSIWMODE
1527  */
1528 int
1529 ar6000_ioctl_siwmode(struct net_device *dev,
1530             struct iw_request_info *info,
1531             __u32 *mode, char *extra)
1532 {
1533     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1534
1535     if (ar->arWlanState == WLAN_DISABLED) {
1536         return -EIO;
1537     }
1538
1539     switch (*mode) {
1540     case IW_MODE_INFRA:
1541         ar->arNetworkType = INFRA_NETWORK;
1542         break;
1543     case IW_MODE_ADHOC:
1544         ar->arNetworkType = ADHOC_NETWORK;
1545         break;
1546     default:
1547         return -EINVAL;
1548     }
1549
1550     return 0;
1551 }
1552
1553 /*
1554  * SIOCGIWMODE
1555  */
1556 int
1557 ar6000_ioctl_giwmode(struct net_device *dev,
1558             struct iw_request_info *info,
1559             __u32 *mode, char *extra)
1560 {
1561     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1562
1563     if (ar->arWlanState == WLAN_DISABLED) {
1564         return -EIO;
1565     }
1566
1567     switch (ar->arNetworkType) {
1568     case INFRA_NETWORK:
1569         *mode = IW_MODE_INFRA;
1570         break;
1571     case ADHOC_NETWORK:
1572         *mode = IW_MODE_ADHOC;
1573         break;
1574     default:
1575         return -EIO;
1576     }
1577     return 0;
1578 }
1579
1580 /*
1581  * SIOCSIWSENS
1582  */
1583 int
1584 ar6000_ioctl_siwsens(struct net_device *dev,
1585             struct iw_request_info *info,
1586             struct iw_param *sens, char *extra)
1587 {
1588     return 0;
1589 }
1590
1591 /*
1592  * SIOCGIWSENS
1593  */
1594 int
1595 ar6000_ioctl_giwsens(struct net_device *dev,
1596             struct iw_request_info *info,
1597             struct iw_param *sens, char *extra)
1598 {
1599     sens->value = 0;
1600     sens->fixed = 1;
1601
1602     return 0;
1603 }
1604
1605 /*
1606  * SIOCGIWRANGE
1607  */
1608 int
1609 ar6000_ioctl_giwrange(struct net_device *dev,
1610              struct iw_request_info *info,
1611              struct iw_point *data, char *extra)
1612 {
1613     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1614     struct iw_range *range = (struct iw_range *) extra;
1615     int i, ret = 0;
1616
1617     if (ar->arWmiReady == FALSE) {
1618         return -EIO;
1619     }
1620
1621     if (ar->arWlanState == WLAN_DISABLED) {
1622         return -EIO;
1623     }
1624
1625     if (down_interruptible(&ar->arSem)) {
1626         return -ERESTARTSYS;
1627     }
1628     ar->arNumChannels = -1;
1629     A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
1630
1631     if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
1632         up(&ar->arSem);
1633         return -EIO;
1634     }
1635
1636     wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
1637
1638     if (signal_pending(current)) {
1639         up(&ar->arSem);
1640         return -EINTR;
1641     }
1642
1643     data->length = sizeof(struct iw_range);
1644     A_MEMZERO(range, sizeof(struct iw_range));
1645
1646     range->txpower_capa = IW_TXPOW_DBM;
1647
1648     range->min_pmp = 1 * 1024;
1649     range->max_pmp = 65535 * 1024;
1650     range->min_pmt = 1 * 1024;
1651     range->max_pmt = 1000 * 1024;
1652     range->pmp_flags = IW_POWER_PERIOD;
1653     range->pmt_flags = IW_POWER_TIMEOUT;
1654     range->pm_capa = 0;
1655
1656     range->we_version_compiled = WIRELESS_EXT;
1657     range->we_version_source = 13;
1658
1659     range->retry_capa = IW_RETRY_LIMIT;
1660     range->retry_flags = IW_RETRY_LIMIT;
1661     range->min_retry = 0;
1662     range->max_retry = 255;
1663
1664     range->num_frequency = range->num_channels = ar->arNumChannels;
1665     for (i = 0; i < ar->arNumChannels; i++) {
1666         range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
1667         range->freq[i].m = ar->arChannelList[i] * 100000;
1668         range->freq[i].e = 1;
1669          /*
1670          * Linux supports max of 32 channels, bail out once you
1671          * reach the max.
1672          */
1673         if (i == IW_MAX_FREQUENCIES) {
1674             break;
1675         }
1676     }
1677
1678     /* Max quality is max field value minus noise floor */
1679     range->max_qual.qual  = 0xff - 161;
1680
1681     /*
1682      * In order to use dBm measurements, 'level' must be lower
1683      * than any possible measurement (see iw_print_stats() in
1684      * wireless tools).  It's unclear how this is meant to be
1685      * done, but setting zero in these values forces dBm and
1686      * the actual numbers are not used.
1687      */
1688     range->max_qual.level = 0;
1689     range->max_qual.noise = 0;
1690
1691     range->sensitivity = 3;
1692
1693     range->max_encoding_tokens = 4;
1694     /* XXX query driver to find out supported key sizes */
1695     range->num_encoding_sizes = 3;
1696     range->encoding_size[0] = 5;        /* 40-bit */
1697     range->encoding_size[1] = 13;       /* 104-bit */
1698     range->encoding_size[2] = 16;       /* 128-bit */
1699
1700     range->num_bitrates = 0;
1701
1702     /* estimated maximum TCP throughput values (bps) */
1703     range->throughput = 22000000;
1704
1705     range->min_rts = 0;
1706     range->max_rts = 2347;
1707     range->min_frag = 256;
1708     range->max_frag = 2346;
1709
1710     up(&ar->arSem);
1711
1712     return ret;
1713 }
1714
1715
1716 /*
1717  * SIOCSIWAP
1718  * This ioctl is used to set the desired bssid for the connect command.
1719  */
1720 int
1721 ar6000_ioctl_siwap(struct net_device *dev,
1722               struct iw_request_info *info,
1723               struct sockaddr *ap_addr, char *extra)
1724 {
1725     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1726
1727     if (ar->arWlanState == WLAN_DISABLED) {
1728         return -EIO;
1729     }
1730
1731     if (ap_addr->sa_family != ARPHRD_ETHER) {
1732         return -EIO;
1733     }
1734
1735     if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
1736         A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
1737     } else {
1738         A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data,  sizeof(ar->arReqBssid));
1739     }
1740
1741     return 0;
1742 }
1743
1744 /*
1745  * SIOCGIWAP
1746  */
1747 int
1748 ar6000_ioctl_giwap(struct net_device *dev,
1749               struct iw_request_info *info,
1750               struct sockaddr *ap_addr, char *extra)
1751 {
1752     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1753
1754     if (ar->arWlanState == WLAN_DISABLED) {
1755         return -EIO;
1756     }
1757
1758     if (ar->arConnected != TRUE) {
1759         return -EINVAL;
1760     }
1761
1762     A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
1763     ap_addr->sa_family = ARPHRD_ETHER;
1764
1765     return 0;
1766 }
1767
1768 /*
1769  * SIOCGIWAPLIST
1770  */
1771 int
1772 ar6000_ioctl_iwaplist(struct net_device *dev,
1773             struct iw_request_info *info,
1774             struct iw_point *data, char *extra)
1775 {
1776     return -EIO;            /* for now */
1777 }
1778
1779 /*
1780  * SIOCSIWSCAN
1781  */
1782 int
1783 ar6000_ioctl_siwscan(struct net_device *dev,
1784                      struct iw_request_info *info,
1785                      struct iw_point *data, char *extra)
1786 {
1787 #define ACT_DWELLTIME_DEFAULT   105
1788 #define HOME_TXDRAIN_TIME       100
1789 #define SCAN_INT                HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
1790     AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1791     int ret = 0;
1792
1793     if (ar->arWmiReady == FALSE) {
1794         return -EIO;
1795     }
1796
1797     if (ar->arWlanState == WLAN_DISABLED) {
1798         return -EIO;
1799     }
1800
1801     /* We ask for everything from the target */
1802     if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
1803             printk("Couldn't set filtering\n");
1804             ret = -EIO;
1805     }
1806
1807     if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
1808                           HOME_TXDRAIN_TIME, SCAN_INT) != A_OK) {
1809         ret = -EIO;
1810     }
1811
1812     ar->scan_complete = 0;
1813     wait_event_interruptible_timeout(ar6000_scan_queue, ar->scan_complete,
1814                                      5 * HZ);
1815
1816     if (wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0) != A_OK) {
1817             printk("Couldn't set filtering\n");
1818             ret = -EIO;
1819     }
1820
1821     return ret;
1822 #undef  ACT_DWELLTIME_DEFAULT
1823 #undef HOME_TXDRAIN_TIME
1824 #undef SCAN_INT
1825 }
1826
1827
1828 /*
1829  * Units are in db above the noise floor. That means the
1830  * rssi values reported in the tx/rx descriptors in the
1831  * driver are the SNR expressed in db.
1832  *
1833  * If you assume that the noise floor is -95, which is an
1834  * excellent assumption 99.5 % of the time, then you can
1835  * derive the absolute signal level (i.e. -95 + rssi).
1836  * There are some other slight factors to take into account
1837  * depending on whether the rssi measurement is from 11b,
1838  * 11g, or 11a.   These differences are at most 2db and
1839  * can be documented.
1840  *
1841  * NB: various calculations are based on the orinoco/wavelan
1842  *     drivers for compatibility
1843  */
1844 static void
1845 ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
1846 {
1847     if (rssi < 0) {
1848         iq->qual = 0;
1849     } else {
1850         iq->qual = rssi;
1851     }
1852
1853     /* NB: max is 94 because noise is hardcoded to 161 */
1854     if (iq->qual > 94)
1855         iq->qual = 94;
1856
1857     iq->noise = 161;        /* -95dBm */
1858     iq->level = iq->noise + iq->qual;
1859     iq->updated = 7;
1860 }
1861
1862
1863 /* Structures to export the Wireless Handlers */
1864 static const iw_handler ath_handlers[] = {
1865     (iw_handler) NULL,                          /* SIOCSIWCOMMIT */
1866     (iw_handler) ar6000_ioctl_giwname,          /* SIOCGIWNAME */
1867     (iw_handler) NULL,                          /* SIOCSIWNWID */
1868     (iw_handler) NULL,                          /* SIOCGIWNWID */
1869     (iw_handler) ar6000_ioctl_siwfreq,          /* SIOCSIWFREQ */
1870     (iw_handler) ar6000_ioctl_giwfreq,          /* SIOCGIWFREQ */
1871     (iw_handler) ar6000_ioctl_siwmode,          /* SIOCSIWMODE */
1872     (iw_handler) ar6000_ioctl_giwmode,          /* SIOCGIWMODE */
1873     (iw_handler) ar6000_ioctl_siwsens,          /* SIOCSIWSENS */
1874     (iw_handler) ar6000_ioctl_giwsens,          /* SIOCGIWSENS */
1875     (iw_handler) NULL /* not _used */,          /* SIOCSIWRANGE */
1876     (iw_handler) ar6000_ioctl_giwrange,         /* SIOCGIWRANGE */
1877     (iw_handler) NULL /* not used */,           /* SIOCSIWPRIV */
1878     (iw_handler) NULL /* kernel code */,        /* SIOCGIWPRIV */
1879     (iw_handler) NULL /* not used */,           /* SIOCSIWSTATS */
1880     (iw_handler) NULL /* kernel code */,        /* SIOCGIWSTATS */
1881     (iw_handler) NULL,                          /* SIOCSIWSPY */
1882     (iw_handler) NULL,                          /* SIOCGIWSPY */
1883     (iw_handler) NULL,                          /* SIOCSIWTHRSPY */
1884     (iw_handler) NULL,                          /* SIOCGIWTHRSPY */
1885     (iw_handler) ar6000_ioctl_siwap,            /* SIOCSIWAP */
1886     (iw_handler) ar6000_ioctl_giwap,            /* SIOCGIWAP */
1887     (iw_handler) NULL,                          /* -- hole -- */
1888     (iw_handler) ar6000_ioctl_iwaplist,         /* SIOCGIWAPLIST */
1889     (iw_handler) ar6000_ioctl_siwscan,          /* SIOCSIWSCAN */
1890     (iw_handler) ar6000_ioctl_giwscan,          /* SIOCGIWSCAN */
1891     (iw_handler) ar6000_ioctl_siwessid,         /* SIOCSIWESSID */
1892     (iw_handler) ar6000_ioctl_giwessid,         /* SIOCGIWESSID */
1893     (iw_handler) NULL,                          /* SIOCSIWNICKN */
1894     (iw_handler) NULL,                          /* SIOCGIWNICKN */
1895     (iw_handler) NULL,                          /* -- hole -- */
1896     (iw_handler) NULL,                          /* -- hole -- */
1897     (iw_handler) ar6000_ioctl_siwrate,          /* SIOCSIWRATE */
1898     (iw_handler) ar6000_ioctl_giwrate,          /* SIOCGIWRATE */
1899     (iw_handler) NULL,           /* SIOCSIWRTS */
1900     (iw_handler) NULL,           /* SIOCGIWRTS */
1901     (iw_handler) NULL,          /* SIOCSIWFRAG */
1902     (iw_handler) NULL,          /* SIOCGIWFRAG */
1903     (iw_handler) ar6000_ioctl_siwtxpow,         /* SIOCSIWTXPOW */
1904     (iw_handler) ar6000_ioctl_giwtxpow,         /* SIOCGIWTXPOW */
1905     (iw_handler) ar6000_ioctl_siwretry,         /* SIOCSIWRETRY */
1906     (iw_handler) ar6000_ioctl_giwretry,         /* SIOCGIWRETRY */
1907     (iw_handler) ar6000_ioctl_siwencode,        /* SIOCSIWENCODE */
1908     (iw_handler) ar6000_ioctl_giwencode,        /* SIOCGIWENCODE */
1909     (iw_handler) ar6000_ioctl_siwpower,         /* SIOCSIWPOWER */
1910     (iw_handler) ar6000_ioctl_giwpower,         /* SIOCGIWPOWER */
1911     (iw_handler) NULL,  /* -- hole -- */
1912     (iw_handler) NULL,  /* -- hole -- */
1913     (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
1914     (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
1915     (iw_handler) ar6000_ioctl_siwauth,  /* SIOCSIWAUTH */
1916     (iw_handler) ar6000_ioctl_giwauth,  /* SIOCGIWAUTH */
1917     (iw_handler) ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */
1918     (iw_handler) ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */
1919     (iw_handler) NULL,          /* SIOCSIWPMKSA */
1920 };
1921
1922 static const iw_handler ath_priv_handlers[] = {
1923     (iw_handler) ar6000_ioctl_setparam,         /* SIOCWFIRSTPRIV+0 */
1924     (iw_handler) ar6000_ioctl_getparam,         /* SIOCWFIRSTPRIV+1 */
1925     (iw_handler) ar6000_ioctl_setkey,           /* SIOCWFIRSTPRIV+2 */
1926     (iw_handler) ar6000_ioctl_setwmmparams,     /* SIOCWFIRSTPRIV+3 */
1927     (iw_handler) ar6000_ioctl_delkey,           /* SIOCWFIRSTPRIV+4 */
1928     (iw_handler) ar6000_ioctl_getwmmparams,     /* SIOCWFIRSTPRIV+5 */
1929     (iw_handler) ar6000_ioctl_setoptie,         /* SIOCWFIRSTPRIV+6 */
1930     (iw_handler) ar6000_ioctl_setmlme,          /* SIOCWFIRSTPRIV+7 */
1931     (iw_handler) ar6000_ioctl_addpmkid,         /* SIOCWFIRSTPRIV+8 */
1932 };
1933
1934 #define IW_PRIV_TYPE_KEY \
1935     (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_key))
1936 #define IW_PRIV_TYPE_DELKEY \
1937     (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_del_key))
1938 #define IW_PRIV_TYPE_MLME \
1939     (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme))
1940 #define IW_PRIV_TYPE_ADDPMKID \
1941     (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_addpmkid))
1942
1943 static const struct iw_priv_args ar6000_priv_args[] = {
1944     { IEEE80211_IOCTL_SETKEY,
1945       IW_PRIV_TYPE_KEY | IW_PRIV_SIZE_FIXED, 0,       "setkey"},
1946     { IEEE80211_IOCTL_DELKEY,
1947       IW_PRIV_TYPE_DELKEY | IW_PRIV_SIZE_FIXED, 0,    "delkey"},
1948     { IEEE80211_IOCTL_SETPARAM,
1949       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,   "setparam"},
1950     { IEEE80211_IOCTL_GETPARAM,
1951       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1952       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,      "getparam"},
1953     { IEEE80211_IOCTL_SETWMMPARAMS,
1954       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, 0,   "setwmmparams"},
1955     { IEEE80211_IOCTL_GETWMMPARAMS,
1956       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
1957       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,      "getwmmparams"},
1958     { IEEE80211_IOCTL_SETOPTIE,
1959       IW_PRIV_TYPE_BYTE, 0,       "setie"},
1960     { IEEE80211_IOCTL_SETMLME,
1961       IW_PRIV_TYPE_MLME, 0,       "setmlme"},
1962     { IEEE80211_IOCTL_ADDPMKID,
1963       IW_PRIV_TYPE_ADDPMKID | IW_PRIV_SIZE_FIXED, 0,  "addpmkid"},
1964 };
1965
1966 void ar6000_ioctl_iwsetup(struct iw_handler_def *def)
1967 {
1968     def->private_args = (struct iw_priv_args *)ar6000_priv_args;
1969     def->num_private_args = ARRAY_SIZE(ar6000_priv_args);
1970 }
1971
1972 struct iw_handler_def ath_iw_handler_def = {
1973     .standard         = (iw_handler *)ath_handlers,
1974     .num_standard     = ARRAY_SIZE(ath_handlers),
1975     .private          = (iw_handler *)ath_priv_handlers,
1976     .num_private      = ARRAY_SIZE(ath_priv_handlers),
1977 };
1978
1979