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
52 static int bcm43xx_wx_get_name(struct net_device
*net_dev
,
53 struct iw_request_info
*info
,
54 union iwreq_data
*data
,
57 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
60 struct bcm43xx_phyinfo
*phy
;
61 char suffix
[7] = { 0 };
62 int have_a
= 0, have_b
= 0, have_g
= 0;
64 bcm43xx_lock(bcm
, flags
);
65 for (i
= 0; i
< bcm
->nr_80211_available
; i
++) {
66 phy
= &(bcm
->core_80211_ext
[i
].phy
);
68 case BCM43xx_PHYTYPE_A
:
71 case BCM43xx_PHYTYPE_G
:
73 case BCM43xx_PHYTYPE_B
:
80 bcm43xx_unlock(bcm
, flags
);
98 snprintf(data
->name
, IFNAMSIZ
, "IEEE 802.11%s", suffix
);
103 static int bcm43xx_wx_set_channelfreq(struct net_device
*net_dev
,
104 struct iw_request_info
*info
,
105 union iwreq_data
*data
,
108 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
109 struct ieee80211softmac_device
*softmac
= bcm
->softmac
;
115 bcm43xx_lock_mmio(bcm
, flags
);
116 if ((data
->freq
.m
>= 0) && (data
->freq
.m
<= 1000)) {
117 channel
= data
->freq
.m
;
118 freq
= bcm43xx_channel_to_freq(bcm
, channel
);
120 channel
= bcm43xx_freq_to_channel(bcm
, data
->freq
.m
);
123 if (!bcm43xx_is_valid_channel(bcm
, channel
))
125 if (bcm
->initialized
) {
126 //ieee80211softmac_disassoc(softmac, $REASON);
127 bcm43xx_mac_suspend(bcm
);
128 err
= bcm43xx_radio_selectchannel(bcm
, channel
, 0);
129 bcm43xx_mac_enable(bcm
);
131 bcm43xx_current_radio(bcm
)->initial_channel
= channel
;
135 bcm43xx_unlock_mmio(bcm
, flags
);
140 static int bcm43xx_wx_get_channelfreq(struct net_device
*net_dev
,
141 struct iw_request_info
*info
,
142 union iwreq_data
*data
,
145 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
146 struct bcm43xx_radioinfo
*radio
;
151 bcm43xx_lock(bcm
, flags
);
152 radio
= bcm43xx_current_radio(bcm
);
153 channel
= radio
->channel
;
154 if (channel
== 0xFF) {
155 assert(!bcm
->initialized
);
156 channel
= radio
->initial_channel
;
160 assert(channel
> 0 && channel
<= 1000);
162 data
->freq
.m
= bcm43xx_channel_to_freq(bcm
, channel
) * 100000;
163 data
->freq
.flags
= 1;
167 bcm43xx_unlock(bcm
, flags
);
172 static int bcm43xx_wx_set_mode(struct net_device
*net_dev
,
173 struct iw_request_info
*info
,
174 union iwreq_data
*data
,
177 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
182 if (mode
== IW_MODE_AUTO
)
183 mode
= BCM43xx_INITIAL_IWMODE
;
185 bcm43xx_lock_mmio(bcm
, flags
);
186 if (bcm
->ieee
->iw_mode
!= mode
)
187 bcm43xx_set_iwmode(bcm
, mode
);
188 bcm43xx_unlock_mmio(bcm
, flags
);
193 static int bcm43xx_wx_get_mode(struct net_device
*net_dev
,
194 struct iw_request_info
*info
,
195 union iwreq_data
*data
,
198 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
201 bcm43xx_lock(bcm
, flags
);
202 data
->mode
= bcm
->ieee
->iw_mode
;
203 bcm43xx_unlock(bcm
, flags
);
208 static int bcm43xx_wx_set_sensitivity(struct net_device
*net_dev
,
209 struct iw_request_info
*info
,
210 union iwreq_data
*data
,
217 static int bcm43xx_wx_get_sensitivity(struct net_device
*net_dev
,
218 struct iw_request_info
*info
,
219 union iwreq_data
*data
,
226 static int bcm43xx_wx_get_rangeparams(struct net_device
*net_dev
,
227 struct iw_request_info
*info
,
228 union iwreq_data
*data
,
231 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
232 struct iw_range
*range
= (struct iw_range
*)extra
;
233 const struct ieee80211_geo
*geo
;
236 struct bcm43xx_phyinfo
*phy
;
238 data
->data
.length
= sizeof(*range
);
239 memset(range
, 0, sizeof(*range
));
241 //TODO: What about 802.11b?
242 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
243 range
->throughput
= 27 * 1000 * 1000;
245 range
->max_qual
.qual
= 100;
246 /* TODO: Real max RSSI */
247 range
->max_qual
.level
= 0;
248 range
->max_qual
.noise
= 0;
249 range
->max_qual
.updated
= 7;
251 range
->avg_qual
.qual
= 70;
252 range
->avg_qual
.level
= 0;
253 range
->avg_qual
.noise
= 0;
254 range
->avg_qual
.updated
= 7;
256 range
->min_rts
= BCM43xx_MIN_RTS_THRESHOLD
;
257 range
->max_rts
= BCM43xx_MAX_RTS_THRESHOLD
;
258 range
->min_frag
= MIN_FRAG_THRESHOLD
;
259 range
->max_frag
= MAX_FRAG_THRESHOLD
;
261 range
->encoding_size
[0] = 5;
262 range
->encoding_size
[1] = 13;
263 range
->num_encoding_sizes
= 2;
264 range
->max_encoding_tokens
= WEP_KEYS
;
266 range
->we_version_compiled
= WIRELESS_EXT
;
267 range
->we_version_source
= BCM43xx_WX_VERSION
;
269 range
->enc_capa
= IW_ENC_CAPA_WPA
|
271 IW_ENC_CAPA_CIPHER_TKIP
|
272 IW_ENC_CAPA_CIPHER_CCMP
;
274 bcm43xx_lock(bcm
, flags
);
275 phy
= bcm43xx_current_phy(bcm
);
277 range
->num_bitrates
= 0;
279 if (phy
->type
== BCM43xx_PHYTYPE_A
||
280 phy
->type
== BCM43xx_PHYTYPE_G
) {
281 range
->num_bitrates
= 8;
282 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_6MB
;
283 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_9MB
;
284 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_12MB
;
285 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_18MB
;
286 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_24MB
;
287 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_36MB
;
288 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_48MB
;
289 range
->bitrate
[i
++] = IEEE80211_OFDM_RATE_54MB
;
291 if (phy
->type
== BCM43xx_PHYTYPE_B
||
292 phy
->type
== BCM43xx_PHYTYPE_G
) {
293 range
->num_bitrates
+= 4;
294 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_1MB
;
295 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_2MB
;
296 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_5MB
;
297 range
->bitrate
[i
++] = IEEE80211_CCK_RATE_11MB
;
300 geo
= ieee80211_get_geo(bcm
->ieee
);
301 range
->num_channels
= geo
->a_channels
+ geo
->bg_channels
;
303 for (i
= 0; i
< geo
->a_channels
; i
++) {
304 if (j
== IW_MAX_FREQUENCIES
)
306 range
->freq
[j
].i
= j
+ 1;
307 range
->freq
[j
].m
= geo
->a
[i
].freq
;//FIXME?
308 range
->freq
[j
].e
= 1;
311 for (i
= 0; i
< geo
->bg_channels
; i
++) {
312 if (j
== IW_MAX_FREQUENCIES
)
314 range
->freq
[j
].i
= j
+ 1;
315 range
->freq
[j
].m
= geo
->bg
[i
].freq
;//FIXME?
316 range
->freq
[j
].e
= 1;
319 range
->num_frequency
= j
;
321 bcm43xx_unlock(bcm
, flags
);
326 static int bcm43xx_wx_set_nick(struct net_device
*net_dev
,
327 struct iw_request_info
*info
,
328 union iwreq_data
*data
,
331 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
335 bcm43xx_lock(bcm
, flags
);
336 len
= min((size_t)data
->data
.length
, (size_t)IW_ESSID_MAX_SIZE
);
337 memcpy(bcm
->nick
, extra
, len
);
338 bcm
->nick
[len
] = '\0';
339 bcm43xx_unlock(bcm
, flags
);
344 static int bcm43xx_wx_get_nick(struct net_device
*net_dev
,
345 struct iw_request_info
*info
,
346 union iwreq_data
*data
,
349 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
353 bcm43xx_lock(bcm
, flags
);
354 len
= strlen(bcm
->nick
) + 1;
355 memcpy(extra
, bcm
->nick
, len
);
356 data
->data
.length
= (__u16
)len
;
357 data
->data
.flags
= 1;
358 bcm43xx_unlock(bcm
, flags
);
363 static int bcm43xx_wx_set_rts(struct net_device
*net_dev
,
364 struct iw_request_info
*info
,
365 union iwreq_data
*data
,
368 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
372 bcm43xx_lock(bcm
, flags
);
373 if (data
->rts
.disabled
) {
374 bcm
->rts_threshold
= BCM43xx_MAX_RTS_THRESHOLD
;
377 if (data
->rts
.value
>= BCM43xx_MIN_RTS_THRESHOLD
&&
378 data
->rts
.value
<= BCM43xx_MAX_RTS_THRESHOLD
) {
379 bcm
->rts_threshold
= data
->rts
.value
;
383 bcm43xx_unlock(bcm
, flags
);
388 static int bcm43xx_wx_get_rts(struct net_device
*net_dev
,
389 struct iw_request_info
*info
,
390 union iwreq_data
*data
,
393 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
396 bcm43xx_lock(bcm
, flags
);
397 data
->rts
.value
= bcm
->rts_threshold
;
399 data
->rts
.disabled
= (bcm
->rts_threshold
== BCM43xx_MAX_RTS_THRESHOLD
);
400 bcm43xx_unlock(bcm
, flags
);
405 static int bcm43xx_wx_set_frag(struct net_device
*net_dev
,
406 struct iw_request_info
*info
,
407 union iwreq_data
*data
,
410 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
414 bcm43xx_lock(bcm
, flags
);
415 if (data
->frag
.disabled
) {
416 bcm
->ieee
->fts
= MAX_FRAG_THRESHOLD
;
419 if (data
->frag
.value
>= MIN_FRAG_THRESHOLD
&&
420 data
->frag
.value
<= MAX_FRAG_THRESHOLD
) {
421 bcm
->ieee
->fts
= data
->frag
.value
& ~0x1;
425 bcm43xx_unlock(bcm
, flags
);
430 static int bcm43xx_wx_get_frag(struct net_device
*net_dev
,
431 struct iw_request_info
*info
,
432 union iwreq_data
*data
,
435 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
438 bcm43xx_lock(bcm
, flags
);
439 data
->frag
.value
= bcm
->ieee
->fts
;
440 data
->frag
.fixed
= 0;
441 data
->frag
.disabled
= (bcm
->ieee
->fts
== MAX_FRAG_THRESHOLD
);
442 bcm43xx_unlock(bcm
, flags
);
447 static int bcm43xx_wx_set_xmitpower(struct net_device
*net_dev
,
448 struct iw_request_info
*info
,
449 union iwreq_data
*data
,
452 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
453 struct bcm43xx_radioinfo
*radio
;
454 struct bcm43xx_phyinfo
*phy
;
459 if ((data
->txpower
.flags
& IW_TXPOW_TYPE
) != IW_TXPOW_DBM
) {
460 printk(PFX KERN_ERR
"TX power not in dBm.\n");
464 bcm43xx_lock_mmio(bcm
, flags
);
465 if (!bcm
->initialized
)
467 radio
= bcm43xx_current_radio(bcm
);
468 phy
= bcm43xx_current_phy(bcm
);
469 if (data
->txpower
.disabled
!= (!(radio
->enabled
))) {
470 if (data
->txpower
.disabled
)
471 bcm43xx_radio_turn_off(bcm
);
473 bcm43xx_radio_turn_on(bcm
);
475 if (data
->txpower
.value
> 0) {
476 /* desired and maxpower dBm values are in Q5.2 */
477 if (phy
->type
== BCM43xx_PHYTYPE_A
)
478 maxpower
= bcm
->sprom
.maxpower_aphy
;
480 maxpower
= bcm
->sprom
.maxpower_bgphy
;
481 radio
->txpower_desired
= limit_value(data
->txpower
.value
<< 2,
483 bcm43xx_phy_xmitpower(bcm
);
488 bcm43xx_unlock_mmio(bcm
, flags
);
493 static int bcm43xx_wx_get_xmitpower(struct net_device
*net_dev
,
494 struct iw_request_info
*info
,
495 union iwreq_data
*data
,
498 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
499 struct bcm43xx_radioinfo
*radio
;
503 bcm43xx_lock(bcm
, flags
);
504 if (!bcm
->initialized
)
506 radio
= bcm43xx_current_radio(bcm
);
507 /* desired dBm value is in Q5.2 */
508 data
->txpower
.value
= radio
->txpower_desired
>> 2;
509 data
->txpower
.fixed
= 1;
510 data
->txpower
.flags
= IW_TXPOW_DBM
;
511 data
->txpower
.disabled
= !(radio
->enabled
);
515 bcm43xx_unlock(bcm
, flags
);
520 static int bcm43xx_wx_set_retry(struct net_device
*net_dev
,
521 struct iw_request_info
*info
,
522 union iwreq_data
*data
,
529 static int bcm43xx_wx_get_retry(struct net_device
*net_dev
,
530 struct iw_request_info
*info
,
531 union iwreq_data
*data
,
538 static int bcm43xx_wx_set_encoding(struct net_device
*net_dev
,
539 struct iw_request_info
*info
,
540 union iwreq_data
*data
,
543 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
546 err
= ieee80211_wx_set_encode(bcm
->ieee
, info
, data
, extra
);
551 static int bcm43xx_wx_set_encodingext(struct net_device
*net_dev
,
552 struct iw_request_info
*info
,
553 union iwreq_data
*data
,
556 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
559 err
= ieee80211_wx_set_encodeext(bcm
->ieee
, info
, data
, extra
);
564 static int bcm43xx_wx_get_encoding(struct net_device
*net_dev
,
565 struct iw_request_info
*info
,
566 union iwreq_data
*data
,
569 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
572 err
= ieee80211_wx_get_encode(bcm
->ieee
, info
, data
, extra
);
577 static int bcm43xx_wx_get_encodingext(struct net_device
*net_dev
,
578 struct iw_request_info
*info
,
579 union iwreq_data
*data
,
582 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
585 err
= ieee80211_wx_get_encodeext(bcm
->ieee
, info
, data
, extra
);
590 static int bcm43xx_wx_set_power(struct net_device
*net_dev
,
591 struct iw_request_info
*info
,
592 union iwreq_data
*data
,
599 static int bcm43xx_wx_get_power(struct net_device
*net_dev
,
600 struct iw_request_info
*info
,
601 union iwreq_data
*data
,
608 static int bcm43xx_wx_set_interfmode(struct net_device
*net_dev
,
609 struct iw_request_info
*info
,
610 union iwreq_data
*data
,
613 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
617 mode
= *((int *)extra
);
620 mode
= BCM43xx_RADIO_INTERFMODE_NONE
;
623 mode
= BCM43xx_RADIO_INTERFMODE_NONWLAN
;
626 mode
= BCM43xx_RADIO_INTERFMODE_MANUALWLAN
;
629 mode
= BCM43xx_RADIO_INTERFMODE_AUTOWLAN
;
632 printk(KERN_ERR PFX
"set_interfmode allowed parameters are: "
633 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
638 bcm43xx_lock_mmio(bcm
, flags
);
639 if (bcm
->initialized
) {
640 err
= bcm43xx_radio_set_interference_mitigation(bcm
, mode
);
642 printk(KERN_ERR PFX
"Interference Mitigation not "
643 "supported by device\n");
646 if (mode
== BCM43xx_RADIO_INTERFMODE_AUTOWLAN
) {
647 printk(KERN_ERR PFX
"Interference Mitigation mode Auto-WLAN "
648 "not supported while the interface is down.\n");
651 bcm43xx_current_radio(bcm
)->interfmode
= mode
;
653 bcm43xx_unlock_mmio(bcm
, flags
);
658 static int bcm43xx_wx_get_interfmode(struct net_device
*net_dev
,
659 struct iw_request_info
*info
,
660 union iwreq_data
*data
,
663 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
667 bcm43xx_lock(bcm
, flags
);
668 mode
= bcm43xx_current_radio(bcm
)->interfmode
;
669 bcm43xx_unlock(bcm
, flags
);
672 case BCM43xx_RADIO_INTERFMODE_NONE
:
673 strncpy(extra
, "0 (No Interference Mitigation)", MAX_WX_STRING
);
675 case BCM43xx_RADIO_INTERFMODE_NONWLAN
:
676 strncpy(extra
, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING
);
678 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN
:
679 strncpy(extra
, "2 (WLAN Interference Mitigation)", MAX_WX_STRING
);
684 data
->data
.length
= strlen(extra
) + 1;
689 static int bcm43xx_wx_set_shortpreamble(struct net_device
*net_dev
,
690 struct iw_request_info
*info
,
691 union iwreq_data
*data
,
694 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
698 on
= *((int *)extra
);
699 bcm43xx_lock(bcm
, flags
);
700 bcm
->short_preamble
= !!on
;
701 bcm43xx_unlock(bcm
, flags
);
706 static int bcm43xx_wx_get_shortpreamble(struct net_device
*net_dev
,
707 struct iw_request_info
*info
,
708 union iwreq_data
*data
,
711 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
715 bcm43xx_lock(bcm
, flags
);
716 on
= bcm
->short_preamble
;
717 bcm43xx_unlock(bcm
, flags
);
720 strncpy(extra
, "1 (Short Preamble enabled)", MAX_WX_STRING
);
722 strncpy(extra
, "0 (Short Preamble disabled)", MAX_WX_STRING
);
723 data
->data
.length
= strlen(extra
) + 1;
728 static int bcm43xx_wx_set_swencryption(struct net_device
*net_dev
,
729 struct iw_request_info
*info
,
730 union iwreq_data
*data
,
733 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
737 on
= *((int *)extra
);
739 bcm43xx_lock(bcm
, flags
);
740 bcm
->ieee
->host_encrypt
= !!on
;
741 bcm
->ieee
->host_decrypt
= !!on
;
742 bcm
->ieee
->host_build_iv
= !on
;
743 bcm43xx_unlock(bcm
, flags
);
748 static int bcm43xx_wx_get_swencryption(struct net_device
*net_dev
,
749 struct iw_request_info
*info
,
750 union iwreq_data
*data
,
753 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
757 bcm43xx_lock(bcm
, flags
);
758 on
= bcm
->ieee
->host_encrypt
;
759 bcm43xx_unlock(bcm
, flags
);
762 strncpy(extra
, "1 (SW encryption enabled) ", MAX_WX_STRING
);
764 strncpy(extra
, "0 (SW encryption disabled) ", MAX_WX_STRING
);
765 data
->data
.length
= strlen(extra
+ 1);
770 /* Enough buffer to hold a hexdump of the sprom data. */
771 #define SPROM_BUFFERSIZE 512
773 static int sprom2hex(const u16
*sprom
, char *dump
)
777 for (i
= 0; i
< BCM43xx_SPROM_SIZE
; i
++) {
778 pos
+= snprintf(dump
+ pos
, SPROM_BUFFERSIZE
- pos
- 1,
779 "%04X", swab16(sprom
[i
]) & 0xFFFF);
785 static int hex2sprom(u16
*sprom
, const char *dump
, unsigned int len
)
789 unsigned long parsed
;
791 if (len
< BCM43xx_SPROM_SIZE
* sizeof(u16
) * 2)
793 while (cnt
< BCM43xx_SPROM_SIZE
) {
794 memcpy(tmp
, dump
, 4);
796 parsed
= simple_strtoul(tmp
, NULL
, 16);
797 sprom
[cnt
++] = swab16((u16
)parsed
);
803 static int bcm43xx_wx_sprom_read(struct net_device
*net_dev
,
804 struct iw_request_info
*info
,
805 union iwreq_data
*data
,
808 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
813 if (!capable(CAP_SYS_RAWIO
))
817 sprom
= kmalloc(BCM43xx_SPROM_SIZE
* sizeof(*sprom
),
822 bcm43xx_lock_mmio(bcm
, flags
);
824 if (bcm
->initialized
)
825 err
= bcm43xx_sprom_read(bcm
, sprom
);
826 bcm43xx_unlock_mmio(bcm
, flags
);
828 data
->data
.length
= sprom2hex(sprom
, extra
);
834 static int bcm43xx_wx_sprom_write(struct net_device
*net_dev
,
835 struct iw_request_info
*info
,
836 union iwreq_data
*data
,
839 struct bcm43xx_private
*bcm
= bcm43xx_priv(net_dev
);
846 if (!capable(CAP_SYS_RAWIO
))
850 sprom
= kmalloc(BCM43xx_SPROM_SIZE
* sizeof(*sprom
),
855 len
= data
->data
.length
;
856 extra
[len
- 1] = '\0';
857 input
= strchr(extra
, ':');
860 len
-= input
- extra
;
863 err
= hex2sprom(sprom
, input
, len
);
867 bcm43xx_lock_mmio(bcm
, flags
);
869 if (bcm
->initialized
)
870 err
= bcm43xx_sprom_write(bcm
, sprom
);
871 bcm43xx_unlock_mmio(bcm
, flags
);
882 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
883 static const iw_handler bcm43xx_wx_handlers
[] = {
884 /* Wireless Identification */
885 WX(SIOCGIWNAME
) = bcm43xx_wx_get_name
,
886 /* Basic operations */
887 WX(SIOCSIWFREQ
) = bcm43xx_wx_set_channelfreq
,
888 WX(SIOCGIWFREQ
) = bcm43xx_wx_get_channelfreq
,
889 WX(SIOCSIWMODE
) = bcm43xx_wx_set_mode
,
890 WX(SIOCGIWMODE
) = bcm43xx_wx_get_mode
,
891 /* Informative stuff */
892 WX(SIOCGIWRANGE
) = bcm43xx_wx_get_rangeparams
,
893 /* Access Point manipulation */
894 WX(SIOCSIWAP
) = ieee80211softmac_wx_set_wap
,
895 WX(SIOCGIWAP
) = ieee80211softmac_wx_get_wap
,
896 WX(SIOCSIWSCAN
) = ieee80211softmac_wx_trigger_scan
,
897 WX(SIOCGIWSCAN
) = ieee80211softmac_wx_get_scan_results
,
898 /* 802.11 specific support */
899 WX(SIOCSIWESSID
) = ieee80211softmac_wx_set_essid
,
900 WX(SIOCGIWESSID
) = ieee80211softmac_wx_get_essid
,
901 WX(SIOCSIWNICKN
) = bcm43xx_wx_set_nick
,
902 WX(SIOCGIWNICKN
) = bcm43xx_wx_get_nick
,
903 /* Other parameters */
904 WX(SIOCSIWRATE
) = ieee80211softmac_wx_set_rate
,
905 WX(SIOCGIWRATE
) = ieee80211softmac_wx_get_rate
,
906 WX(SIOCSIWRTS
) = bcm43xx_wx_set_rts
,
907 WX(SIOCGIWRTS
) = bcm43xx_wx_get_rts
,
908 WX(SIOCSIWFRAG
) = bcm43xx_wx_set_frag
,
909 WX(SIOCGIWFRAG
) = bcm43xx_wx_get_frag
,
910 WX(SIOCSIWTXPOW
) = bcm43xx_wx_set_xmitpower
,
911 WX(SIOCGIWTXPOW
) = bcm43xx_wx_get_xmitpower
,
912 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
913 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
915 WX(SIOCSIWENCODE
) = bcm43xx_wx_set_encoding
,
916 WX(SIOCGIWENCODE
) = bcm43xx_wx_get_encoding
,
917 WX(SIOCSIWENCODEEXT
) = bcm43xx_wx_set_encodingext
,
918 WX(SIOCGIWENCODEEXT
) = bcm43xx_wx_get_encodingext
,
920 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
921 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
922 WX(SIOCSIWGENIE
) = ieee80211softmac_wx_set_genie
,
923 WX(SIOCGIWGENIE
) = ieee80211softmac_wx_get_genie
,
924 WX(SIOCSIWAUTH
) = ieee80211_wx_set_auth
,
925 WX(SIOCGIWAUTH
) = ieee80211_wx_get_auth
,
929 static const iw_handler bcm43xx_priv_wx_handlers
[] = {
930 /* Set Interference Mitigation Mode. */
931 bcm43xx_wx_set_interfmode
,
932 /* Get Interference Mitigation Mode. */
933 bcm43xx_wx_get_interfmode
,
934 /* Enable/Disable Short Preamble mode. */
935 bcm43xx_wx_set_shortpreamble
,
936 /* Get Short Preamble mode. */
937 bcm43xx_wx_get_shortpreamble
,
938 /* Enable/Disable Software Encryption mode */
939 bcm43xx_wx_set_swencryption
,
940 /* Get Software Encryption mode */
941 bcm43xx_wx_get_swencryption
,
942 /* Write SRPROM data. */
943 bcm43xx_wx_sprom_write
,
944 /* Read SPROM data. */
945 bcm43xx_wx_sprom_read
,
948 #define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
949 #define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
950 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
951 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
952 #define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
953 #define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
954 #define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
955 #define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
957 #define PRIV_WX_DUMMY(ioctl) \
963 static const struct iw_priv_args bcm43xx_priv_wx_args
[] = {
965 .cmd
= PRIV_WX_SET_INTERFMODE
,
966 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
967 .name
= "set_interfmode",
970 .cmd
= PRIV_WX_GET_INTERFMODE
,
971 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
972 .name
= "get_interfmode",
975 .cmd
= PRIV_WX_SET_SHORTPREAMBLE
,
976 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
977 .name
= "set_shortpreambl",
980 .cmd
= PRIV_WX_GET_SHORTPREAMBLE
,
981 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
982 .name
= "get_shortpreambl",
985 .cmd
= PRIV_WX_SET_SWENCRYPTION
,
986 .set_args
= IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
987 .name
= "set_swencryption",
990 .cmd
= PRIV_WX_GET_SWENCRYPTION
,
991 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| MAX_WX_STRING
,
992 .name
= "get_swencryption",
995 .cmd
= PRIV_WX_SPROM_WRITE
,
996 .set_args
= IW_PRIV_TYPE_CHAR
| SPROM_BUFFERSIZE
,
997 .name
= "write_sprom",
1000 .cmd
= PRIV_WX_SPROM_READ
,
1001 .get_args
= IW_PRIV_TYPE_CHAR
| IW_PRIV_SIZE_FIXED
| SPROM_BUFFERSIZE
,
1002 .name
= "read_sprom",
1006 const struct iw_handler_def bcm43xx_wx_handlers_def
= {
1007 .standard
= bcm43xx_wx_handlers
,
1008 .num_standard
= ARRAY_SIZE(bcm43xx_wx_handlers
),
1009 .num_private
= ARRAY_SIZE(bcm43xx_priv_wx_handlers
),
1010 .num_private_args
= ARRAY_SIZE(bcm43xx_priv_wx_args
),
1011 .private = bcm43xx_priv_wx_handlers
,
1012 .private_args
= bcm43xx_priv_wx_args
,
1015 /* vim: set ts=8 sw=8 sts=8: */