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/delay.h>
39 #include "bcm43xx_wx.h"
40 #include "bcm43xx_main.h"
41 #include "bcm43xx_radio.h"
42 #include "bcm43xx_phy.h"
45 /* The WIRELESS_EXT version, which is implemented by this driver. */
46 #define BCM43xx_WX_VERSION 18
48 #define MAX_WX_STRING 80
50 static int bcm43xx_wx_get_name(struct net_device
*net_dev
,
51 struct iw_request_info
*info
,
52 union iwreq_data
*data
,
55 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
57 struct bcm43xx_phyinfo
*phy
;
58 char suffix
[7] = { 0 };
59 int have_a
= 0, have_b
= 0, have_g
= 0;
61 mutex_lock(&bcm
->mutex
);
62 for (i
= 0; i
< bcm
->nr_80211_available
; i
++) {
63 phy
= &(bcm
->core_80211_ext
[i
].phy
);
65 case BCM43xx_PHYTYPE_A
:
68 case BCM43xx_PHYTYPE_G
:
70 case BCM43xx_PHYTYPE_B
:
77 mutex_unlock(&bcm
->mutex
);
95 snprintf(data
->name
, IFNAMSIZ
, "IEEE 802.11%s", suffix
);
100 static int bcm43xx_wx_set_channelfreq(struct net_device
*net_dev
,
101 struct iw_request_info
*info
,
102 union iwreq_data
*data
,
105 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
112 mutex_lock(&bcm
->mutex
);
113 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
115 if ((data
->freq
.e
== 0) &&
116 (data
->freq
.m
>= 0) && (data
->freq
.m
<= 1000)) {
117 channel
= data
->freq
.m
;
118 freq
= bcm43xx_channel_to_freq(bcm
, channel
);
121 expon
= 6 - data
->freq
.e
;
122 while (--expon
>= 0) /* scale down the frequency to MHz */
125 channel
= bcm43xx_freq_to_channel(bcm
, freq
);
127 if (!ieee80211_is_valid_channel(bcm
->ieee
, channel
))
129 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
) {
130 //ieee80211softmac_disassoc(softmac, $REASON);
131 bcm43xx_mac_suspend(bcm
);
132 err
= bcm43xx_radio_selectchannel(bcm
, channel
, 0);
133 bcm43xx_mac_enable(bcm
);
135 bcm43xx_current_radio(bcm
)->initial_channel
= channel
;
139 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
140 mutex_unlock(&bcm
->mutex
);
145 static int bcm43xx_wx_get_channelfreq(struct net_device
*net_dev
,
146 struct iw_request_info
*info
,
147 union iwreq_data
*data
,
150 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
151 struct bcm43xx_radioinfo
*radio
;
155 mutex_lock(&bcm
->mutex
);
156 radio
= bcm43xx_current_radio(bcm
);
157 channel
= radio
->channel
;
158 if (channel
== 0xFF) {
159 channel
= radio
->initial_channel
;
163 assert(channel
> 0 && channel
<= 1000);
165 data
->freq
.m
= bcm43xx_channel_to_freq(bcm
, channel
) * 100000;
166 data
->freq
.flags
= 1;
170 mutex_unlock(&bcm
->mutex
);
175 static int bcm43xx_wx_set_mode(struct net_device
*net_dev
,
176 struct iw_request_info
*info
,
177 union iwreq_data
*data
,
180 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
185 if (mode
== IW_MODE_AUTO
)
186 mode
= BCM43xx_INITIAL_IWMODE
;
188 mutex_lock(&bcm
->mutex
);
189 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
190 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
) {
191 if (bcm
->ieee
->iw_mode
!= mode
)
192 bcm43xx_set_iwmode(bcm
, mode
);
194 bcm
->ieee
->iw_mode
= mode
;
195 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
196 mutex_unlock(&bcm
->mutex
);
201 static int bcm43xx_wx_get_mode(struct net_device
*net_dev
,
202 struct iw_request_info
*info
,
203 union iwreq_data
*data
,
206 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
208 mutex_lock(&bcm
->mutex
);
209 data
->mode
= bcm
->ieee
->iw_mode
;
210 mutex_unlock(&bcm
->mutex
);
215 static int bcm43xx_wx_get_rangeparams(struct net_device
*net_dev
,
216 struct iw_request_info
*info
,
217 union iwreq_data
*data
,
220 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
221 struct iw_range
*range
= (struct iw_range
*)extra
;
222 const struct ieee80211_geo
*geo
;
224 struct bcm43xx_phyinfo
*phy
;
226 data
->data
.length
= sizeof(*range
);
227 memset(range
, 0, sizeof(*range
));
229 //TODO: What about 802.11b?
230 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
231 range
->throughput
= 27 * 1000 * 1000;
233 range
->max_qual
.qual
= 100;
234 range
->max_qual
.level
= 146; /* set floor at -110 dBm (146 - 256) */
235 range
->max_qual
.noise
= 146;
236 range
->max_qual
.updated
= IW_QUAL_ALL_UPDATED
;
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_UPDATED
;
243 range
->min_rts
= BCM43xx_MIN_RTS_THRESHOLD
;
244 range
->max_rts
= BCM43xx_MAX_RTS_THRESHOLD
;
245 range
->min_frag
= MIN_FRAG_THRESHOLD
;
246 range
->max_frag
= MAX_FRAG_THRESHOLD
;
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
;
253 range
->we_version_compiled
= WIRELESS_EXT
;
254 range
->we_version_source
= BCM43xx_WX_VERSION
;
256 range
->enc_capa
= IW_ENC_CAPA_WPA
|
258 IW_ENC_CAPA_CIPHER_TKIP
|
259 IW_ENC_CAPA_CIPHER_CCMP
;
261 mutex_lock(&bcm
->mutex
);
262 phy
= bcm43xx_current_phy(bcm
);
264 range
->num_bitrates
= 0;
266 if (phy
->type
== BCM43xx_PHYTYPE_A
||
267 phy
->type
== BCM43xx_PHYTYPE_G
) {
268 range
->num_bitrates
= 8;
269 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_6MB
* 500000;
270 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_9MB
* 500000;
271 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_12MB
* 500000;
272 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_18MB
* 500000;
273 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_24MB
* 500000;
274 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_36MB
* 500000;
275 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_48MB
* 500000;
276 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_54MB
* 500000;
278 if (phy
->type
== BCM43xx_PHYTYPE_B
||
279 phy
->type
== BCM43xx_PHYTYPE_G
) {
280 range
->num_bitrates
+= 4;
281 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_1MB
* 500000;
282 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_2MB
* 500000;
283 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_5MB
* 500000;
284 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_11MB
* 500000;
287 geo
= ieee80211_get_geo(bcm
->ieee
);
288 range
->num_channels
= geo
->a_channels
+ geo
->bg_channels
;
290 for (i
= 0; i
< geo
->a_channels
; i
++) {
291 if (j
== IW_MAX_FREQUENCIES
)
293 range
->freq
[j
].i
= j
+ 1;
294 range
->freq
[j
].m
= geo
->a
[i
].freq
* 100000;
295 range
->freq
[j
].e
= 1;
298 for (i
= 0; i
< geo
->bg_channels
; i
++) {
299 if (j
== IW_MAX_FREQUENCIES
)
301 range
->freq
[j
].i
= j
+ 1;
302 range
->freq
[j
].m
= geo
->bg
[i
].freq
* 100000;
303 range
->freq
[j
].e
= 1;
306 range
->num_frequency
= j
;
308 mutex_unlock(&bcm
->mutex
);
313 static int bcm43xx_wx_set_nick(struct net_device
*net_dev
,
314 struct iw_request_info
*info
,
315 union iwreq_data
*data
,
318 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
321 mutex_lock(&bcm
->mutex
);
322 len
= min((size_t)data
->data
.length
, (size_t)IW_ESSID_MAX_SIZE
);
323 memcpy(bcm
->nick
, extra
, len
);
324 bcm
->nick
[len
] = '\0';
325 mutex_unlock(&bcm
->mutex
);
330 static int bcm43xx_wx_get_nick(struct net_device
*net_dev
,
331 struct iw_request_info
*info
,
332 union iwreq_data
*data
,
335 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
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
);
348 static int bcm43xx_wx_set_rts(struct net_device
*net_dev
,
349 struct iw_request_info
*info
,
350 union iwreq_data
*data
,
353 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
357 mutex_lock(&bcm
->mutex
);
358 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
359 if (data
->rts
.disabled
) {
360 bcm
->rts_threshold
= BCM43xx_MAX_RTS_THRESHOLD
;
363 if (data
->rts
.value
>= BCM43xx_MIN_RTS_THRESHOLD
&&
364 data
->rts
.value
<= BCM43xx_MAX_RTS_THRESHOLD
) {
365 bcm
->rts_threshold
= data
->rts
.value
;
369 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
370 mutex_unlock(&bcm
->mutex
);
375 static int bcm43xx_wx_get_rts(struct net_device
*net_dev
,
376 struct iw_request_info
*info
,
377 union iwreq_data
*data
,
380 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
382 mutex_lock(&bcm
->mutex
);
383 data
->rts
.value
= bcm
->rts_threshold
;
385 data
->rts
.disabled
= (bcm
->rts_threshold
== BCM43xx_MAX_RTS_THRESHOLD
);
386 mutex_unlock(&bcm
->mutex
);
391 static int bcm43xx_wx_set_frag(struct net_device
*net_dev
,
392 struct iw_request_info
*info
,
393 union iwreq_data
*data
,
396 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
400 mutex_lock(&bcm
->mutex
);
401 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
402 if (data
->frag
.disabled
) {
403 bcm
->ieee
->fts
= MAX_FRAG_THRESHOLD
;
406 if (data
->frag
.value
>= MIN_FRAG_THRESHOLD
&&
407 data
->frag
.value
<= MAX_FRAG_THRESHOLD
) {
408 bcm
->ieee
->fts
= data
->frag
.value
& ~0x1;
412 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
413 mutex_unlock(&bcm
->mutex
);
418 static int bcm43xx_wx_get_frag(struct net_device
*net_dev
,
419 struct iw_request_info
*info
,
420 union iwreq_data
*data
,
423 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
425 mutex_lock(&bcm
->mutex
);
426 data
->frag
.value
= bcm
->ieee
->fts
;
427 data
->frag
.fixed
= 0;
428 data
->frag
.disabled
= (bcm
->ieee
->fts
== MAX_FRAG_THRESHOLD
);
429 mutex_unlock(&bcm
->mutex
);
434 static int bcm43xx_wx_set_xmitpower(struct net_device
*net_dev
,
435 struct iw_request_info
*info
,
436 union iwreq_data
*data
,
439 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
440 struct bcm43xx_radioinfo
*radio
;
441 struct bcm43xx_phyinfo
*phy
;
446 if ((data
->txpower
.flags
& IW_TXPOW_TYPE
) != IW_TXPOW_DBM
) {
447 printk(KERN_ERR PFX
"TX power not in dBm.\n");
451 mutex_lock(&bcm
->mutex
);
452 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
453 if (bcm43xx_status(bcm
) != BCM43xx_STAT_INITIALIZED
)
455 radio
= bcm43xx_current_radio(bcm
);
456 phy
= bcm43xx_current_phy(bcm
);
457 if (data
->txpower
.disabled
!= (!(radio
->enabled
))) {
458 if (data
->txpower
.disabled
)
459 bcm43xx_radio_turn_off(bcm
);
461 bcm43xx_radio_turn_on(bcm
);
463 if (data
->txpower
.value
> 0) {
464 /* desired and maxpower dBm values are in Q5.2 */
465 if (phy
->type
== BCM43xx_PHYTYPE_A
)
466 maxpower
= bcm
->sprom
.maxpower_aphy
;
468 maxpower
= bcm
->sprom
.maxpower_bgphy
;
469 radio
->txpower_desired
= limit_value(data
->txpower
.value
<< 2,
471 bcm43xx_phy_xmitpower(bcm
);
476 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
477 mutex_unlock(&bcm
->mutex
);
482 static int bcm43xx_wx_get_xmitpower(struct net_device
*net_dev
,
483 struct iw_request_info
*info
,
484 union iwreq_data
*data
,
487 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
488 struct bcm43xx_radioinfo
*radio
;
491 mutex_lock(&bcm
->mutex
);
492 if (bcm43xx_status(bcm
) != BCM43xx_STAT_INITIALIZED
)
494 radio
= bcm43xx_current_radio(bcm
);
495 /* desired dBm value is in Q5.2 */
496 data
->txpower
.value
= radio
->txpower_desired
>> 2;
497 data
->txpower
.fixed
= 1;
498 data
->txpower
.flags
= IW_TXPOW_DBM
;
499 data
->txpower
.disabled
= !(radio
->enabled
);
503 mutex_unlock(&bcm
->mutex
);
508 static int bcm43xx_wx_set_encoding(struct net_device
*net_dev
,
509 struct iw_request_info
*info
,
510 union iwreq_data
*data
,
513 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
516 err
= ieee80211_wx_set_encode(bcm
->ieee
, info
, data
, extra
);
521 static int bcm43xx_wx_set_encodingext(struct net_device
*net_dev
,
522 struct iw_request_info
*info
,
523 union iwreq_data
*data
,
526 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
529 err
= ieee80211_wx_set_encodeext(bcm
->ieee
, info
, data
, extra
);
534 static int bcm43xx_wx_get_encoding(struct net_device
*net_dev
,
535 struct iw_request_info
*info
,
536 union iwreq_data
*data
,
539 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
542 err
= ieee80211_wx_get_encode(bcm
->ieee
, info
, data
, extra
);
547 static int bcm43xx_wx_get_encodingext(struct net_device
*net_dev
,
548 struct iw_request_info
*info
,
549 union iwreq_data
*data
,
552 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
555 err
= ieee80211_wx_get_encodeext(bcm
->ieee
, info
, data
, extra
);
560 static int bcm43xx_wx_set_interfmode(struct net_device
*net_dev
,
561 struct iw_request_info
*info
,
562 union iwreq_data
*data
,
565 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
569 mode
= *((int *)extra
);
572 mode
= BCM43xx_RADIO_INTERFMODE_NONE
;
575 mode
= BCM43xx_RADIO_INTERFMODE_NONWLAN
;
578 mode
= BCM43xx_RADIO_INTERFMODE_MANUALWLAN
;
581 mode
= BCM43xx_RADIO_INTERFMODE_AUTOWLAN
;
584 printk(KERN_ERR PFX
"set_interfmode allowed parameters are: "
585 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
590 mutex_lock(&bcm
->mutex
);
591 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
592 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
) {
593 err
= bcm43xx_radio_set_interference_mitigation(bcm
, mode
);
595 printk(KERN_ERR PFX
"Interference Mitigation not "
596 "supported by device\n");
599 if (mode
== BCM43xx_RADIO_INTERFMODE_AUTOWLAN
) {
600 printk(KERN_ERR PFX
"Interference Mitigation mode Auto-WLAN "
601 "not supported while the interface is down.\n");
604 bcm43xx_current_radio(bcm
)->interfmode
= mode
;
606 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
607 mutex_unlock(&bcm
->mutex
);
612 static int bcm43xx_wx_get_interfmode(struct net_device
*net_dev
,
613 struct iw_request_info
*info
,
614 union iwreq_data
*data
,
617 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
620 mutex_lock(&bcm
->mutex
);
621 mode
= bcm43xx_current_radio(bcm
)->interfmode
;
622 mutex_unlock(&bcm
->mutex
);
625 case BCM43xx_RADIO_INTERFMODE_NONE
:
626 strncpy(extra
, "0 (No Interference Mitigation)", MAX_WX_STRING
);
628 case BCM43xx_RADIO_INTERFMODE_NONWLAN
:
629 strncpy(extra
, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING
);
631 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN
:
632 strncpy(extra
, "2 (WLAN Interference Mitigation)", MAX_WX_STRING
);
637 data
->data
.length
= strlen(extra
) + 1;
642 static int bcm43xx_wx_set_shortpreamble(struct net_device
*net_dev
,
643 struct iw_request_info
*info
,
644 union iwreq_data
*data
,
647 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
651 on
= *((int *)extra
);
652 mutex_lock(&bcm
->mutex
);
653 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
654 bcm
->short_preamble
= !!on
;
655 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
656 mutex_unlock(&bcm
->mutex
);
661 static int bcm43xx_wx_get_shortpreamble(struct net_device
*net_dev
,
662 struct iw_request_info
*info
,
663 union iwreq_data
*data
,
666 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
669 mutex_lock(&bcm
->mutex
);
670 on
= bcm
->short_preamble
;
671 mutex_unlock(&bcm
->mutex
);
674 strncpy(extra
, "1 (Short Preamble enabled)", MAX_WX_STRING
);
676 strncpy(extra
, "0 (Short Preamble disabled)", MAX_WX_STRING
);
677 data
->data
.length
= strlen(extra
) + 1;
682 static int bcm43xx_wx_set_swencryption(struct net_device
*net_dev
,
683 struct iw_request_info
*info
,
684 union iwreq_data
*data
,
687 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
691 on
= *((int *)extra
);
693 mutex_lock(&bcm
->mutex
);
694 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
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
, flags
);
700 mutex_unlock(&bcm
->mutex
);
705 static int bcm43xx_wx_get_swencryption(struct net_device
*net_dev
,
706 struct iw_request_info
*info
,
707 union iwreq_data
*data
,
710 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
713 mutex_lock(&bcm
->mutex
);
714 on
= bcm
->ieee
->host_encrypt
;
715 mutex_unlock(&bcm
->mutex
);
718 strncpy(extra
, "1 (SW encryption enabled) ", MAX_WX_STRING
);
720 strncpy(extra
, "0 (SW encryption disabled) ", MAX_WX_STRING
);
721 data
->data
.length
= strlen(extra
+ 1);
726 /* Enough buffer to hold a hexdump of the sprom data. */
727 #define SPROM_BUFFERSIZE 512
729 static int sprom2hex(const u16
*sprom
, char *dump
)
733 for (i
= 0; i
< BCM43xx_SPROM_SIZE
; i
++) {
734 pos
+= snprintf(dump
+ pos
, SPROM_BUFFERSIZE
- pos
- 1,
735 "%04X", swab16(sprom
[i
]) & 0xFFFF);
741 static int hex2sprom(u16
*sprom
, const char *dump
, unsigned int len
)
745 unsigned long parsed
;
747 if (len
< BCM43xx_SPROM_SIZE
* sizeof(u16
) * 2)
749 while (cnt
< BCM43xx_SPROM_SIZE
) {
750 memcpy(tmp
, dump
, 4);
752 parsed
= simple_strtoul(tmp
, NULL
, 16);
753 sprom
[cnt
++] = swab16((u16
)parsed
);
759 static int bcm43xx_wx_sprom_read(struct net_device
*net_dev
,
760 struct iw_request_info
*info
,
761 union iwreq_data
*data
,
764 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
769 if (!capable(CAP_SYS_RAWIO
))
773 sprom
= kmalloc(BCM43xx_SPROM_SIZE
* sizeof(*sprom
),
778 mutex_lock(&bcm
->mutex
);
779 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
781 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
)
782 err
= bcm43xx_sprom_read(bcm
, sprom
);
783 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
784 mutex_unlock(&bcm
->mutex
);
786 data
->data
.length
= sprom2hex(sprom
, extra
);
792 static int bcm43xx_wx_sprom_write(struct net_device
*net_dev
,
793 struct iw_request_info
*info
,
794 union iwreq_data
*data
,
797 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
804 if (!capable(CAP_SYS_RAWIO
))
808 sprom
= kmalloc(BCM43xx_SPROM_SIZE
* sizeof(*sprom
),
813 len
= data
->data
.length
;
814 extra
[len
- 1] = '\0';
815 input
= strchr(extra
, ':');
818 len
-= input
- extra
;
821 err
= hex2sprom(sprom
, input
, len
);
825 mutex_lock(&bcm
->mutex
);
826 spin_lock_irqsave(&bcm
->irq_lock
, flags
);
827 spin_lock(&bcm
->leds_lock
);
829 if (bcm43xx_status(bcm
) == BCM43xx_STAT_INITIALIZED
)
830 err
= bcm43xx_sprom_write(bcm
, sprom
);
831 spin_unlock(&bcm
->leds_lock
);
832 spin_unlock_irqrestore(&bcm
->irq_lock
, flags
);
833 mutex_unlock(&bcm
->mutex
);
840 /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
842 static struct iw_statistics
*bcm43xx_get_wireless_stats(struct net_device
*net_dev
)
844 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
845 struct ieee80211softmac_device
*mac
= ieee80211_priv(net_dev
);
846 struct iw_statistics
*wstats
;
847 struct ieee80211_network
*network
= NULL
;
848 static int tmp_level
= 0;
849 static int tmp_qual
= 0;
852 wstats
= &bcm
->stats
.wstats
;
853 if (!mac
->associnfo
.associated
) {
854 wstats
->miss
.beacon
= 0;
855 // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
856 wstats
->discard
.retries
= 0;
857 // bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
858 wstats
->discard
.nwid
= 0;
859 // bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
860 wstats
->discard
.code
= 0;
861 // bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
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_QUAL_ALL_UPDATED
| IW_QUAL_DBM
;
871 /* fill in the real statistics when iface associated */
872 spin_lock_irqsave(&mac
->ieee
->lock
, flags
);
873 list_for_each_entry(network
, &mac
->ieee
->network_list
, list
) {
874 if (!memcmp(mac
->associnfo
.bssid
, network
->bssid
, ETH_ALEN
)) {
875 if (!tmp_level
) { /* get initial values */
876 tmp_level
= network
->stats
.signal
;
877 tmp_qual
= network
->stats
.rssi
;
878 } else { /* smooth results */
879 tmp_level
= (15 * tmp_level
+ network
->stats
.signal
)/16;
880 tmp_qual
= (15 * tmp_qual
+ network
->stats
.rssi
)/16;
885 spin_unlock_irqrestore(&mac
->ieee
->lock
, flags
);
886 wstats
->qual
.level
= tmp_level
;
887 wstats
->qual
.qual
= 100 * tmp_qual
/ RX_RSSI_MAX
;
888 wstats
->qual
.noise
= bcm
->stats
.noise
;
889 wstats
->qual
.updated
= IW_QUAL_ALL_UPDATED
| IW_QUAL_DBM
;
890 wstats
->discard
.code
= bcm
->ieee
->ieee_stats
.rx_discards_undecryptable
;
891 wstats
->discard
.retries
= bcm
->ieee
->ieee_stats
.tx_retry_limit_exceeded
;
892 wstats
->discard
.nwid
= bcm
->ieee
->ieee_stats
.tx_discards_wrong_sa
;
893 wstats
->discard
.fragment
= bcm
->ieee
->ieee_stats
.rx_fragments
;
894 wstats
->discard
.misc
= 0; // FIXME
895 wstats
->miss
.beacon
= 0; // FIXME
903 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
904 static const iw_handler bcm43xx_wx_handlers
[] = {
905 /* Wireless Identification */
906 WX(SIOCGIWNAME
) = bcm43xx_wx_get_name
,
907 /* Basic operations */
908 WX(SIOCSIWFREQ
) = bcm43xx_wx_set_channelfreq
,
909 WX(SIOCGIWFREQ
) = bcm43xx_wx_get_channelfreq
,
910 WX(SIOCSIWMODE
) = bcm43xx_wx_set_mode
,
911 WX(SIOCGIWMODE
) = bcm43xx_wx_get_mode
,
912 /* Informative stuff */
913 WX(SIOCGIWRANGE
) = bcm43xx_wx_get_rangeparams
,
914 /* Access Point manipulation */
915 WX(SIOCSIWAP
) = ieee80211softmac_wx_set_wap
,
916 WX(SIOCGIWAP
) = ieee80211softmac_wx_get_wap
,
917 WX(SIOCSIWSCAN
) = ieee80211softmac_wx_trigger_scan
,
918 WX(SIOCGIWSCAN
) = ieee80211softmac_wx_get_scan_results
,
919 /* 802.11 specific support */
920 WX(SIOCSIWESSID
) = ieee80211softmac_wx_set_essid
,
921 WX(SIOCGIWESSID
) = ieee80211softmac_wx_get_essid
,
922 WX(SIOCSIWNICKN
) = bcm43xx_wx_set_nick
,
923 WX(SIOCGIWNICKN
) = bcm43xx_wx_get_nick
,
924 /* Other parameters */
925 WX(SIOCSIWRATE
) = ieee80211softmac_wx_set_rate
,
926 WX(SIOCGIWRATE
) = ieee80211softmac_wx_get_rate
,
927 WX(SIOCSIWRTS
) = bcm43xx_wx_set_rts
,
928 WX(SIOCGIWRTS
) = bcm43xx_wx_get_rts
,
929 WX(SIOCSIWFRAG
) = bcm43xx_wx_set_frag
,
930 WX(SIOCGIWFRAG
) = bcm43xx_wx_get_frag
,
931 WX(SIOCSIWTXPOW
) = bcm43xx_wx_set_xmitpower
,
932 WX(SIOCGIWTXPOW
) = bcm43xx_wx_get_xmitpower
,
933 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
934 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
936 WX(SIOCSIWENCODE
) = bcm43xx_wx_set_encoding
,
937 WX(SIOCGIWENCODE
) = bcm43xx_wx_get_encoding
,
938 WX(SIOCSIWENCODEEXT
) = bcm43xx_wx_set_encodingext
,
939 WX(SIOCGIWENCODEEXT
) = bcm43xx_wx_get_encodingext
,
941 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
942 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
943 WX(SIOCSIWGENIE
) = ieee80211softmac_wx_set_genie
,
944 WX(SIOCGIWGENIE
) = ieee80211softmac_wx_get_genie
,
945 WX(SIOCSIWAUTH
) = ieee80211_wx_set_auth
,
946 WX(SIOCGIWAUTH
) = ieee80211_wx_get_auth
,
950 static const iw_handler bcm43xx_priv_wx_handlers
[] = {
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 mode */
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
,
969 #define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
970 #define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
971 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
972 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
973 #define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
974 #define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
975 #define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
976 #define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
978 #define PRIV_WX_DUMMY(ioctl) \
984 static const struct iw_priv_args bcm43xx_priv_wx_args
[] = {
986 .cmd
= PRIV_WX_SET_INTERFMODE
,
987 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
988 .name
= "set_interfmode",
991 .cmd
= PRIV_WX_GET_INTERFMODE
,
992 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
993 .name
= "get_interfmode",
996 .cmd
= PRIV_WX_SET_SHORTPREAMBLE
,
997 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
998 .name
= "set_shortpreamb",
1001 .cmd
= PRIV_WX_GET_SHORTPREAMBLE
,
1002 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
1003 .name
= "get_shortpreamb",
1006 .cmd
= PRIV_WX_SET_SWENCRYPTION
,
1007 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1008 .name
= "set_swencrypt",
1011 .cmd
= PRIV_WX_GET_SWENCRYPTION
,
1012 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
1013 .name
= "get_swencrypt",
1016 .cmd
= PRIV_WX_SPROM_WRITE
,
1017 .set_args
= IW_PRIV_TYPE_CHAR
| SPROM_BUFFERSIZE
,
1018 .name
= "write_sprom",
1021 .cmd
= PRIV_WX_SPROM_READ
,
1022 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| SPROM_BUFFERSIZE
,
1023 .name
= "read_sprom",
1027 const struct iw_handler_def bcm43xx_wx_handlers_def
= {
1028 .standard
= bcm43xx_wx_handlers
,
1029 .num_standard
= ARRAY_SIZE(bcm43xx_wx_handlers
),
1030 .num_private
= ARRAY_SIZE(bcm43xx_priv_wx_handlers
),
1031 .num_private_args
= ARRAY_SIZE(bcm43xx_priv_wx_args
),
1032 .private = bcm43xx_priv_wx_handlers
,
1033 .private_args
= bcm43xx_priv_wx_args
,
1034 .get_wireless_stats
= bcm43xx_get_wireless_stats
,