3 Broadcom BCM43xx wireless driver
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
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/sched.h> /* for capable() */
37 #include <linux/delay.h>
40 #include "bcm43xx_wx.h"
41 #include "bcm43xx_main.h"
42 #include "bcm43xx_radio.h"
43 #include "bcm43xx_phy.h"
46 /* The WIRELESS_EXT version, which is implemented by this driver. */
47 #define BCM43xx_WX_VERSION 18
49 #define MAX_WX_STRING 80
50 /* FIXME: the next line is a guess as to what the maximum RSSI value might be */
51 #define RX_RSSI_MAX 60
54 static int bcm43xx_wx_get_name(struct net_device
*net_dev
,
55 struct iw_request_info
*info
,
56 union iwreq_data
*data
,
59 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
61 struct bcm43xx_phyinfo
*phy
;
62 char suffix
[7] = { 0 };
63 int have_a
= 0, have_b
= 0, have_g
= 0;
65 mutex_lock(&bcm
->mutex
);
66 for (i
= 0; i
< bcm
->nr_80211_available
; i
++) {
67 phy
= &(bcm
->core_80211_ext
[i
].phy
);
69 case BCM43xx_PHYTYPE_A
:
72 case BCM43xx_PHYTYPE_G
:
74 case BCM43xx_PHYTYPE_B
:
81 mutex_unlock(&bcm
->mutex
);
99 snprintf(data
->name
, IFNAMSIZ
, "IEEE 802.11%s", suffix
);
104 static int bcm43xx_wx_set_channelfreq(struct net_device
*net_dev
,
105 struct iw_request_info
*info
,
106 union iwreq_data
*data
,
109 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
115 mutex_lock(&bcm
->mutex
);
116 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
118 if ((data
->freq
.m
>= 0) && (data
->freq
.m
<= 1000)) {
119 channel
= data
->freq
.m
;
120 freq
= bcm43xx_channel_to_freq(bcm
, channel
);
122 channel
= bcm43xx_freq_to_channel(bcm
, data
->freq
.m
);
125 if (!ieee80211_is_valid_channel(bcm
->ieee
, channel
))
127 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
) {
128 //ieee80211softmac_disassoc(softmac, $REASON);
129 bcm43xx_mac_suspend(bcm
);
130 err
= bcm43xx_radio_selectchannel(bcm
, channel
, 0);
131 bcm43xx_mac_enable(bcm
);
133 bcm43xx_current_radio(bcm
)->initial_channel
= channel
;
137 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
138 mutex_unlock(&bcm
->mutex
);
143 static int bcm43xx_wx_get_channelfreq(struct net_device
*net_dev
,
144 struct iw_request_info
*info
,
145 union iwreq_data
*data
,
148 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
149 struct bcm43xx_radioinfo
*radio
;
153 mutex_lock(&bcm
->mutex
);
154 radio
= bcm43xx_current_radio(bcm
);
155 channel
= radio
->channel
;
156 if (channel
== 0xFF) {
157 channel
= radio
->initial_channel
;
161 assert(channel
> 0 && channel
<= 1000);
163 data
->freq
.m
= bcm43xx_channel_to_freq(bcm
, channel
) * 100000;
164 data
->freq
.flags
= 1;
168 mutex_unlock(&bcm
->mutex
);
173 static int bcm43xx_wx_set_mode(struct net_device
*net_dev
,
174 struct iw_request_info
*info
,
175 union iwreq_data
*data
,
178 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
183 if (mode
== IW_MODE_AUTO
)
184 mode
= BCM43xx_INITIAL_IWMODE
;
186 mutex_lock(&bcm
->mutex
);
187 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
188 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
) {
189 if (bcm
->ieee
->iw_mode
!= mode
)
190 bcm43xx_set_iwmode(bcm
, mode
);
192 bcm
->ieee
->iw_mode
= mode
;
193 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
194 mutex_unlock(&bcm
->mutex
);
199 static int bcm43xx_wx_get_mode(struct net_device
*net_dev
,
200 struct iw_request_info
*info
,
201 union iwreq_data
*data
,
204 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
206 mutex_lock(&bcm
->mutex
);
207 data
->mode
= bcm
->ieee
->iw_mode
;
208 mutex_unlock(&bcm
->mutex
);
213 static int bcm43xx_wx_get_rangeparams(struct net_device
*net_dev
,
214 struct iw_request_info
*info
,
215 union iwreq_data
*data
,
218 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
219 struct iw_range
*range
= (struct iw_range
*)extra
;
220 const struct ieee80211_geo
*geo
;
222 struct bcm43xx_phyinfo
*phy
;
224 data
->data
.length
= sizeof(*range
);
225 memset(range
, 0, sizeof(*range
));
227 //TODO: What about 802.11b?
228 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
229 range
->throughput
= 27 * 1000 * 1000;
231 range
->max_qual
.qual
= 100;
232 range
->max_qual
.level
= 146; /* set floor at -110 dBm (146 - 256) */
233 range
->max_qual
.noise
= 146;
234 range
->max_qual
.updated
= IW_QUAL_ALL_UPDATED
;
236 range
->avg_qual
.qual
= 50;
237 range
->avg_qual
.level
= 0;
238 range
->avg_qual
.noise
= 0;
239 range
->avg_qual
.updated
= IW_QUAL_ALL_UPDATED
;
241 range
->min_rts
= BCM43xx_MIN_RTS_THRESHOLD
;
242 range
->max_rts
= BCM43xx_MAX_RTS_THRESHOLD
;
243 range
->min_frag
= MIN_FRAG_THRESHOLD
;
244 range
->max_frag
= MAX_FRAG_THRESHOLD
;
246 range
->encoding_size
[0] = 5;
247 range
->encoding_size
[1] = 13;
248 range
->num_encoding_sizes
= 2;
249 range
->max_encoding_tokens
= WEP_KEYS
;
251 range
->we_version_compiled
= WIRELESS_EXT
;
252 range
->we_version_source
= BCM43xx_WX_VERSION
;
254 range
->enc_capa
= IW_ENC_CAPA_WPA
|
256 IW_ENC_CAPA_CIPHER_TKIP
|
257 IW_ENC_CAPA_CIPHER_CCMP
;
259 mutex_lock(&bcm
->mutex
);
260 phy
= bcm43xx_current_phy(bcm
);
262 range
->num_bitrates
= 0;
264 if (phy
->type
== BCM43xx_PHYTYPE_A
||
265 phy
->type
== BCM43xx_PHYTYPE_G
) {
266 range
->num_bitrates
= 8;
267 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_6MB
;
268 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_9MB
;
269 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_12MB
;
270 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_18MB
;
271 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_24MB
;
272 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_36MB
;
273 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_48MB
;
274 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_54MB
;
276 if (phy
->type
== BCM43xx_PHYTYPE_B
||
277 phy
->type
== BCM43xx_PHYTYPE_G
) {
278 range
->num_bitrates
+= 4;
279 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_1MB
;
280 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_2MB
;
281 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_5MB
;
282 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_11MB
;
285 geo
= ieee80211_get_geo(bcm
->ieee
);
286 range
->num_channels
= geo
->a_channels
+ geo
->bg_channels
;
288 for (i
= 0; i
< geo
->a_channels
; i
++) {
289 if (j
== IW_MAX_FREQUENCIES
)
291 range
->freq
[j
].i
= j
+ 1;
292 range
->freq
[j
].m
= geo
->a
[i
].freq
;//FIXME?
293 range
->freq
[j
].e
= 1;
296 for (i
= 0; i
< geo
->bg_channels
; i
++) {
297 if (j
== IW_MAX_FREQUENCIES
)
299 range
->freq
[j
].i
= j
+ 1;
300 range
->freq
[j
].m
= geo
->bg
[i
].freq
;//FIXME?
301 range
->freq
[j
].e
= 1;
304 range
->num_frequency
= j
;
306 mutex_unlock(&bcm
->mutex
);
311 static int bcm43xx_wx_set_nick(struct net_device
*net_dev
,
312 struct iw_request_info
*info
,
313 union iwreq_data
*data
,
316 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
319 mutex_lock(&bcm
->mutex
);
320 len
= min((size_t)data
->data
.length
, (size_t)IW_ESSID_MAX_SIZE
);
321 memcpy(bcm
->nick
, extra
, len
);
322 bcm
->nick
[len
] = '\0';
323 mutex_unlock(&bcm
->mutex
);
328 static int bcm43xx_wx_get_nick(struct net_device
*net_dev
,
329 struct iw_request_info
*info
,
330 union iwreq_data
*data
,
333 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
336 mutex_lock(&bcm
->mutex
);
337 len
= strlen(bcm
->nick
) + 1;
338 memcpy(extra
, bcm
->nick
, len
);
339 data
->data
.length
= (__u16
)len
;
340 data
->data
.flags
= 1;
341 mutex_unlock(&bcm
->mutex
);
346 static int bcm43xx_wx_set_rts(struct net_device
*net_dev
,
347 struct iw_request_info
*info
,
348 union iwreq_data
*data
,
351 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
355 mutex_lock(&bcm
->mutex
);
356 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
357 if (data
->rts
.disabled
) {
358 bcm
->rts_threshold
= BCM43xx_MAX_RTS_THRESHOLD
;
361 if (data
->rts
.value
>= BCM43xx_MIN_RTS_THRESHOLD
&&
362 data
->rts
.value
<= BCM43xx_MAX_RTS_THRESHOLD
) {
363 bcm
->rts_threshold
= data
->rts
.value
;
367 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
368 mutex_unlock(&bcm
->mutex
);
373 static int bcm43xx_wx_get_rts(struct net_device
*net_dev
,
374 struct iw_request_info
*info
,
375 union iwreq_data
*data
,
378 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
380 mutex_lock(&bcm
->mutex
);
381 data
->rts
.value
= bcm
->rts_threshold
;
383 data
->rts
.disabled
= (bcm
->rts_threshold
== BCM43xx_MAX_RTS_THRESHOLD
);
384 mutex_unlock(&bcm
->mutex
);
389 static int bcm43xx_wx_set_frag(struct net_device
*net_dev
,
390 struct iw_request_info
*info
,
391 union iwreq_data
*data
,
394 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
398 mutex_lock(&bcm
->mutex
);
399 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
400 if (data
->frag
.disabled
) {
401 bcm
->ieee
->fts
= MAX_FRAG_THRESHOLD
;
404 if (data
->frag
.value
>= MIN_FRAG_THRESHOLD
&&
405 data
->frag
.value
<= MAX_FRAG_THRESHOLD
) {
406 bcm
->ieee
->fts
= data
->frag
.value
& ~0x1;
410 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
411 mutex_unlock(&bcm
->mutex
);
416 static int bcm43xx_wx_get_frag(struct net_device
*net_dev
,
417 struct iw_request_info
*info
,
418 union iwreq_data
*data
,
421 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
423 mutex_lock(&bcm
->mutex
);
424 data
->frag
.value
= bcm
->ieee
->fts
;
425 data
->frag
.fixed
= 0;
426 data
->frag
.disabled
= (bcm
->ieee
->fts
== MAX_FRAG_THRESHOLD
);
427 mutex_unlock(&bcm
->mutex
);
432 static int bcm43xx_wx_set_xmitpower(struct net_device
*net_dev
,
433 struct iw_request_info
*info
,
434 union iwreq_data
*data
,
437 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
438 struct bcm43xx_radioinfo
*radio
;
439 struct bcm43xx_phyinfo
*phy
;
444 if ((data
->txpower
.flags
& IW_TXPOW_TYPE
) != IW_TXPOW_DBM
) {
445 printk(PFX KERN_ERR
"TX power not in dBm.\n");
449 mutex_lock(&bcm
->mutex
);
450 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
451 if (bcm43xx_status(bcm
) != BCM43xx_STAT_INITIALIZED
)
453 radio
= bcm43xx_current_radio(bcm
);
454 phy
= bcm43xx_current_phy(bcm
);
455 if (data
->txpower
.disabled
!= (!(radio
->enabled
))) {
456 if (data
->txpower
.disabled
)
457 bcm43xx_radio_turn_off(bcm
);
459 bcm43xx_radio_turn_on(bcm
);
461 if (data
->txpower
.value
> 0) {
462 /* desired and maxpower dBm values are in Q5.2 */
463 if (phy
->type
== BCM43xx_PHYTYPE_A
)
464 maxpower
= bcm
->sprom
.maxpower_aphy
;
466 maxpower
= bcm
->sprom
.maxpower_bgphy
;
467 radio
->txpower_desired
= limit_value(data
->txpower
.value
<< 2,
469 bcm43xx_phy_xmitpower(bcm
);
474 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
475 mutex_unlock(&bcm
->mutex
);
480 static int bcm43xx_wx_get_xmitpower(struct net_device
*net_dev
,
481 struct iw_request_info
*info
,
482 union iwreq_data
*data
,
485 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
486 struct bcm43xx_radioinfo
*radio
;
489 mutex_lock(&bcm
->mutex
);
490 if (bcm43xx_status(bcm
) != BCM43xx_STAT_INITIALIZED
)
492 radio
= bcm43xx_current_radio(bcm
);
493 /* desired dBm value is in Q5.2 */
494 data
->txpower
.value
= radio
->txpower_desired
>> 2;
495 data
->txpower
.fixed
= 1;
496 data
->txpower
.flags
= IW_TXPOW_DBM
;
497 data
->txpower
.disabled
= !(radio
->enabled
);
501 mutex_unlock(&bcm
->mutex
);
506 static int bcm43xx_wx_set_encoding(struct net_device
*net_dev
,
507 struct iw_request_info
*info
,
508 union iwreq_data
*data
,
511 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
514 err
= ieee80211_wx_set_encode(bcm
->ieee
, info
, data
, extra
);
519 static int bcm43xx_wx_set_encodingext(struct net_device
*net_dev
,
520 struct iw_request_info
*info
,
521 union iwreq_data
*data
,
524 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
527 err
= ieee80211_wx_set_encodeext(bcm
->ieee
, info
, data
, extra
);
532 static int bcm43xx_wx_get_encoding(struct net_device
*net_dev
,
533 struct iw_request_info
*info
,
534 union iwreq_data
*data
,
537 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
540 err
= ieee80211_wx_get_encode(bcm
->ieee
, info
, data
, extra
);
545 static int bcm43xx_wx_get_encodingext(struct net_device
*net_dev
,
546 struct iw_request_info
*info
,
547 union iwreq_data
*data
,
550 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
553 err
= ieee80211_wx_get_encodeext(bcm
->ieee
, info
, data
, extra
);
558 static int bcm43xx_wx_set_interfmode(struct net_device
*net_dev
,
559 struct iw_request_info
*info
,
560 union iwreq_data
*data
,
563 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
567 mode
= *((int *)extra
);
570 mode
= BCM43xx_RADIO_INTERFMODE_NONE
;
573 mode
= BCM43xx_RADIO_INTERFMODE_NONWLAN
;
576 mode
= BCM43xx_RADIO_INTERFMODE_MANUALWLAN
;
579 mode
= BCM43xx_RADIO_INTERFMODE_AUTOWLAN
;
582 printk(KERN_ERR PFX
"set_interfmode allowed parameters are: "
583 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
588 mutex_lock(&bcm
->mutex
);
589 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
590 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
) {
591 err
= bcm43xx_radio_set_interference_mitigation(bcm
, mode
);
593 printk(KERN_ERR PFX
"Interference Mitigation not "
594 "supported by device\n");
597 if (mode
== BCM43xx_RADIO_INTERFMODE_AUTOWLAN
) {
598 printk(KERN_ERR PFX
"Interference Mitigation mode Auto-WLAN "
599 "not supported while the interface is down.\n");
602 bcm43xx_current_radio(bcm
)->interfmode
= mode
;
604 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
605 mutex_unlock(&bcm
->mutex
);
610 static int bcm43xx_wx_get_interfmode(struct net_device
*net_dev
,
611 struct iw_request_info
*info
,
612 union iwreq_data
*data
,
615 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
618 mutex_lock(&bcm
->mutex
);
619 mode
= bcm43xx_current_radio(bcm
)->interfmode
;
620 mutex_unlock(&bcm
->mutex
);
623 case BCM43xx_RADIO_INTERFMODE_NONE
:
624 strncpy(extra
, "0 (No Interference Mitigation)", MAX_WX_STRING
);
626 case BCM43xx_RADIO_INTERFMODE_NONWLAN
:
627 strncpy(extra
, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING
);
629 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN
:
630 strncpy(extra
, "2 (WLAN Interference Mitigation)", MAX_WX_STRING
);
635 data
->data
.length
= strlen(extra
) + 1;
640 static int bcm43xx_wx_set_shortpreamble(struct net_device
*net_dev
,
641 struct iw_request_info
*info
,
642 union iwreq_data
*data
,
645 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
649 on
= *((int *)extra
);
650 mutex_lock(&bcm
->mutex
);
651 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
652 bcm
->short_preamble
= !!on
;
653 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
654 mutex_unlock(&bcm
->mutex
);
659 static int bcm43xx_wx_get_shortpreamble(struct net_device
*net_dev
,
660 struct iw_request_info
*info
,
661 union iwreq_data
*data
,
664 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
667 mutex_lock(&bcm
->mutex
);
668 on
= bcm
->short_preamble
;
669 mutex_unlock(&bcm
->mutex
);
672 strncpy(extra
, "1 (Short Preamble enabled)", MAX_WX_STRING
);
674 strncpy(extra
, "0 (Short Preamble disabled)", MAX_WX_STRING
);
675 data
->data
.length
= strlen(extra
) + 1;
680 static int bcm43xx_wx_set_swencryption(struct net_device
*net_dev
,
681 struct iw_request_info
*info
,
682 union iwreq_data
*data
,
685 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
689 on
= *((int *)extra
);
691 mutex_lock(&bcm
->mutex
);
692 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
693 bcm
->ieee
->host_encrypt
= !!on
;
694 bcm
->ieee
->host_decrypt
= !!on
;
695 bcm
->ieee
->host_build_iv
= !on
;
696 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
697 mutex_unlock(&bcm
->mutex
);
702 static int bcm43xx_wx_get_swencryption(struct net_device
*net_dev
,
703 struct iw_request_info
*info
,
704 union iwreq_data
*data
,
707 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
710 mutex_lock(&bcm
->mutex
);
711 on
= bcm
->ieee
->host_encrypt
;
712 mutex_unlock(&bcm
->mutex
);
715 strncpy(extra
, "1 (SW encryption enabled) ", MAX_WX_STRING
);
717 strncpy(extra
, "0 (SW encryption disabled) ", MAX_WX_STRING
);
718 data
->data
.length
= strlen(extra
+ 1);
723 /* Enough buffer to hold a hexdump of the sprom data. */
724 #define SPROM_BUFFERSIZE 512
726 static int sprom2hex(const u16
*sprom
, char *dump
)
730 for (i
= 0; i
< BCM43xx_SPROM_SIZE
; i
++) {
731 pos
+= snprintf(dump
+ pos
, SPROM_BUFFERSIZE
- pos
- 1,
732 "%04X", swab16(sprom
[i
]) & 0xFFFF);
738 static int hex2sprom(u16
*sprom
, const char *dump
, unsigned int len
)
742 unsigned long parsed
;
744 if (len
< BCM43xx_SPROM_SIZE
* sizeof(u16
) * 2)
746 while (cnt
< BCM43xx_SPROM_SIZE
) {
747 memcpy(tmp
, dump
, 4);
749 parsed
= simple_strtoul(tmp
, NULL
, 16);
750 sprom
[cnt
++] = swab16((u16
)parsed
);
756 static int bcm43xx_wx_sprom_read(struct net_device
*net_dev
,
757 struct iw_request_info
*info
,
758 union iwreq_data
*data
,
761 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
766 if (!capable(CAP_SYS_RAWIO
))
770 sprom
= kmalloc(BCM43xx_SPROM_SIZE
* sizeof(*sprom
),
775 mutex_lock(&bcm
->mutex
);
776 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
778 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
)
779 err
= bcm43xx_sprom_read(bcm
, sprom
);
780 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
781 mutex_unlock(&bcm
->mutex
);
783 data
->data
.length
= sprom2hex(sprom
, extra
);
789 static int bcm43xx_wx_sprom_write(struct net_device
*net_dev
,
790 struct iw_request_info
*info
,
791 union iwreq_data
*data
,
794 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
801 if (!capable(CAP_SYS_RAWIO
))
805 sprom
= kmalloc(BCM43xx_SPROM_SIZE
* sizeof(*sprom
),
810 len
= data
->data
.length
;
811 extra
[len
- 1] = '\0';
812 input
= strchr(extra
, ':');
815 len
-= input
- extra
;
818 err
= hex2sprom(sprom
, input
, len
);
822 mutex_lock(&bcm
->mutex
);
823 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
824 spin_lock(&bcm
->leds_lock
);
826 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
)
827 err
= bcm43xx_sprom_write(bcm
, sprom
);
828 spin_unlock(&bcm
->leds_lock
);
829 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
830 mutex_unlock(&bcm
->mutex
);
837 /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
839 static struct iw_statistics
*bcm43xx_get_wireless_stats(struct net_device
*net_dev
)
841 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
842 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
843 struct iw_statistics
*wstats
;
844 struct ieee80211_network
*network
= NULL
;
845 static int tmp_level
= 0;
846 static int tmp_qual
= 0;
849 wstats
= &bcm
->stats
.wstats
;
850 if (!mac
->associated
) {
851 wstats
->miss
.beacon
= 0;
852 // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
853 wstats
->discard
.retries
= 0;
854 // bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
855 wstats
->discard
.nwid
= 0;
856 // bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
857 wstats
->discard
.code
= 0;
858 // bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
859 wstats
->discard
.fragment
= 0;
860 wstats
->discard
.misc
= 0;
861 wstats
->qual
.qual
= 0;
862 wstats
->qual
.level
= 0;
863 wstats
->qual
.noise
= 0;
864 wstats
->qual
.updated
= 7;
865 wstats
->qual
.updated
|= IW_QUAL_ALL_UPDATED
| IW_QUAL_DBM
;
868 /* fill in the real statistics when iface associated */
869 spin_lock_irqsave(&mac
->ieee
->lock
, flags
);
870 list_for_each_entry(network
, &mac
->ieee
->network_list
, list
) {
871 if (!memcmp(mac
->associnfo
.bssid
, network
->bssid
, ETH_ALEN
)) {
872 if (!tmp_level
) { /* get initial values */
873 tmp_level
= network
->stats
.signal
;
874 tmp_qual
= network
->stats
.rssi
;
875 } else { /* smooth results */
876 tmp_level
= (15 * tmp_level
+ network
->stats
.signal
)/16;
877 tmp_qual
= (15 * tmp_qual
+ network
->stats
.rssi
)/16;
882 spin_unlock_irqrestore(&mac
->ieee
->lock
, flags
);
883 wstats
->qual
.level
= tmp_level
;
884 wstats
->qual
.qual
= 100 * tmp_qual
/ RX_RSSI_MAX
;
885 wstats
->qual
.noise
= bcm
->stats
.noise
;
886 wstats
->qual
.updated
= IW_QUAL_ALL_UPDATED
| IW_QUAL_DBM
;
887 wstats
->discard
.code
= bcm
->ieee
->ieee_stats
.rx_discards_undecryptable
;
888 wstats
->discard
.retries
= bcm
->ieee
->ieee_stats
.tx_retry_limit_exceeded
;
889 wstats
->discard
.nwid
= bcm
->ieee
->ieee_stats
.tx_discards_wrong_sa
;
890 wstats
->discard
.fragment
= bcm
->ieee
->ieee_stats
.rx_fragments
;
891 wstats
->discard
.misc
= 0; // FIXME
892 wstats
->miss
.beacon
= 0; // FIXME
900 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
901 static const iw_handler bcm43xx_wx_handlers
[] = {
902 /* Wireless Identification */
903 WX(SIOCGIWNAME
) = bcm43xx_wx_get_name
,
904 /* Basic operations */
905 WX(SIOCSIWFREQ
) = bcm43xx_wx_set_channelfreq
,
906 WX(SIOCGIWFREQ
) = bcm43xx_wx_get_channelfreq
,
907 WX(SIOCSIWMODE
) = bcm43xx_wx_set_mode
,
908 WX(SIOCGIWMODE
) = bcm43xx_wx_get_mode
,
909 /* Informative stuff */
910 WX(SIOCGIWRANGE
) = bcm43xx_wx_get_rangeparams
,
911 /* Access Point manipulation */
912 WX(SIOCSIWAP
) = ieee80211softmac_wx_set_wap
,
913 WX(SIOCGIWAP
) = ieee80211softmac_wx_get_wap
,
914 WX(SIOCSIWSCAN
) = ieee80211softmac_wx_trigger_scan
,
915 WX(SIOCGIWSCAN
) = ieee80211softmac_wx_get_scan_results
,
916 /* 802.11 specific support */
917 WX(SIOCSIWESSID
) = ieee80211softmac_wx_set_essid
,
918 WX(SIOCGIWESSID
) = ieee80211softmac_wx_get_essid
,
919 WX(SIOCSIWNICKN
) = bcm43xx_wx_set_nick
,
920 WX(SIOCGIWNICKN
) = bcm43xx_wx_get_nick
,
921 /* Other parameters */
922 WX(SIOCSIWRATE
) = ieee80211softmac_wx_set_rate
,
923 WX(SIOCGIWRATE
) = ieee80211softmac_wx_get_rate
,
924 WX(SIOCSIWRTS
) = bcm43xx_wx_set_rts
,
925 WX(SIOCGIWRTS
) = bcm43xx_wx_get_rts
,
926 WX(SIOCSIWFRAG
) = bcm43xx_wx_set_frag
,
927 WX(SIOCGIWFRAG
) = bcm43xx_wx_get_frag
,
928 WX(SIOCSIWTXPOW
) = bcm43xx_wx_set_xmitpower
,
929 WX(SIOCGIWTXPOW
) = bcm43xx_wx_get_xmitpower
,
930 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
931 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
933 WX(SIOCSIWENCODE
) = bcm43xx_wx_set_encoding
,
934 WX(SIOCGIWENCODE
) = bcm43xx_wx_get_encoding
,
935 WX(SIOCSIWENCODEEXT
) = bcm43xx_wx_set_encodingext
,
936 WX(SIOCGIWENCODEEXT
) = bcm43xx_wx_get_encodingext
,
938 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
939 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
940 WX(SIOCSIWGENIE
) = ieee80211softmac_wx_set_genie
,
941 WX(SIOCGIWGENIE
) = ieee80211softmac_wx_get_genie
,
942 WX(SIOCSIWAUTH
) = ieee80211_wx_set_auth
,
943 WX(SIOCGIWAUTH
) = ieee80211_wx_get_auth
,
947 static const iw_handler bcm43xx_priv_wx_handlers
[] = {
948 /* Set Interference Mitigation Mode. */
949 bcm43xx_wx_set_interfmode
,
950 /* Get Interference Mitigation Mode. */
951 bcm43xx_wx_get_interfmode
,
952 /* Enable/Disable Short Preamble mode. */
953 bcm43xx_wx_set_shortpreamble
,
954 /* Get Short Preamble mode. */
955 bcm43xx_wx_get_shortpreamble
,
956 /* Enable/Disable Software Encryption mode */
957 bcm43xx_wx_set_swencryption
,
958 /* Get Software Encryption mode */
959 bcm43xx_wx_get_swencryption
,
960 /* Write SRPROM data. */
961 bcm43xx_wx_sprom_write
,
962 /* Read SPROM data. */
963 bcm43xx_wx_sprom_read
,
966 #define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
967 #define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
968 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
969 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
970 #define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
971 #define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
972 #define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
973 #define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
975 #define PRIV_WX_DUMMY(ioctl) \
981 static const struct iw_priv_args bcm43xx_priv_wx_args
[] = {
983 .cmd
= PRIV_WX_SET_INTERFMODE
,
984 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
985 .name
= "set_interfmode",
988 .cmd
= PRIV_WX_GET_INTERFMODE
,
989 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
990 .name
= "get_interfmode",
993 .cmd
= PRIV_WX_SET_SHORTPREAMBLE
,
994 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
995 .name
= "set_shortpreamb",
998 .cmd
= PRIV_WX_GET_SHORTPREAMBLE
,
999 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
1000 .name
= "get_shortpreamb",
1003 .cmd
= PRIV_WX_SET_SWENCRYPTION
,
1004 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1005 .name
= "set_swencrypt",
1008 .cmd
= PRIV_WX_GET_SWENCRYPTION
,
1009 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
1010 .name
= "get_swencrypt",
1013 .cmd
= PRIV_WX_SPROM_WRITE
,
1014 .set_args
= IW_PRIV_TYPE_CHAR
| SPROM_BUFFERSIZE
,
1015 .name
= "write_sprom",
1018 .cmd
= PRIV_WX_SPROM_READ
,
1019 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| SPROM_BUFFERSIZE
,
1020 .name
= "read_sprom",
1024 const struct iw_handler_def bcm43xx_wx_handlers_def
= {
1025 .standard
= bcm43xx_wx_handlers
,
1026 .num_standard
= ARRAY_SIZE(bcm43xx_wx_handlers
),
1027 .num_private
= ARRAY_SIZE(bcm43xx_priv_wx_handlers
),
1028 .num_private_args
= ARRAY_SIZE(bcm43xx_priv_wx_args
),
1029 .private = bcm43xx_priv_wx_handlers
,
1030 .private_args
= bcm43xx_priv_wx_args
,
1031 .get_wireless_stats
= bcm43xx_get_wireless_stats
,