| Linux kernel & device driver programming |
| [ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] |
1 /* 1
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-lan
6 Stefano Brivio <st3@riseu
7 Michael Buesch <mbuesch@f
8 Danny van Dyk <kugelfang@
9 Andreas Jaggi <andreas.ja
10
11 Some parts of the code in this file are deri
12 driver Copyright(c) 2003 - 2004 Intel Corpo
13
14 This program is free software; you can redis
15 it under the terms of the GNU General Public
16 the Free Software Foundation; either version
17 (at your option) any later version.
18
19 This program is distributed in the hope that
20 but WITHOUT ANY WARRANTY; without even the i
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU G
25 along with this program; see the file COPYIN
26 the Free Software Foundation, Inc., 51 Frank
27 Boston, MA 02110-1301, USA.
28
29 */
30
31 #include <linux/wireless.h>
32 #include <net/iw_handler.h>
33 #include <net/ieee80211softmac.h>
34 #include <net/ieee80211softmac_wx.h>
35 #include <linux/capability.h>
36 #include <linux/delay.h>
37
38 #include "bcm43xx.h"
39 #include "bcm43xx_wx.h"
40 #include "bcm43xx_main.h"
41 #include "bcm43xx_radio.h"
42 #include "bcm43xx_phy.h"
43
44
45 /* The WIRELESS_EXT version, which is implemen
46 #define BCM43xx_WX_VERSION 18
47
48 #define MAX_WX_STRING 80
49
50 static int bcm43xx_wx_get_name(struct net_devi
51 struct iw_reque
52 union iwreq_dat
53 char *extra)
54 {
55 struct bcm43xx_private *bcm = bcm43xx_
56 int i;
57 struct bcm43xx_phyinfo *phy;
58 char suffix[7] = { 0 };
59 int have_a = 0, have_b = 0, have_g = 0
60
61 mutex_lock(&bcm->mutex);
62 for (i = 0; i < bcm->nr_80211_availabl
63 phy = &(bcm->core_80211_ext[i]
64 switch (phy->type) {
65 case BCM43xx_PHYTYPE_A:
66 have_a = 1;
67 break;
68 case BCM43xx_PHYTYPE_G:
69 have_g = 1;
70 case BCM43xx_PHYTYPE_B:
71 have_b = 1;
72 break;
73 default:
74 assert(0);
75 }
76 }
77 mutex_unlock(&bcm->mutex);
78
79 i = 0;
80 if (have_a) {
81 suffix[i++] = 'a';
82 suffix[i++] = '/';
83 }
84 if (have_b) {
85 suffix[i++] = 'b';
86 suffix[i++] = '/';
87 }
88 if (have_g) {
89 suffix[i++] = 'g';
90 suffix[i++] = '/';
91 }
92 if (i != 0)
93 suffix[i - 1] = '\0';
94
95 snprintf(data->name, IFNAMSIZ, "IEEE 8
96
97 return 0;
98 }
99
100 static int bcm43xx_wx_set_channelfreq(struct n
101 struct i
102 union iw
103 char *ex
104 {
105 struct bcm43xx_private *bcm = bcm43xx_
106 unsigned long flags;
107 u8 channel;
108 s8 expon;
109 int freq;
110 int err = -EINVAL;
111
112 mutex_lock(&bcm->mutex);
113 spin_lock_irqsave(&bcm->irq_lock, flag
114
115 if ((data->freq.e == 0) &&
116 (data->freq.m >= 0) && (data->freq
117 channel = data->freq.m;
118 freq = bcm43xx_channel_to_freq
119 } else {
120 freq = data->freq.m;
121 expon = 6 - data->freq.e;
122 while (--expon >= 0) /* sca
123 freq /= 10;
124 assert(freq > 1000);
125 channel = bcm43xx_freq_to_chan
126 }
127 if (!ieee80211_is_valid_channel(bcm->i
128 goto out_unlock;
129 if (bcm43xx_status(bcm) == BCM43xx_STA
130 //ieee80211softmac_disassoc(so
131 bcm43xx_mac_suspend(bcm);
132 err = bcm43xx_radio_selectchan
133 bcm43xx_mac_enable(bcm);
134 } else {
135 bcm43xx_current_radio(bcm)->in
136 err = 0;
137 }
138 out_unlock:
139 spin_unlock_irqrestore(&bcm->irq_lock,
140 mutex_unlock(&bcm->mutex);
141
142 return err;
143 }
144
145 static int bcm43xx_wx_get_channelfreq(struct n
146 struct i
147 union iw
148 char *ex
149 {
150 struct bcm43xx_private *bcm = bcm43xx_
151 struct bcm43xx_radioinfo *radio;
152 int err = -ENODEV;
153 u16 channel;
154
155 mutex_lock(&bcm->mutex);
156 radio = bcm43xx_current_radio(bcm);
157 channel = radio->channel;
158 if (channel == 0xFF) {
159 channel = radio->initial_chann
160 if (channel == 0xFF)
161 goto out_unlock;
162 }
163 assert(channel > 0 && channel <= 1000)
164 data->freq.e = 1;
165 data->freq.m = bcm43xx_channel_to_freq
166 data->freq.flags = 1;
167
168 err = 0;
169 out_unlock:
170 mutex_unlock(&bcm->mutex);
171
172 return err;
173 }
174
175 static int bcm43xx_wx_set_mode(struct net_devi
176 struct iw_reque
177 union iwreq_dat
178 char *extra)
179 {
180 struct bcm43xx_private *bcm = bcm43xx_
181 unsigned long flags;
182 int mode;
183
184 mode = data->mode;
185 if (mode == IW_MODE_AUTO)
186 mode = BCM43xx_INITIAL_IWMODE;
187
188 mutex_lock(&bcm->mutex);
189 spin_lock_irqsave(&bcm->irq_lock, flag
190 if (bcm43xx_status(bcm) == BCM43xx_STA
191 if (bcm->ieee->iw_mode != mode
192 bcm43xx_set_iwmode(bcm
193 } else
194 bcm->ieee->iw_mode = mode;
195 spin_unlock_irqrestore(&bcm->irq_lock,
196 mutex_unlock(&bcm->mutex);
197
198 return 0;
199 }
200
201 static int bcm43xx_wx_get_mode(struct net_devi
202 struct iw_reque
203 union iwreq_dat
204 char *extra)
205 {
206 struct bcm43xx_private *bcm = bcm43xx_
207
208 mutex_lock(&bcm->mutex);
209 data->mode = bcm->ieee->iw_mode;
210 mutex_unlock(&bcm->mutex);
211
212 return 0;
213 }
214
215 static int bcm43xx_wx_get_rangeparams(struct n
216 struct i
217 union iw
218 char *ex
219 {
220 struct bcm43xx_private *bcm = bcm43xx_
221 struct iw_range *range = (struct iw_ra
222 const struct ieee80211_geo *geo;
223 int i, j;
224 struct bcm43xx_phyinfo *phy;
225
226 data->data.length = sizeof(*range);
227 memset(range, 0, sizeof(*range));
228
229 //TODO: What about 802.11b?
230 /* 54Mb/s == ~27Mb/s payload throughpu
231 range->throughput = 27 * 1000 * 1000;
232
233 range->max_qual.qual = 100;
234 range->max_qual.level = 146; /* set fl
235 range->max_qual.noise = 146;
236 range->max_qual.updated = IW_QUAL_ALL_
237
238 range->avg_qual.qual = 50;
239 range->avg_qual.level = 0;
240 range->avg_qual.noise = 0;
241 range->avg_qual.updated = IW_QUAL_ALL_
242
243 range->min_rts = BCM43xx_MIN_RTS_THRES
244 range->max_rts = BCM43xx_MAX_RTS_THRES
245 range->min_frag = MIN_FRAG_THRESHOLD;
246 range->max_frag = MAX_FRAG_THRESHOLD;
247
248 range->encoding_size[0] = 5;
249 range->encoding_size[1] = 13;
250 range->num_encoding_sizes = 2;
251 range->max_encoding_tokens = WEP_KEYS;
252
253 range->we_version_compiled = WIRELESS_
254 range->we_version_source = BCM43xx_WX_
255
256 range->enc_capa = IW_ENC_CAPA_WPA |
257 IW_ENC_CAPA_WPA2 |
258 IW_ENC_CAPA_CIPHER_T
259 IW_ENC_CAPA_CIPHER_C
260
261 mutex_lock(&bcm->mutex);
262 phy = bcm43xx_current_phy(bcm);
263
264 range->num_bitrates = 0;
265 i = 0;
266 if (phy->type == BCM43xx_PHYTYPE_A ||
267 phy->type == BCM43xx_PHYTYPE_G) {
268 range->num_bitrates = 8;
269 range->bitrate[i++] = IEEE8021
270 range->bitrate[i++] = IEEE8021
271 range->bitrate[i++] = IEEE8021
272 range->bitrate[i++] = IEEE8021
273 range->bitrate[i++] = IEEE8021
274 range->bitrate[i++] = IEEE8021
275 range->bitrate[i++] = IEEE8021
276 range->bitrate[i++] = IEEE8021
277 }
278 if (phy->type == BCM43xx_PHYTYPE_B ||
279 phy->type == BCM43xx_PHYTYPE_G) {
280 range->num_bitrates += 4;
281 range->bitrate[i++] = IEEE8021
282 range->bitrate[i++] = IEEE8021
283 range->bitrate[i++] = IEEE8021
284 range->bitrate[i++] = IEEE8021
285 }
286
287 geo = ieee80211_get_geo(bcm->ieee);
288 range->num_channels = geo->a_channels
289 j = 0;
290 for (i = 0; i < geo->a_channels; i++)
291 if (j == IW_MAX_FREQUENCIES)
292 break;
293 range->freq[j].i = j + 1;
294 range->freq[j].m = geo->a[i].f
295 range->freq[j].e = 1;
296 j++;
297 }
298 for (i = 0; i < geo->bg_channels; i++)
299 if (j == IW_MAX_FREQUENCIES)
300 break;
301 range->freq[j].i = j + 1;
302 range->freq[j].m = geo->bg[i].
303 range->freq[j].e = 1;
304 j++;
305 }
306 range->num_frequency = j;
307
308 mutex_unlock(&bcm->mutex);
309
310 return 0;
311 }
312
313 static int bcm43xx_wx_set_nick(struct net_devi
314 struct iw_reque
315 union iwreq_dat
316 char *extra)
317 {
318 struct bcm43xx_private *bcm = bcm43xx_
319 size_t len;
320
321 mutex_lock(&bcm->mutex);
322 len = min((size_t)data->data.length,
323 memcpy(bcm->nick, extra, len);
324 bcm->nick[len] = '\0';
325 mutex_unlock(&bcm->mutex);
326
327 return 0;
328 }
329
330 static int bcm43xx_wx_get_nick(struct net_devi
331 struct iw_reque
332 union iwreq_dat
333 char *extra)
334 {
335 struct bcm43xx_private *bcm = bcm43xx_
336 size_t len;
337
338 mutex_lock(&bcm->mutex);
339 len = strlen(bcm->nick);
340 memcpy(extra, bcm->nick, len);
341 data->data.length = (__u16)len;
342 data->data.flags = 1;
343 mutex_unlock(&bcm->mutex);
344
345 return 0;
346 }
347
348 static int bcm43xx_wx_set_rts(struct net_devic
349 struct iw_reques
350 union iwreq_data
351 char *extra)
352 {
353 struct bcm43xx_private *bcm = bcm43xx_
354 unsigned long flags;
355 int err = -EINVAL;
356
357 mutex_lock(&bcm->mutex);
358 spin_lock_irqsave(&bcm->irq_lock, flag
359 if (data->rts.disabled) {
360 bcm->rts_threshold = BCM43xx_M
361 err = 0;
362 } else {
363 if (data->rts.value >= BCM43xx
364 data->rts.value <= BCM43xx
365 bcm->rts_threshold = d
366 err = 0;
367 }
368 }
369 spin_unlock_irqrestore(&bcm->irq_lock,
370 mutex_unlock(&bcm->mutex);
371
372 return err;
373 }
374
375 static int bcm43xx_wx_get_rts(struct net_devic
376 struct iw_reques
377 union iwreq_data
378 char *extra)
379 {
380 struct bcm43xx_private *bcm = bcm43xx_
381
382 mutex_lock(&bcm->mutex);
383 data->rts.value = bcm->rts_threshold;
384 data->rts.fixed = 0;
385 data->rts.disabled = (bcm->rts_thresho
386 mutex_unlock(&bcm->mutex);
387
388 return 0;
389 }
390
391 static int bcm43xx_wx_set_frag(struct net_devi
392 struct iw_reque
393 union iwreq_dat
394 char *extra)
395 {
396 struct bcm43xx_private *bcm = bcm43xx_
397 unsigned long flags;
398 int err = -EINVAL;
399
400 mutex_lock(&bcm->mutex);
401 spin_lock_irqsave(&bcm->irq_lock, flag
402 if (data->frag.disabled) {
403 bcm->ieee->fts = MAX_FRAG_THRE
404 err = 0;
405 } else {
406 if (data->frag.value >= MIN_FR
407 data->frag.value <= MAX_FR
408 bcm->ieee->fts = data-
409 err = 0;
410 }
411 }
412 spin_unlock_irqrestore(&bcm->irq_lock,
413 mutex_unlock(&bcm->mutex);
414
415 return err;
416 }
417
418 static int bcm43xx_wx_get_frag(struct net_devi
419 struct iw_reque
420 union iwreq_dat
421 char *extra)
422 {
423 struct bcm43xx_private *bcm = bcm43xx_
424
425 mutex_lock(&bcm->mutex);
426 data->frag.value = bcm->ieee->fts;
427 data->frag.fixed = 0;
428 data->frag.disabled = (bcm->ieee->fts
429 mutex_unlock(&bcm->mutex);
430
431 return 0;
432 }
433
434 static int bcm43xx_wx_set_xmitpower(struct net
435 struct iw_
436 union iwre
437 char *extr
438 {
439 struct bcm43xx_private *bcm = bcm43xx_
440 struct bcm43xx_radioinfo *radio;
441 struct bcm43xx_phyinfo *phy;
442 unsigned long flags;
443 int err = -ENODEV;
444 u16 maxpower;
445
446 if ((data->txpower.flags & IW_TXPOW_TY
447 printk(KERN_ERR PFX "TX power
448 return -EOPNOTSUPP;
449 }
450
451 mutex_lock(&bcm->mutex);
452 spin_lock_irqsave(&bcm->irq_lock, flag
453 if (bcm43xx_status(bcm) != BCM43xx_STA
454 goto out_unlock;
455 radio = bcm43xx_current_radio(bcm);
456 phy = bcm43xx_current_phy(bcm);
457 if (data->txpower.disabled != (!(radio
458 if (data->txpower.disabled)
459 bcm43xx_radio_turn_off
460 else
461 bcm43xx_radio_turn_on(
462 }
463 if (data->txpower.value > 0) {
464 /* desired and maxpower dBm va
465 if (phy->type == BCM43xx_PHYTY
466 maxpower = bcm->sprom.
467 else
468 maxpower = bcm->sprom.
469 radio->txpower_desired = limit
470
471 bcm43xx_phy_xmitpower(bcm);
472 }
473 err = 0;
474
475 out_unlock:
476 spin_unlock_irqrestore(&bcm->irq_lock,
477 mutex_unlock(&bcm->mutex);
478
479 return err;
480 }
481
482 static int bcm43xx_wx_get_xmitpower(struct net
483 struct iw_
484 union iwre
485 char *extr
486 {
487 struct bcm43xx_private *bcm = bcm43xx_
488 struct bcm43xx_radioinfo *radio;
489 int err = -ENODEV;
490
491 mutex_lock(&bcm->mutex);
492 if (bcm43xx_status(bcm) != BCM43xx_STA
493 goto out_unlock;
494 radio = bcm43xx_current_radio(bcm);
495 /* desired dBm value is in Q5.2 */
496 data->txpower.value = radio->txpower_d
497 data->txpower.fixed = 1;
498 data->txpower.flags = IW_TXPOW_DBM;
499 data->txpower.disabled = !(radio->enab
500
501 err = 0;
502 out_unlock:
503 mutex_unlock(&bcm->mutex);
504
505 return err;
506 }
507
508 static int bcm43xx_wx_set_encoding(struct net_
509 struct iw_r
510 union iwreq
511 char *extra
512 {
513 struct bcm43xx_private *bcm = bcm43xx_
514 int err;
515
516 err = ieee80211_wx_set_encode(bcm->iee
517
518 return err;
519 }
520
521 static int bcm43xx_wx_set_encodingext(struct n
522 struct iw_r
523 union iwreq
524 char *extra
525 {
526 struct bcm43xx_private *bcm = bcm43xx_
527 int err;
528
529 err = ieee80211_wx_set_encodeext(bcm->
530
531 return err;
532 }
533
534 static int bcm43xx_wx_get_encoding(struct net_
535 struct iw_r
536 union iwreq
537 char *extra
538 {
539 struct bcm43xx_private *bcm = bcm43xx_
540 int err;
541
542 err = ieee80211_wx_get_encode(bcm->iee
543
544 return err;
545 }
546
547 static int bcm43xx_wx_get_encodingext(struct n
548 struct iw_r
549 union iwreq
550 char *extra
551 {
552 struct bcm43xx_private *bcm = bcm43xx_
553 int err;
554
555 err = ieee80211_wx_get_encodeext(bcm->
556
557 return err;
558 }
559
560 static int bcm43xx_wx_set_interfmode(struct ne
561 struct iw
562 union iwr
563 char *ext
564 {
565 struct bcm43xx_private *bcm = bcm43xx_
566 unsigned long flags;
567 int mode, err = 0;
568
569 mode = *((int *)extra);
570 switch (mode) {
571 case 0:
572 mode = BCM43xx_RADIO_INTERFMOD
573 break;
574 case 1:
575 mode = BCM43xx_RADIO_INTERFMOD
576 break;
577 case 2:
578 mode = BCM43xx_RADIO_INTERFMOD
579 break;
580 case 3:
581 mode = BCM43xx_RADIO_INTERFMOD
582 break;
583 default:
584 printk(KERN_ERR PFX "set_inter
585 "0 => None
586 "3 => Auto
587 return -EINVAL;
588 }
589
590 mutex_lock(&bcm->mutex);
591 spin_lock_irqsave(&bcm->irq_lock, flag
592 if (bcm43xx_status(bcm) == BCM43xx_STA
593 err = bcm43xx_radio_set_interf
594 if (err) {
595 printk(KERN_ERR PFX "I
596 "s
597 }
598 } else {
599 if (mode == BCM43xx_RADIO_INTE
600 printk(KERN_ERR PFX "I
601 "n
602 err = -ENODEV;
603 } else
604 bcm43xx_current_radio(
605 }
606 spin_unlock_irqrestore(&bcm->irq_lock,
607 mutex_unlock(&bcm->mutex);
608
609 return err;
610 }
611
612 static int bcm43xx_wx_get_interfmode(struct ne
613 struct iw
614 union iwr
615 char *ext
616 {
617 struct bcm43xx_private *bcm = bcm43xx_
618 int mode;
619
620 mutex_lock(&bcm->mutex);
621 mode = bcm43xx_current_radio(bcm)->int
622 mutex_unlock(&bcm->mutex);
623
624 switch (mode) {
625 case BCM43xx_RADIO_INTERFMODE_NONE:
626 strncpy(extra, "0 (No Interfer
627 break;
628 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
629 strncpy(extra, "1 (Non-WLAN In
630 break;
631 case BCM43xx_RADIO_INTERFMODE_MANUALWL
632 strncpy(extra, "2 (WLAN Interf
633 break;
634 default:
635 assert(0);
636 }
637 data->data.length = strlen(extra) + 1;
638
639 return 0;
640 }
641
642 static int bcm43xx_wx_set_shortpreamble(struct
643 struct
644 union
645 char *
646 {
647 struct bcm43xx_private *bcm = bcm43xx_
648 unsigned long flags;
649 int on;
650
651 on = *((int *)extra);
652 mutex_lock(&bcm->mutex);
653 spin_lock_irqsave(&bcm->irq_lock, flag
654 bcm->short_preamble = !!on;
655 spin_unlock_irqrestore(&bcm->irq_lock,
656 mutex_unlock(&bcm->mutex);
657
658 return 0;
659 }
660
661 static int bcm43xx_wx_get_shortpreamble(struct
662 struct
663 union
664 char *
665 {
666 struct bcm43xx_private *bcm = bcm43xx_
667 int on;
668
669 mutex_lock(&bcm->mutex);
670 on = bcm->short_preamble;
671 mutex_unlock(&bcm->mutex);
672
673 if (on)
674 strncpy(extra, "1 (Short Pream
675 else
676 strncpy(extra, "0 (Short Pream
677 data->data.length = strlen(extra) + 1;
678
679 return 0;
680 }
681
682 static int bcm43xx_wx_set_swencryption(struct
683 struct
684 union i
685 char *e
686 {
687 struct bcm43xx_private *bcm = bcm43xx_
688 unsigned long flags;
689 int on;
690
691 on = *((int *)extra);
692
693 mutex_lock(&bcm->mutex);
694 spin_lock_irqsave(&bcm->irq_lock, flag
695 bcm->ieee->host_encrypt = !!on;
696 bcm->ieee->host_decrypt = !!on;
697 bcm->ieee->host_build_iv = !on;
698 bcm->ieee->host_strip_iv_icv = !on;
699 spin_unlock_irqrestore(&bcm->irq_lock,
700 mutex_unlock(&bcm->mutex);
701
702 return 0;
703 }
704
705 static int bcm43xx_wx_get_swencryption(struct
706 struct
707 union i
708 char *e
709 {
710 struct bcm43xx_private *bcm = bcm43xx_
711 int on;
712
713 mutex_lock(&bcm->mutex);
714 on = bcm->ieee->host_encrypt;
715 mutex_unlock(&bcm->mutex);
716
717 if (on)
718 strncpy(extra, "1 (SW encrypti
719 else
720 strncpy(extra, "0 (SW encrypti
721 data->data.length = strlen(extra + 1);
722
723 return 0;
724 }
725
726 /* Enough buffer to hold a hexdump of the spro
727 #define SPROM_BUFFERSIZE 512
728
729 static int sprom2hex(const u16 *sprom, char *d
730 {
731 int i, pos = 0;
732
733 for (i = 0; i < BCM43xx_SPROM_SIZE; i+
734 pos += snprintf(dump + pos, SP
735 "%04X", swab16
736 }
737
738 return pos + 1;
739 }
740
741 static int hex2sprom(u16 *sprom, const char *d
742 {
743 char tmp[5] = { 0 };
744 int cnt = 0;
745 unsigned long parsed;
746
747 if (len < BCM43xx_SPROM_SIZE * sizeof(
748 return -EINVAL;
749 while (cnt < BCM43xx_SPROM_SIZE) {
750 memcpy(tmp, dump, 4);
751 dump += 4;
752 parsed = simple_strtoul(tmp, N
753 sprom[cnt++] = swab16((u16)par
754 }
755
756 return 0;
757 }
758
759 static int bcm43xx_wx_sprom_read(struct net_de
760 struct iw_req
761 union iwreq_d
762 char *extra)
763 {
764 struct bcm43xx_private *bcm = bcm43xx_
765 int err = -EPERM;
766 u16 *sprom;
767 unsigned long flags;
768
769 if (!capable(CAP_SYS_RAWIO))
770 goto out;
771
772 err = -ENOMEM;
773 sprom = kmalloc(BCM43xx_SPROM_SIZE * s
774 GFP_KERNEL);
775 if (!sprom)
776 goto out;
777
778 mutex_lock(&bcm->mutex);
779 spin_lock_irqsave(&bcm->irq_lock, flag
780 err = -ENODEV;
781 if (bcm43xx_status(bcm) == BCM43xx_STA
782 err = bcm43xx_sprom_read(bcm,
783 spin_unlock_irqrestore(&bcm->irq_lock,
784 mutex_unlock(&bcm->mutex);
785 if (!err)
786 data->data.length = sprom2hex(
787 kfree(sprom);
788 out:
789 return err;
790 }
791
792 static int bcm43xx_wx_sprom_write(struct net_d
793 struct iw_re
794 union iwreq_
795 char *extra)
796 {
797 struct bcm43xx_private *bcm = bcm43xx_
798 int err = -EPERM;
799 u16 *sprom;
800 unsigned long flags;
801 char *input;
802 unsigned int len;
803
804 if (!capable(CAP_SYS_RAWIO))
805 goto out;
806
807 err = -ENOMEM;
808 sprom = kmalloc(BCM43xx_SPROM_SIZE * s
809 GFP_KERNEL);
810 if (!sprom)
811 goto out;
812
813 len = data->data.length;
814 extra[len - 1] = '\0';
815 input = strchr(extra, ':');
816 if (input) {
817 input++;
818 len -= input - extra;
819 } else
820 input = extra;
821 err = hex2sprom(sprom, input, len);
822 if (err)
823 goto out_kfree;
824
825 mutex_lock(&bcm->mutex);
826 spin_lock_irqsave(&bcm->irq_lock, flag
827 spin_lock(&bcm->leds_lock);
828 err = -ENODEV;
829 if (bcm43xx_status(bcm) == BCM43xx_STA
830 err = bcm43xx_sprom_write(bcm,
831 spin_unlock(&bcm->leds_lock);
832 spin_unlock_irqrestore(&bcm->irq_lock,
833 mutex_unlock(&bcm->mutex);
834 out_kfree:
835 kfree(sprom);
836 out:
837 return err;
838 }
839
840 /* Get wireless statistics. Called by /proc/n
841
842 static struct iw_statistics *bcm43xx_get_wirel
843 {
844 struct bcm43xx_private *bcm = bcm43xx_
845 struct ieee80211softmac_device *mac =
846 struct iw_statistics *wstats;
847 struct ieee80211_network *network = NU
848 static int tmp_level = 0;
849 static int tmp_qual = 0;
850 unsigned long flags;
851
852 wstats = &bcm->stats.wstats;
853 if (!mac->associnfo.associated) {
854 wstats->miss.beacon = 0;
855 // bcm->ieee->ieee_stats.tx_retry
856 wstats->discard.retries = 0;
857 // bcm->ieee->ieee_stats.tx_disca
858 wstats->discard.nwid = 0;
859 // bcm->ieee->ieee_stats.rx_disca
860 wstats->discard.code = 0;
861 // bcm->ieee->ieee_stats.rx_fragm
862 wstats->discard.fragment = 0;
863 wstats->discard.misc = 0;
864 wstats->qual.qual = 0;
865 wstats->qual.level = 0;
866 wstats->qual.noise = 0;
867 wstats->qual.updated = 7;
868 wstats->qual.updated |= IW_QUA
869 return wstats;
870 }
871 /* fill in the real statistics when if
872 spin_lock_irqsave(&mac->ieee->lock, fl
873 list_for_each_entry(network, &mac->iee
874 if (!memcmp(mac->associnfo.bss
875 if (!tmp_level) {
876 tmp_level = ne
877 tmp_qual = net
878 } else {
879 tmp_level = (1
880 tmp_qual = (15
881 }
882 break;
883 }
884 }
885 spin_unlock_irqrestore(&mac->ieee->loc
886 wstats->qual.level = tmp_level;
887 wstats->qual.qual = 100 * tmp_qual / R
888 wstats->qual.noise = bcm->stats.noise;
889 wstats->qual.updated = IW_QUAL_ALL_UPD
890 wstats->discard.code = bcm->ieee->ieee
891 wstats->discard.retries = bcm->ieee->i
892 wstats->discard.nwid = bcm->ieee->ieee
893 wstats->discard.fragment = bcm->ieee->
894 wstats->discard.misc = 0; // FIX
895 wstats->miss.beacon = 0; // FIX
896 return wstats;
897 }
898
899
900 #ifdef WX
901 # undef WX
902 #endif
903 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
904 static const iw_handler bcm43xx_wx_handlers[]
905 /* Wireless Identification */
906 WX(SIOCGIWNAME) = bcm43xx_wx_g
907 /* Basic operations */
908 WX(SIOCSIWFREQ) = bcm43xx_wx_s
909 WX(SIOCGIWFREQ) = bcm43xx_wx_g
910 WX(SIOCSIWMODE) = bcm43xx_wx_s
911 WX(SIOCGIWMODE) = bcm43xx_wx_g
912 /* Informative stuff */
913 WX(SIOCGIWRANGE) = bcm43xx_wx_g
914 /* Access Point manipulation */
915 WX(SIOCSIWAP) = ieee80211sof
916 WX(SIOCGIWAP) = ieee80211sof
917 WX(SIOCSIWSCAN) = ieee80211sof
918 WX(SIOCGIWSCAN) = ieee80211sof
919 /* 802.11 specific support */
920 WX(SIOCSIWESSID) = ieee80211sof
921 WX(SIOCGIWESSID) = ieee80211sof
922 WX(SIOCSIWNICKN) = bcm43xx_wx_s
923 WX(SIOCGIWNICKN) = bcm43xx_wx_g
924 /* Other parameters */
925 WX(SIOCSIWRATE) = ieee80211sof
926 WX(SIOCGIWRATE) = ieee80211sof
927 WX(SIOCSIWRTS) = bcm43xx_wx_s
928 WX(SIOCGIWRTS) = bcm43xx_wx_g
929 WX(SIOCSIWFRAG) = bcm43xx_wx_s
930 WX(SIOCGIWFRAG) = bcm43xx_wx_g
931 WX(SIOCSIWTXPOW) = bcm43xx_wx_s
932 WX(SIOCGIWTXPOW) = bcm43xx_wx_g
933 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_s
934 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_g
935 /* Encoding */
936 WX(SIOCSIWENCODE) = bcm43xx_wx_s
937 WX(SIOCGIWENCODE) = bcm43xx_wx_g
938 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_s
939 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_g
940 /* Power saving */
941 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_s
942 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_g
943 WX(SIOCSIWGENIE) = ieee80211sof
944 WX(SIOCGIWGENIE) = ieee80211sof
945 WX(SIOCSIWAUTH) = ieee80211_wx
946 WX(SIOCGIWAUTH) = ieee80211_wx
947 };
948 #undef WX
949
950 static const iw_handler bcm43xx_priv_wx_handle
951 /* Set Interference Mitigation Mode. *
952 bcm43xx_wx_set_interfmode,
953 /* Get Interference Mitigation Mode. *
954 bcm43xx_wx_get_interfmode,
955 /* Enable/Disable Short Preamble mode.
956 bcm43xx_wx_set_shortpreamble,
957 /* Get Short Preamble mode. */
958 bcm43xx_wx_get_shortpreamble,
959 /* Enable/Disable Software Encryption
960 bcm43xx_wx_set_swencryption,
961 /* Get Software Encryption mode */
962 bcm43xx_wx_get_swencryption,
963 /* Write SRPROM data. */
964 bcm43xx_wx_sprom_write,
965 /* Read SPROM data. */
966 bcm43xx_wx_sprom_read,
967 };
968
969 #define PRIV_WX_SET_INTERFMODE (SIOCI
970 #define PRIV_WX_GET_INTERFMODE (SIOCI
971 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCI
972 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCI
973 #define PRIV_WX_SET_SWENCRYPTION (SIOCI
974 #define PRIV_WX_GET_SWENCRYPTION (SIOCI
975 #define PRIV_WX_SPROM_WRITE (SIOCI
976 #define PRIV_WX_SPROM_READ (SIOCI
977
978 #define PRIV_WX_DUMMY(ioctl) \
979 {
980 .cmd = (ioctl),
981 .name = "__unused"
982 }
983
984 static const struct iw_priv_args bcm43xx_priv_
985 {
986 .cmd = PRIV_WX_SET_
987 .set_args = IW_PRIV_TYPE
988 .name = "set_interfm
989 },
990 {
991 .cmd = PRIV_WX_GET_
992 .get_args = IW_PRIV_TYPE
993 .name = "get_interfm
994 },
995 {
996 .cmd = PRIV_WX_SET_
997 .set_args = IW_PRIV_TYPE
998 .name = "set_shortpr
999 },
1000 {
1001 .cmd = PRIV_WX_GET
1002 .get_args = IW_PRIV_TYP
1003 .name = "get_shortp
1004 },
1005 {
1006 .cmd = PRIV_WX_SET
1007 .set_args = IW_PRIV_TYP
1008 .name = "set_swencr
1009 },
1010 {
1011 .cmd = PRIV_WX_GET
1012 .get_args = IW_PRIV_TYP
1013 .name = "get_swencr
1014 },
1015 {
1016 .cmd = PRIV_WX_SPR
1017 .set_args = IW_PRIV_TYP
1018 .name = "write_spro
1019 },
1020 {
1021 .cmd = PRIV_WX_SPR
1022 .get_args = IW_PRIV_TYP
1023 .name = "read_sprom
1024 },
1025 };
1026
1027 const struct iw_handler_def bcm43xx_wx_handle
1028 .standard = bcm43xx_wx_
1029 .num_standard = ARRAY_SIZE(
1030 .num_private = ARRAY_SIZE(
1031 .num_private_args = ARRAY_SIZE(
1032 .private = bcm43xx_pri
1033 .private_args = bcm43xx_pri
1034 .get_wireless_stats = bcm43xx_get
1035 };
1036
| This page was automatically generated by the LXR engine. |