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