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
22static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
23static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
24extern unsigned int wmitimeout;
25extern A_WAITQUEUE_HEAD arEvent;
26extern 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 */
32static u_int
33encode_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
51void
52ar6000_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
206int
207ar6000_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
252extern int reconnect_flag;
253/* SIOCSIWESSID */
254static int
255ar6000_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 */
432static int
433ar6000_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
451void 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
474int
475ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
476             void *w, char *extra)
477{
478    return 0;
479}
480
481int
482ar6000_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
503int
504ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info,
505             void *w, char *extra)
506{
507    return -EIO;            /* for now */
508}
509
510int
511ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info,
512             void *w, char *extra)
513{
514    return -EIO;            /* for now */
515}
516
517int 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
524int
525ar6000_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}
549static int
550ar6000_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 */
579int
580ar6000_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 */
610int
611ar6000_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 */
652static int
653ar6000_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 */
697int
698ar6000_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 */
753static int
754ar6000_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 */
789static int
790ar6000_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 */
825static int
826ar6000_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
908static int
909ar6000_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
955static 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
973static 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
992static 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
1001static 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
1009static 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
1124static 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
1132static 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
1218static 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
1227static int
1228ar6000_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
1364int
1365ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
1366            void *w, char *extra)
1367{
1368    return -EIO;            /* for now */
1369}
1370
1371int
1372ar6000_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 */
1439int
1440ar6000_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 */
1471int
1472ar6000_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 */
1504int
1505ar6000_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 */
1528int
1529ar6000_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 */
1556int
1557ar6000_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 */
1583int
1584ar6000_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 */
1594int
1595ar6000_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 */
1608int
1609ar6000_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 */
1720int
1721ar6000_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 */
1747int
1748ar6000_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 */
1771int
1772ar6000_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 */
1782int
1783ar6000_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 */
1844static void
1845ar6000_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 */
1864static 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
1922static 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
1943static 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
1966void 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
1972struct 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
1980