Add ar6000 wireless driver.
[kernel.git] / 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 bypasswmi;
29
30 static int
31 ar6000_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
46 static int
47 ar6000_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
65 static int
66 ar6000_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
98 static int
99 ar6000_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
124 static int
125 ar6000_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
165 static int
166 ar6000_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
200 static int
201 ar6000_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 */
219 static int
220 ar6000_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
239 static int
240 ar6000_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
289 static int
290 ar6000_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
312 static int
313 ar6000_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
391 static int
392 ar6000_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
415 static int
416 ar6000_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
439 static int
440 ar6000_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
475 static int
476 ar6000_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
508 static int
509 ar6000_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
538 static int
539 ar6000_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
565 static A_STATUS
566 ar6000_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
603 void
604 ar6000_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
617 static int
618 ar6000_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
637 static int
638 ar6000_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
653 static int
654 ar6000_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
697 static int
698 ar6000_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
723 static int
724 ar6000_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
748 static int
749 ar6000_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
774 static int
775 ar6000_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
800 static int
801 ar6000_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
825 static int
826 ar6000_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
851 struct ar6000_gpio_intr_wait_cmd_s  gpio_intr_results;
852 /* gpio_reg_results and gpio_data_available are protected by arSem */
853 static struct ar6000_gpio_register_cmd_s gpio_reg_results;
854 static A_BOOL gpio_data_available; /* Requested GPIO data available */
855 static A_BOOL gpio_intr_available; /* GPIO interrupt info available */
856 static A_BOOL gpio_ack_received;   /* GPIO ack was received */
857
858 /* Host-side initialization for General Purpose I/O support */
859 void 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  */
871 void
872 ar6000_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  */
885 void
886 ar6000_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  */
899 void
900 ar6000_gpio_ack_rx(void)
901 {
902     gpio_ack_received = TRUE;
903     wake_up(&arEvent);
904 }
905
906 A_STATUS
907 ar6000_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
920 static A_STATUS
921 ar6000_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
929 static A_STATUS
930 ar6000_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
940 static A_STATUS
941 ar6000_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
950 static A_STATUS
951 ar6000_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
961 int 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