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