[s3c24xx] ar6000: use net_device_ops
[openwrt/svn-archive/archive.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 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