Root/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/ar6000/ioctl.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
22static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
23static A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
24extern USER_RSSI_THOLD rssi_map[12];
25extern unsigned int wmitimeout;
26extern A_WAITQUEUE_HEAD arEvent;
27extern int tspecCompliance;
28extern int bypasswmi;
29
30static int
31ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
32{
33    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
34
35    if (ar->arWmiReady == FALSE) {
36        return -EIO;
37    }
38
39    if(wmi_get_roam_tbl_cmd(ar->arWmi) != A_OK) {
40        return -EIO;
41    }
42
43    return 0;
44}
45
46static int
47ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
48{
49    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
50
51    if (ar->arWmiReady == FALSE) {
52        return -EIO;
53    }
54
55
56    /* currently assume only roam times are required */
57    if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != A_OK) {
58        return -EIO;
59    }
60
61
62    return 0;
63}
64
65static int
66ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
67{
68    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
69    WMI_SET_ROAM_CTRL_CMD cmd;
70    A_UINT8 size = sizeof(cmd);
71
72    if (ar->arWmiReady == FALSE) {
73        return -EIO;
74    }
75
76
77    if (copy_from_user(&cmd, userdata, size)) {
78        return -EFAULT;
79    }
80
81    if (cmd.roamCtrlType == WMI_SET_HOST_BIAS) {
82        if (cmd.info.bssBiasInfo.numBss > 1) {
83            size += (cmd.info.bssBiasInfo.numBss - 1) * sizeof(WMI_BSS_BIAS);
84        }
85    }
86
87    if (copy_from_user(&cmd, userdata, size)) {
88        return -EFAULT;
89    }
90
91    if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != A_OK) {
92        return -EIO;
93    }
94
95    return 0;
96}
97
98static int
99ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
100{
101    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
102    WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
103    A_UINT8 size = sizeof(cmd);
104
105    if (ar->arWmiReady == FALSE) {
106        return -EIO;
107    }
108
109    if (copy_from_user(&cmd, userdata, size)) {
110        return -EFAULT;
111    }
112
113    if (copy_from_user(&cmd, userdata, size)) {
114        return -EFAULT;
115    }
116
117    if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != A_OK) {
118        return -EIO;
119    }
120
121    return 0;
122}
123
124static int
125ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
126{
127    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
128    WMI_SET_WMM_CMD cmd;
129    A_STATUS ret;
130
131    if ((dev->flags & IFF_UP) != IFF_UP) {
132        return -EIO;
133    }
134    if (ar->arWmiReady == FALSE) {
135        return -EIO;
136    }
137
138    if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
139                                sizeof(cmd)))
140    {
141        return -EFAULT;
142    }
143
144    if (cmd.status == WMI_WMM_ENABLED) {
145        ar->arWmmEnabled = TRUE;
146    } else {
147        ar->arWmmEnabled = FALSE;
148    }
149
150    ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
151
152    switch (ret) {
153        case A_OK:
154            return 0;
155        case A_EBUSY :
156            return -EBUSY;
157        case A_NO_MEMORY:
158            return -ENOMEM;
159        case A_EINVAL:
160        default:
161            return -EFAULT;
162    }
163}
164
165static int
166ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
167{
168    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
169    WMI_SET_WMM_TXOP_CMD cmd;
170    A_STATUS ret;
171
172    if ((dev->flags & IFF_UP) != IFF_UP) {
173        return -EIO;
174    }
175    if (ar->arWmiReady == FALSE) {
176        return -EIO;
177    }
178
179    if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
180                                sizeof(cmd)))
181    {
182        return -EFAULT;
183    }
184
185    ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
186
187    switch (ret) {
188        case A_OK:
189            return 0;
190        case A_EBUSY :
191            return -EBUSY;
192        case A_NO_MEMORY:
193            return -ENOMEM;
194        case A_EINVAL:
195        default:
196            return -EFAULT;
197    }
198}
199
200static int
201ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
202{
203    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
204    A_STATUS ret = 0;
205
206    if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == FALSE) {
207        return -EIO;
208    }
209
210    if(copy_to_user((char *)((unsigned int*)rq->ifr_data + 1),
211                            &ar->arRegCode, sizeof(ar->arRegCode)))
212        ret = -EFAULT;
213
214    return ret;
215}
216
217
218/* Get power mode command */
219static int
220ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
221{
222    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
223    WMI_POWER_MODE_CMD power_mode;
224    int ret = 0;
225
226    if (ar->arWmiReady == FALSE) {
227        return -EIO;
228    }
229
230    power_mode.powerMode = wmi_get_power_mode_cmd(ar->arWmi);
231    if (copy_to_user(rq->ifr_data, &power_mode, sizeof(WMI_POWER_MODE_CMD))) {
232        ret = -EFAULT;
233    }
234
235    return ret;
236}
237
238
239static int
240ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
241{
242    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
243    WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
244    int ret = 0;
245
246    if (ar->arWmiReady == FALSE) {
247        return -EIO;
248    }
249
250
251    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
252        return -EFAULT;
253    }
254
255    if (cmd.numChannels > 1) {
256        cmdp = A_MALLOC(130);
257        if (copy_from_user(cmdp, rq->ifr_data,
258                           sizeof (*cmdp) +
259                           ((cmd.numChannels - 1) * sizeof(A_UINT16))))
260        {
261            kfree(cmdp);
262            return -EFAULT;
263        }
264    } else {
265        cmdp = &cmd;
266    }
267
268    if ((ar->arPhyCapability == WMI_11G_CAPABILITY) &&
269        ((cmdp->phyMode == WMI_11A_MODE) || (cmdp->phyMode == WMI_11AG_MODE)))
270    {
271        ret = -EINVAL;
272    }
273
274    if (!ret &&
275        (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
276                                   cmdp->numChannels, cmdp->channelList)
277         != A_OK))
278    {
279        ret = -EIO;
280    }
281
282    if (cmd.numChannels > 1) {
283        kfree(cmdp);
284    }
285
286    return ret;
287}
288
289static int
290ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
291{
292
293    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
294    WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
295    int ret = 0;
296
297    if (ar->arWmiReady == FALSE) {
298        return -EIO;
299    }
300
301    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
302        return -EFAULT;
303    }
304
305    if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != A_OK ) {
306        ret = -EIO;
307    }
308
309    return ret;
310}
311
312static int
313ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
314{
315#define SWAP_THOLD(thold1, thold2) do { \
316    USER_RSSI_THOLD tmpThold; \
317    tmpThold.tag = thold1.tag; \
318    tmpThold.rssi = thold1.rssi; \
319    thold1.tag = thold2.tag; \
320    thold1.rssi = thold2.rssi; \
321    thold2.tag = tmpThold.tag; \
322    thold2.rssi = tmpThold.rssi; \
323} while (0)
324
325    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
326    WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
327    USER_RSSI_PARAMS rssiParams;
328    A_INT32 i, j;
329
330    int ret = 0;
331
332    if (ar->arWmiReady == FALSE) {
333        return -EIO;
334    }
335
336    if (copy_from_user((char *)&rssiParams, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(USER_RSSI_PARAMS))) {
337        return -EFAULT;
338    }
339    cmd.weight = rssiParams.weight;
340    cmd.pollTime = rssiParams.pollTime;
341
342    A_MEMCPY(rssi_map, &rssiParams.tholds, sizeof(rssi_map));
343    /*
344     * only 6 elements, so use bubble sorting, in ascending order
345     */
346    for (i = 5; i > 0; i--) {
347        for (j = 0; j < i; j++) { /* above tholds */
348            if (rssi_map[j+1].rssi < rssi_map[j].rssi) {
349                SWAP_THOLD(rssi_map[j+1], rssi_map[j]);
350            } else if (rssi_map[j+1].rssi == rssi_map[j].rssi) {
351                return EFAULT;
352            }
353        }
354    }
355    for (i = 11; i > 6; i--) {
356        for (j = 6; j < i; j++) { /* below tholds */
357            if (rssi_map[j+1].rssi < rssi_map[j].rssi) {
358                SWAP_THOLD(rssi_map[j+1], rssi_map[j]);
359            } else if (rssi_map[j+1].rssi == rssi_map[j].rssi) {
360                return EFAULT;
361            }
362        }
363    }
364
365#ifdef DEBUG
366    for (i = 0; i < 12; i++) {
367        AR_DEBUG2_PRINTF("thold[%d].tag: %d, thold[%d].rssi: %d \n",
368                i, rssi_map[i].tag, i, rssi_map[i].rssi);
369    }
370#endif
371    cmd.thresholdAbove1_Val = rssi_map[0].rssi;
372    cmd.thresholdAbove2_Val = rssi_map[1].rssi;
373    cmd.thresholdAbove3_Val = rssi_map[2].rssi;
374    cmd.thresholdAbove4_Val = rssi_map[3].rssi;
375    cmd.thresholdAbove5_Val = rssi_map[4].rssi;
376    cmd.thresholdAbove6_Val = rssi_map[5].rssi;
377    cmd.thresholdBelow1_Val = rssi_map[6].rssi;
378    cmd.thresholdBelow2_Val = rssi_map[7].rssi;
379    cmd.thresholdBelow3_Val = rssi_map[8].rssi;
380    cmd.thresholdBelow4_Val = rssi_map[9].rssi;
381    cmd.thresholdBelow5_Val = rssi_map[10].rssi;
382    cmd.thresholdBelow6_Val = rssi_map[11].rssi;
383
384    if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != A_OK ) {
385        ret = -EIO;
386    }
387
388    return ret;
389}
390
391static int
392ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
393{
394
395    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
396    WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
397    int ret = 0;
398
399    if (ar->arWmiReady == FALSE) {
400        return -EIO;
401    }
402
403    if (copy_from_user(&cmd, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(cmd))) {
404        return -EFAULT;
405    }
406
407    if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != A_OK ) {
408        ret = -EIO;
409    }
410
411    return ret;
412}
413
414
415static int
416ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
417{
418    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
419    WMI_PROBED_SSID_CMD cmd;
420    int ret = 0;
421
422    if (ar->arWmiReady == FALSE) {
423        return -EIO;
424    }
425
426    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
427        return -EFAULT;
428    }
429
430    if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
431                                  cmd.ssid) != A_OK)
432    {
433        ret = -EIO;
434    }
435
436    return ret;
437}
438
439static int
440ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
441{
442    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
443    WMI_ADD_BAD_AP_CMD cmd;
444    int ret = 0;
445
446    if (ar->arWmiReady == FALSE) {
447        return -EIO;
448    }
449
450
451    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
452        return -EFAULT;
453    }
454
455    if (cmd.badApIndex > WMI_MAX_BAD_AP_INDEX) {
456        return -EIO;
457    }
458
459    if (A_MEMCMP(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
460        /*
461         * This is a delete badAP.
462         */
463        if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != A_OK) {
464            ret = -EIO;
465        }
466    } else {
467        if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != A_OK) {
468            ret = -EIO;
469        }
470    }
471
472    return ret;
473}
474
475static int
476ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
477{
478    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
479    WMI_CREATE_PSTREAM_CMD cmd;
480    A_STATUS ret;
481
482    if (ar->arWmiReady == FALSE) {
483        return -EIO;
484    }
485
486
487    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
488        return -EFAULT;
489    }
490
491    ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
492    if (ret == A_OK)
493        ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
494
495    switch (ret) {
496        case A_OK:
497            return 0;
498        case A_EBUSY :
499            return -EBUSY;
500        case A_NO_MEMORY:
501            return -ENOMEM;
502        case A_EINVAL:
503        default:
504            return -EFAULT;
505    }
506}
507
508static int
509ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
510{
511    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
512    WMI_DELETE_PSTREAM_CMD cmd;
513    int ret = 0;
514
515    if (ar->arWmiReady == FALSE) {
516        return -EIO;
517    }
518
519    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
520        return -EFAULT;
521    }
522
523    ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
524
525    switch (ret) {
526        case A_OK:
527            return 0;
528        case A_EBUSY :
529            return -EBUSY;
530        case A_NO_MEMORY:
531            return -ENOMEM;
532        case A_EINVAL:
533        default:
534            return -EFAULT;
535    }
536}
537
538static int
539ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
540{
541    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
542    struct ar6000_queuereq qreq;
543    int ret = 0;
544
545    if (ar->arWmiReady == FALSE) {
546        return -EIO;
547    }
548
549    if( copy_from_user(&qreq, rq->ifr_data,
550                  sizeof(struct ar6000_queuereq)))
551        return -EFAULT;
552
553    qreq.activeTsids = wmi_get_mapped_qos_queue(ar->arWmi, qreq.trafficClass);
554
555    if (copy_to_user(rq->ifr_data, &qreq,
556                 sizeof(struct ar6000_queuereq)))
557    {
558        ret = -EFAULT;
559    }
560
561    return ret;
562}
563
564#ifdef CONFIG_HOST_TCMD_SUPPORT
565static A_STATUS
566ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
567                                 struct ifreq *rq, A_UINT8 *data, A_UINT32 len)
568{
569    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
570    A_UINT32 buf[2];
571    int ret = 0;
572
573    if (ar->arWmiReady == FALSE) {
574        return -EIO;
575    }
576
577    if (down_interruptible(&ar->arSem)) {
578        return -ERESTARTSYS;
579    }
580    ar->tcmdRxReport = 0;
581    if (wmi_test_cmd(ar->arWmi, data, len) != A_OK) {
582        up(&ar->arSem);
583        return -EIO;
584    }
585
586    wait_event_interruptible_timeout(arEvent, ar->tcmdRxReport != 0, wmitimeout * HZ);
587
588    if (signal_pending(current)) {
589        ret = -EINTR;
590    }
591
592    buf[0] = ar->tcmdRxTotalPkt;
593    buf[1] = ar->tcmdRxRssi;
594    if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
595        ret = -EFAULT;
596    }
597
598    up(&ar->arSem);
599
600    return ret;
601}
602
603void
604ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
605{
606    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
607    TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
608
609    ar->tcmdRxTotalPkt = rx_rep->u.report.totalPkt;
610    ar->tcmdRxRssi = rx_rep->u.report.rssiInDBm;
611    ar->tcmdRxReport = 1;
612
613    wake_up(&arEvent);
614}
615#endif /* CONFIG_HOST_TCMD_SUPPORT*/
616
617static int
618ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
619{
620    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
621    WMI_TARGET_ERROR_REPORT_BITMASK cmd;
622    int ret = 0;
623
624    if (ar->arWmiReady == FALSE) {
625        return -EIO;
626    }
627
628    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
629        return -EFAULT;
630    }
631
632    ret = wmi_set_error_report_bitmask(ar->arWmi, cmd.bitmask);
633
634    return (ret==0 ? ret : -EINVAL);
635}
636
637static int
638ar6000_clear_target_stats(struct net_device *dev)
639{
640    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
641    TARGET_STATS *pStats = &ar->arTargetStats;
642    int ret = 0;
643
644    if (ar->arWmiReady == FALSE) {
645       return -EIO;
646    }
647    AR6000_SPIN_LOCK(&ar->arLock, 0);
648    A_MEMZERO(pStats, sizeof(TARGET_STATS));
649    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
650    return ret;
651}
652
653static int
654ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
655{
656    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
657    TARGET_STATS_CMD cmd;
658    TARGET_STATS *pStats = &ar->arTargetStats;
659    int ret = 0;
660
661    if (ar->arWmiReady == FALSE) {
662        return -EIO;
663    }
664    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
665        return -EFAULT;
666    }
667    if (down_interruptible(&ar->arSem)) {
668        return -ERESTARTSYS;
669    }
670
671    ar->statsUpdatePending = TRUE;
672
673    if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
674        up(&ar->arSem);
675        return -EIO;
676    }
677
678    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
679
680    if (signal_pending(current)) {
681        ret = -EINTR;
682    }
683
684    if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
685        ret = -EFAULT;
686    }
687
688    if (cmd.clearStats == 1) {
689        ret = ar6000_clear_target_stats(dev);
690    }
691
692    up(&ar->arSem);
693
694    return ret;
695}
696
697static int
698ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
699{
700    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
701    WMI_SET_ACCESS_PARAMS_CMD cmd;
702    int ret = 0;
703
704    if (ar->arWmiReady == FALSE) {
705        return -EIO;
706    }
707
708    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
709        return -EFAULT;
710    }
711
712    if (wmi_set_access_params_cmd(ar->arWmi, cmd.txop, cmd.eCWmin, cmd.eCWmax,
713                                  cmd.aifsn) == A_OK)
714    {
715        ret = 0;
716    } else {
717        ret = -EINVAL;
718    }
719
720    return (ret);
721}
722
723static int
724ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
725{
726    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
727    WMI_DISC_TIMEOUT_CMD cmd;
728    int ret = 0;
729
730    if (ar->arWmiReady == FALSE) {
731        return -EIO;
732    }
733
734    if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
735        return -EFAULT;
736    }
737
738    if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == A_OK)
739    {
740        ret = 0;
741    } else {
742        ret = -EINVAL;
743    }
744
745    return (ret);
746}
747
748static int
749ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
750{
751    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
752    WMI_SET_VOICE_PKT_SIZE_CMD cmd;
753    int ret = 0;
754
755    if (ar->arWmiReady == FALSE) {
756        return -EIO;
757    }
758
759    if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
760        return -EFAULT;
761    }
762
763    if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == A_OK)
764    {
765        ret = 0;
766    } else {
767        ret = -EINVAL;
768    }
769
770
771    return (ret);
772}
773
774static int
775ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
776{
777    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
778    WMI_SET_MAX_SP_LEN_CMD cmd;
779    int ret = 0;
780
781    if (ar->arWmiReady == FALSE) {
782        return -EIO;
783    }
784
785    if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
786        return -EFAULT;
787    }
788
789    if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == A_OK)
790    {
791        ret = 0;
792    } else {
793        ret = -EINVAL;
794    }
795
796    return (ret);
797}
798
799
800static int
801ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
802{
803    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
804    WMI_SET_BT_STATUS_CMD cmd;
805    int ret = 0;
806
807    if (ar->arWmiReady == FALSE) {
808        return -EIO;
809    }
810
811    if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
812        return -EFAULT;
813    }
814
815    if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == A_OK)
816    {
817        ret = 0;
818    } else {
819        ret = -EINVAL;
820    }
821
822    return (ret);
823}
824
825static int
826ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
827{
828    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
829    WMI_SET_BT_PARAMS_CMD cmd;
830    int ret = 0;
831
832    if (ar->arWmiReady == FALSE) {
833        return -EIO;
834    }
835
836    if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
837        return -EFAULT;
838    }
839
840    if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == A_OK)
841    {
842        ret = 0;
843    } else {
844        ret = -EINVAL;
845    }
846
847    return (ret);
848}
849
850#ifdef CONFIG_HOST_GPIO_SUPPORT
851struct ar6000_gpio_intr_wait_cmd_s gpio_intr_results;
852/* gpio_reg_results and gpio_data_available are protected by arSem */
853static struct ar6000_gpio_register_cmd_s gpio_reg_results;
854static A_BOOL gpio_data_available; /* Requested GPIO data available */
855static A_BOOL gpio_intr_available; /* GPIO interrupt info available */
856static A_BOOL gpio_ack_received; /* GPIO ack was received */
857
858/* Host-side initialization for General Purpose I/O support */
859void ar6000_gpio_init(void)
860{
861    gpio_intr_available = FALSE;
862    gpio_data_available = FALSE;
863    gpio_ack_received = FALSE;
864}
865
866/*
867 * Called when a GPIO interrupt is received from the Target.
868 * intr_values shows which GPIO pins have interrupted.
869 * input_values shows a recent value of GPIO pins.
870 */
871void
872ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values)
873{
874    gpio_intr_results.intr_mask = intr_mask;
875    gpio_intr_results.input_values = input_values;
876    *((volatile A_BOOL *)&gpio_intr_available) = TRUE;
877    wake_up(&arEvent);
878}
879
880/*
881 * This is called when a response is received from the Target
882 * for a previous or ar6000_gpio_input_get or ar6000_gpio_register_get
883 * call.
884 */
885void
886ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value)
887{
888    gpio_reg_results.gpioreg_id = reg_id;
889    gpio_reg_results.value = value;
890    *((volatile A_BOOL *)&gpio_data_available) = TRUE;
891    wake_up(&arEvent);
892}
893
894/*
895 * This is called when an acknowledgement is received from the Target
896 * for a previous or ar6000_gpio_output_set or ar6000_gpio_register_set
897 * call.
898 */
899void
900ar6000_gpio_ack_rx(void)
901{
902    gpio_ack_received = TRUE;
903    wake_up(&arEvent);
904}
905
906A_STATUS
907ar6000_gpio_output_set(struct net_device *dev,
908                       A_UINT32 set_mask,
909                       A_UINT32 clear_mask,
910                       A_UINT32 enable_mask,
911                       A_UINT32 disable_mask)
912{
913    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
914
915    gpio_ack_received = FALSE;
916    return wmi_gpio_output_set(ar->arWmi,
917                set_mask, clear_mask, enable_mask, disable_mask);
918}
919
920static A_STATUS
921ar6000_gpio_input_get(struct net_device *dev)
922{
923    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
924
925    *((volatile A_BOOL *)&gpio_data_available) = FALSE;
926    return wmi_gpio_input_get(ar->arWmi);
927}
928
929static A_STATUS
930ar6000_gpio_register_set(struct net_device *dev,
931                         A_UINT32 gpioreg_id,
932                         A_UINT32 value)
933{
934    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
935
936    gpio_ack_received = FALSE;
937    return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
938}
939
940static A_STATUS
941ar6000_gpio_register_get(struct net_device *dev,
942                         A_UINT32 gpioreg_id)
943{
944    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
945
946    *((volatile A_BOOL *)&gpio_data_available) = FALSE;
947    return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
948}
949
950static A_STATUS
951ar6000_gpio_intr_ack(struct net_device *dev,
952                     A_UINT32 ack_mask)
953{
954    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
955
956    gpio_intr_available = FALSE;
957    return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
958}
959#endif /* CONFIG_HOST_GPIO_SUPPORT */
960
961int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
962{
963    AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
964    HIF_DEVICE *hifDevice = ar->arHifDevice;
965    int ret, param, param2;
966    unsigned int address = 0;
967    unsigned int length = 0;
968    unsigned char *buffer;
969    char *userdata;
970    A_UINT32 connectCtrlFlags;
971
972
973    static WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0,
974                                           WMI_SHORTSCANRATIO_DEFAULT,
975                                           DEFAULT_SCAN_CTRL_FLAGS,
976                                           0};
977    WMI_SET_AKMP_PARAMS_CMD akmpParams;
978    WMI_SET_PMKID_LIST_CMD pmkidInfo;
979
980    if (cmd == AR6000_IOCTL_EXTENDED)
981    {
982        /*
983         * This allows for many more wireless ioctls than would otherwise
984         * be available. Applications embed the actual ioctl command in
985         * the first word of the parameter block, and use the command
986         * AR6000_IOCTL_EXTENDED_CMD on the ioctl call.
987         */
988        get_user(cmd, (int *)rq->ifr_data);
989        userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
990    }
991    else
992    {
993        userdata = (char *)rq->ifr_data;
994    }
995
996    if ((ar->arWlanState == WLAN_DISABLED) &&
997        ((cmd != AR6000_XIOCTRL_WMI_SET_WLAN_STATE) &&
998         (cmd != AR6000_XIOCTL_DIAG_READ) &&
999         (cmd != AR6000_XIOCTL_DIAG_WRITE)))
1000    {
1001        return -EIO;
1002    }
1003
1004    ret = 0;
1005    switch(cmd)
1006    {
1007#ifdef CONFIG_HOST_TCMD_SUPPORT
1008        case AR6000_XIOCTL_TCMD_CONT_TX:
1009            {
1010                TCMD_CONT_TX txCmd;
1011
1012                if (ar->tcmdPm == TCMD_PM_SLEEP) {
1013                    A_PRINTF("Can NOT send tx tcmd when target is asleep! \n");
1014                    return -EFAULT;
1015                }
1016
1017                if(copy_from_user(&txCmd, userdata, sizeof(TCMD_CONT_TX)))
1018                    return -EFAULT;
1019                wmi_test_cmd(ar->arWmi,(A_UINT8 *)&txCmd, sizeof(TCMD_CONT_TX));
1020            }
1021            break;
1022        case AR6000_XIOCTL_TCMD_CONT_RX:
1023            {
1024                TCMD_CONT_RX rxCmd;
1025
1026                if (ar->tcmdPm == TCMD_PM_SLEEP) {
1027                    A_PRINTF("Can NOT send rx tcmd when target is asleep! \n");
1028                    return -EFAULT;
1029                }
1030                if(copy_from_user(&rxCmd, userdata, sizeof(TCMD_CONT_RX)))
1031                    return -EFAULT;
1032                switch(rxCmd.act)
1033                {
1034                    case TCMD_CONT_RX_PROMIS:
1035                    case TCMD_CONT_RX_FILTER:
1036                    case TCMD_CONT_RX_SETMAC:
1037                         wmi_test_cmd(ar->arWmi,(A_UINT8 *)&rxCmd,
1038                                                sizeof(TCMD_CONT_RX));
1039                         break;
1040                    case TCMD_CONT_RX_REPORT:
1041                         ar6000_ioctl_tcmd_get_rx_report(dev, rq,
1042                         (A_UINT8 *)&rxCmd, sizeof(TCMD_CONT_RX));
1043                         break;
1044                    default:
1045                         A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
1046                         return -EINVAL;
1047                }
1048            }
1049            break;
1050        case AR6000_XIOCTL_TCMD_PM:
1051            {
1052                TCMD_PM pmCmd;
1053
1054                if(copy_from_user(&pmCmd, userdata, sizeof(TCMD_PM)))
1055                    return -EFAULT;
1056                ar->tcmdPm = pmCmd.mode;
1057                wmi_test_cmd(ar->arWmi, (A_UINT8*)&pmCmd, sizeof(TCMD_PM));
1058            }
1059            break;
1060#endif /* CONFIG_HOST_TCMD_SUPPORT */
1061
1062        case AR6000_XIOCTL_BMI_DONE:
1063            ret = BMIDone(hifDevice);
1064            break;
1065
1066        case AR6000_XIOCTL_BMI_READ_MEMORY:
1067            get_user(address, (unsigned int *)userdata);
1068            get_user(length, (unsigned int *)userdata + 1);
1069            AR_DEBUG_PRINTF("Read Memory (address: 0x%x, length: %d)\n",
1070                             address, length);
1071            if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
1072                A_MEMZERO(buffer, length);
1073                ret = BMIReadMemory(hifDevice, address, buffer, length);
1074                if (copy_to_user(rq->ifr_data, buffer, length)) {
1075                    ret = -EFAULT;
1076                }
1077                A_FREE(buffer);
1078            } else {
1079                ret = -ENOMEM;
1080            }
1081            break;
1082
1083        case AR6000_XIOCTL_BMI_WRITE_MEMORY:
1084            get_user(address, (unsigned int *)userdata);
1085            get_user(length, (unsigned int *)userdata + 1);
1086            AR_DEBUG_PRINTF("Write Memory (address: 0x%x, length: %d)\n",
1087                             address, length);
1088            if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
1089                A_MEMZERO(buffer, length);
1090                if (copy_from_user(buffer, &userdata[sizeof(address) +
1091                                   sizeof(length)], length))
1092                {
1093                    ret = -EFAULT;
1094                } else {
1095                    ret = BMIWriteMemory(hifDevice, address, buffer, length);
1096                }
1097                A_FREE(buffer);
1098            } else {
1099                ret = -ENOMEM;
1100            }
1101            break;
1102
1103        case AR6000_XIOCTL_BMI_TEST:
1104           AR_DEBUG_PRINTF("No longer supported\n");
1105           ret = -EOPNOTSUPP;
1106           break;
1107
1108        case AR6000_XIOCTL_BMI_EXECUTE:
1109            get_user(address, (unsigned int *)userdata);
1110            get_user(param, (unsigned int *)userdata + 1);
1111            AR_DEBUG_PRINTF("Execute (address: 0x%x, param: %d)\n",
1112                             address, param);
1113            ret = BMIExecute(hifDevice, address, &param);
1114            put_user(param, (unsigned int *)rq->ifr_data); /* return value */
1115            break;
1116
1117        case AR6000_XIOCTL_BMI_SET_APP_START:
1118            get_user(address, (unsigned int *)userdata);
1119            AR_DEBUG_PRINTF("Set App Start (address: 0x%x)\n", address);
1120            ret = BMISetAppStart(hifDevice, address);
1121            break;
1122
1123        case AR6000_XIOCTL_BMI_READ_SOC_REGISTER:
1124            get_user(address, (unsigned int *)userdata);
1125            ret = BMIReadSOCRegister(hifDevice, address, &param);
1126            put_user(param, (unsigned int *)rq->ifr_data); /* return value */
1127            break;
1128
1129        case AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER:
1130            get_user(address, (unsigned int *)userdata);
1131            get_user(param, (unsigned int *)userdata + 1);
1132            ret = BMIWriteSOCRegister(hifDevice, address, param);
1133            break;
1134
1135#ifdef HTC_RAW_INTERFACE
1136        case AR6000_XIOCTL_HTC_RAW_OPEN:
1137            ret = A_OK;
1138            if (!arRawIfEnabled(ar)) {
1139                /* make sure block size is set in case the target was reset since last
1140                  * BMI phase (i.e. flashup downloads) */
1141                ret = ar6000_SetHTCBlockSize(ar);
1142                if (A_FAILED(ret)) {
1143                    break;
1144                }
1145                /* Terminate the BMI phase */
1146                ret = BMIDone(hifDevice);
1147                if (ret == A_OK) {
1148                    ret = ar6000_htc_raw_open(ar);
1149                }
1150            }
1151            break;
1152
1153        case AR6000_XIOCTL_HTC_RAW_CLOSE:
1154            if (arRawIfEnabled(ar)) {
1155                ret = ar6000_htc_raw_close(ar);
1156                arRawIfEnabled(ar) = FALSE;
1157            } else {
1158                ret = A_ERROR;
1159            }
1160            break;
1161
1162        case AR6000_XIOCTL_HTC_RAW_READ:
1163            if (arRawIfEnabled(ar)) {
1164                unsigned int streamID;
1165                get_user(streamID, (unsigned int *)userdata);
1166                get_user(length, (unsigned int *)userdata + 1);
1167                buffer = rq->ifr_data + sizeof(length);
1168                ret = ar6000_htc_raw_read(ar, (HTC_RAW_STREAM_ID)streamID,
1169                                          buffer, length);
1170                put_user(ret, (unsigned int *)rq->ifr_data);
1171            } else {
1172                ret = A_ERROR;
1173            }
1174            break;
1175
1176        case AR6000_XIOCTL_HTC_RAW_WRITE:
1177            if (arRawIfEnabled(ar)) {
1178                unsigned int streamID;
1179                get_user(streamID, (unsigned int *)userdata);
1180                get_user(length, (unsigned int *)userdata + 1);
1181                buffer = userdata + sizeof(streamID) + sizeof(length);
1182                ret = ar6000_htc_raw_write(ar, (HTC_RAW_STREAM_ID)streamID,
1183                                           buffer, length);
1184                put_user(ret, (unsigned int *)rq->ifr_data);
1185            } else {
1186                ret = A_ERROR;
1187            }
1188            break;
1189#endif /* HTC_RAW_INTERFACE */
1190
1191        case AR6000_IOCTL_WMI_GETREV:
1192        {
1193            if (copy_to_user(rq->ifr_data, &ar->arVersion,
1194                             sizeof(ar->arVersion)))
1195            {
1196                ret = -EFAULT;
1197            }
1198            break;
1199        }
1200        case AR6000_IOCTL_WMI_SETPWR:
1201        {
1202            WMI_POWER_MODE_CMD pwrModeCmd;
1203
1204            if (ar->arWmiReady == FALSE) {
1205                ret = -EIO;
1206            } else if (copy_from_user(&pwrModeCmd, userdata,
1207                                   sizeof(pwrModeCmd)))
1208            {
1209                ret = -EFAULT;
1210            } else {
1211                if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
1212                       != A_OK)
1213                {
1214                    ret = -EIO;
1215                }
1216            }
1217            break;
1218        }
1219        case AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS:
1220        {
1221            WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
1222
1223            if (ar->arWmiReady == FALSE) {
1224                ret = -EIO;
1225            } else if (copy_from_user(&ibssPmCaps, userdata,
1226                                   sizeof(ibssPmCaps)))
1227            {
1228                ret = -EFAULT;
1229            } else {
1230                if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
1231                    ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != A_OK)
1232                {
1233                    ret = -EIO;
1234                }
1235                AR6000_SPIN_LOCK(&ar->arLock, 0);
1236                ar->arIbssPsEnable = ibssPmCaps.power_saving;
1237                AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1238            }
1239            break;
1240        }
1241        case AR6000_IOCTL_WMI_SET_PMPARAMS:
1242        {
1243            WMI_POWER_PARAMS_CMD pmParams;
1244
1245            if (ar->arWmiReady == FALSE) {
1246                ret = -EIO;
1247            } else if (copy_from_user(&pmParams, userdata,
1248                                      sizeof(pmParams)))
1249            {
1250                ret = -EFAULT;
1251            } else {
1252                if (wmi_pmparams_cmd(ar->arWmi, pmParams.idle_period,
1253                                     pmParams.pspoll_number,
1254                                     pmParams.dtim_policy) != A_OK)
1255                {
1256                    ret = -EIO;
1257                }
1258            }
1259            break;
1260        }
1261        case AR6000_IOCTL_WMI_SETSCAN:
1262        {
1263            if (ar->arWmiReady == FALSE) {
1264                ret = -EIO;
1265            } else if (copy_from_user(&scParams, userdata,
1266                                      sizeof(scParams)))
1267            {
1268                ret = -EFAULT;
1269            } else {
1270                if (CAN_SCAN_IN_CONNECT(scParams.scanCtrlFlags)) {
1271                    ar->arSkipScan = FALSE;
1272                } else {
1273                    ar->arSkipScan = TRUE;
1274                }
1275
1276                if (wmi_scanparams_cmd(ar->arWmi, scParams.fg_start_period,
1277                                       scParams.fg_end_period,
1278                                       scParams.bg_period,
1279                                       scParams.minact_chdwell_time,
1280                                       scParams.maxact_chdwell_time,
1281                                       scParams.pas_chdwell_time,
1282                                       scParams.shortScanRatio,
1283                                       scParams.scanCtrlFlags,
1284                                       scParams.max_dfsch_act_time) != A_OK)
1285                {
1286                    ret = -EIO;
1287                }
1288            }
1289            break;
1290        }
1291        case AR6000_IOCTL_WMI_SETLISTENINT:
1292        {
1293            WMI_LISTEN_INT_CMD listenCmd;
1294
1295            if (ar->arWmiReady == FALSE) {
1296                ret = -EIO;
1297            } else if (copy_from_user(&listenCmd, userdata,
1298                                      sizeof(listenCmd)))
1299            {
1300                ret = -EFAULT;
1301            } else {
1302                    if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != A_OK) {
1303                        ret = -EIO;
1304                    } else {
1305                        AR6000_SPIN_LOCK(&ar->arLock, 0);
1306                        ar->arListenInterval = param;
1307                        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1308                    }
1309
1310                }
1311            break;
1312        }
1313        case AR6000_IOCTL_WMI_SET_BMISS_TIME:
1314        {
1315            WMI_BMISS_TIME_CMD bmissCmd;
1316
1317            if (ar->arWmiReady == FALSE) {
1318                ret = -EIO;
1319            } else if (copy_from_user(&bmissCmd, userdata,
1320                                      sizeof(bmissCmd)))
1321            {
1322                ret = -EFAULT;
1323            } else {
1324                if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != A_OK) {
1325                    ret = -EIO;
1326                }
1327            }
1328            break;
1329        }
1330        case AR6000_IOCTL_WMI_SETBSSFILTER:
1331        {
1332            if (ar->arWmiReady == FALSE) {
1333                ret = -EIO;
1334            } else {
1335
1336                get_user(param, (unsigned char *)userdata);
1337                get_user(param2, (unsigned int *)(userdata + 1));
1338        printk("SETBSSFILTER: filter 0x%x, mask: 0x%x\n", param, param2);
1339                if (wmi_bssfilter_cmd(ar->arWmi, param, param2) != A_OK) {
1340                    ret = -EIO;
1341                }
1342            }
1343            break;
1344        }
1345        case AR6000_IOCTL_WMI_SET_SNRTHRESHOLD:
1346        {
1347            ret = ar6000_ioctl_set_snr_threshold(dev, rq);
1348            break;
1349        }
1350        case AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD:
1351        {
1352            ret = ar6000_ioctl_set_rssi_threshold(dev, rq);
1353            break;
1354        }
1355        case AR6000_XIOCTL_WMI_CLR_RSSISNR:
1356        {
1357            if (ar->arWmiReady == FALSE) {
1358                ret = -EIO;
1359            }
1360            ret = wmi_clr_rssi_snr(ar->arWmi);
1361            break;
1362        }
1363        case AR6000_XIOCTL_WMI_SET_LQTHRESHOLD:
1364        {
1365            ret = ar6000_ioctl_set_lq_threshold(dev, rq);
1366            break;
1367        }
1368        case AR6000_XIOCTL_WMI_SET_LPREAMBLE:
1369        {
1370            WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
1371
1372            if (ar->arWmiReady == FALSE) {
1373                ret = -EIO;
1374            } else if (copy_from_user(&setLpreambleCmd, userdata,
1375                                   sizeof(setLpreambleCmd)))
1376            {
1377                ret = -EFAULT;
1378            } else {
1379                if (wmi_set_lpreamble_cmd(ar->arWmi, setLpreambleCmd.status)
1380                       != A_OK)
1381                {
1382                    ret = -EIO;
1383                }
1384            }
1385
1386            break;
1387        }
1388        case AR6000_XIOCTL_WMI_SET_RTS:
1389        {
1390            WMI_SET_RTS_CMD rtsCmd;
1391
1392            if (ar->arWmiReady == FALSE) {
1393                ret = -EIO;
1394            } else if (copy_from_user(&rtsCmd, userdata,
1395                                   sizeof(rtsCmd)))
1396            {
1397                ret = -EFAULT;
1398            } else {
1399                if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
1400                       != A_OK)
1401                {
1402                    ret = -EIO;
1403                }
1404            }
1405
1406            break;
1407        }
1408        case AR6000_XIOCTL_WMI_SET_WMM:
1409        {
1410            ret = ar6000_ioctl_set_wmm(dev, rq);
1411            break;
1412        }
1413        case AR6000_XIOCTL_WMI_SET_TXOP:
1414        {
1415            ret = ar6000_ioctl_set_txop(dev, rq);
1416            break;
1417        }
1418        case AR6000_XIOCTL_WMI_GET_RD:
1419        {
1420            ret = ar6000_ioctl_get_rd(dev, rq);
1421            break;
1422        }
1423        case AR6000_IOCTL_WMI_SET_CHANNELPARAMS:
1424        {
1425            ret = ar6000_ioctl_set_channelParams(dev, rq);
1426            break;
1427        }
1428        case AR6000_IOCTL_WMI_SET_PROBEDSSID:
1429        {
1430            ret = ar6000_ioctl_set_probedSsid(dev, rq);
1431            break;
1432        }
1433        case AR6000_IOCTL_WMI_SET_BADAP:
1434        {
1435            ret = ar6000_ioctl_set_badAp(dev, rq);
1436            break;
1437        }
1438        case AR6000_IOCTL_WMI_CREATE_QOS:
1439        {
1440            ret = ar6000_ioctl_create_qos(dev, rq);
1441            break;
1442        }
1443        case AR6000_IOCTL_WMI_DELETE_QOS:
1444        {
1445            ret = ar6000_ioctl_delete_qos(dev, rq);
1446            break;
1447        }
1448        case AR6000_IOCTL_WMI_GET_QOS_QUEUE:
1449        {
1450            ret = ar6000_ioctl_get_qos_queue(dev, rq);
1451            break;
1452        }
1453        case AR6000_IOCTL_WMI_GET_TARGET_STATS:
1454        {
1455            ret = ar6000_ioctl_get_target_stats(dev, rq);
1456            break;
1457        }
1458        case AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK:
1459        {
1460            ret = ar6000_ioctl_set_error_report_bitmask(dev, rq);
1461            break;
1462        }
1463        case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
1464        {
1465            WMI_SET_ASSOC_INFO_CMD cmd;
1466            A_UINT8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
1467
1468            if (ar->arWmiReady == FALSE) {
1469                ret = -EIO;
1470            } else {
1471                get_user(cmd.ieType, userdata);
1472                if (cmd.ieType >= WMI_MAX_ASSOC_INFO_TYPE) {
1473                    ret = -EIO;
1474                } else {
1475                    get_user(cmd.bufferSize, userdata + 1);
1476                    if (cmd.bufferSize > WMI_MAX_ASSOC_INFO_LEN) {
1477                        ret = -EFAULT;
1478                        break;
1479                    }
1480                    if (copy_from_user(assocInfo, userdata + 2,
1481                                       cmd.bufferSize))
1482                    {
1483                        ret = -EFAULT;
1484                    } else {
1485                        if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
1486                                                 cmd.bufferSize,
1487                                                 assocInfo) != A_OK)
1488                        {
1489                            ret = -EIO;
1490                        }
1491                    }
1492                }
1493            }
1494            break;
1495        }
1496        case AR6000_IOCTL_WMI_SET_ACCESS_PARAMS:
1497        {
1498            ret = ar6000_ioctl_set_access_params(dev, rq);
1499            break;
1500        }
1501        case AR6000_IOCTL_WMI_SET_DISC_TIMEOUT:
1502        {
1503            ret = ar6000_ioctl_set_disconnect_timeout(dev, rq);
1504            break;
1505        }
1506        case AR6000_XIOCTL_FORCE_TARGET_RESET:
1507        {
1508            if (ar->arHtcTarget)
1509            {
1510// HTCForceReset(htcTarget);
1511            }
1512            else
1513            {
1514                AR_DEBUG_PRINTF("ar6000_ioctl cannot attempt reset.\n");
1515            }
1516            break;
1517        }
1518        case AR6000_XIOCTL_TARGET_INFO:
1519        case AR6000_XIOCTL_CHECK_TARGET_READY: /* backwards compatibility */
1520        {
1521            /* If we made it to here, then the Target exists and is ready. */
1522
1523            if (cmd == AR6000_XIOCTL_TARGET_INFO) {
1524                if (copy_to_user((A_UINT32 *)rq->ifr_data, &ar->arVersion.target_ver,
1525                                 sizeof(ar->arVersion.target_ver)))
1526                {
1527                    ret = -EFAULT;
1528                }
1529                if (copy_to_user(((A_UINT32 *)rq->ifr_data)+1, &ar->arTargetType,
1530                                 sizeof(ar->arTargetType)))
1531                {
1532                    ret = -EFAULT;
1533                }
1534            }
1535            break;
1536        }
1537        case AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS:
1538        {
1539            WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD hbparam;
1540
1541            if (copy_from_user(&hbparam, userdata, sizeof(hbparam)))
1542            {
1543                ret = -EFAULT;
1544            } else {
1545                AR6000_SPIN_LOCK(&ar->arLock, 0);
1546                /* Start a cyclic timer with the parameters provided. */
1547                if (hbparam.frequency) {
1548                    ar->arHBChallengeResp.frequency = hbparam.frequency;
1549                }
1550                if (hbparam.threshold) {
1551                    ar->arHBChallengeResp.missThres = hbparam.threshold;
1552                }
1553
1554                /* Delete the pending timer and start a new one */
1555                if (timer_pending(&ar->arHBChallengeResp.timer)) {
1556                    A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
1557                }
1558                A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
1559                AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1560            }
1561            break;
1562        }
1563        case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
1564        {
1565            A_UINT32 cookie;
1566
1567            if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
1568                return -EFAULT;
1569            }
1570
1571            /* Send the challenge on the control channel */
1572            if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != A_OK) {
1573                return -EIO;
1574            }
1575            break;
1576        }
1577#ifdef USER_KEYS
1578        case AR6000_XIOCTL_USER_SETKEYS:
1579        {
1580
1581            ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_RUN;
1582
1583            if (copy_from_user(&ar->user_key_ctrl, userdata,
1584                               sizeof(ar->user_key_ctrl)))
1585            {
1586                return -EFAULT;
1587            }
1588
1589            A_PRINTF("ar6000 USER set key %x\n", ar->user_key_ctrl);
1590            break;
1591        }
1592#endif /* USER_KEYS */
1593
1594#ifdef CONFIG_HOST_GPIO_SUPPORT
1595        case AR6000_XIOCTL_GPIO_OUTPUT_SET:
1596        {
1597            struct ar6000_gpio_output_set_cmd_s gpio_output_set_cmd;
1598
1599            if (ar->arWmiReady == FALSE) {
1600                return -EIO;
1601            }
1602            if (down_interruptible(&ar->arSem)) {
1603                return -ERESTARTSYS;
1604            }
1605
1606            if (copy_from_user(&gpio_output_set_cmd, userdata,
1607                                sizeof(gpio_output_set_cmd)))
1608            {
1609                ret = -EFAULT;
1610            } else {
1611                ret = ar6000_gpio_output_set(dev,
1612                                             gpio_output_set_cmd.set_mask,
1613                                             gpio_output_set_cmd.clear_mask,
1614                                             gpio_output_set_cmd.enable_mask,
1615                                             gpio_output_set_cmd.disable_mask);
1616                if (ret != A_OK) {
1617                    ret = EIO;
1618                }
1619            }
1620            up(&ar->arSem);
1621            break;
1622        }
1623        case AR6000_XIOCTL_GPIO_INPUT_GET:
1624        {
1625            if (ar->arWmiReady == FALSE) {
1626                return -EIO;
1627            }
1628            if (down_interruptible(&ar->arSem)) {
1629                return -ERESTARTSYS;
1630            }
1631
1632            ret = ar6000_gpio_input_get(dev);
1633            if (ret != A_OK) {
1634                up(&ar->arSem);
1635                return -EIO;
1636            }
1637
1638            /* Wait for Target to respond. */
1639            wait_event_interruptible(arEvent, gpio_data_available);
1640            if (signal_pending(current)) {
1641                ret = -EINTR;
1642            } else {
1643                A_ASSERT(gpio_reg_results.gpioreg_id == GPIO_ID_NONE);
1644
1645                if (copy_to_user(userdata, &gpio_reg_results.value,
1646                                 sizeof(gpio_reg_results.value)))
1647                {
1648                    ret = -EFAULT;
1649                }
1650            }
1651            up(&ar->arSem);
1652            break;
1653        }
1654        case AR6000_XIOCTL_GPIO_REGISTER_SET:
1655        {
1656            struct ar6000_gpio_register_cmd_s gpio_register_cmd;
1657
1658            if (ar->arWmiReady == FALSE) {
1659                return -EIO;
1660            }
1661            if (down_interruptible(&ar->arSem)) {
1662                return -ERESTARTSYS;
1663            }
1664
1665            if (copy_from_user(&gpio_register_cmd, userdata,
1666                                sizeof(gpio_register_cmd)))
1667            {
1668                ret = -EFAULT;
1669            } else {
1670                ret = ar6000_gpio_register_set(dev,
1671                                               gpio_register_cmd.gpioreg_id,
1672                                               gpio_register_cmd.value);
1673                if (ret != A_OK) {
1674                    ret = EIO;
1675                }
1676
1677                /* Wait for acknowledgement from Target */
1678                wait_event_interruptible(arEvent, gpio_ack_received);
1679                if (signal_pending(current)) {
1680                    ret = -EINTR;
1681                }
1682            }
1683            up(&ar->arSem);
1684            break;
1685        }
1686        case AR6000_XIOCTL_GPIO_REGISTER_GET:
1687        {
1688            struct ar6000_gpio_register_cmd_s gpio_register_cmd;
1689
1690            if (ar->arWmiReady == FALSE) {
1691                return -EIO;
1692            }
1693            if (down_interruptible(&ar->arSem)) {
1694                return -ERESTARTSYS;
1695            }
1696
1697            if (copy_from_user(&gpio_register_cmd, userdata,
1698                                sizeof(gpio_register_cmd)))
1699            {
1700                ret = -EFAULT;
1701            } else {
1702                ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
1703                if (ret != A_OK) {
1704                    up(&ar->arSem);
1705                    return -EIO;
1706                }
1707
1708                /* Wait for Target to respond. */
1709                wait_event_interruptible(arEvent, gpio_data_available);
1710                if (signal_pending(current)) {
1711                    ret = -EINTR;
1712                } else {
1713                    A_ASSERT(gpio_register_cmd.gpioreg_id == gpio_reg_results.gpioreg_id);
1714                    if (copy_to_user(userdata, &gpio_reg_results,
1715                                     sizeof(gpio_reg_results)))
1716                    {
1717                        ret = -EFAULT;
1718                    }
1719                }
1720            }
1721            up(&ar->arSem);
1722            break;
1723        }
1724        case AR6000_XIOCTL_GPIO_INTR_ACK:
1725        {
1726            struct ar6000_gpio_intr_ack_cmd_s gpio_intr_ack_cmd;
1727
1728            if (ar->arWmiReady == FALSE) {
1729                return -EIO;
1730            }
1731            if (down_interruptible(&ar->arSem)) {
1732                return -ERESTARTSYS;
1733            }
1734
1735            if (copy_from_user(&gpio_intr_ack_cmd, userdata,
1736                                sizeof(gpio_intr_ack_cmd)))
1737            {
1738                ret = -EFAULT;
1739            } else {
1740                ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
1741                if (ret != A_OK) {
1742                    ret = EIO;
1743                }
1744            }
1745            up(&ar->arSem);
1746            break;
1747        }
1748        case AR6000_XIOCTL_GPIO_INTR_WAIT:
1749        {
1750            /* Wait for Target to report an interrupt. */
1751            dev_hold(dev);
1752            rtnl_unlock();
1753            wait_event_interruptible(arEvent, gpio_intr_available);
1754            rtnl_lock();
1755            __dev_put(dev);
1756
1757            if (signal_pending(current)) {
1758                ret = -EINTR;
1759            } else {
1760                if (copy_to_user(userdata, &gpio_intr_results,
1761                                 sizeof(gpio_intr_results)))
1762                {
1763                    ret = -EFAULT;
1764                }
1765            }
1766            break;
1767        }
1768#endif /* CONFIG_HOST_GPIO_SUPPORT */
1769
1770        case AR6000_XIOCTL_DBGLOG_CFG_MODULE:
1771        {
1772            struct ar6000_dbglog_module_config_s config;
1773
1774            if (copy_from_user(&config, userdata, sizeof(config))) {
1775                return -EFAULT;
1776            }
1777
1778            /* Send the challenge on the control channel */
1779            if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask,
1780                                            config.tsr, config.rep,
1781                                            config.size, config.valid) != A_OK)
1782            {
1783                return -EIO;
1784            }
1785            break;
1786        }
1787
1788        case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
1789        {
1790            /* Send the challenge on the control channel */
1791            if (ar6000_dbglog_get_debug_logs(ar) != A_OK)
1792            {
1793                return -EIO;
1794            }
1795            break;
1796        }
1797
1798        case AR6000_XIOCTL_SET_ADHOC_BSSID:
1799        {
1800            WMI_SET_ADHOC_BSSID_CMD adhocBssid;
1801
1802            if (ar->arWmiReady == FALSE) {
1803                ret = -EIO;
1804            } else if (copy_from_user(&adhocBssid, userdata,
1805                                      sizeof(adhocBssid)))
1806            {
1807                ret = -EFAULT;
1808            } else if (A_MEMCMP(adhocBssid.bssid, bcast_mac,
1809                                AR6000_ETH_ADDR_LEN) == 0)
1810            {
1811                ret = -EFAULT;
1812            } else {
1813
1814                A_MEMCPY(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
1815        }
1816            break;
1817        }
1818
1819        case AR6000_XIOCTL_SET_OPT_MODE:
1820        {
1821        WMI_SET_OPT_MODE_CMD optModeCmd;
1822            AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1823
1824            if (ar->arWmiReady == FALSE) {
1825                ret = -EIO;
1826            } else if (copy_from_user(&optModeCmd, userdata,
1827                                      sizeof(optModeCmd)))
1828            {
1829                ret = -EFAULT;
1830            } else if (ar->arConnected && optModeCmd.optMode == SPECIAL_ON) {
1831                ret = -EFAULT;
1832
1833            } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
1834                       != A_OK)
1835            {
1836                ret = -EIO;
1837            }
1838            break;
1839        }
1840
1841        case AR6000_XIOCTL_OPT_SEND_FRAME:
1842        {
1843        WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
1844            A_UINT8 data[MAX_OPT_DATA_LEN];
1845
1846            if (ar->arWmiReady == FALSE) {
1847                ret = -EIO;
1848            } else if (copy_from_user(&optTxFrmCmd, userdata,
1849                                      sizeof(optTxFrmCmd)))
1850            {
1851                ret = -EFAULT;
1852            } else if (copy_from_user(data,
1853                                      userdata+sizeof(WMI_OPT_TX_FRAME_CMD)-1,
1854                                      optTxFrmCmd.optIEDataLen))
1855            {
1856                ret = -EFAULT;
1857            } else {
1858                ret = wmi_opt_tx_frame_cmd(ar->arWmi,
1859                                           optTxFrmCmd.frmType,
1860                                           optTxFrmCmd.dstAddr,
1861                                           optTxFrmCmd.bssid,
1862                                           optTxFrmCmd.optIEDataLen,
1863                                           data);
1864            }
1865
1866            break;
1867        }
1868        case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
1869        {
1870            WMI_SET_RETRY_LIMITS_CMD setRetryParams;
1871
1872            if (ar->arWmiReady == FALSE) {
1873                ret = -EIO;
1874            } else if (copy_from_user(&setRetryParams, userdata,
1875                                      sizeof(setRetryParams)))
1876            {
1877                ret = -EFAULT;
1878            } else {
1879                if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
1880                                          setRetryParams.trafficClass,
1881                                          setRetryParams.maxRetries,
1882                                          setRetryParams.enableNotify) != A_OK)
1883                {
1884                    ret = -EIO;
1885                }
1886                AR6000_SPIN_LOCK(&ar->arLock, 0);
1887                ar->arMaxRetries = setRetryParams.maxRetries;
1888                AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1889            }
1890            break;
1891        }
1892
1893        case AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL:
1894        {
1895            WMI_BEACON_INT_CMD bIntvlCmd;
1896
1897            if (ar->arWmiReady == FALSE) {
1898                ret = -EIO;
1899            } else if (copy_from_user(&bIntvlCmd, userdata,
1900                       sizeof(bIntvlCmd)))
1901            {
1902                ret = -EFAULT;
1903            } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
1904                        != A_OK)
1905            {
1906                ret = -EIO;
1907            }
1908            break;
1909        }
1910        case IEEE80211_IOCTL_SETAUTHALG:
1911        {
1912            AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1913            struct ieee80211req_authalg req;
1914
1915            if (ar->arWmiReady == FALSE) {
1916                ret = -EIO;
1917            } else if (copy_from_user(&req, userdata,
1918                       sizeof(struct ieee80211req_authalg)))
1919            {
1920                ret = -EFAULT;
1921            } else if (req.auth_alg == AUTH_ALG_OPEN_SYSTEM) {
1922                ar->arDot11AuthMode = OPEN_AUTH;
1923                ar->arPairwiseCrypto = NONE_CRYPT;
1924                ar->arGroupCrypto = NONE_CRYPT;
1925            } else if (req.auth_alg == AUTH_ALG_LEAP) {
1926                ar->arDot11AuthMode = LEAP_AUTH;
1927            } else {
1928                ret = -EIO;
1929            }
1930            break;
1931        }
1932
1933        case AR6000_XIOCTL_SET_VOICE_PKT_SIZE:
1934            ret = ar6000_xioctl_set_voice_pkt_size(dev, userdata);
1935            break;
1936
1937        case AR6000_XIOCTL_SET_MAX_SP:
1938            ret = ar6000_xioctl_set_max_sp_len(dev, userdata);
1939            break;
1940
1941        case AR6000_XIOCTL_WMI_GET_ROAM_TBL:
1942            ret = ar6000_ioctl_get_roam_tbl(dev, rq);
1943            break;
1944        case AR6000_XIOCTL_WMI_SET_ROAM_CTRL:
1945            ret = ar6000_ioctl_set_roam_ctrl(dev, userdata);
1946            break;
1947        case AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS:
1948            ret = ar6000_ioctl_set_powersave_timers(dev, userdata);
1949            break;
1950        case AR6000_XIOCTRL_WMI_GET_POWER_MODE:
1951            ret = ar6000_ioctl_get_power_mode(dev, rq);
1952            break;
1953        case AR6000_XIOCTRL_WMI_SET_WLAN_STATE:
1954            get_user(ar->arWlanState, (unsigned int *)userdata);
1955            if (ar->arWmiReady == FALSE) {
1956                ret = -EIO;
1957                break;
1958            }
1959
1960            if (ar->arWlanState == WLAN_ENABLED) {
1961                /* Enable foreground scanning */
1962                if (wmi_scanparams_cmd(ar->arWmi, scParams.fg_start_period,
1963                                       scParams.fg_end_period,
1964                                       scParams.bg_period,
1965                                       scParams.minact_chdwell_time,
1966                                       scParams.maxact_chdwell_time,
1967                                       scParams.pas_chdwell_time,
1968                                       scParams.shortScanRatio,
1969                                       scParams.scanCtrlFlags,
1970                                       scParams.max_dfsch_act_time) != A_OK)
1971                {
1972                    ret = -EIO;
1973                }
1974                if (ar->arSsidLen) {
1975                    ar->arConnectPending = TRUE;
1976                    if (wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
1977                                        ar->arDot11AuthMode, ar->arAuthMode,
1978                                        ar->arPairwiseCrypto,
1979                                        ar->arPairwiseCryptoLen,
1980                                        ar->arGroupCrypto, ar->arGroupCryptoLen,
1981                                        ar->arSsidLen, ar->arSsid,
1982                                        ar->arReqBssid, ar->arChannelHint,
1983                                        ar->arConnectCtrlFlags) != A_OK)
1984                    {
1985                        ret = -EIO;
1986                        ar->arConnectPending = FALSE;
1987                    }
1988                }
1989            } else {
1990                /* Disconnect from the AP and disable foreground scanning */
1991                AR6000_SPIN_LOCK(&ar->arLock, 0);
1992                if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
1993                    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1994                    wmi_disconnect_cmd(ar->arWmi);
1995                } else {
1996                    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1997                }
1998
1999                if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0xFF, 0) != A_OK)
2000                {
2001                    ret = -EIO;
2002                }
2003            }
2004            break;
2005        case AR6000_XIOCTL_WMI_GET_ROAM_DATA:
2006            ret = ar6000_ioctl_get_roam_data(dev, rq);
2007            break;
2008        case AR6000_XIOCTL_WMI_SET_BT_STATUS:
2009            ret = ar6000_xioctl_set_bt_status_cmd(dev, userdata);
2010            break;
2011        case AR6000_XIOCTL_WMI_SET_BT_PARAMS:
2012            ret = ar6000_xioctl_set_bt_params_cmd(dev, userdata);
2013            break;
2014        case AR6000_XIOCTL_WMI_STARTSCAN:
2015        {
2016            WMI_START_SCAN_CMD setStartScanCmd;
2017
2018            if (ar->arWmiReady == FALSE) {
2019                    ret = -EIO;
2020                } else if (copy_from_user(&setStartScanCmd, userdata,
2021                                          sizeof(setStartScanCmd)))
2022                {
2023                    ret = -EFAULT;
2024                } else {
2025                    if (wmi_startscan_cmd(ar->arWmi, setStartScanCmd.scanType,
2026                                    setStartScanCmd.forceFgScan,
2027                                    setStartScanCmd.isLegacy,
2028                                    setStartScanCmd.homeDwellTime,
2029                                    setStartScanCmd.forceScanInterval) != A_OK)
2030                    {
2031                        ret = -EIO;
2032                    }
2033                }
2034            break;
2035        }
2036        case AR6000_XIOCTL_WMI_SETFIXRATES:
2037        {
2038            WMI_FIX_RATES_CMD setFixRatesCmd;
2039            A_STATUS returnStatus;
2040
2041            if (ar->arWmiReady == FALSE) {
2042                    ret = -EIO;
2043                } else if (copy_from_user(&setFixRatesCmd, userdata,
2044                                          sizeof(setFixRatesCmd)))
2045                {
2046                    ret = -EFAULT;
2047                } else {
2048                    returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
2049                    if (returnStatus == A_EINVAL)
2050                    {
2051                        ret = -EINVAL;
2052                    }
2053                    else if(returnStatus != A_OK) {
2054                        ret = -EIO;
2055                    }
2056                }
2057            break;
2058        }
2059
2060        case AR6000_XIOCTL_WMI_GETFIXRATES:
2061        {
2062            WMI_FIX_RATES_CMD getFixRatesCmd;
2063            AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
2064            int ret = 0;
2065
2066            if (ar->arWmiReady == FALSE) {
2067                return -EIO;
2068            }
2069
2070            if (down_interruptible(&ar->arSem)) {
2071                return -ERESTARTSYS;
2072            }
2073            /* Used copy_from_user/copy_to_user to access user space data */
2074            if (copy_from_user(&getFixRatesCmd, userdata, sizeof(getFixRatesCmd))) {
2075                ret = -EFAULT;
2076            } else {
2077                ar->arRateMask = 0xFFFF;
2078
2079                if (wmi_get_ratemask_cmd(ar->arWmi) != A_OK) {
2080                    up(&ar->arSem);
2081                    return -EIO;
2082                }
2083
2084                wait_event_interruptible_timeout(arEvent, ar->arRateMask != 0xFFFF, wmitimeout * HZ);
2085
2086                if (signal_pending(current)) {
2087                    ret = -EINTR;
2088                }
2089
2090                if (!ret) {
2091                    getFixRatesCmd.fixRateMask = ar->arRateMask;
2092                }
2093
2094                if(copy_to_user(userdata, &getFixRatesCmd, sizeof(getFixRatesCmd))) {
2095                   ret = -EFAULT;
2096                }
2097
2098                up(&ar->arSem);
2099            }
2100            break;
2101        }
2102        case AR6000_XIOCTL_WMI_SET_AUTHMODE:
2103        {
2104            WMI_SET_AUTH_MODE_CMD setAuthMode;
2105
2106            if (ar->arWmiReady == FALSE) {
2107                ret = -EIO;
2108            } else if (copy_from_user(&setAuthMode, userdata,
2109                                      sizeof(setAuthMode)))
2110            {
2111                ret = -EFAULT;
2112            } else {
2113                if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != A_OK)
2114                {
2115                    ret = -EIO;
2116                }
2117            }
2118            break;
2119        }
2120        case AR6000_XIOCTL_WMI_SET_REASSOCMODE:
2121        {
2122            WMI_SET_REASSOC_MODE_CMD setReassocMode;
2123
2124            if (ar->arWmiReady == FALSE) {
2125                ret = -EIO;
2126            } else if (copy_from_user(&setReassocMode, userdata,
2127                                      sizeof(setReassocMode)))
2128            {
2129                ret = -EFAULT;
2130            } else {
2131                if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != A_OK)
2132                {
2133                    ret = -EIO;
2134                }
2135            }
2136            break;
2137        }
2138        case AR6000_XIOCTL_DIAG_READ:
2139        {
2140            A_UINT32 addr, data;
2141            get_user(addr, (unsigned int *)userdata);
2142            if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
2143                ret = -EIO;
2144            }
2145            put_user(data, (unsigned int *)userdata + 1);
2146            break;
2147        }
2148        case AR6000_XIOCTL_DIAG_WRITE:
2149        {
2150            A_UINT32 addr, data;
2151            get_user(addr, (unsigned int *)userdata);
2152            get_user(data, (unsigned int *)userdata + 1);
2153            if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
2154                ret = -EIO;
2155            }
2156            break;
2157        }
2158        case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
2159        {
2160             WMI_SET_KEEPALIVE_CMD setKeepAlive;
2161             if (ar->arWmiReady == FALSE) {
2162                 return -EIO;
2163             } else if (copy_from_user(&setKeepAlive, userdata,
2164                        sizeof(setKeepAlive))){
2165                 ret = -EFAULT;
2166             } else {
2167                 if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != A_OK) {
2168                     ret = -EIO;
2169               }
2170             }
2171             break;
2172        }
2173        case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
2174        {
2175            AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
2176            WMI_GET_KEEPALIVE_CMD getKeepAlive;
2177            int ret = 0;
2178            if (ar->arWmiReady == FALSE) {
2179               return -EIO;
2180            }
2181            if (down_interruptible(&ar->arSem)) {
2182                return -ERESTARTSYS;
2183            }
2184            if (copy_from_user(&getKeepAlive, userdata,sizeof(getKeepAlive))) {
2185               ret = -EFAULT;
2186            } else {
2187            getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
2188            ar->arKeepaliveConfigured = 0xFF;
2189            if (wmi_get_keepalive_configured(ar->arWmi) != A_OK){
2190                up(&ar->arSem);
2191                return -EIO;
2192            }
2193            wait_event_interruptible_timeout(arEvent, ar->arKeepaliveConfigured != 0xFF, wmitimeout * HZ);
2194            if (signal_pending(current)) {
2195                ret = -EINTR;
2196            }
2197
2198            if (!ret) {
2199                getKeepAlive.configured = ar->arKeepaliveConfigured;
2200            }
2201            if (copy_to_user(userdata, &getKeepAlive, sizeof(getKeepAlive))) {
2202               ret = -EFAULT;
2203            }
2204            up(&ar->arSem);
2205            }
2206            break;
2207        }
2208        case AR6000_XIOCTL_WMI_SET_APPIE:
2209        {
2210            WMI_SET_APPIE_CMD appIEcmd;
2211            A_UINT8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
2212            A_UINT32 fType,ieLen;
2213
2214        if (ar->arWmiReady == FALSE) {
2215            return -EIO;
2216        }
2217        get_user(fType, (A_UINT32 *)userdata);
2218        appIEcmd.mgmtFrmType = fType;
2219        if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
2220            ret = -EIO;
2221        } else {
2222            get_user(ieLen, (A_UINT32 *)(userdata + 4));
2223            appIEcmd.ieLen = ieLen;
2224            if (appIEcmd.ieLen > IEEE80211_APPIE_FRAME_MAX_LEN) {
2225                ret = -EIO;
2226                break;
2227            }
2228            if (copy_from_user(appIeInfo, userdata + 8, appIEcmd.ieLen)) {
2229                ret = -EFAULT;
2230            } else {
2231                if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
2232                          appIEcmd.ieLen, appIeInfo) != A_OK)
2233                {
2234                    ret = -EIO;
2235                }
2236            }
2237            }
2238            break;
2239        }
2240        case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
2241        {
2242            WMI_BSS_FILTER_CMD cmd;
2243            A_UINT32 filterType;
2244
2245            if (copy_from_user(&filterType, userdata, sizeof(A_UINT32)))
2246            {
2247                return -EFAULT;
2248            }
2249            if (filterType & (IEEE80211_FILTER_TYPE_BEACON |
2250                                    IEEE80211_FILTER_TYPE_PROBE_RESP))
2251            {
2252                cmd.bssFilter = ALL_BSS_FILTER;
2253            } else {
2254                cmd.bssFilter = NONE_BSS_FILTER;
2255            }
2256            if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != A_OK) {
2257                ret = -EIO;
2258            }
2259
2260            AR6000_SPIN_LOCK(&ar->arLock, 0);
2261            ar->arMgmtFilter = filterType;
2262            AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2263            break;
2264        }
2265        case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
2266        {
2267            A_UINT32 wsc_status;
2268
2269            if (copy_from_user(&wsc_status, userdata, sizeof(A_UINT32)))
2270            {
2271                return -EFAULT;
2272            }
2273            if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != A_OK) {
2274                ret = -EIO;
2275            }
2276            break;
2277        }
2278        case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
2279        {
2280            A_UINT32 ROM_addr;
2281            A_UINT32 RAM_addr;
2282            A_UINT32 nbytes;
2283            A_UINT32 do_activate;
2284            A_UINT32 rompatch_id;
2285
2286            get_user(ROM_addr, (A_UINT32 *)userdata);
2287            get_user(RAM_addr, (A_UINT32 *)userdata + 1);
2288            get_user(nbytes, (A_UINT32 *)userdata + 2);
2289            get_user(do_activate, (A_UINT32 *)userdata + 3);
2290            AR_DEBUG_PRINTF("Install rompatch from ROM: 0x%x to RAM: 0x%x length: %d\n",
2291                             ROM_addr, RAM_addr, nbytes);
2292            ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr,
2293                                        nbytes, do_activate, &rompatch_id);
2294            if (ret == A_OK) {
2295                put_user(rompatch_id, (unsigned int *)rq->ifr_data); /* return value */
2296            }
2297            break;
2298        }
2299
2300        case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
2301        {
2302            A_UINT32 rompatch_id;
2303
2304            get_user(rompatch_id, (A_UINT32 *)userdata);
2305            AR_DEBUG_PRINTF("UNinstall rompatch_id %d\n", rompatch_id);
2306            ret = BMIrompatchUninstall(hifDevice, rompatch_id);
2307            break;
2308        }
2309
2310        case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
2311        case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
2312        {
2313            A_UINT32 rompatch_count;
2314
2315            get_user(rompatch_count, (A_UINT32 *)userdata);
2316            AR_DEBUG_PRINTF("Change rompatch activation count=%d\n", rompatch_count);
2317            length = sizeof(A_UINT32) * rompatch_count;
2318            if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2319                A_MEMZERO(buffer, length);
2320                if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length))
2321                {
2322                    ret = -EFAULT;
2323                } else {
2324                    if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
2325                        ret = BMIrompatchActivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
2326                    } else {
2327                        ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
2328                    }
2329                }
2330                A_FREE(buffer);
2331            } else {
2332                ret = -ENOMEM;
2333            }
2334
2335            break;
2336        }
2337
2338        case AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE:
2339        {
2340            WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
2341
2342            if (ar->arWmiReady == FALSE) {
2343                ret = -EIO;
2344            } else if (copy_from_user(&setHostSleepMode, userdata,
2345                                      sizeof(setHostSleepMode)))
2346            {
2347                ret = -EFAULT;
2348            } else {
2349                if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
2350                                &setHostSleepMode) != A_OK)
2351                {
2352                    ret = -EIO;
2353                }
2354            }
2355            break;
2356        }
2357        case AR6000_XIOCTL_WMI_SET_WOW_MODE:
2358        {
2359            WMI_SET_WOW_MODE_CMD setWowMode;
2360
2361            if (ar->arWmiReady == FALSE) {
2362                ret = -EIO;
2363            } else if (copy_from_user(&setWowMode, userdata,
2364                                      sizeof(setWowMode)))
2365            {
2366                ret = -EFAULT;
2367            } else {
2368                if (wmi_set_wow_mode_cmd(ar->arWmi,
2369                                &setWowMode) != A_OK)
2370                {
2371                    ret = -EIO;
2372                }
2373            }
2374            break;
2375        }
2376        case AR6000_XIOCTL_WMI_GET_WOW_LIST:
2377        {
2378            WMI_GET_WOW_LIST_CMD getWowList;
2379
2380            if (ar->arWmiReady == FALSE) {
2381                ret = -EIO;
2382            } else if (copy_from_user(&getWowList, userdata,
2383                                      sizeof(getWowList)))
2384            {
2385                ret = -EFAULT;
2386            } else {
2387                if (wmi_get_wow_list_cmd(ar->arWmi,
2388                                &getWowList) != A_OK)
2389                {
2390                    ret = -EIO;
2391                }
2392            }
2393            break;
2394        }
2395        case AR6000_XIOCTL_WMI_ADD_WOW_PATTERN:
2396        {
2397#define WOW_PATTERN_SIZE 64
2398#define WOW_MASK_SIZE 64
2399
2400            WMI_ADD_WOW_PATTERN_CMD cmd;
2401            A_UINT8 mask_data[WOW_PATTERN_SIZE]={0};
2402            A_UINT8 pattern_data[WOW_PATTERN_SIZE]={0};
2403
2404            if (ar->arWmiReady == FALSE) {
2405                ret = -EIO;
2406            } else {
2407
2408                if(copy_from_user(&cmd, userdata,
2409                            sizeof(WMI_ADD_WOW_PATTERN_CMD)))
2410                      return -EFAULT;
2411                if (copy_from_user(pattern_data,
2412                                      userdata + 3,
2413                                      cmd.filter_size)){
2414                        ret = -EFAULT;
2415                        break;
2416                }
2417                if (copy_from_user(mask_data,
2418                                      (userdata + 3 + cmd.filter_size),
2419                                      cmd.filter_size)){
2420                        ret = -EFAULT;
2421                        break;
2422                } else {
2423                    if (wmi_add_wow_pattern_cmd(ar->arWmi,
2424                                &cmd, pattern_data, mask_data, cmd.filter_size) != A_OK){
2425                        ret = -EIO;
2426                    }
2427                }
2428            }
2429#undef WOW_PATTERN_SIZE
2430#undef WOW_MASK_SIZE
2431            break;
2432        }
2433        case AR6000_XIOCTL_WMI_DEL_WOW_PATTERN:
2434        {
2435            WMI_DEL_WOW_PATTERN_CMD delWowPattern;
2436
2437            if (ar->arWmiReady == FALSE) {
2438                ret = -EIO;
2439            } else if (copy_from_user(&delWowPattern, userdata,
2440                                      sizeof(delWowPattern)))
2441            {
2442                ret = -EFAULT;
2443            } else {
2444                if (wmi_del_wow_pattern_cmd(ar->arWmi,
2445                                &delWowPattern) != A_OK)
2446                {
2447                    ret = -EIO;
2448                }
2449            }
2450            break;
2451        }
2452        case AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE:
2453            if (ar->arHtcTarget != NULL) {
2454                HTCDumpCreditStates(ar->arHtcTarget);
2455            }
2456            break;
2457        case AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE:
2458            if (ar->arHtcTarget != NULL) {
2459                struct ar6000_traffic_activity_change data;
2460
2461                if (copy_from_user(&data, userdata, sizeof(data)))
2462                {
2463                    return -EFAULT;
2464                }
2465                    /* note, this is used for testing (mbox ping testing), indicate activity
2466                     * change using the stream ID as the traffic class */
2467                ar6000_indicate_tx_activity(ar,
2468                                            (A_UINT8)data.StreamID,
2469                                            data.Active ? TRUE : FALSE);
2470            }
2471            break;
2472        case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
2473            if (ar->arWmiReady == FALSE) {
2474                ret = -EIO;
2475            } else if (copy_from_user(&connectCtrlFlags, userdata,
2476                                      sizeof(connectCtrlFlags)))
2477            {
2478                ret = -EFAULT;
2479            } else {
2480                ar->arConnectCtrlFlags = connectCtrlFlags;
2481            }
2482            break;
2483        case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
2484            if (ar->arWmiReady == FALSE) {
2485                ret = -EIO;
2486            } else if (copy_from_user(&akmpParams, userdata,
2487                                      sizeof(WMI_SET_AKMP_PARAMS_CMD)))
2488            {
2489                ret = -EFAULT;
2490            } else {
2491                if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != A_OK) {
2492                    ret = -EIO;
2493                }
2494            }
2495            break;
2496        case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
2497            if (ar->arWmiReady == FALSE) {
2498                ret = -EIO;
2499            } else {
2500                if (copy_from_user(&pmkidInfo.numPMKID, userdata,
2501                                      sizeof(pmkidInfo.numPMKID)))
2502                {
2503                    ret = -EFAULT;
2504                    break;
2505                }
2506                if (copy_from_user(&pmkidInfo.pmkidList,
2507                                   userdata + sizeof(pmkidInfo.numPMKID),
2508                                   pmkidInfo.numPMKID * sizeof(WMI_PMKID)))
2509                {
2510                    ret = -EFAULT;
2511                    break;
2512                }
2513                if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != A_OK) {
2514                    ret = -EIO;
2515                }
2516            }
2517            break;
2518        case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
2519            if (ar->arWmiReady == FALSE) {
2520                ret = -EIO;
2521            } else {
2522                if (wmi_get_pmkid_list_cmd(ar->arWmi) != A_OK) {
2523                    ret = -EIO;
2524                }
2525            }
2526            break;
2527        default:
2528            ret = -EOPNOTSUPP;
2529    }
2530    return ret;
2531}
2532
2533

Archive Download this file



interactive