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
50 /* Define to enable a printk on each wx handler function invocation */
51 //#define BCM43xx_WX_DEBUG
54 #ifdef BCM43xx_WX_DEBUG
55 # define printk_wx printk
57 # define printk_wx(x...) do { /* nothing */ } while (0)
59 #define wx_enter() printk_wx(KERN_INFO PFX "WX handler called: %s\n", __FUNCTION__);
61 #define MAX_WX_STRING 80
64 static int bcm43xx_wx_get_name(struct net_device *net_dev,
65 struct iw_request_info *info,
66 union iwreq_data *data,
69 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
72 struct bcm43xx_phyinfo *phy;
73 char suffix[7] = { 0 };
74 int have_a = 0, have_b = 0, have_g = 0;
78 spin_lock_irqsave(&bcm->lock, flags);
79 nr_80211 = bcm43xx_num_80211_cores(bcm);
80 for (i = 0; i < nr_80211; i++) {
83 case BCM43xx_PHYTYPE_A:
86 case BCM43xx_PHYTYPE_G:
88 case BCM43xx_PHYTYPE_B:
95 spin_unlock_irqrestore(&bcm->lock, flags);
111 suffix[i - 1] = '\0';
113 snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
118 static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
119 struct iw_request_info *info,
120 union iwreq_data *data,
123 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
124 struct ieee80211softmac_device *softmac = bcm->softmac;
132 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
133 channel = data->freq.m;
134 freq = bcm43xx_channel_to_freq(bcm, channel);
136 channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
139 if (!bcm43xx_is_valid_channel(bcm, channel))
142 spin_lock_irqsave(&bcm->lock, flags);
143 if (bcm->initialized) {
144 //ieee80211softmac_disassoc(softmac, $REASON);
145 bcm43xx_mac_suspend(bcm);
146 err = bcm43xx_radio_selectchannel(bcm, channel, 0);
147 bcm43xx_mac_enable(bcm);
149 bcm->current_core->radio->initial_channel = channel;
150 spin_unlock_irqrestore(&bcm->lock, flags);
152 printk_wx(KERN_INFO PFX "Selected channel: %d\n", channel);
157 static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
158 struct iw_request_info *info,
159 union iwreq_data *data,
162 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
169 spin_lock_irqsave(&bcm->lock, flags);
170 channel = bcm->current_core->radio->channel;
171 if (channel == 0xFF) {
172 assert(!bcm->initialized);
173 channel = bcm->current_core->radio->initial_channel;
177 assert(channel > 0 && channel <= 1000);
179 data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
180 data->freq.flags = 1;
184 spin_unlock_irqrestore(&bcm->lock, flags);
189 static int bcm43xx_wx_set_mode(struct net_device *net_dev,
190 struct iw_request_info *info,
191 union iwreq_data *data,
194 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
201 if (mode == IW_MODE_AUTO)
202 mode = BCM43xx_INITIAL_IWMODE;
204 spin_lock_irqsave(&bcm->lock, flags);
205 if (bcm->ieee->iw_mode != mode)
206 bcm43xx_set_iwmode(bcm, mode);
207 spin_unlock_irqrestore(&bcm->lock, flags);
212 static int bcm43xx_wx_get_mode(struct net_device *net_dev,
213 struct iw_request_info *info,
214 union iwreq_data *data,
217 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
222 spin_lock_irqsave(&bcm->lock, flags);
223 data->mode = bcm->ieee->iw_mode;
224 spin_unlock_irqrestore(&bcm->lock, flags);
229 static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev,
230 struct iw_request_info *info,
231 union iwreq_data *data,
239 static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev,
240 struct iw_request_info *info,
241 union iwreq_data *data,
249 static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
250 struct iw_request_info *info,
251 union iwreq_data *data,
254 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
255 struct iw_range *range = (struct iw_range *)extra;
256 const struct ieee80211_geo *geo;
262 data->data.length = sizeof(*range);
263 memset(range, 0, sizeof(*range));
265 //TODO: What about 802.11b?
266 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
267 range->throughput = 27 * 1000 * 1000;
269 range->max_qual.qual = 100;
270 /* TODO: Real max RSSI */
271 range->max_qual.level = 0;
272 range->max_qual.noise = 0;
273 range->max_qual.updated = 7;
275 range->avg_qual.qual = 70;
276 range->avg_qual.level = 0;
277 range->avg_qual.noise = 0;
278 range->avg_qual.updated = 7;
280 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
281 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
282 range->min_frag = MIN_FRAG_THRESHOLD;
283 range->max_frag = MAX_FRAG_THRESHOLD;
285 range->encoding_size[0] = 5;
286 range->encoding_size[1] = 13;
287 range->num_encoding_sizes = 2;
288 range->max_encoding_tokens = WEP_KEYS;
290 range->we_version_compiled = WIRELESS_EXT;
291 range->we_version_source = BCM43xx_WX_VERSION;
293 range->enc_capa = IW_ENC_CAPA_WPA |
295 IW_ENC_CAPA_CIPHER_TKIP |
296 IW_ENC_CAPA_CIPHER_CCMP;
298 spin_lock_irqsave(&bcm->lock, flags);
300 range->num_bitrates = 0;
302 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ||
303 bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) {
304 range->num_bitrates = 8;
305 range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
306 range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
307 range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
308 range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
309 range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
310 range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
311 range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
312 range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
314 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B ||
315 bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) {
316 range->num_bitrates += 4;
317 range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
318 range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
319 range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
320 range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
323 geo = ieee80211_get_geo(bcm->ieee);
324 range->num_channels = geo->a_channels + geo->bg_channels;
326 for (i = 0; i < geo->a_channels; i++) {
327 if (j == IW_MAX_FREQUENCIES)
329 range->freq[j].i = j + 1;
330 range->freq[j].m = geo->a[i].freq;//FIXME?
331 range->freq[j].e = 1;
334 for (i = 0; i < geo->bg_channels; i++) {
335 if (j == IW_MAX_FREQUENCIES)
337 range->freq[j].i = j + 1;
338 range->freq[j].m = geo->bg[i].freq;//FIXME?
339 range->freq[j].e = 1;
342 range->num_frequency = j;
344 spin_unlock_irqrestore(&bcm->lock, flags);
349 static int bcm43xx_wx_set_nick(struct net_device *net_dev,
350 struct iw_request_info *info,
351 union iwreq_data *data,
354 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
360 spin_lock_irqsave(&bcm->lock, flags);
361 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
362 memcpy(bcm->nick, extra, len);
363 bcm->nick[len] = '\0';
364 spin_unlock_irqrestore(&bcm->lock, flags);
369 static int bcm43xx_wx_get_nick(struct net_device *net_dev,
370 struct iw_request_info *info,
371 union iwreq_data *data,
374 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
380 spin_lock_irqsave(&bcm->lock, flags);
381 len = strlen(bcm->nick) + 1;
382 memcpy(extra, bcm->nick, len);
383 data->data.length = (__u16)len;
384 data->data.flags = 1;
385 spin_unlock_irqrestore(&bcm->lock, flags);
390 static int bcm43xx_wx_set_rts(struct net_device *net_dev,
391 struct iw_request_info *info,
392 union iwreq_data *data,
395 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
401 spin_lock_irqsave(&bcm->lock, flags);
402 if (data->rts.disabled) {
403 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
406 if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
407 data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
408 bcm->rts_threshold = data->rts.value;
412 spin_unlock_irqrestore(&bcm->lock, flags);
417 static int bcm43xx_wx_get_rts(struct net_device *net_dev,
418 struct iw_request_info *info,
419 union iwreq_data *data,
422 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
427 spin_lock_irqsave(&bcm->lock, flags);
428 data->rts.value = bcm->rts_threshold;
430 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
431 spin_unlock_irqrestore(&bcm->lock, flags);
436 static int bcm43xx_wx_set_frag(struct net_device *net_dev,
437 struct iw_request_info *info,
438 union iwreq_data *data,
441 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
447 spin_lock_irqsave(&bcm->lock, flags);
448 if (data->frag.disabled) {
449 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
452 if (data->frag.value >= MIN_FRAG_THRESHOLD &&
453 data->frag.value <= MAX_FRAG_THRESHOLD) {
454 bcm->ieee->fts = data->frag.value & ~0x1;
458 spin_unlock_irqrestore(&bcm->lock, flags);
463 static int bcm43xx_wx_get_frag(struct net_device *net_dev,
464 struct iw_request_info *info,
465 union iwreq_data *data,
468 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
473 spin_lock_irqsave(&bcm->lock, flags);
474 data->frag.value = bcm->ieee->fts;
475 data->frag.fixed = 0;
476 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
477 spin_unlock_irqrestore(&bcm->lock, flags);
482 static int bcm43xx_wx_set_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;
489 struct bcm43xx_phyinfo *phy;
496 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
497 printk(PFX KERN_ERR "TX power not in dBm.\n");
501 spin_lock_irqsave(&bcm->lock, flags);
502 if (!bcm->initialized)
504 radio = bcm->current_core->radio;
505 phy = bcm->current_core->phy;
506 if (data->txpower.disabled != (!(radio->enabled))) {
507 if (data->txpower.disabled)
508 bcm43xx_radio_turn_off(bcm);
510 bcm43xx_radio_turn_on(bcm);
512 if (data->txpower.value > 0) {
513 /* desired and maxpower dBm values are in Q5.2 */
514 if (phy->type == BCM43xx_PHYTYPE_A)
515 maxpower = bcm->sprom.maxpower_aphy;
517 maxpower = bcm->sprom.maxpower_bgphy;
518 radio->txpower_desired = limit_value(data->txpower.value << 2,
520 bcm43xx_phy_xmitpower(bcm);
525 spin_unlock_irqrestore(&bcm->lock, flags);
530 static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
531 struct iw_request_info *info,
532 union iwreq_data *data,
535 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
536 struct bcm43xx_radioinfo *radio;
542 spin_lock_irqsave(&bcm->lock, flags);
543 if (!bcm->initialized)
545 radio = bcm->current_core->radio;
546 /* desired dBm value is in Q5.2 */
547 data->txpower.value = radio->txpower_desired >> 2;
548 data->txpower.fixed = 1;
549 data->txpower.flags = IW_TXPOW_DBM;
550 data->txpower.disabled = !(radio->enabled);
554 spin_unlock_irqrestore(&bcm->lock, flags);
559 static int bcm43xx_wx_set_retry(struct net_device *net_dev,
560 struct iw_request_info *info,
561 union iwreq_data *data,
569 static int bcm43xx_wx_get_retry(struct net_device *net_dev,
570 struct iw_request_info *info,
571 union iwreq_data *data,
579 static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
580 struct iw_request_info *info,
581 union iwreq_data *data,
584 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
589 err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
594 static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
595 struct iw_request_info *info,
596 union iwreq_data *data,
599 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
604 err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
609 static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
610 struct iw_request_info *info,
611 union iwreq_data *data,
614 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
619 err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
624 static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
625 struct iw_request_info *info,
626 union iwreq_data *data,
629 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
634 err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
639 static int bcm43xx_wx_set_power(struct net_device *net_dev,
640 struct iw_request_info *info,
641 union iwreq_data *data,
649 static int bcm43xx_wx_get_power(struct net_device *net_dev,
650 struct iw_request_info *info,
651 union iwreq_data *data,
659 static int bcm43xx_wx_set_interfmode(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);
670 mode = *((int *)extra);
673 mode = BCM43xx_RADIO_INTERFMODE_NONE;
676 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
679 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
682 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
685 printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
686 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
691 spin_lock_irqsave(&bcm->lock, flags);
692 if (bcm->initialized) {
693 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
695 printk(KERN_ERR PFX "Interference Mitigation not "
696 "supported by device\n");
699 if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
700 printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
701 "not supported while the interface is down.\n");
704 bcm->current_core->radio->interfmode = mode;
706 spin_unlock_irqrestore(&bcm->lock, flags);
711 static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
712 struct iw_request_info *info,
713 union iwreq_data *data,
716 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
722 spin_lock_irqsave(&bcm->lock, flags);
723 mode = bcm->current_core->radio->interfmode;
724 spin_unlock_irqrestore(&bcm->lock, flags);
727 case BCM43xx_RADIO_INTERFMODE_NONE:
728 strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
730 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
731 strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
733 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
734 strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
739 data->data.length = strlen(extra) + 1;
744 static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
745 struct iw_request_info *info,
746 union iwreq_data *data,
749 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
755 on = *((int *)extra);
756 spin_lock_irqsave(&bcm->lock, flags);
757 bcm->short_preamble = !!on;
758 spin_unlock_irqrestore(&bcm->lock, flags);
763 static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
764 struct iw_request_info *info,
765 union iwreq_data *data,
768 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
774 spin_lock_irqsave(&bcm->lock, flags);
775 on = bcm->short_preamble;
776 spin_unlock_irqrestore(&bcm->lock, flags);
779 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
781 strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
782 data->data.length = strlen(extra) + 1;
787 static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
788 struct iw_request_info *info,
789 union iwreq_data *data,
792 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
798 on = *((int *)extra);
799 spin_lock_irqsave(&bcm->lock, flags);
800 bcm->ieee->host_encrypt = !!on;
801 bcm->ieee->host_decrypt = !!on;
802 bcm->ieee->host_build_iv = !on;
804 spin_unlock_irqrestore(&bcm->lock, flags);
809 static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
810 struct iw_request_info *info,
811 union iwreq_data *data,
814 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
820 spin_lock_irqsave(&bcm->lock, flags);
821 on = bcm->ieee->host_encrypt;
822 spin_unlock_irqrestore(&bcm->lock, flags);
825 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
827 strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
828 data->data.length = strlen(extra + 1);
833 /* Enough buffer to hold a hexdump of the sprom data. */
834 #define SPROM_BUFFERSIZE 512
836 static int sprom2hex(const u16 *sprom, char *dump)
840 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
841 pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
842 "%04X", swab16(sprom[i]) & 0xFFFF);
848 static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
852 unsigned long parsed;
853 u8 crc, expected_crc;
855 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
857 while (cnt < BCM43xx_SPROM_SIZE) {
858 memcpy(tmp, dump, 4);
860 parsed = simple_strtoul(tmp, NULL, 16);
861 sprom[cnt++] = swab16((u16)parsed);
864 crc = bcm43xx_sprom_crc(sprom);
865 expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
866 if (crc != expected_crc) {
867 printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
874 static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
875 struct iw_request_info *info,
876 union iwreq_data *data,
879 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
884 if (!capable(CAP_SYS_RAWIO))
888 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
893 spin_lock_irqsave(&bcm->lock, flags);
895 if (!bcm->initialized) {
896 spin_unlock_irqrestore(&bcm->lock, flags);
899 for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
900 sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
901 spin_unlock_irqrestore(&bcm->lock, flags);
903 data->data.length = sprom2hex(sprom, extra);
912 static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
913 struct iw_request_info *info,
914 union iwreq_data *data,
917 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
926 if (!capable(CAP_SYS_RAWIO))
930 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
935 len = data->data.length;
936 extra[len - 1] = '\0';
937 input = strchr(extra, ':');
940 len -= input - extra;
943 err = hex2sprom(sprom, input, len);
947 spin_lock_irqsave(&bcm->lock, flags);
949 if (!bcm->initialized) {
950 spin_unlock_irqrestore(&bcm->lock, flags);
954 printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
955 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
957 printk(KERN_ERR PFX "Could not access SPROM control register.\n");
960 spromctl |= 0x10; /* SPROM WRITE enable. */
961 bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
963 printk(KERN_ERR PFX "Could not access SPROM control register.\n");
966 /* We must burn lots of CPU cycles here, but that does not
967 * really matter as one does not write the SPROM every other minute...
969 printk(KERN_INFO PFX "[ 0%%");
971 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
980 bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
983 spromctl &= ~0x10; /* SPROM WRITE enable. */
984 bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
986 printk(KERN_ERR PFX "Could not access SPROM control register.\n");
991 printk(KERN_INFO PFX "SPROM written.\n");
994 spin_unlock_irqrestore(&bcm->lock, flags);
1005 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
1006 static const iw_handler bcm43xx_wx_handlers[] = {
1007 /* Wireless Identification */
1008 WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
1009 /* Basic operations */
1010 WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
1011 WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
1012 WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
1013 WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
1014 /* Informative stuff */
1015 WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
1016 /* Access Point manipulation */
1017 WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
1018 WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
1019 WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
1020 WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
1021 /* 802.11 specific support */
1022 WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
1023 WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
1024 WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
1025 WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
1026 /* Other parameters */
1027 WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
1028 WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
1029 WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
1030 WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
1031 WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
1032 WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
1033 WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
1034 WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
1035 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
1036 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
1038 WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
1039 WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
1040 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
1041 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
1043 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
1044 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
1045 WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
1046 WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
1047 WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
1048 WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
1052 static const iw_handler bcm43xx_priv_wx_handlers[] = {
1053 /* Set Interference Mitigation Mode. */
1054 bcm43xx_wx_set_interfmode,
1055 /* Get Interference Mitigation Mode. */
1056 bcm43xx_wx_get_interfmode,
1057 /* Enable/Disable Short Preamble mode. */
1058 bcm43xx_wx_set_shortpreamble,
1059 /* Get Short Preamble mode. */
1060 bcm43xx_wx_get_shortpreamble,
1061 /* Enable/Disable Software Encryption mode */
1062 bcm43xx_wx_set_swencryption,
1063 /* Get Software Encryption mode */
1064 bcm43xx_wx_get_swencryption,
1065 /* Write SRPROM data. */
1066 bcm43xx_wx_sprom_write,
1067 /* Read SPROM data. */
1068 bcm43xx_wx_sprom_read,
1071 #define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
1072 #define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
1073 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
1074 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
1075 #define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
1076 #define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
1077 #define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
1078 #define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
1080 #define PRIV_WX_DUMMY(ioctl) \
1083 .name = "__unused" \
1086 static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
1088 .cmd = PRIV_WX_SET_INTERFMODE,
1089 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1090 .name = "set_interfmode",
1093 .cmd = PRIV_WX_GET_INTERFMODE,
1094 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
1095 .name = "get_interfmode",
1098 .cmd = PRIV_WX_SET_SHORTPREAMBLE,
1099 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1100 .name = "set_shortpreambl",
1103 .cmd = PRIV_WX_GET_SHORTPREAMBLE,
1104 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
1105 .name = "get_shortpreambl",
1108 .cmd = PRIV_WX_SET_SWENCRYPTION,
1109 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1110 .name = "set_swencryption",
1113 .cmd = PRIV_WX_GET_SWENCRYPTION,
1114 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
1115 .name = "get_swencryption",
1118 .cmd = PRIV_WX_SPROM_WRITE,
1119 .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
1120 .name = "write_sprom",
1123 .cmd = PRIV_WX_SPROM_READ,
1124 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
1125 .name = "read_sprom",
1129 const struct iw_handler_def bcm43xx_wx_handlers_def = {
1130 .standard = bcm43xx_wx_handlers,
1131 .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
1132 .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
1133 .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
1134 .private = bcm43xx_priv_wx_handlers,
1135 .private_args = bcm43xx_priv_wx_args,
1138 /* vim: set ts=8 sw=8 sts=8: */