Original 0.2.0pre8_plus_fixes_8 tarball
[acx-mac80211.git] / src / acx100_ioctl.c
blob15a29b85c2b6a000f4f06d70b1897d8cc081e57f
1 /* src/acx100_ioctl.c - all the ioctl calls
3 * --------------------------------------------------------------------
5 * Copyright (C) 2003 ACX100 Open Source Project
7 * The contents of this file are subject to the Mozilla Public
8 * License Version 1.1 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS
13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * Alternatively, the contents of this file may be used under the
18 * terms of the GNU Public License version 2 (the "GPL"), in which
19 * case the provisions of the GPL are applicable instead of the
20 * above. If you wish to allow the use of your version of this file
21 * only under the terms of the GPL and not to allow others to use
22 * your version of this file under the MPL, indicate your decision
23 * by deleting the provisions above and replace them with the notice
24 * and other provisions required by the GPL. If you do not delete
25 * the provisions above, a recipient may use your version of this
26 * file under either the MPL or the GPL.
28 * --------------------------------------------------------------------
30 * Inquiries regarding the ACX100 Open Source Project can be
31 * made directly to:
33 * acx100-users@lists.sf.net
34 * http://acx100.sf.net
36 * --------------------------------------------------------------------
39 #ifdef S_SPLINT_S /* some crap that splint needs to not crap out */
40 #define __signed__ signed
41 #define __u64 unsigned long long
42 #define u64 unsigned long long
43 #define loff_t unsigned long
44 #define sigval_t unsigned long
45 #define siginfo_t unsigned long
46 #define stack_t unsigned long
47 #define __s64 signed long long
48 #endif
49 #include <linux/config.h>
50 #include <linux/version.h>
51 #include <linux/kernel.h>
52 #include <linux/types.h>
54 #include <linux/if_arp.h>
55 #include <linux/wireless.h>
56 #if WIRELESS_EXT > 12
57 #include <net/iw_handler.h>
58 #endif /* WE > 12 */
59 #include <asm/uaccess.h>
61 /*================================================================*/
62 /* Project Includes */
64 #include <p80211mgmt.h>
65 #include <acx100.h>
66 #include <acx100_helper.h>
67 #include <acx100_helper2.h>
68 #include <ihw.h>
69 #include <idma.h>
71 /* About the locking:
72 * I only locked the device whenever calls to the hardware are made or
73 * parts of the wlandevice struct are modified, otherwise no locking is
74 * performed. I don't now if this is safe, we'll see.
77 extern UINT8 acx_signal_determine_quality(UINT8 signal, UINT8 noise);
80 /* if you plan to reorder something, make sure to reorder all other places
81 * accordingly! */
82 #define ACX100_IOCTL SIOCIWFIRSTPRIV
83 #define ACX100_IOCTL_DEBUG ACX100_IOCTL + 0x00
84 #define ACX100_IOCTL_LIST_DOM ACX100_IOCTL + 0x01
85 #define ACX100_IOCTL_SET_DOM ACX100_IOCTL + 0x02
86 #define ACX100_IOCTL_GET_DOM ACX100_IOCTL + 0x03
87 #define ACX100_IOCTL_SET_PREAMB ACX100_IOCTL + 0x04
88 #define ACX100_IOCTL_GET_PREAMB ACX100_IOCTL + 0x05
89 #define ACX100_IOCTL_SET_ANT ACX100_IOCTL + 0x06
90 #define ACX100_IOCTL_GET_ANT ACX100_IOCTL + 0x07
91 #define ACX100_IOCTL_RX_ANT ACX100_IOCTL + 0x08
92 #define ACX100_IOCTL_TX_ANT ACX100_IOCTL + 0x09
93 #define ACX100_IOCTL_SET_ED ACX100_IOCTL + 0x0a
94 #define ACX100_IOCTL_SET_CCA ACX100_IOCTL + 0x0b
95 #define ACX100_IOCTL_SET_PLED ACX100_IOCTL + 0x0c
96 #define ACX100_IOCTL_MONITOR ACX100_IOCTL + 0x0d
97 #define ACX100_IOCTL_TEST ACX100_IOCTL + 0x0e
98 #define ACX100_IOCTL_DBG_SET_MASKS ACX100_IOCTL + 0x0f
99 #define ACX100_IOCTL_ACX111_INFO ACX100_IOCTL + 0x10
102 /* channel frequencies
103 * TODO: Currently, every other 802.11 driver keeps its own copy of this. In
104 * the long run this should be integrated into ieee802_11.h or wireless.h or
105 * whatever IEEE802.11x framework evolves */
106 static const long acx100_channel_freq[] = {
107 2412, 2417, 2422, 2427, 2432, 2437, 2442,
108 2447, 2452, 2457, 2462, 2467, 2472, 2484,
111 static const struct iw_priv_args acx100_ioctl_private_args[] = {
112 #ifdef ACX_DEBUG
113 { cmd : ACX100_IOCTL_DEBUG,
114 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
115 get_args : 0,
116 name : "set_debug" },
117 #endif
118 { cmd : ACX100_IOCTL_LIST_DOM,
119 set_args : 0,
120 get_args : 0,
121 name : "list_reg_domain" },
122 { cmd : ACX100_IOCTL_SET_DOM,
123 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
124 get_args : 0,
125 name : "set_reg_domain" },
126 { cmd : ACX100_IOCTL_GET_DOM,
127 set_args : 0,
128 get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
129 name : "get_reg_domain" },
130 { cmd : ACX100_IOCTL_SET_PREAMB,
131 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
132 get_args : 0,
133 name : "set_s_preamble" },
134 { cmd : ACX100_IOCTL_GET_PREAMB,
135 set_args : 0,
136 get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
137 name : "get_s_preamble" },
138 { cmd : ACX100_IOCTL_SET_ANT,
139 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
140 get_args : 0,
141 name : "set_antenna" },
142 { cmd : ACX100_IOCTL_GET_ANT,
143 set_args : 0,
144 get_args : 0,
145 name : "get_antenna" },
146 { cmd : ACX100_IOCTL_RX_ANT,
147 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
148 get_args : 0,
149 name : "set_rx_ant" },
150 { cmd : ACX100_IOCTL_TX_ANT,
151 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
152 get_args : 0,
153 name : "set_tx_ant" },
154 { cmd : ACX100_IOCTL_SET_ED,
155 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
156 get_args : 0,
157 name : "set_ed" },
158 { cmd : ACX100_IOCTL_SET_CCA,
159 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
160 get_args : 0,
161 name : "set_cca" },
162 { cmd : ACX100_IOCTL_SET_PLED,
163 set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
164 get_args : 0,
165 name : "set_led_power" },
166 { cmd : ACX100_IOCTL_MONITOR,
167 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
168 get_args : 0,
169 name : "monitor" },
170 { cmd : ACX100_IOCTL_TEST,
171 set_args : 0,
172 get_args : 0,
173 name : "test" },
174 { cmd : ACX100_IOCTL_DBG_SET_MASKS,
175 set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
176 get_args : 0,
177 name : "DbgSetMasks" },
178 { cmd : ACX100_IOCTL_ACX111_INFO,
179 set_args : 0,
180 get_args : 0,
181 name : "Acx111Info" }
184 /*------------------------------------------------------------------------------
185 * acx100_ioctl_commit
188 * Arguments:
190 * Returns:
192 * Side effects:
194 * Call context:
196 * STATUS: NEW
198 *----------------------------------------------------------------------------*/
199 static inline int acx100_ioctl_commit(struct net_device *dev,
200 struct iw_request_info *info,
201 void *zwrq, char *extra)
203 wlandevice_t *priv = (wlandevice_t *)dev->priv;
205 FN_ENTER;
206 acx100_update_card_settings(priv, 0, 0, 0);
207 FN_EXIT(0, 0);
208 return 0;
211 static inline int acx100_ioctl_get_name(struct net_device *dev, struct iw_request_info *info, char *cwrq, char *extra)
213 const char * const protocol_name = "IEEE 802.11b+";
214 acxlog(L_IOCTL, "Get Name ==> %s\n", protocol_name);
215 strcpy(cwrq, protocol_name);
216 return 0;
219 /*----------------------------------------------------------------
220 * acx100_ioctl_set_freq
223 * Arguments:
225 * Returns:
227 * Side effects:
229 * Call context:
231 * STATUS: NEW
233 * Comment:
235 *----------------------------------------------------------------*/
236 static inline int acx100_ioctl_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra)
238 wlandevice_t *priv = (wlandevice_t *) dev->priv;
239 int channel = -1;
240 int mult = 1;
241 unsigned long flags;
242 int err;
243 int result = -EINVAL;
245 FN_ENTER;
246 acxlog(L_IOCTL, "Set Frequency <== %i (%i)\n", fwrq->m, fwrq->e);
248 if (fwrq->e == 0 && fwrq->m <= 1000) {
249 /* Setting by channel number */
250 channel = fwrq->m;
251 } else {
252 /* If setting by frequency, convert to a channel */
253 int i;
255 for (i = 0; i < (6 - fwrq->e); i++)
256 mult *= 10;
258 for (i = 1; i <= 14; i++)
259 if (fwrq->m == acx100_channel_freq[i - 1] * mult)
260 channel = i;
263 if (channel > 14) {
264 result = -EINVAL;
265 goto end;
268 if (0 != (err = acx100_lock(priv, &flags))) {
269 result = err;
270 goto end;
273 priv->channel = (UINT16)channel;
274 /* hmm, the following code part is strange, but this is how
275 * it was being done before... */
276 if (ACX_MODE_3_MANAGED_AP == priv->macmode_wanted) {
277 /* hmm, AP mode? So simply set channel... */
278 acxlog(L_IOCTL, "Changing to channel %d\n", priv->channel);
279 priv->set_mask |= GETSET_TX|GETSET_RX;
281 else
282 if ((ACX_MODE_2_MANAGED_STA == priv->macmode_wanted)
283 || (ACX_MODE_0_IBSS_ADHOC == priv->macmode_wanted)) {
284 /* trigger scanning... */
285 priv->set_mask |= GETSET_CHANNEL;
287 acx100_unlock(priv, &flags);
288 result = -EINPROGRESS; /* need to call commit handler */
289 end:
290 FN_EXIT(1, result);
291 return result;
294 static inline int acx100_ioctl_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra)
296 wlandevice_t *priv = (wlandevice_t *) dev->priv;
297 fwrq->e = 0;
298 fwrq->m = priv->channel;
299 return 0;
302 /*----------------------------------------------------------------
303 * acx100_ioctl_set_mode
306 * Arguments:
308 * Returns:
310 * Side effects:
312 * Call context:
314 * STATUS: NEW
316 * Comment:
318 *----------------------------------------------------------------*/
319 static inline int acx100_ioctl_set_mode(struct net_device *dev, struct iw_request_info *info, __u32 *uwrq, char *extra)
321 wlandevice_t *priv = (wlandevice_t *) dev->priv;
322 unsigned long flags;
323 int err;
324 int result = -EINVAL;
326 FN_ENTER;
327 acxlog(L_IOCTL, "Set Mode <== %i\n", *uwrq);
329 if (0 != (err = acx100_lock(priv, &flags))) {
330 result = err;
331 goto end;
334 switch(*uwrq) {
335 case IW_MODE_AUTO:
336 priv->macmode_wanted = ACX_MODE_FF_AUTO;
337 break;
338 case IW_MODE_ADHOC:
339 priv->macmode_wanted = ACX_MODE_0_IBSS_ADHOC;
340 break;
341 case IW_MODE_INFRA:
342 priv->macmode_wanted = ACX_MODE_2_MANAGED_STA;
343 break;
344 case IW_MODE_MASTER:
345 priv->macmode_wanted = ACX_MODE_3_MANAGED_AP;
346 break;
347 default:
348 result = -EOPNOTSUPP;
349 goto end_unlock;
352 priv->set_mask |= GETSET_MODE;
353 result = -EINPROGRESS;
355 end_unlock:
356 acx100_unlock(priv, &flags);
357 end:
358 FN_EXIT(1, result);
359 return result;
362 static inline int acx100_ioctl_get_mode(struct net_device *dev, struct iw_request_info *info, __u32 *uwrq, char *extra)
364 wlandevice_t *priv = (wlandevice_t *) dev->priv;
365 int result;
367 #if SHOW_SPECIFIC_MACMODE_JOINED
368 if (priv->status != ISTATUS_4_ASSOCIATED)
369 #endif
370 { /* connection not up yet, so for now indicate the mode we want,
371 not the one we are in */
372 switch (priv->macmode_wanted) {
373 case ACX_MODE_FF_AUTO:
374 *uwrq = IW_MODE_AUTO;
375 break;
376 case ACX_MODE_0_IBSS_ADHOC:
377 *uwrq = IW_MODE_ADHOC;
378 break;
379 case ACX_MODE_2_MANAGED_STA:
380 *uwrq = IW_MODE_INFRA;
381 break;
382 case ACX_MODE_3_MANAGED_AP:
383 *uwrq = IW_MODE_MASTER;
384 break;
385 default:
386 result = -EOPNOTSUPP;
387 goto end;
390 #if SHOW_SPECIFIC_MACMODE_JOINED
391 else
393 switch (priv->macmode_joined) {
394 case ACX_MODE_0_IBSS_ADHOC:
395 *uwrq = IW_MODE_ADHOC;
396 break;
397 case ACX_MODE_2_MANAGED_STA:
398 *uwrq = IW_MODE_INFRA;
399 break;
400 case ACX_MODE_3_MANAGED_AP:
401 *uwrq = IW_MODE_MASTER;
402 break;
403 default:
404 result = -EOPNOTSUPP;
405 goto end;
408 #endif
409 result = 0;
410 end:
411 acxlog(L_IOCTL, "Get Mode ==> %d\n", *uwrq);
413 return result;
416 static inline int acx100_ioctl_set_sens(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
418 wlandevice_t *priv = (wlandevice_t *) dev->priv;
420 acxlog(L_IOCTL, "Set Sensitivity <== %d\n", vwrq->value);
422 if ((RADIO_RFMD_11 == priv->radio_type) || (RADIO_MAXIM_0D == priv->radio_type)) {
423 priv->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
424 priv->set_mask |= GETSET_SENSITIVITY;
425 return -EINPROGRESS;
426 } else {
427 printk("ERROR: don't know how to set sensitivity for this radio type, please try to add that!\n");
428 return -EINVAL;
432 static inline int acx100_ioctl_get_sens(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
434 wlandevice_t *priv = (wlandevice_t *) dev->priv;
436 if ((RADIO_RFMD_11 == priv->radio_type) || (RADIO_MAXIM_0D == priv->radio_type)) {
437 acxlog(L_IOCTL, "Get Sensitivity ==> %d\n", priv->sensitivity);
439 vwrq->value = priv->sensitivity;
440 vwrq->disabled = (vwrq->value == 0);
441 vwrq->fixed = 1;
442 return 0;
443 } else {
444 printk("ERROR: don't know how to get sensitivity for this radio type, please try to add that!\n");
445 return -EINVAL;
449 /*------------------------------------------------------------------------------
450 * acx100_set_ap
452 * Sets the MAC address of the AP to associate with
454 * Arguments:
456 * Returns:
458 * Side effects:
460 * Call context: Process
462 * STATUS: NEW
464 *----------------------------------------------------------------------------*/
465 static inline int acx100_ioctl_set_ap(struct net_device *dev,
466 struct iw_request_info *info,
467 struct sockaddr *awrq, char *extra)
469 wlandevice_t *priv = (wlandevice_t *)dev->priv;
470 static const unsigned char off[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
471 int result = 0;
472 UINT16 i;
473 unsigned char *ap;
475 FN_ENTER;
476 if (NULL == awrq) {
477 result = -EFAULT;
478 goto end;
480 if (ARPHRD_ETHER != awrq->sa_family) {
481 result = -EINVAL;
482 goto end;
485 ap = awrq->sa_data;
486 acxlog(L_IOCTL, "Set AP <== %02x:%02x:%02x:%02x:%02x:%02x\n",
487 ap[0], ap[1], ap[2], ap[3], ap[4], ap[5]);
489 if (ACX_MODE_2_MANAGED_STA != priv->macmode_wanted) {
490 result = -EINVAL;
491 goto end;
494 if (0 != acx100_is_mac_address_broadcast(ap)) {
495 /* "any" == "auto" == FF:FF:FF:FF:FF:FF */
496 MAC_BCAST(priv->ap);
497 acxlog(L_IOCTL, "Forcing reassociation\n");
498 acx100_scan_chan(priv);
499 result = -EINPROGRESS;
500 } else if (!memcmp(off, ap, ETH_ALEN)) {
501 /* "off" == 00:00:00:00:00:00 */
502 MAC_BCAST(priv->ap);
503 acxlog(L_IOCTL, "Not reassociating\n");
504 } else {
505 /* AB:CD:EF:01:23:45 */
506 for (i = 0; i < priv->bss_table_count; i++) {
507 struct bss_info *bss = &priv->bss_table[i];
508 if (!memcmp(bss->bssid, ap, ETH_ALEN)) {
509 if ((!!priv->wep_enabled) != !!(bss->caps & IEEE802_11_MGMT_CAP_WEP)) {
510 result = -EINVAL;
511 goto end;
512 } else {
513 MAC_COPY(priv->ap, ap);
514 acxlog(L_IOCTL, "Forcing reassociation\n");
515 acx100_scan_chan(priv);
516 result = -EINPROGRESS;
517 goto end;
523 end:
524 FN_EXIT(1, result);
525 return result;
528 static inline int acx100_ioctl_get_ap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra)
530 wlandevice_t *priv = (wlandevice_t *) dev->priv;
532 acxlog(L_IOCTL, "Get BSSID\n");
533 if (ISTATUS_4_ASSOCIATED == priv->status) {
534 /* as seen in Aironet driver, airo.c */
535 MAC_COPY(awrq->sa_data, priv->bssid);
536 } else {
537 MAC_FILL(awrq->sa_data, 0x0);
539 awrq->sa_family = ARPHRD_ETHER;
540 return 0;
543 /*----------------------------------------------------------------
544 * acx100_ioctl_get_aplist
547 * Arguments:
549 * Returns:
551 * Side effects:
553 * Call context:
555 * STATUS: NEW
557 * Comment: deprecated in favour of iwscan.
558 * We simply return the list of currently available stations in range,
559 * don't do a new scan.
561 *----------------------------------------------------------------*/
562 static inline int acx100_ioctl_get_aplist(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
564 wlandevice_t *priv = (wlandevice_t *) dev->priv;
565 struct sockaddr *address = (struct sockaddr *) extra;
566 struct iw_quality qual[IW_MAX_AP];
567 UINT16 i;
568 int result = 0;
570 FN_ENTER;
572 /* in Master mode of course we don't have an AP list... */
573 if (ACX_MODE_3_MANAGED_AP == priv->macmode_joined)
575 result = -EOPNOTSUPP;
576 goto end;
579 for (i = 0; i < priv->bss_table_count; i++) {
580 MAC_COPY(address[i].sa_data, priv->bss_table[i].bssid);
581 address[i].sa_family = ARPHRD_ETHER;
582 qual[i].level = priv->bss_table[i].sir;
583 qual[i].noise = priv->bss_table[i].snr;
584 #ifndef OLD_QUALITY
585 qual[i].qual = acx_signal_determine_quality(qual[i].level, qual[i].noise);
586 #else
587 qual[i].qual = (qual[i].noise <= 100) ?
588 100 - qual[i].noise : 0;;
589 #endif
590 qual[i].updated = 0; /* no scan: level/noise/qual not updated */
592 if (0 != i)
594 dwrq->flags = 1;
595 memcpy(extra + sizeof(struct sockaddr)*i, &qual,
596 sizeof(struct iw_quality)*i);
599 dwrq->length = priv->bss_table_count;
601 end:
602 FN_EXIT(1, result);
603 return result;
606 static inline int acx100_ioctl_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
608 wlandevice_t *priv = (wlandevice_t *) dev->priv;
609 int result = -EINVAL;
611 FN_ENTER;
613 /* don't start scan if device is not up yet */
614 if (0 == (priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
615 result = -EAGAIN;
616 goto end;
619 acx100_scan_chan(priv);
620 priv->scan_start = jiffies;
621 priv->scan_running = 1;
622 result = 0;
624 end:
625 FN_EXIT(1, result);
626 return result;
629 #if WIRELESS_EXT > 13
630 static char *acx100_ioctl_scan_add_station(wlandevice_t *priv, char *ptr, char *end_buf, struct bss_info *bss)
632 struct iw_event iwe;
633 int i;
634 char *ptr_rate;
636 FN_ENTER;
638 /* MAC address has to be added first */
639 iwe.cmd = SIOCGIWAP;
640 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
641 MAC_COPY(iwe.u.ap_addr.sa_data, bss->bssid);
642 acxlog(L_IOCTL, "scan, station address:\n");
643 acx100_log_mac_address(L_IOCTL, bss->bssid);
644 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_ADDR_LEN);
646 /* Add ESSID */
647 iwe.cmd = SIOCGIWESSID;
648 iwe.u.data.length = bss->essid_len;
649 iwe.u.data.flags = 1;
650 acxlog(L_IOCTL, "scan, essid: %s\n", bss->essid);
651 ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
653 /* Add mode */
654 iwe.cmd = SIOCGIWMODE;
655 if (0 != (bss->caps & (IEEE802_11_MGMT_CAP_ESS | IEEE802_11_MGMT_CAP_IBSS))) {
656 if (0 != (bss->caps & IEEE802_11_MGMT_CAP_ESS))
657 iwe.u.mode = IW_MODE_MASTER;
658 else
659 iwe.u.mode = IW_MODE_ADHOC;
660 acxlog(L_IOCTL, "scan, mode: %d\n", iwe.u.mode);
661 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_UINT_LEN);
664 /* Add frequency */
665 iwe.cmd = SIOCGIWFREQ;
666 iwe.u.freq.m = acx100_channel_freq[bss->channel - 1] * 100000;
667 iwe.u.freq.e = 1;
668 acxlog(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m);
669 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_FREQ_LEN);
671 /* Add link quality */
672 iwe.cmd = IWEVQUAL;
673 /* FIXME: these values should be expressed in dBm, but we don't know
674 * how to calibrate it yet */
675 iwe.u.qual.level = bss->sir;
676 iwe.u.qual.noise = bss->snr;
677 #ifndef OLD_QUALITY
678 iwe.u.qual.qual = acx_signal_determine_quality(iwe.u.qual.level, iwe.u.qual.noise);
679 #else
680 iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ?
681 100 - iwe.u.qual.noise : 0;
682 #endif
683 iwe.u.qual.updated = 7;
684 acxlog(L_IOCTL, "scan, link quality: %d/%d/%d\n", iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual);
685 ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_QUAL_LEN);
687 /* Add encryption */
688 iwe.cmd = SIOCGIWENCODE;
689 if (0 != (bss->caps & IEEE802_11_MGMT_CAP_WEP))
690 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
691 else
692 iwe.u.data.flags = IW_ENCODE_DISABLED;
693 iwe.u.data.length = 0;
694 acxlog(L_IOCTL, "scan, encryption flags: %x\n", iwe.u.data.flags);
695 ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
697 /* add rates */
698 iwe.cmd = SIOCGIWRATE;
699 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
700 ptr_rate = ptr + IW_EV_LCP_LEN;
701 for (i = 0; 0 != bss->supp_rates[i]; i++)
703 iwe.u.bitrate.value = (bss->supp_rates[i] & ~0x80) * 500000; /* units of 500kb/s */
704 acxlog(L_IOCTL, "scan, rate: %d [%02x]\n", iwe.u.bitrate.value, bss->supp_rates[i]);
705 ptr = iwe_stream_add_value(ptr, ptr_rate, end_buf, &iwe, IW_EV_PARAM_LEN);
707 if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN)
708 ptr = ptr_rate;
710 /* drop remaining station data items for now */
712 FN_EXIT(1, (int)ptr);
713 return ptr;
716 static inline int acx100_ioctl_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
718 wlandevice_t *priv = (wlandevice_t *) dev->priv;
719 char *ptr = extra;
720 int i;
721 int result = 0;
723 FN_ENTER;
725 /* no scan available if device is not up yet */
726 if (0 == (priv->dev_state_mask & ACX_STATE_IFACE_UP))
728 result = -EAGAIN;
729 goto end;
732 if (priv->scan_start && time_before(jiffies, priv->scan_start + 3*HZ))
734 /* scan still in progress, so no results yet, sorry */
735 result = -EAGAIN;
736 goto end;
738 priv->scan_start = 0;
740 if (priv->bss_table_count == 0)
742 /* no stations found */
743 result = -ENODATA;
744 goto end;
747 for (i = 0; i < priv->bss_table_count; i++)
749 struct bss_info *bss = &priv->bss_table[i];
751 ptr = acx100_ioctl_scan_add_station(priv, ptr, extra + IW_SCAN_MAX_DATA, bss);
753 dwrq->length = ptr - extra;
754 dwrq->flags = 0;
756 end:
757 FN_EXIT(1, result);
758 return result;
760 #endif /* WIRELESS_EXT > 13 */
762 /*----------------------------------------------------------------
763 * acx100_ioctl_set_essid
766 * Arguments:
768 * Returns:
770 * Side effects:
772 * Call context:
774 * STATUS: NEW
776 * Comment:
778 *----------------------------------------------------------------*/
779 static inline int acx100_ioctl_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
781 wlandevice_t *priv = (wlandevice_t *) dev->priv;
782 int len = dwrq->length;
783 unsigned long flags;
784 int err;
785 int result = -EINVAL;
787 FN_ENTER;
788 acxlog(L_IOCTL, "Set ESSID <== %s, length %d, flags 0x%04x\n", extra, len, dwrq->flags);
790 if (len < 0) {
791 result = -EINVAL;
792 goto end;
795 if (0 != (err = acx100_lock(priv, &flags))) {
796 result = err;
797 goto end;
800 /* ESSID disabled? */
801 if (0 == dwrq->flags)
803 priv->essid_active = (UINT8)0;
805 else
807 if (dwrq->length > IW_ESSID_MAX_SIZE+1)
809 result = -E2BIG;
810 goto end_unlock;
813 priv->essid_len = (UINT8)(len - 1);
814 memcpy(priv->essid, extra, priv->essid_len);
815 priv->essid[priv->essid_len] = '\0';
816 priv->essid_active = (UINT8)1;
819 priv->set_mask |= GETSET_ESSID;
821 end_unlock:
822 acx100_unlock(priv, &flags);
823 result = -EINPROGRESS;
824 end:
825 FN_EXIT(1, result);
826 return result;
829 static inline int acx100_ioctl_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
831 wlandevice_t *priv = (wlandevice_t *) dev->priv;
833 acxlog(L_IOCTL, "Get ESSID ==> %s\n", priv->essid);
835 dwrq->flags = priv->essid_active;
836 if ((UINT8)0 != priv->essid_active)
838 memcpy(extra, priv->essid, priv->essid_len);
839 extra[priv->essid_len] = '\0';
840 dwrq->length = priv->essid_len + 1;
841 dwrq->flags = 1;
843 return 0;
846 /*----------------------------------------------------------------
847 * acx100_ioctl_set_rate
850 * Arguments:
852 * Returns:
854 * Side effects:
856 * Call context:
858 * STATUS: NEW
860 * Comment:
862 *----------------------------------------------------------------*/
863 static inline int acx100_ioctl_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
865 wlandevice_t *priv = (wlandevice_t *) dev->priv;
866 unsigned long flags;
867 int err;
868 UINT8 txrate_cfg, txrate_auto_idx_max;
869 int result = -EINVAL;
871 FN_ENTER;
872 acxlog(L_IOCTL,
873 "rate = %d, fixed = 0x%x, disabled = 0x%x, flags = 0x%x\n",
874 vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags);
876 #define BITRATE_AUTO 1
877 #if BITRATE_AUTO
878 if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) {
879 #else
880 if (1 == vwrq->fixed) {
881 #endif
883 switch (vwrq->value) {
885 case 1000000: /* 1Mbps */
886 txrate_cfg = ACX_TXRATE_1;
887 txrate_auto_idx_max = 0;
888 break;
890 case 2000000: /* 2Mbps */
891 txrate_cfg = ACX_TXRATE_2;
892 txrate_auto_idx_max = 1;
893 break;
895 case 5500000: /* 5.5Mbps */
896 txrate_cfg = ACX_TXRATE_5_5;
897 txrate_auto_idx_max = 2;
898 break;
900 case 11000000: /* 11Mbps */
901 txrate_cfg = ACX_TXRATE_11;
902 txrate_auto_idx_max = 3;
903 break;
905 case 22000000: /* 22Mbps */
906 txrate_cfg = ACX_TXRATE_22PBCC;
907 txrate_auto_idx_max = 4;
908 break;
910 #if BITRATE_AUTO
911 case -1: /* highest available */
912 /* -1 is used to set highest available rate in
913 * case of iwconfig calls without rate given
914 * (iwconfig wlan0 rate auto etc.) */
915 txrate_cfg = ACX_TXRATE_22PBCC; /* 22Mbps is not supported by many APs, thus fallback needs to work properly to be able to safely go back to 11! */
916 txrate_auto_idx_max = 4;
917 break;
918 #endif
919 default:
920 result = -EINVAL;
921 goto end;
924 } else if (2 == vwrq->fixed) {
926 switch (vwrq->value) {
928 case 0:
929 txrate_cfg = ACX_TXRATE_1;
930 txrate_auto_idx_max = 0;
931 break;
933 case 1:
934 txrate_cfg = ACX_TXRATE_2;
935 txrate_auto_idx_max = 1;
936 break;
938 case 2:
939 txrate_cfg = ACX_TXRATE_5_5;
940 txrate_auto_idx_max = 2;
941 break;
943 case 3:
944 txrate_cfg = ACX_TXRATE_5_5PBCC;
945 txrate_auto_idx_max = 2;
946 break;
948 case 4:
949 txrate_cfg = ACX_TXRATE_11;
950 txrate_auto_idx_max = 3;
951 break;
953 case 5:
954 txrate_cfg = ACX_TXRATE_11PBCC;
955 txrate_auto_idx_max = 3;
956 break;
958 case 6:
959 txrate_cfg = ACX_TXRATE_22PBCC;
960 txrate_auto_idx_max = 4;
961 break;
963 default:
964 result = -EINVAL;
965 goto end;
968 } else {
969 result = -EOPNOTSUPP;
970 goto end;
973 if (0 != (err = acx100_lock(priv, &flags))) {
974 result = err;
975 goto end;
978 priv->txrate_cfg = txrate_cfg;
979 #if BITRATE_AUTO
980 priv->txrate_auto = (UINT8)(vwrq->fixed == (__u8)0);
981 if (1 == priv->txrate_auto)
983 if (ACX_TXRATE_1 == txrate_cfg) { /* auto rate with 1Mbps max. useless */
984 priv->txrate_auto = (UINT8)0;
985 priv->txrate_curr = priv->txrate_cfg;
986 } else {
987 priv->txrate_auto_idx_max = txrate_auto_idx_max;
988 priv->txrate_auto_idx = 1; /* 2Mbps */
989 priv->txrate_curr = ACX_TXRATE_2; /* 2Mbps, play it safe at the beginning */
990 priv->txrate_fallback_count = 0;
991 priv->txrate_stepup_count = 0;
994 else
995 #endif
996 priv->txrate_curr = priv->txrate_cfg;
998 acx100_unlock(priv, &flags);
1000 #if BITRATE_AUTO
1001 acxlog(L_IOCTL, "Tx rate = %d, auto rate %d, current rate %d\n", priv->txrate_cfg, priv->txrate_auto, priv->txrate_curr);
1002 priv->set_mask |= SET_RATE_FALLBACK;
1003 result = -EINPROGRESS;
1004 #else
1005 acxlog(L_IOCTL, "Tx rate = %d\n", priv->txrate_cfg);
1006 result = 0;
1007 #endif
1009 end:
1010 FN_EXIT(1, result);
1011 return result;
1013 /*----------------------------------------------------------------
1014 * acx100_ioctl_get_rate
1017 * Arguments:
1019 * Returns:
1021 * Side effects:
1023 * Call context:
1025 * STATUS: NEW
1027 * Comment:
1029 *----------------------------------------------------------------*/
1030 static inline int acx100_ioctl_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1032 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1034 vwrq->value = priv->txrate_curr * 100000;
1035 #if BITRATE_AUTO
1036 vwrq->fixed = (__u8)(priv->txrate_auto == (UINT8)0);
1037 #else
1038 vwrq->fixed = 1;
1039 #endif
1040 vwrq->disabled = (__u8)0;
1041 return 0;
1044 static inline int acx100_ioctl_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1046 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1047 int val = vwrq->value;
1049 if ((__u8)0 != vwrq->disabled)
1050 val = 2312;
1051 if ((val < 0) || (val > 2312))
1052 return -EINVAL;
1054 priv->rts_threshold = val;
1055 return 0;
1059 static inline int acx100_ioctl_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1061 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1063 vwrq->value = priv->rts_threshold;
1064 vwrq->disabled = (__u8)(vwrq->value >= 2312);
1065 vwrq->fixed = (__u8)1;
1066 return 0;
1069 /*----------------------------------------------------------------
1070 * acx100_ioctl_set_encode
1073 * Arguments:
1075 * Returns:
1077 * Side effects:
1079 * Call context:
1081 * STATUS: NEW
1083 * Comment:
1085 *----------------------------------------------------------------*/
1086 static inline int acx100_ioctl_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
1088 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1089 int index;
1090 unsigned long flags;
1091 int err;
1092 int result = -EINVAL;
1094 FN_ENTER;
1095 acxlog(L_IOCTL,
1096 "Set Encoding flags = 0x%04x, size = %i, key: %s\n",
1097 dwrq->flags, dwrq->length, extra ? "set" : "No key");
1099 if (0 != (err = acx100_lock(priv, &flags))) {
1100 result = err;
1101 goto end;
1104 index = dwrq->flags & IW_ENCODE_INDEX;
1106 if (dwrq->length > 0) {
1108 /* if index is 0 or invalid, use default key */
1109 if ((index == 0) || (index > 4))
1110 index = (int)priv->wep_current_index;
1111 else
1112 index--;
1114 if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
1115 if (dwrq->length > 29)
1116 dwrq->length = 29; /* restrict it */
1118 if (dwrq->length > 13)
1119 priv->wep_keys[index].size = 29; /* 29*8 == 232, WEP256 */
1120 else
1121 if (dwrq->length > 5)
1122 priv->wep_keys[index].size = 13; /* 13*8 == 104bit, WEP128 */
1123 else
1124 if (dwrq->length > 0)
1125 priv->wep_keys[index].size = 5; /* 5*8 == 40bit, WEP64 */
1126 else
1127 /* disable key */
1128 priv->wep_keys[index].size = 0;
1130 memset(priv->wep_keys[index].key, 0, sizeof(priv->wep_keys[index].key));
1131 memcpy(priv->wep_keys[index].key, extra, dwrq->length);
1134 } else {
1135 /* set transmit key */
1136 if ((index >= 1) && (index <= 4))
1137 priv->wep_current_index = (UINT8)(index - 1);
1138 else
1139 if (0 == (dwrq->flags & IW_ENCODE_MODE))
1141 /* complain if we were not just setting
1142 * the key mode */
1143 result = -EINVAL;
1144 goto end_unlock;
1148 priv->wep_enabled = (UINT8)(0 == (dwrq->flags & IW_ENCODE_DISABLED));
1150 if (0 != (dwrq->flags & IW_ENCODE_OPEN)) {
1151 priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
1152 priv->wep_restricted = (UINT8)0;
1153 } else if (0 != (dwrq->flags & IW_ENCODE_RESTRICTED)) {
1154 priv->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
1155 priv->wep_restricted = (UINT8)1;
1158 /* set flag to make sure the card WEP settings get updated */
1159 priv->set_mask |= GETSET_WEP;
1161 acxlog(L_IOCTL, "len = %d, key at 0x%p, flags = 0x%x\n",
1162 dwrq->length, extra,
1163 dwrq->flags);
1165 for (index = 0; index <= 3; index++) {
1166 if (0 != priv->wep_keys[index].size) {
1167 acxlog(L_IOCTL,
1168 "index = %d, size = %d, key at 0x%p\n",
1169 priv->wep_keys[index].index,
1170 priv->wep_keys[index].size,
1171 priv->wep_keys[index].key);
1174 result = -EINPROGRESS;
1176 end_unlock:
1177 acx100_unlock(priv, &flags);
1178 end:
1179 FN_EXIT(1, result);
1180 return result;
1183 /*----------------------------------------------------------------
1184 * acx100_ioctl_get_encode
1187 * Arguments:
1189 * Returns:
1191 * Side effects:
1193 * Call context:
1195 * STATUS: NEW
1197 * Comment:
1199 *----------------------------------------------------------------*/
1200 static inline int acx100_ioctl_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
1202 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1204 if (ACX_MODE_0_IBSS_ADHOC == priv->macmode_wanted) {
1205 /* ok, let's assume it's supported, but print a
1206 * warning message
1207 * FIXME: should be removed once it's definitely working. */
1208 acxlog(L_STD, "Warning: WEP support might not be supported in Ad-Hoc mode yet!\n");
1209 /* return -EOPNOTSUPP; */
1212 if (priv->wep_enabled == (UINT8)0)
1214 dwrq->flags = IW_ENCODE_DISABLED;
1216 else
1218 dwrq->flags =
1219 (priv->wep_restricted == (UINT8)1) ? IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
1221 dwrq->length =
1222 priv->wep_keys[priv->wep_current_index].size;
1224 memcpy(extra,
1225 priv->wep_keys[priv->wep_current_index].key,
1226 priv->wep_keys[priv->wep_current_index].size);
1229 /* set the current index */
1230 dwrq->flags |=
1231 priv->wep_keys[priv->wep_current_index].index + 1;
1233 acxlog(L_IOCTL, "len = %d, key = %p, flags = 0x%x\n",
1234 dwrq->length, dwrq->pointer,
1235 dwrq->flags);
1237 return 0;
1240 static inline int acx100_ioctl_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1242 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1244 acxlog(L_IOCTL, "Set 802.11 Power Save flags = 0x%04x\n", vwrq->flags);
1245 if ((__u8)0 != vwrq->disabled) {
1246 priv->ps_wakeup_cfg &= ~PS_CFG_ENABLE;
1247 priv->set_mask |= GETSET_POWER_80211;
1248 return -EINPROGRESS;
1250 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
1251 UINT16 ps_timeout = (vwrq->value * 1024) / 1000;
1253 if (ps_timeout > 255)
1254 ps_timeout = 255;
1255 acxlog(L_IOCTL, "setting PS timeout value to %d time units due to %dus\n", ps_timeout, vwrq->value);
1256 priv->ps_hangover_period = ps_timeout;
1257 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
1258 UINT16 ps_periods = vwrq->value / 1000000;
1260 if (ps_periods > 255)
1261 ps_periods = 255;
1262 acxlog(L_IOCTL, "setting PS period value to %d periods due to %dus\n", ps_periods, vwrq->value);
1263 priv->ps_listen_interval = ps_periods;
1264 priv->ps_wakeup_cfg &= ~PS_CFG_WAKEUP_MODE_MASK;
1265 priv->ps_wakeup_cfg |= PS_CFG_WAKEUP_EACH_ITVL;
1267 switch (vwrq->flags & IW_POWER_MODE) {
1268 /* FIXME: are we doing the right thing here? */
1269 case IW_POWER_UNICAST_R:
1270 priv->ps_options &= ~PS_OPT_STILL_RCV_BCASTS;
1271 break;
1272 case IW_POWER_MULTICAST_R:
1273 priv->ps_options |= PS_OPT_STILL_RCV_BCASTS;
1274 break;
1275 case IW_POWER_ALL_R:
1276 priv->ps_options |= PS_OPT_STILL_RCV_BCASTS;
1277 break;
1278 case IW_POWER_ON:
1279 break;
1280 default:
1281 acxlog(L_IOCTL, "unknown PS mode\n");
1282 return -EINVAL;
1284 priv->ps_wakeup_cfg |= PS_CFG_ENABLE;
1285 priv->set_mask |= GETSET_POWER_80211;
1286 return -EINPROGRESS;
1290 static inline int acx100_ioctl_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1292 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1294 acxlog(L_IOCTL, "Get 802.11 Power Save flags = 0x%04x\n", vwrq->flags);
1295 vwrq->disabled = ((priv->ps_wakeup_cfg & PS_CFG_ENABLE) == (UINT8)0);
1296 if (0 != vwrq->disabled)
1297 return 0;
1298 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
1299 vwrq->value = priv->ps_hangover_period * 1000 / 1024;
1300 vwrq->flags = IW_POWER_TIMEOUT;
1301 } else {
1302 vwrq->value = priv->ps_listen_interval * 1000000;
1303 vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
1305 if (0 != (priv->ps_options & PS_OPT_STILL_RCV_BCASTS))
1306 vwrq->flags |= IW_POWER_ALL_R;
1307 else
1308 vwrq->flags |= IW_POWER_UNICAST_R;
1310 return 0;
1313 /*----------------------------------------------------------------
1314 * acx100_ioctl_get_txpow
1317 * Arguments:
1319 * Returns:
1321 * Side effects:
1323 * Call context:
1325 * STATUS: NEW
1327 * Comment:
1329 *----------------------------------------------------------------*/
1330 static inline int acx100_ioctl_get_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1332 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1334 vwrq->flags = IW_TXPOW_DBM;
1335 vwrq->disabled = (__u8)0;
1336 vwrq->fixed = (__u8)0;
1337 vwrq->value = priv->tx_level_dbm;
1339 acxlog(L_IOCTL, "Get Tx power ==> %d dBm\n", priv->tx_level_dbm);
1341 return 0;
1344 /*----------------------------------------------------------------
1345 * acx100_ioctl_set_txpow
1348 * Arguments:
1350 * Returns:
1352 * Side effects:
1354 * Call context:
1356 * STATUS: NEW
1358 * Comment:
1360 *----------------------------------------------------------------*/
1361 static inline int acx100_ioctl_set_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1363 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1364 unsigned long flags;
1365 int err;
1366 int result = -EINVAL;
1368 FN_ENTER;
1369 acxlog(L_IOCTL, "Set Tx power <== %d, disabled %d, flags 0x%04x\n", vwrq->value, vwrq->disabled, vwrq->flags);
1370 if (0 != (err = acx100_lock(priv, &flags))) {
1371 result = err;
1372 goto end;
1374 if (vwrq->disabled != priv->tx_disabled) {
1375 priv->set_mask |= GETSET_TX; /* Tx status needs update later */
1378 priv->tx_disabled = vwrq->disabled;
1379 if (vwrq->value == -1) {
1380 if (0 != vwrq->disabled) {
1381 priv->tx_level_dbm = (UINT8)0;
1382 acxlog(L_IOCTL, "Disable radio Tx\n");
1383 } else {
1384 priv->tx_level_auto = (UINT8)1;
1385 acxlog(L_IOCTL, "Set Tx power auto (NIY)\n");
1387 } else {
1388 priv->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
1389 priv->tx_level_auto = (UINT8)0;
1390 acxlog(L_IOCTL, "Set Tx power = %d dBm\n", priv->tx_level_dbm);
1392 priv->set_mask |= GETSET_TXPOWER;
1393 acx100_unlock(priv, &flags);
1394 result = -EINPROGRESS;
1395 end:
1396 FN_EXIT(1, result);
1397 return result;
1400 /*----------------------------------------------------------------
1401 * acx100_ioctl_get_range
1404 * Arguments:
1406 * Returns:
1408 * Side effects:
1410 * Call context:
1412 * STATUS: NEW
1414 * Comment:
1416 *----------------------------------------------------------------*/
1417 static inline int acx100_ioctl_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
1419 if (dwrq->pointer != NULL) {
1420 struct iw_range *range = (struct iw_range *)extra;
1421 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1422 UINT16 i;
1424 dwrq->length = sizeof(struct iw_range);
1425 memset(range, 0, sizeof(struct iw_range));
1426 range->num_channels = 0;
1427 for (i = 1; i <= 14; i++)
1428 if (0 != (priv->reg_dom_chanmask & (1 << (i - 1))))
1430 range->freq[range->num_channels].i = i;
1431 range->freq[range->num_channels].m = acx100_channel_freq[i - 1] * 100000;
1432 range->freq[range->num_channels++].e = 1; /* MHz values */
1434 range->num_frequency = (__u8)range->num_channels;
1436 range->min_rts = 0;
1437 range->max_rts = 2312;
1438 /* range->min_frag = 256;
1439 * range->max_frag = 2312;
1442 range->encoding_size[0] = 5;
1443 range->encoding_size[1] = 13;
1444 range->encoding_size[2] = 29;
1445 range->num_encoding_sizes = (__u8)3;
1446 range->max_encoding_tokens = (__u8)4;
1448 range->min_pmp = 0;
1449 range->max_pmp = 5000000;
1450 range->min_pmt = 0;
1451 range->max_pmt = 65535 * 1000;
1452 range->pmp_flags = IW_POWER_PERIOD;
1453 range->pmt_flags = IW_POWER_TIMEOUT;
1454 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
1456 for (i = 0; i <= IW_MAX_TXPOWER - 1; i++)
1457 range->txpower[i] = 20 * i / (IW_MAX_TXPOWER - 1);
1458 range->num_txpower = (__u8)IW_MAX_TXPOWER;
1459 range->txpower_capa = IW_TXPOW_DBM;
1461 range->we_version_compiled = (__u8)WIRELESS_EXT;
1462 range->we_version_source = (__u8)0x9;
1464 range->retry_capa = IW_RETRY_LIMIT;
1465 range->retry_flags = IW_RETRY_LIMIT;
1466 range->min_retry = 1;
1467 range->max_retry = 255;
1469 range->r_time_flags = IW_RETRY_LIFETIME;
1470 range->min_r_time = 0;
1471 range->max_r_time = 65535; /* FIXME: lifetime ranges and orders of magnitude are strange?? */
1473 range->sensitivity = 0xff;
1475 for (i=0; i < (UINT16)priv->rate_spt_len; i++) {
1476 range->bitrate[i] = (priv->rate_support1[i] & ~0x80) * 500000;
1477 if (range->bitrate[i] == 0)
1478 break;
1480 range->num_bitrates = (__u8)i;
1482 range->max_qual.qual = (__u8)100;
1483 range->max_qual.level = (__u8)100;
1484 range->max_qual.noise = (__u8)100;
1485 /* FIXME: better values */
1486 range->avg_qual.qual = (__u8)90;
1487 range->avg_qual.level = (__u8)80;
1488 range->avg_qual.noise = (__u8)2;
1491 return 0;
1495 /*================================================================*/
1496 /* Private functions */
1497 /*================================================================*/
1499 /*----------------------------------------------------------------
1500 * acx100_ioctl_get_iw_priv
1503 * Arguments:
1505 * Returns:
1507 * Side effects:
1509 * Call context:
1511 * STATUS: FINISHED
1513 * Comment: I added the monitor mode and changed the stuff below to look more like the orinoco driver
1515 *----------------------------------------------------------------*/
1516 static inline int acx100_ioctl_get_iw_priv(struct iwreq *iwr)
1518 int result = -EINVAL;
1520 if (iwr->u.data.pointer != 0) {
1521 result =
1522 verify_area(VERIFY_WRITE, iwr->u.data.pointer,
1523 sizeof(acx100_ioctl_private_args));
1524 if (result != 0)
1525 return result;
1527 iwr->u.data.length = sizeof(acx100_ioctl_private_args) / sizeof(acx100_ioctl_private_args[0]);
1528 if (copy_to_user(iwr->u.data.pointer, acx100_ioctl_private_args, sizeof(acx100_ioctl_private_args)) !=
1530 result = -EFAULT;
1532 return result;
1535 /*----------------------------------------------------------------
1536 * acx100_ioctl_get_nick
1539 * Arguments:
1541 * Returns:
1543 * Side effects:
1545 * Call context:
1547 * STATUS: NEW
1549 * Comment:
1551 *----------------------------------------------------------------*/
1552 static inline int acx100_ioctl_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
1554 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1556 /* FIXME : consider spinlock here */
1557 strcpy(extra, priv->nick);
1558 /* FIXME : consider spinlock here */
1560 dwrq->length = strlen(extra)+1;
1562 return 0;
1565 /*----------------------------------------------------------------
1566 * acx100_ioctl_set_nick
1569 * Arguments:
1571 * Returns:
1573 * Side effects:
1575 * Call context:
1577 * STATUS: NEW
1579 * Comment: copied from orinoco.c
1581 *----------------------------------------------------------------*/
1582 static inline int acx100_ioctl_set_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra)
1584 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1585 unsigned long flags;
1586 int err;
1587 int result = -EINVAL;
1589 FN_ENTER;
1591 if (0 != (err = acx100_lock(priv, &flags))) {
1592 result = err;
1593 goto end;
1596 if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
1597 result = -E2BIG;
1598 goto end_unlock;
1601 /* extra includes trailing \0, so it's ok */
1602 strcpy(priv->nick, extra);
1603 result = 0;
1605 end_unlock:
1606 acx100_unlock(priv, &flags);
1607 end:
1608 FN_EXIT(1, result);
1609 return result;
1612 /*------------------------------------------------------------------------------
1613 * acx100_ioctl_get_retry
1615 * Arguments:
1617 * Returns:
1619 * Side effects:
1621 * Call context:
1623 * STATUS: NEW
1625 * Comment:
1627 *----------------------------------------------------------------------------*/
1628 static inline int acx100_ioctl_get_retry(struct net_device *dev,
1629 struct iw_request_info *info,
1630 struct iw_param *vwrq, char *extra)
1632 wlandevice_t *priv = (wlandevice_t *)dev->priv;
1633 __u16 type = vwrq->flags & IW_RETRY_TYPE;
1634 __u16 modifier = vwrq->flags & IW_RETRY_MODIFIER;
1635 unsigned long flags;
1636 int err;
1637 int result = -EINVAL;
1639 if (0 != (err = acx100_lock(priv, &flags))) {
1640 result = err;
1641 goto end;
1643 /* return the short retry number by default */
1644 if (type == IW_RETRY_LIFETIME) {
1645 vwrq->flags = IW_RETRY_LIFETIME;
1646 vwrq->value = priv->msdu_lifetime;
1647 } else if (modifier == IW_RETRY_MAX) {
1648 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
1649 vwrq->value = priv->long_retry;
1650 } else {
1651 vwrq->flags = IW_RETRY_LIMIT;
1652 if (priv->long_retry != priv->short_retry)
1653 vwrq->flags |= IW_RETRY_MIN;
1654 vwrq->value = priv->short_retry;
1656 acx100_unlock(priv, &flags);
1657 /* can't be disabled */
1658 vwrq->disabled = (__u8)0;
1659 result = 0;
1661 end:
1662 return result;
1665 /*----------------------------------------------------------------
1666 * acx100_ioctl_set_retry
1669 * Arguments:
1671 * Returns:
1673 * Side effects:
1675 * Call context:
1677 * STATUS: NEW
1679 * Comment:
1681 *----------------------------------------------------------------*/
1682 static inline int acx100_ioctl_set_retry(struct net_device *dev,
1683 struct iw_request_info *info,
1684 struct iw_param *vwrq, char *extra)
1686 wlandevice_t *priv = (wlandevice_t *)dev->priv;
1687 unsigned long flags;
1688 int err;
1689 int result = -EINVAL;
1691 FN_ENTER;
1692 if (!vwrq) {
1693 result = -EFAULT;
1694 goto end;
1696 if ((__u8)0 != vwrq->disabled) {
1697 result = -EINVAL;
1698 goto end;
1700 if (0 != (err = acx100_lock(priv, &flags))) {
1701 result = err;
1702 goto end;
1704 if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
1705 (void)printk("current retry limits: short %d long %d\n", priv->short_retry, priv->long_retry);
1706 if (0 != (vwrq->flags & IW_RETRY_MAX)) {
1707 priv->long_retry = vwrq->value;
1708 } else if (0 != (vwrq->flags & IW_RETRY_MIN)) {
1709 priv->short_retry = vwrq->value;
1710 } else {
1711 /* no modifier: set both */
1712 priv->long_retry = vwrq->value;
1713 priv->short_retry = vwrq->value;
1715 (void)printk("new retry limits: short %d long %d\n", priv->short_retry, priv->long_retry);
1716 priv->set_mask |= GETSET_RETRY;
1717 result = -EINPROGRESS;
1719 else
1720 if (0 != (vwrq->flags & IW_RETRY_LIFETIME)) {
1721 priv->msdu_lifetime = vwrq->value;
1722 (void)printk("new MSDU lifetime: %d\n", priv->msdu_lifetime);
1723 priv->set_mask |= SET_MSDU_LIFETIME;
1724 result = -EINPROGRESS;
1726 acx100_unlock(priv, &flags);
1727 end:
1728 FN_EXIT(1, result);
1729 return result;
1733 /******************************* private ioctls ******************************/
1736 /*----------------------------------------------------------------
1737 * acx100_ioctl_set_debug
1740 * Arguments:
1742 * Returns:
1744 * Side effects:
1746 * Call context:
1748 * STATUS: NEW
1750 * Comment:
1752 *----------------------------------------------------------------*/
1753 #ifdef ACX_DEBUG
1754 static inline int acx100_ioctl_set_debug(struct net_device *dev,
1755 struct iw_request_info *info,
1756 struct iw_param *vwrq, char *extra)
1758 int debug_new = *((int *)extra);
1759 int result = -EINVAL;
1761 acxlog(L_STD, "%s: setting debug from 0x%04X to 0x%04X\n", __func__,
1762 debug, debug_new);
1763 debug = debug_new;
1765 result = 0;
1766 return result;
1769 #endif
1771 extern const UINT8 reg_domain_ids[];
1772 extern const UINT8 reg_domain_ids_len;
1774 const char *reg_domain_strings[] =
1775 { "FCC (USA) (1-11)",
1776 "DOC/IC (Canada) (1-11)",
1777 /* BTW: WLAN use in ETSI is regulated by
1778 * ETSI standard EN 300 328-2 V1.1.2 */
1779 "ETSI (Europe) (1-13)",
1780 "Spain (10-11)",
1781 "France (10-13)",
1782 "MKK (Japan) (14)",
1783 "MKK1 (1-14)",
1784 "Israel? (new!) (4?-8?) (not all firmware versions)",
1785 NULL /* needs to remain as last entry */
1788 /*----------------------------------------------------------------
1789 * acx100_ioctl_list_reg_domain
1792 * Arguments:
1794 * Returns:
1796 * Side effects:
1798 * Call context:
1800 * STATUS: NEW
1802 * Comment:
1804 *----------------------------------------------------------------*/
1805 static inline int acx100_ioctl_list_reg_domain(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1807 int i;
1808 const char **entry;
1810 (void)printk("Domain/Country Channels Setting\n");
1811 for (i = 0, entry = reg_domain_strings; *entry; i++, entry++)
1812 (void)printk("%s %d\n", *entry, i+1);
1813 return 0;
1816 /*----------------------------------------------------------------
1817 * acx100_ioctl_set_reg_domain
1820 * Arguments:
1822 * Returns:
1824 * Side effects:
1826 * Call context:
1828 * STATUS: NEW
1830 * Comment:
1832 *----------------------------------------------------------------*/
1833 static inline int acx100_ioctl_set_reg_domain(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1835 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1836 unsigned long flags;
1837 int err;
1838 int result = -EINVAL;
1840 FN_ENTER;
1841 if (0 != (err = acx100_lock(priv, &flags))) {
1842 result = err;
1843 goto end;
1846 if ((*extra < 1) || ((size_t)*extra > reg_domain_ids_len)) {
1847 result = -EINVAL;
1848 goto end_unlock;
1850 priv->reg_dom_id = reg_domain_ids[*extra - 1];
1851 priv->set_mask |= GETSET_REG_DOMAIN;
1852 result = -EINPROGRESS;
1854 end_unlock:
1855 acx100_unlock(priv, &flags);
1856 end:
1857 FN_EXIT(1, result);
1858 return result;
1861 /*----------------------------------------------------------------
1862 * acx100_ioctl_get_reg_domain
1865 * Arguments:
1867 * Returns:
1869 * Side effects:
1871 * Call context:
1873 * STATUS: NEW
1875 * Comment:
1877 *----------------------------------------------------------------*/
1878 static inline int acx100_ioctl_get_reg_domain(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1880 wlandevice_t *priv = (wlandevice_t *) dev->priv;
1881 int i;
1883 for (i=1; i <= 7; i++)
1884 if (reg_domain_ids[i-1] == priv->reg_dom_id)
1886 acxlog(L_STD, "regulatory domain is currently set to %d (0x%x): %s\n", i, priv->reg_dom_id, reg_domain_strings[i-1]);
1887 *extra = i;
1888 break;
1891 return 0;
1894 /*----------------------------------------------------------------
1895 * acx100_ioctl_set_short_preamble
1898 * Arguments:
1900 * Returns:
1902 * Side effects:
1904 * Call context:
1906 * STATUS: NEW
1908 * Comment:
1910 *----------------------------------------------------------------*/
1911 static inline int acx100_ioctl_set_short_preamble(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1913 wlandevice_t *priv = (wlandevice_t *)dev->priv;
1914 char *descr = NULL;
1916 if ((*extra < (char)0) || (*extra > (char)2))
1917 return -EINVAL;
1919 priv->preamble_mode = (UINT8)*extra;
1920 switch (*extra) {
1921 case 0:
1922 descr = "off";
1923 priv->preamble_flag = (UINT8)0;
1924 break;
1925 case 1:
1926 descr = "on";
1927 priv->preamble_flag = (UINT8)1;
1928 break;
1929 case 2:
1930 descr = "auto (peer capability dependent)";
1932 /* associated to a station? */
1933 if ((UINT8)0x0 != priv->station_assoc.bssid[0])
1934 priv->preamble_flag = (UINT8)((priv->station_assoc.caps & IEEE802_11_MGMT_CAP_SHORT_PRE) == IEEE802_11_MGMT_CAP_SHORT_PRE);
1935 break;
1936 default:
1937 descr = "unknown mode, error";
1938 break;
1940 (void)printk("new Short Preamble setting: %s\n", descr);
1942 return 0;
1945 /*----------------------------------------------------------------
1946 * acx100_ioctl_get_short_preamble
1949 * Arguments:
1951 * Returns:
1953 * Side effects:
1955 * Call context:
1957 * STATUS: NEW
1959 * Comment:
1961 *----------------------------------------------------------------*/
1962 static inline int acx100_ioctl_get_short_preamble(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
1964 wlandevice_t *priv = (wlandevice_t *)dev->priv;
1965 char *descr = NULL;
1967 switch(priv->preamble_mode) {
1968 case 0:
1969 descr = "off";
1970 break;
1971 case 1:
1972 descr = "on";
1973 break;
1974 case 2:
1975 descr = "auto (peer capability dependent)";
1976 break;
1977 default:
1978 descr = "unknown mode, error";
1979 break;
1981 (void)printk("current Short Preamble setting: %s\n", descr);
1983 *extra = (char)priv->preamble_mode;
1985 return 0;
1988 /*----------------------------------------------------------------
1989 * acx100_ioctl_set_antenna
1992 * Arguments:
1994 * Returns:
1996 * Side effects:
1998 * Call context:
2000 * STATUS: NEW
2002 * Comment: TX and RX antenna can be set separately but this function good
2003 * for testing 0-4 bits
2004 *----------------------------------------------------------------*/
2005 static inline int acx100_ioctl_set_antenna(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2007 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2009 (void)printk("current antenna value: 0x%02X\n", priv->antenna);
2010 (void)printk("Rx antenna selection seems to be bit 6 (0x40)\n");
2011 (void)printk("Tx antenna selection seems to be bit 5 (0x20)\n");
2012 priv->antenna = (UINT8)*extra;
2013 (void)printk("new antenna value: 0x%02X\n", priv->antenna);
2014 priv->set_mask |= GETSET_ANTENNA;
2016 return -EINPROGRESS;
2019 /*----------------------------------------------------------------
2020 * acx100_ioctl_get_antenna
2023 * Arguments:
2025 * Returns:
2027 * Side effects:
2029 * Call context:
2031 * STATUS: NEW
2033 * Comment:
2035 *----------------------------------------------------------------*/
2036 static inline int acx100_ioctl_get_antenna(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2038 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2040 (void)printk("current antenna value: 0x%02X\n", priv->antenna);
2041 (void)printk("Rx antenna selection seems to be bit 6 (0x40)\n");
2042 (void)printk("Tx antenna selection seems to be bit 5 (0x20)\n");
2044 return 0;
2047 /*----------------------------------------------------------------
2048 * acx100_ioctl_set_rx_antenna
2051 * Arguments: 0 = antenna1; 1 = antenna2;
2052 * / 2 and 3 = diversity? - need test /
2053 * Returns:
2055 * Side effects:
2057 * Call context:
2059 * STATUS: NEW
2061 * Comment: Could anybody test which antenna is the external one
2063 *----------------------------------------------------------------*/
2064 static inline int acx100_ioctl_set_rx_antenna(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2066 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2067 unsigned long flags;
2068 int err;
2069 int result = -EINVAL;
2071 FN_ENTER;
2072 (void)printk("current antenna value: 0x%02X\n", priv->antenna);
2073 /* better keep the separate operations atomic */
2074 if (0 != (err = acx100_lock(priv, &flags))) {
2075 result = err;
2076 goto end;
2078 priv->antenna &= 0x3f;
2079 priv->antenna |= (*extra << 6);
2080 priv->set_mask |= GETSET_ANTENNA;
2081 acx100_unlock(priv, &flags);
2082 (void)printk("new antenna value: 0x%02X\n", priv->antenna);
2083 result = -EINPROGRESS;
2085 end:
2086 FN_EXIT(1, result);
2087 return result;
2090 /*----------------------------------------------------------------
2091 * acx100_ioctl_set_tx_antenna
2094 * Arguments: 0 = antenna1; 1 = antenna2;
2096 * Returns:
2098 * Side effects:
2100 * Call context:
2102 * STATUS: NEW
2104 * Comment: Could anybody test which antenna is the external one
2106 *----------------------------------------------------------------*/
2107 static inline int acx100_ioctl_set_tx_antenna(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2109 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2110 unsigned long flags;
2111 int err;
2112 int result = -EINVAL;
2114 FN_ENTER;
2115 (void)printk("current antenna value: 0x%02X\n", priv->antenna);
2116 /* better keep the separate operations atomic */
2117 if (0 != (err = acx100_lock(priv, &flags))) {
2118 result = err;
2119 goto end;
2121 priv->antenna &= 0xdf;
2122 priv->antenna |= ((*extra &= 0x01) << 5);
2123 priv->set_mask |= GETSET_ANTENNA;
2124 acx100_unlock(priv, &flags);
2125 (void)printk("new antenna value: 0x%02X\n", priv->antenna);
2126 result = -EINPROGRESS;
2128 end:
2129 FN_EXIT(1, result);
2130 return result;
2133 /*----------------------------------------------------------------
2134 * acx100_ioctl_wlansniff
2137 * Arguments:
2139 * Returns:
2141 * Side effects:
2143 * Call context:
2145 * STATUS: NEW
2147 * Comment:
2149 *----------------------------------------------------------------*/
2150 static inline int acx100_ioctl_wlansniff(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2152 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2153 int *parms = (int*)extra;
2154 int enable = (int)(parms[0] > 0);
2155 unsigned long flags;
2156 int err;
2157 int result = -EINVAL;
2159 FN_ENTER;
2161 if (0 != (err = acx100_lock(priv, &flags))) {
2162 result = err;
2163 goto end;
2166 priv->monitor = parms[0];
2167 /* not using printk() here, since it distorts kismet display
2168 * when printk messages activated */
2169 acxlog(L_IOCTL, "setting monitor to: 0x%02X\n", priv->monitor);
2171 switch (parms[0])
2173 case 0:
2174 priv->netdev->type = ARPHRD_ETHER;
2175 break;
2176 case 1:
2177 priv->netdev->type = ARPHRD_IEEE80211_PRISM;
2178 break;
2179 case 2:
2180 priv->netdev->type = ARPHRD_IEEE80211;
2181 break;
2184 if (0 != priv->monitor)
2185 priv->monitor_setting = 0x02; /* don't decrypt default key only, override decryption mechanism */
2186 else
2187 priv->monitor_setting = 0x00; /* don't decrypt default key only, don't override decryption */
2189 priv->set_mask |= SET_RXCONFIG | SET_WEP_OPTIONS;
2191 if (0 != enable)
2193 priv->channel = parms[1];
2194 priv->set_mask |= GETSET_RX;
2196 acx100_unlock(priv, &flags);
2197 result = -EINPROGRESS;
2199 end:
2200 FN_EXIT(1, result);
2201 return result;
2204 /*----------------------------------------------------------------
2205 * acx100_ioctl_unknown11
2208 * Arguments:
2210 * Returns:
2212 * Side effects:
2214 * Call context:
2216 * STATUS: NEW
2218 * Comment:
2220 *----------------------------------------------------------------*/
2221 static inline int acx100_ioctl_unknown11(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2223 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2224 unsigned long flags;
2225 client_t client;
2226 int err;
2227 int result = -EINVAL;
2229 if (0 != (err = acx100_lock(priv, &flags))) {
2230 result = err;
2231 goto end;
2233 acx100_transmit_disassoc(&client, priv);
2234 acx100_unlock(priv, &flags);
2235 result = 0;
2237 end:
2238 return result;
2241 /* debug helper function to be able to debug various issues relatively easily */
2242 static inline int acx100_ioctl_dbg_set_masks(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2244 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2245 int *parms = (int*)extra;
2246 int result = -EINVAL;
2248 acxlog(L_IOCTL, "setting flags in settings mask: get_mask %08x set_mask %08x\n", (UINT32)parms[0], (UINT32)parms[1]);
2249 acxlog(L_IOCTL, "before: get_mask %08x set_mask %08x\n", priv->get_mask, priv->set_mask);
2250 priv->get_mask |= (UINT32)parms[0];
2251 priv->set_mask |= (UINT32)parms[1];
2252 acxlog(L_IOCTL, "after: get_mask %08x set_mask %08x\n", priv->get_mask, priv->set_mask);
2253 result = -EINPROGRESS; /* immediately call commit handler */
2255 return result;
2258 /*----------------------------------------------------------------
2259 * acx100_ioctl_acx111_info
2262 * Arguments:
2264 * Returns:
2266 * Side effects:
2268 * Call context:
2270 * STATUS: NEW
2272 * Comment:
2274 *----------------------------------------------------------------*/
2275 static inline int acx100_ioctl_acx111_info(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2277 wlandevice_t *priv = (wlandevice_t *) dev->priv;
2278 TIWLAN_DC *pDc = &priv->dc;
2279 struct rxdescriptor *rx_desc = (struct rxdescriptor *) pDc->pRxDescQPool;
2280 int i;
2281 int result = -EINVAL;
2282 struct ACX111MemoryConfig memconf;
2283 struct ACX111QueueConfig queueconf;
2284 char memmap[0x34];
2285 char rxconfig[0x8];
2286 char fcserror[0x8];
2287 char ratefallback[0x5];
2288 struct rxhostdescriptor *rx_host_desc;
2289 struct txdescriptor *tx_desc;
2290 struct txhostdescriptor *tx_host_desc;
2293 if ((err = acx100_lock(priv, &flags))) {
2294 result = err;
2295 goto end;
2298 if (CHIPTYPE_ACX111 != priv->chip_type) {
2299 acxlog(L_STD | L_IOCTL, "ACX111-specific function called with non-ACX111 chip, aborting!\n");
2300 return 0;
2303 /* get Acx111 Memory Configuration */
2304 memset(&memconf, 0x00, sizeof(memconf));
2306 if (!acx100_interrogate(priv, &memconf, 0x03)) {
2307 acxlog(L_BINSTD, "read memconf returns error\n");
2310 /* get Acx111 Queue Configuration */
2311 memset(&queueconf, 0x00, sizeof(queueconf));
2313 if (!acx100_interrogate(priv, &queueconf, 0x05)) {
2314 acxlog(L_BINSTD, "read queuehead returns error\n");
2317 /* get Acx111 Memory Map */
2318 memset(memmap, 0x00, sizeof(memmap));
2320 if (!acx100_interrogate(priv, &memmap, 0x08)) {
2321 acxlog(L_BINSTD, "read mem map returns error\n");
2324 /* get Acx111 Rx Config */
2325 memset(rxconfig, 0x00, sizeof(rxconfig));
2327 if (!acx100_interrogate(priv, &rxconfig, 0x10)) {
2328 acxlog(L_BINSTD, "read rxconfig returns error\n");
2331 /* get Acx111 fcs error count */
2332 memset(fcserror, 0x00, sizeof(fcserror));
2334 if (!acx100_interrogate(priv, &fcserror, 0x0e)) {
2335 acxlog(L_BINSTD, "read fcserror returns error\n");
2338 /* get Acx111 rate fallback */
2339 memset(ratefallback, 0x00, sizeof(ratefallback));
2341 if (!acx100_interrogate(priv, &ratefallback, 0x06)) {
2342 acxlog(L_BINSTD, "read ratefallback returns error\n");
2345 #if (WLAN_HOSTIF!=WLAN_USB)
2346 /* force occurrence of a beacon interrupt */
2347 acx100_write_reg16(priv, priv->io[IO_ACX_HINT_TRIG], 0x20);
2348 #endif
2350 /* dump Acx111 Mem Configuration */
2351 acxlog(L_STD, "dump mem config:\n");
2352 acxlog(L_STD, "data read: %d, struct size: %d\n", memconf.length, sizeof(memconf));
2353 acxlog(L_STD, "Number of stations: %1X\n", memconf.no_of_stations);
2354 acxlog(L_STD, "Memory block size: %1X\n", memconf.memory_block_size);
2355 acxlog(L_STD, "tx/rx memory block allocation: %1X\n", memconf.tx_rx_memory_block_allocation);
2356 acxlog(L_STD, "count rx: %X / tx: %X queues\n", memconf.count_rx_queues, memconf.count_tx_queues);
2357 acxlog(L_STD, "options %1X\n", memconf.options);
2358 acxlog(L_STD, "fragmentation %1X\n", memconf.fragmentation);
2360 acxlog(L_STD, "Rx Queue 1 Count Descriptors: %X\n", memconf.rx_queue1_count_descs);
2361 acxlog(L_STD, "Rx Queue 1 Host Memory Start: %X\n", memconf.rx_queue1_host_rx_start);
2363 acxlog(L_STD, "Tx Queue 1 Count Descriptors: %X\n", memconf.tx_queue1_count_descs);
2364 acxlog(L_STD, "Tx Queue 1 Attributes: %X\n", memconf.tx_queue1_attributes);
2367 /* dump Acx111 Queue Configuration */
2368 acxlog(L_STD, "dump queue head:\n");
2369 acxlog(L_STD, "data read: %d, struct size: %d\n", queueconf.length, sizeof(queueconf));
2370 acxlog(L_STD, "tx_memory_block_address (from card): %X\n", queueconf.tx_memory_block_address);
2371 acxlog(L_STD, "rx_memory_block_address (from card): %X\n", queueconf.rx_memory_block_address);
2373 acxlog(L_STD, "rx1_queue address (from card): %X\n", queueconf.rx1_queue_address);
2374 acxlog(L_STD, "tx1_queue address (from card): %X\n", queueconf.tx1_queue_address);
2375 acxlog(L_STD, "tx1_queue attributes (from card): %X\n", queueconf.tx1_attributes);
2377 /* dump Acx111 Mem Map */
2378 acxlog(L_STD, "dump mem map:\n");
2379 acxlog(L_STD, "data read: %d, struct size: %d\n", *((UINT16 *)&memmap[0x02]), sizeof(memmap));
2380 acxlog(L_STD, "Code start: %X\n", *((UINT32 *)&memmap[0x04]));
2381 acxlog(L_STD, "Code end: %X\n", *((UINT32 *)&memmap[0x08]));
2382 acxlog(L_STD, "WEP default key start: %X\n", *((UINT32 *)&memmap[0x0C]));
2383 acxlog(L_STD, "WEP default key end: %X\n", *((UINT32 *)&memmap[0x10]));
2384 acxlog(L_STD, "STA table start: %X\n", *((UINT32 *)&memmap[0x14]));
2385 acxlog(L_STD, "STA table end: %X\n", *((UINT32 *)&memmap[0x18]));
2386 acxlog(L_STD, "Packet template start: %X\n", *((UINT32 *)&memmap[0x1C]));
2387 acxlog(L_STD, "Packet template end: %X\n", *((UINT32 *)&memmap[0x20]));
2388 acxlog(L_STD, "Queue memory start: %X\n", *((UINT32 *)&memmap[0x24]));
2389 acxlog(L_STD, "Queue memory end: %X\n", *((UINT32 *)&memmap[0x28]));
2390 acxlog(L_STD, "Packet memory pool start: %X\n", *((UINT32 *)&memmap[0x2C]));
2391 acxlog(L_STD, "Packet memory pool end: %X\n", *((UINT32 *)&memmap[0x30]));
2393 acxlog(L_STD, "iobase: %p\n", priv->iobase);
2394 acxlog(L_STD, "iobase2: %p\n", priv->iobase2);
2396 /* dump Acx111 Rx Config */
2397 acxlog(L_STD, "dump rx config:\n");
2398 acxlog(L_STD, "data read: %d, struct size: %d\n", *((UINT16 *)&rxconfig[0x02]), sizeof(rxconfig));
2399 acxlog(L_STD, "rx config: %X\n", *((UINT16 *)&rxconfig[0x04]));
2400 acxlog(L_STD, "rx filter config: %X\n", *((UINT16 *)&rxconfig[0x06]));
2402 /* dump Acx111 fcs error */
2403 acxlog(L_STD, "dump fcserror:\n");
2404 acxlog(L_STD, "data read: %d, struct size: %d\n", *((UINT16 *)&fcserror[0x02]), sizeof(fcserror));
2405 acxlog(L_STD, "fcserrors: %X\n", *((UINT32 *)&fcserror[0x04]));
2407 /* dump Acx111 rate fallback */
2408 acxlog(L_STD, "dump rate fallback:\n");
2409 acxlog(L_STD, "data read: %d, struct size: %d\n", *((UINT16 *)&ratefallback[0x02]), sizeof(ratefallback));
2410 acxlog(L_STD, "ratefallback: %X\n", *((UINT8 *)&ratefallback[0x04]));
2412 /* dump acx111 internal rx descriptor ring buffer */
2414 /* loop over complete receive pool */
2415 for (i = 0; i < pDc->rx_pool_count; i++) {
2417 acxlog(L_STD, "\ndump internal rxdescriptor %d:\n", i);
2418 acxlog(L_STD, "mem pos %p\n", rx_desc);
2419 acxlog(L_STD, "next 0x%X\n", rx_desc->pNextDesc);
2420 acxlog(L_STD, "acx mem pointer (dynamic) 0x%X\n", rx_desc->ACXMemPtr);
2421 acxlog(L_STD, "CTL (dynamic) 0x%X\n", rx_desc->Ctl);
2422 acxlog(L_STD, "Rate (dynamic) 0x%X\n", rx_desc->rate);
2423 acxlog(L_STD, "RxStatus (dynamic) 0x%X\n", rx_desc->error);
2424 acxlog(L_STD, "Mod/Pre (dynamic) 0x%X\n", rx_desc->SNR);
2426 rx_desc++;
2429 /* dump host rx descriptor ring buffer */
2431 rx_host_desc = (struct rxhostdescriptor *) pDc->pRxHostDescQPool;
2433 /* loop over complete receive pool */
2434 for (i = 0; i < pDc->rx_pool_count; i++) {
2436 acxlog(L_STD, "\ndump host rxdescriptor %d:\n", i);
2437 acxlog(L_STD, "mem pos 0x%X\n", (UINT32)rx_host_desc);
2438 acxlog(L_STD, "buffer mem pos 0x%X\n", (UINT32)rx_host_desc->data_phy);
2439 acxlog(L_STD, "buffer mem offset 0x%X\n", rx_host_desc->data_offset);
2440 acxlog(L_STD, "CTL 0x%X\n", rx_host_desc->Ctl);
2441 acxlog(L_STD, "Length 0x%X\n", rx_host_desc->length);
2442 acxlog(L_STD, "next 0x%X\n", (UINT32)rx_host_desc->desc_phy_next);
2443 acxlog(L_STD, "Status 0x%X\n", rx_host_desc->Status);
2445 rx_host_desc ++;
2449 /* dump acx111 internal tx descriptor ring buffer */
2450 tx_desc = (struct txdescriptor *) pDc->pTxDescQPool;
2452 /* loop over complete transmit pool */
2453 for (i = 0; i < pDc->tx_pool_count; i++) {
2455 acxlog(L_STD, "\ndump internal txdescriptor %d:\n", i);
2456 acxlog(L_STD, "size 0x%X\n", sizeof(struct txdescriptor));
2457 acxlog(L_STD, "mem pos 0x%X\n", (UINT32)tx_desc);
2458 acxlog(L_STD, "next 0x%X\n", tx_desc->pNextDesc);
2459 acxlog(L_STD, "acx mem pointer (dynamic) 0x%X\n", tx_desc->AcxMemPtr);
2460 acxlog(L_STD, "host mem pointer (dynamic) 0x%X\n", tx_desc->HostMemPtr);
2461 acxlog(L_STD, "length (dynamic) 0x%X\n", tx_desc->total_length);
2462 acxlog(L_STD, "CTL (dynamic) 0x%X\n", tx_desc->Ctl);
2463 acxlog(L_STD, "CTL2 (dynamic) 0x%X\n", tx_desc->Ctl2);
2464 acxlog(L_STD, "Status (dynamic) 0x%X\n", tx_desc->error);
2465 acxlog(L_STD, "Rate (dynamic) 0x%X\n", tx_desc->rate);
2467 tx_desc++;
2468 if(priv->chip_type == CHIPTYPE_ACX111) {
2469 /* the acx111 txdescriptor is 4 byte larger = 0x34 */
2470 tx_desc = (struct txdescriptor *) (((UINT32)tx_desc) + 4);
2475 /* dump host tx descriptor ring buffer */
2477 tx_host_desc = (struct txhostdescriptor *) pDc->pTxHostDescQPool;
2479 /* loop over complete host send pool */
2480 for (i = 0; i < pDc->tx_pool_count * 2; i++) {
2482 acxlog(L_STD, "\ndump host txdescriptor %d:\n", i);
2483 acxlog(L_STD, "mem pos 0x%X\n", (UINT32)tx_host_desc);
2484 acxlog(L_STD, "buffer mem pos 0x%X\n", (UINT32)tx_host_desc->data_phy);
2485 acxlog(L_STD, "buffer mem offset 0x%X\n", tx_host_desc->data_offset);
2486 acxlog(L_STD, "CTL 0x%X\n", tx_host_desc->Ctl);
2487 acxlog(L_STD, "Length 0x%X\n", tx_host_desc->length);
2488 acxlog(L_STD, "next 0x%X\n", (UINT32)tx_host_desc->desc_phy_next);
2489 acxlog(L_STD, "Status 0x%X\n", tx_host_desc->Status);
2491 tx_host_desc ++;
2495 /* acx100_write_reg16(priv, 0xb4, 0x4); */
2497 /* acx100_unlock(priv, &flags); */
2498 result = 0;
2500 return result;
2504 /*----------------------------------------------------------------
2505 * acx100_ioctl_set_ed_threshold
2508 * Arguments:
2510 * Returns:
2512 * Side effects:
2514 * Call context:
2516 * STATUS: NEW
2518 * Comment:
2520 *----------------------------------------------------------------*/
2521 static inline int acx100_ioctl_set_ed_threshold(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2523 wlandevice_t *priv = (wlandevice_t *)dev->priv;
2525 (void)printk("current ED threshold value: %d\n", priv->ed_threshold);
2526 priv->ed_threshold = (unsigned char)*extra;
2527 (void)printk("new ED threshold value: %d\n", (unsigned char)*extra);
2528 priv->set_mask |= GETSET_ED_THRESH;
2530 return -EINPROGRESS;
2533 /*----------------------------------------------------------------
2534 * acx100_ioctl_set_cca
2537 * Arguments:
2539 * Returns:
2541 * Side effects:
2543 * Call context:
2545 * STATUS: NEW
2547 * Comment:
2549 *----------------------------------------------------------------*/
2550 static inline int acx100_ioctl_set_cca(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2552 wlandevice_t *priv = (wlandevice_t *)dev->priv;
2553 unsigned long flags;
2554 int err;
2555 int result = -EINVAL;
2557 if (0 != (err = acx100_lock(priv, &flags))) {
2558 result = err;
2559 goto end;
2562 (void)printk("current CCA value: 0x%02X\n", priv->cca);
2563 priv->cca = (unsigned char)*extra;
2564 (void)printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
2565 priv->set_mask |= GETSET_CCA;
2566 acx100_unlock(priv, &flags);
2567 result = -EINPROGRESS;
2569 end:
2570 return result;
2573 static inline int acx100_ioctl_set_led_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra)
2575 wlandevice_t *priv = (wlandevice_t *)dev->priv;
2576 unsigned long flags;
2577 int err;
2578 int result = -EINVAL;
2580 if (0 != (err = acx100_lock(priv, &flags))) {
2581 result = err;
2582 goto end;
2584 (void)printk("current power LED status: %d\n", priv->led_power);
2585 priv->led_power = (unsigned char)*extra;
2586 (void)printk("new power LED status: %d\n", (unsigned char)*extra);
2587 priv->set_mask |= GETSET_LED_POWER;
2589 acx100_unlock(priv, &flags);
2590 result = -EINPROGRESS;
2592 end:
2593 return result;
2596 #if WIRELESS_EXT >= 13
2597 static const iw_handler acx100_ioctl_handler[] =
2599 (iw_handler) acx100_ioctl_commit, /* SIOCSIWCOMMIT */
2600 (iw_handler) acx100_ioctl_get_name, /* SIOCGIWNAME */
2601 (iw_handler) NULL, /* SIOCSIWNWID */
2602 (iw_handler) NULL, /* SIOCGIWNWID */
2603 (iw_handler) acx100_ioctl_set_freq, /* SIOCSIWFREQ */
2604 (iw_handler) acx100_ioctl_get_freq, /* SIOCGIWFREQ */
2605 (iw_handler) acx100_ioctl_set_mode, /* SIOCSIWMODE */
2606 (iw_handler) acx100_ioctl_get_mode, /* SIOCGIWMODE */
2607 (iw_handler) acx100_ioctl_set_sens, /* SIOCSIWSENS */
2608 (iw_handler) acx100_ioctl_get_sens, /* SIOCGIWSENS */
2609 (iw_handler) NULL, /* SIOCSIWRANGE */
2610 (iw_handler) acx100_ioctl_get_range, /* SIOCGIWRANGE */
2611 (iw_handler) NULL, /* SIOCSIWPRIV */
2612 (iw_handler) NULL, /* SIOCGIWPRIV */
2613 (iw_handler) NULL, /* SIOCSIWSTATS */
2614 (iw_handler) NULL, /* SIOCGIWSTATS */
2615 #if IW_HANDLER_VERSION > 4
2616 iw_handler_set_spy, /* SIOCSIWSPY */
2617 iw_handler_get_spy, /* SIOCGIWSPY */
2618 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2619 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2620 #else /* IW_HANDLER_VERSION > 4 */
2621 #ifdef WIRELESS_SPY
2622 (iw_handler) NULL /* acx100_ioctl_set_spy */, /* SIOCSIWSPY */
2623 (iw_handler) NULL /* acx100_ioctl_get_spy */, /* SIOCGIWSPY */
2624 #else /* WSPY */
2625 (iw_handler) NULL, /* SIOCSIWSPY */
2626 (iw_handler) NULL, /* SIOCGIWSPY */
2627 #endif /* WSPY */
2628 (iw_handler) NULL, /* [nothing] */
2629 (iw_handler) NULL, /* [nothing] */
2630 #endif /* IW_HANDLER_VERSION > 4 */
2631 (iw_handler) acx100_ioctl_set_ap, /* SIOCSIWAP */
2632 (iw_handler) acx100_ioctl_get_ap, /* SIOCGIWAP */
2633 (iw_handler) NULL, /* [nothing] */
2634 (iw_handler) acx100_ioctl_get_aplist, /* SIOCGIWAPLIST */
2635 #if WIRELESS_EXT > 13
2636 (iw_handler) acx100_ioctl_set_scan, /* SIOCSIWSCAN */
2637 (iw_handler) acx100_ioctl_get_scan, /* SIOCGIWSCAN */
2638 #else /* WE > 13 */
2639 (iw_handler) NULL, /* SIOCSIWSCAN */
2640 (iw_handler) NULL, /* SIOCGIWSCAN */
2641 #endif /* WE > 13 */
2642 (iw_handler) acx100_ioctl_set_essid, /* SIOCSIWESSID */
2643 (iw_handler) acx100_ioctl_get_essid, /* SIOCGIWESSID */
2644 (iw_handler) acx100_ioctl_set_nick, /* SIOCSIWNICKN */
2645 (iw_handler) acx100_ioctl_get_nick, /* SIOCGIWNICKN */
2646 (iw_handler) NULL, /* [nothing] */
2647 (iw_handler) NULL, /* [nothing] */
2648 (iw_handler) acx100_ioctl_set_rate, /* SIOCSIWRATE */
2649 (iw_handler) acx100_ioctl_get_rate, /* SIOCGIWRATE */
2650 (iw_handler) acx100_ioctl_set_rts, /* SIOCSIWRTS */
2651 (iw_handler) acx100_ioctl_get_rts, /* SIOCGIWRTS */
2652 (iw_handler) NULL /* acx100_ioctl_set_frag FIXME */, /* SIOCSIWFRAG */
2653 (iw_handler) NULL /* acx100_ioctl_get_frag FIXME */, /* SIOCGIWFRAG */
2654 (iw_handler) acx100_ioctl_set_txpow, /* SIOCSIWTXPOW */
2655 (iw_handler) acx100_ioctl_get_txpow, /* SIOCGIWTXPOW */
2656 (iw_handler) acx100_ioctl_set_retry, /* SIOCSIWRETRY */
2657 (iw_handler) acx100_ioctl_get_retry, /* SIOCGIWRETRY */
2658 (iw_handler) acx100_ioctl_set_encode, /* SIOCSIWENCODE */
2659 (iw_handler) acx100_ioctl_get_encode, /* SIOCGIWENCODE */
2660 (iw_handler) acx100_ioctl_set_power, /* SIOCSIWPOWER */
2661 (iw_handler) acx100_ioctl_get_power, /* SIOCGIWPOWER */
2664 static const iw_handler acx100_ioctl_private_handler[] =
2666 #ifdef ACX_DEBUG
2667 (iw_handler) acx100_ioctl_set_debug, /* SIOCIWFIRSTPRIV */
2668 #else
2669 (iw_handler) NULL,
2670 #endif
2671 (iw_handler) acx100_ioctl_list_reg_domain,
2672 (iw_handler) acx100_ioctl_set_reg_domain,
2673 (iw_handler) acx100_ioctl_get_reg_domain,
2674 (iw_handler) acx100_ioctl_set_short_preamble,
2675 (iw_handler) acx100_ioctl_get_short_preamble,
2676 (iw_handler) acx100_ioctl_set_antenna,
2677 (iw_handler) acx100_ioctl_get_antenna,
2678 (iw_handler) acx100_ioctl_set_rx_antenna,
2679 (iw_handler) acx100_ioctl_set_tx_antenna,
2680 (iw_handler) acx100_ioctl_set_ed_threshold,
2681 (iw_handler) acx100_ioctl_set_cca,
2682 (iw_handler) acx100_ioctl_set_led_power,
2683 (iw_handler) acx100_ioctl_wlansniff,
2684 (iw_handler) acx100_ioctl_unknown11,
2685 (iw_handler) acx100_ioctl_dbg_set_masks,
2686 (iw_handler) acx100_ioctl_acx111_info
2689 const struct iw_handler_def acx100_ioctl_handler_def =
2691 .num_standard = sizeof(acx100_ioctl_handler)/sizeof(iw_handler),
2692 .num_private = sizeof(acx100_ioctl_private_handler)/sizeof(iw_handler),
2693 .num_private_args = sizeof(acx100_ioctl_private_args)/sizeof(struct iw_priv_args),
2694 .standard = (iw_handler *) acx100_ioctl_handler,
2695 .private = (iw_handler *) acx100_ioctl_private_handler,
2696 .private_args = (struct iw_priv_args *) acx100_ioctl_private_args,
2697 #if WIRELESS_EXT > 15
2698 .spy_offset = 0 /* FIXME */,
2699 #endif /* WE > 15 */
2702 #endif /* WE > 12 */
2706 #if WIRELESS_EXT < 13
2707 /*================================================================*/
2708 /* Main function */
2709 /*================================================================*/
2710 /*----------------------------------------------------------------
2711 * acx_ioctl_old
2714 * Arguments:
2716 * Returns:
2718 * Side effects:
2720 * Call context:
2722 * STATUS: FINISHED
2724 * Comment:
2725 * This is the *OLD* ioctl handler.
2726 * Make sure to not only place your additions here, but instead mainly
2727 * in the new one (acx100_ioctl_handler[])!
2729 *----------------------------------------------------------------*/
2730 int acx_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd)
2732 wlandevice_t *priv = (wlandevice_t *)dev->priv;
2733 int result = 0;
2734 #if WIRELESS_EXT < 13
2735 struct iwreq *iwr = (struct iwreq *)ifr;
2736 #endif
2738 acxlog(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd);
2740 /* This is the way it is done in the orinoco driver.
2741 * Check to see if device is present.
2743 if (0 == netif_device_present(dev))
2745 return -ENODEV;
2748 switch (cmd) {
2749 /* WE 13 and higher will use acx100_ioctl_handler_def */
2750 #if WIRELESS_EXT < 13
2751 case SIOCGIWNAME:
2752 /* get name == wireless protocol */
2753 result = acx100_ioctl_get_name(dev, NULL,
2754 (char *)&(iwr->u.name), NULL);
2755 break;
2757 case SIOCSIWNWID: /* pre-802.11, */
2758 case SIOCGIWNWID: /* not supported. */
2759 result = -EOPNOTSUPP;
2760 break;
2762 case SIOCSIWFREQ:
2763 /* set channel/frequency (Hz)
2764 data can be frequency or channel :
2765 0-1000 = channel
2766 > 1000 = frequency in Hz */
2767 result = acx100_ioctl_set_freq(dev, NULL, &(iwr->u.freq), NULL);
2768 break;
2770 case SIOCGIWFREQ:
2771 /* get channel/frequency (Hz) */
2772 result = acx100_ioctl_get_freq(dev, NULL, &(iwr->u.freq), NULL);
2773 break;
2775 case SIOCSIWMODE:
2776 /* set operation mode */
2777 result = acx100_ioctl_set_mode(dev, NULL, &(iwr->u.mode), NULL);
2778 break;
2780 case SIOCGIWMODE:
2781 /* get operation mode */
2782 result = acx100_ioctl_get_mode(dev, NULL, &(iwr->u.mode), NULL);
2783 break;
2785 case SIOCSIWSENS:
2786 /* Set sensitivity */
2787 result = acx100_ioctl_set_sens(dev, NULL, &(iwr->u.sens), NULL);
2788 break;
2790 case SIOCGIWSENS:
2791 /* Get sensitivity */
2792 result = acx100_ioctl_get_sens(dev, NULL, &(iwr->u.sens), NULL);
2793 break;
2795 #if WIRELESS_EXT > 10
2796 case SIOCGIWRANGE:
2797 /* Get range of parameters */
2799 struct iw_range range;
2800 result = acx100_ioctl_get_range(dev, NULL,
2801 &(iwr->u.data), (char *)&range);
2802 if (copy_to_user(iwr->u.data.pointer, &range,
2803 sizeof(struct iw_range)))
2804 result = -EFAULT;
2806 break;
2807 #endif
2809 case SIOCGIWPRIV:
2810 result = acx100_ioctl_get_iw_priv(iwr);
2811 break;
2813 /* case SIOCSIWSPY: FIXME */
2814 /* case SIOCGIWSPY: FIXME */
2815 /* case SIOCSIWTHRSPY: FIXME */
2816 /* case SIOCGIWTHRSPY: FIXME */
2818 case SIOCSIWAP:
2819 /* set access point by MAC address */
2820 result = acx100_ioctl_set_ap(dev, NULL, &(iwr->u.ap_addr),
2821 NULL);
2822 break;
2824 case SIOCGIWAP:
2825 /* get access point MAC address */
2826 result = acx100_ioctl_get_ap(dev, NULL, &(iwr->u.ap_addr),
2827 NULL);
2828 break;
2830 case SIOCGIWAPLIST:
2831 /* get list of access points in range */
2832 result = acx100_ioctl_get_aplist(dev, NULL, &(iwr->u.data),
2833 NULL);
2834 break;
2836 #if NOT_FINISHED_YET
2837 /* FIXME: do proper interfacing to activate that! */
2838 case SIOCSIWSCAN:
2839 /* start a station scan */
2840 result = acx100_ioctl_set_scan(iwr, priv);
2841 break;
2843 case SIOCGIWSCAN:
2844 /* get list of stations found during scan */
2845 result = acx100_ioctl_get_scan(iwr, priv);
2846 break;
2847 #endif
2849 case SIOCSIWESSID:
2850 /* set ESSID (network name) */
2852 char essid[IW_ESSID_MAX_SIZE+1];
2854 if (iwr->u.essid.length > IW_ESSID_MAX_SIZE)
2856 result = -E2BIG;
2857 break;
2859 if (copy_from_user(essid, iwr->u.essid.pointer,
2860 iwr->u.essid.length))
2862 result = -EFAULT;
2863 break;
2865 result = acx100_ioctl_set_essid(dev, NULL,
2866 &(iwr->u.essid), essid);
2868 break;
2870 case SIOCGIWESSID:
2871 /* get ESSID */
2873 char essid[IW_ESSID_MAX_SIZE+1];
2874 if (iwr->u.essid.pointer)
2875 result = acx100_ioctl_get_essid(dev, NULL,
2876 &(iwr->u.essid), essid);
2877 if (copy_to_user(iwr->u.essid.pointer, essid,
2878 iwr->u.essid.length))
2879 result = -EFAULT;
2881 break;
2883 case SIOCSIWNICKN:
2884 /* set nick */
2886 char nick[IW_ESSID_MAX_SIZE+1];
2888 if (iwr->u.data.length > IW_ESSID_MAX_SIZE)
2890 result = -E2BIG;
2891 break;
2893 if (copy_from_user(nick, iwr->u.data.pointer,
2894 iwr->u.data.length))
2896 result = -EFAULT;
2897 break;
2899 result = acx100_ioctl_set_nick(dev, NULL,
2900 &(iwr->u.data), nick);
2902 break;
2904 case SIOCGIWNICKN:
2905 /* get nick */
2907 char nick[IW_ESSID_MAX_SIZE+1];
2908 if (iwr->u.data.pointer)
2909 result = acx100_ioctl_get_nick(dev, NULL,
2910 &(iwr->u.data), nick);
2911 if (copy_to_user(iwr->u.data.pointer, nick,
2912 iwr->u.data.length))
2913 result = -EFAULT;
2915 break;
2917 case SIOCSIWRATE:
2918 /* set default bit rate (bps) */
2919 result = acx100_ioctl_set_rate(dev, NULL, &(iwr->u.bitrate),
2920 NULL);
2921 break;
2923 case SIOCGIWRATE:
2924 /* get default bit rate (bps) */
2925 result = acx100_ioctl_get_rate(dev, NULL, &(iwr->u.bitrate),
2926 NULL);
2927 break;
2929 case SIOCSIWRTS:
2930 /* set RTS threshold value */
2931 result = acx100_ioctl_set_rts(dev, NULL, &(iwr->u.rts), NULL);
2932 break;
2933 case SIOCGIWRTS:
2934 /* get RTS threshold value */
2935 result = acx100_ioctl_get_rts(dev, NULL, &(iwr->u.rts), NULL);
2936 break;
2938 /* case SIOCSIWFRAG: FIXME */
2939 /* case SIOCGIWFRAG: FIXME */
2941 #if WIRELESS_EXT > 9
2942 case SIOCGIWTXPOW:
2943 /* get tx power */
2944 result = acx100_ioctl_get_txpow(dev, NULL, &(iwr->u.txpower),
2945 NULL);
2946 break;
2948 case SIOCSIWTXPOW:
2949 /* set tx power */
2950 result = acx100_ioctl_set_txpow(dev, NULL, &(iwr->u.txpower),
2951 NULL);
2952 break;
2953 #endif
2955 case SIOCSIWRETRY:
2956 result = acx100_ioctl_set_retry(dev, NULL, &(iwr->u.retry), NULL);
2957 break;
2959 case SIOCGIWRETRY:
2960 result = acx100_ioctl_get_retry(dev, NULL, &(iwr->u.retry), NULL);
2961 break;
2963 case SIOCSIWENCODE:
2965 /* set encoding token & mode */
2966 UINT8 key[29];
2967 if (iwr->u.encoding.pointer) {
2968 if (iwr->u.encoding.length > 29) {
2969 result = -E2BIG;
2970 break;
2972 if (copy_from_user(key, iwr->u.encoding.pointer, iwr->u.encoding.length)) {
2973 result = -EFAULT;
2974 break;
2977 else
2978 if (0 != iwr->u.encoding.length) {
2979 result = -EINVAL;
2980 break;
2982 result = acx100_ioctl_set_encode(dev, NULL,
2983 &(iwr->u.encoding), key);
2985 break;
2987 case SIOCGIWENCODE:
2989 /* get encoding token & mode */
2990 UINT8 key[29];
2992 result = acx100_ioctl_get_encode(dev, NULL,
2993 &(iwr->u.encoding), key);
2994 if (iwr->u.encoding.pointer) {
2995 if (copy_to_user(iwr->u.encoding.pointer,
2996 key, iwr->u.encoding.length))
2997 result = -EFAULT;
3000 break;
3002 /******************** iwpriv ioctls below ********************/
3003 #ifdef ACX_DEBUG
3004 case ACX100_IOCTL_DEBUG:
3005 acx100_ioctl_set_debug(dev, NULL, NULL, iwr->u.name);
3006 break;
3007 #endif
3009 case ACX100_IOCTL_LIST_DOM:
3010 acx100_ioctl_list_reg_domain(dev, NULL, NULL, NULL);
3011 break;
3013 case ACX100_IOCTL_SET_DOM:
3014 acx100_ioctl_set_reg_domain(dev, NULL, NULL, iwr->u.name);
3015 break;
3017 case ACX100_IOCTL_GET_DOM:
3018 acx100_ioctl_get_reg_domain(dev, NULL, NULL, iwr->u.name);
3019 break;
3021 case ACX100_IOCTL_SET_PREAMB:
3022 acx100_ioctl_set_short_preamble(dev, NULL, NULL, iwr->u.name);
3023 break;
3025 case ACX100_IOCTL_GET_PREAMB:
3026 acx100_ioctl_get_short_preamble(dev, NULL, NULL, iwr->u.name);
3027 break;
3029 case ACX100_IOCTL_SET_ANT:
3030 acx100_ioctl_set_antenna(dev, NULL, NULL, iwr->u.name);
3031 break;
3033 case ACX100_IOCTL_GET_ANT:
3034 acx100_ioctl_get_antenna(dev, NULL, NULL, NULL);
3035 break;
3037 case ACX100_IOCTL_SET_ED:
3038 acx100_ioctl_set_ed_threshold(dev, NULL, NULL, iwr->u.name);
3039 break;
3041 case ACX100_IOCTL_SET_CCA:
3042 acx100_ioctl_set_cca(dev, NULL, NULL, iwr->u.name);
3043 break;
3045 case ACX100_IOCTL_SET_PLED:
3046 acx100_ioctl_set_led_power(dev, NULL, NULL, iwr->u.name);
3047 break;
3049 case ACX100_IOCTL_MONITOR: /* set sniff (monitor) mode */
3050 acxlog(L_IOCTL, "%s: IWPRIV monitor\n", dev->name);
3052 /* can only be done by admin */
3053 if (!capable(CAP_NET_ADMIN)) {
3054 result = -EPERM;
3055 break;
3057 result = acx100_ioctl_wlansniff(dev, NULL, NULL, iwr->u.name);
3058 break;
3060 case ACX100_IOCTL_RX_ANT:
3061 acx100_ioctl_set_rx_antenna(dev, NULL, NULL, iwr->u.name);
3062 break;
3064 case ACX100_IOCTL_TX_ANT:
3065 acx100_ioctl_set_tx_antenna(dev, NULL, NULL, iwr->u.name);
3066 break;
3068 case ACX100_IOCTL_TEST:
3069 acx100_ioctl_unknown11(dev, NULL, NULL, NULL);
3070 break;
3072 case ACX100_IOCTL_ACX111_INFO:
3073 acx100_ioctl_acx111_info(dev, NULL, NULL, NULL);
3074 break;
3076 #endif
3078 default:
3079 acxlog(L_IOCTL, "wireless ioctl 0x%04X queried but not implemented yet!\n", cmd);
3080 result = -EOPNOTSUPP;
3081 break;
3084 if ((0 != (priv->dev_state_mask & ACX_STATE_IFACE_UP))
3085 && (0 != priv->set_mask))
3086 acx100_update_card_settings(priv, 0, 0, 0);
3088 #if WIRELESS_EXT < 13
3089 /* older WEs don't have a commit handler,
3090 * so we need to fix return code in this case */
3091 if (-EINPROGRESS == result)
3092 result = 0;
3093 #endif
3095 return result;
3097 #endif