[PATCH] bcm43xx: sync with svn.berlios.de
[linux-2.6/cjktty.git] / drivers / net / wireless / bcm43xx / bcm43xx_main.c
blob4b4e60a22c0b488ec3ad2dc621b7e3b872c52b71
1 /*
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/delay.h>
32 #include <linux/init.h>
33 #include <linux/moduleparam.h>
34 #include <linux/if_arp.h>
35 #include <linux/etherdevice.h>
36 #include <linux/version.h>
37 #include <linux/firmware.h>
38 #include <linux/wireless.h>
39 #include <linux/workqueue.h>
40 #include <linux/skbuff.h>
41 #include <net/iw_handler.h>
43 #include "bcm43xx.h"
44 #include "bcm43xx_main.h"
45 #include "bcm43xx_debugfs.h"
46 #include "bcm43xx_radio.h"
47 #include "bcm43xx_phy.h"
48 #include "bcm43xx_dma.h"
49 #include "bcm43xx_pio.h"
50 #include "bcm43xx_power.h"
51 #include "bcm43xx_wx.h"
54 MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
55 MODULE_AUTHOR("Martin Langer");
56 MODULE_AUTHOR("Stefano Brivio");
57 MODULE_AUTHOR("Michael Buesch");
58 MODULE_LICENSE("GPL");
60 #ifdef CONFIG_BCM947XX
61 extern char *nvram_get(char *name);
62 #endif
64 /* Module parameters */
65 static int modparam_pio;
66 module_param_named(pio, modparam_pio, int, 0444);
67 MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
69 static int modparam_bad_frames_preempt;
70 module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
71 MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
73 static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
74 module_param_named(short_retry, modparam_short_retry, int, 0444);
75 MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
77 static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
78 module_param_named(long_retry, modparam_long_retry, int, 0444);
79 MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
81 static int modparam_locale = -1;
82 module_param_named(locale, modparam_locale, int, 0444);
83 MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
85 static int modparam_outdoor;
86 module_param_named(outdoor, modparam_outdoor, int, 0444);
87 MODULE_PARM_DESC(outdoor, "Set to 1, if you are using the device outdoor, 0 otherwise.");
89 static int modparam_noleds;
90 module_param_named(noleds, modparam_noleds, int, 0444);
91 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
93 #ifdef CONFIG_BCM43XX_DEBUG
94 static char modparam_fwpostfix[64];
95 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
96 MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
97 #else
98 # define modparam_fwpostfix ""
99 #endif /* CONFIG_BCM43XX_DEBUG*/
102 /* If you want to debug with just a single device, enable this,
103 * where the string is the pci device ID (as given by the kernel's
104 * pci_name function) of the device to be used.
106 //#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0"
108 /* If you want to enable printing of each MMIO access, enable this. */
109 //#define DEBUG_ENABLE_MMIO_PRINT
111 /* If you want to enable printing of MMIO access within
112 * ucode/pcm upload, initvals write, enable this.
114 //#define DEBUG_ENABLE_UCODE_MMIO_PRINT
116 /* If you want to enable printing of PCI Config Space access, enable this */
117 //#define DEBUG_ENABLE_PCILOG
120 static struct pci_device_id bcm43xx_pci_tbl[] = {
122 /* Detailed list maintained at:
123 * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
126 #ifdef CONFIG_BCM947XX
127 /* SB bus on BCM947xx */
128 { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
129 #endif
131 /* Broadcom 4303 802.11b */
132 { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
134 /* Broadcom 4307 802.11b */
135 { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
137 /* Broadcom 4318 802.11b/g */
138 { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
140 /* Broadcom 4306 802.11b/g */
141 { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
143 /* Broadcom 4306 802.11a */
144 // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
146 /* Broadcom 4309 802.11a/b/g */
147 { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
149 /* Broadcom 43XG 802.11b/g */
150 { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
152 /* required last entry */
153 { 0, },
155 MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
157 static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
159 u32 status;
161 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
162 if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
163 val = swab32(val);
165 bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
166 bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
169 static inline
170 void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
171 u16 routing, u16 offset)
173 u32 control;
175 /* "offset" is the WORD offset. */
177 control = routing;
178 control <<= 16;
179 control |= offset;
180 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
183 u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
184 u16 routing, u16 offset)
186 u32 ret;
188 if (routing == BCM43xx_SHM_SHARED) {
189 if (offset & 0x0003) {
190 /* Unaligned access */
191 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
192 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
193 ret <<= 16;
194 bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
195 ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
197 return ret;
199 offset >>= 2;
201 bcm43xx_shm_control_word(bcm, routing, offset);
202 ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
204 return ret;
207 u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
208 u16 routing, u16 offset)
210 u16 ret;
212 if (routing == BCM43xx_SHM_SHARED) {
213 if (offset & 0x0003) {
214 /* Unaligned access */
215 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
216 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
218 return ret;
220 offset >>= 2;
222 bcm43xx_shm_control_word(bcm, routing, offset);
223 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
225 return ret;
228 void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
229 u16 routing, u16 offset,
230 u32 value)
232 if (routing == BCM43xx_SHM_SHARED) {
233 if (offset & 0x0003) {
234 /* Unaligned access */
235 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
236 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
237 (value >> 16) & 0xffff);
238 bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
239 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
240 value & 0xffff);
241 return;
243 offset >>= 2;
245 bcm43xx_shm_control_word(bcm, routing, offset);
246 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
249 void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
250 u16 routing, u16 offset,
251 u16 value)
253 if (routing == BCM43xx_SHM_SHARED) {
254 if (offset & 0x0003) {
255 /* Unaligned access */
256 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
257 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
258 value);
259 return;
261 offset >>= 2;
263 bcm43xx_shm_control_word(bcm, routing, offset);
264 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
267 void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
269 /* We need to be careful. As we read the TSF from multiple
270 * registers, we should take care of register overflows.
271 * In theory, the whole tsf read process should be atomic.
272 * We try to be atomic here, by restaring the read process,
273 * if any of the high registers changed (overflew).
275 if (bcm->current_core->rev >= 3) {
276 u32 low, high, high2;
278 do {
279 high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
280 low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
281 high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
282 } while (unlikely(high != high2));
284 *tsf = high;
285 *tsf <<= 32;
286 *tsf |= low;
287 } else {
288 u64 tmp;
289 u16 v0, v1, v2, v3;
290 u16 test1, test2, test3;
292 do {
293 v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
294 v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
295 v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
296 v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
298 test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
299 test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
300 test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
301 } while (v3 != test3 || v2 != test2 || v1 != test1);
303 *tsf = v3;
304 *tsf <<= 48;
305 tmp = v2;
306 tmp <<= 32;
307 *tsf |= tmp;
308 tmp = v1;
309 tmp <<= 16;
310 *tsf |= tmp;
311 *tsf |= v0;
315 void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
317 u32 status;
319 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
320 status |= BCM43xx_SBF_TIME_UPDATE;
321 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
323 /* Be careful with the in-progress timer.
324 * First zero out the low register, so we have a full
325 * register-overflow duration to complete the operation.
327 if (bcm->current_core->rev >= 3) {
328 u32 lo = (tsf & 0x00000000FFFFFFFFULL);
329 u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
331 barrier();
332 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
333 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
334 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
335 } else {
336 u16 v0 = (tsf & 0x000000000000FFFFULL);
337 u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
338 u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
339 u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
341 barrier();
342 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
343 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
344 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
345 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
346 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
349 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
350 status &= ~BCM43xx_SBF_TIME_UPDATE;
351 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
354 static inline
355 u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp,
356 const int ofdm_modulation)
358 u8 rate;
360 if (ofdm_modulation) {
361 switch (plcp->raw[0] & 0xF) {
362 case 0xB:
363 rate = IEEE80211_OFDM_RATE_6MB;
364 break;
365 case 0xF:
366 rate = IEEE80211_OFDM_RATE_9MB;
367 break;
368 case 0xA:
369 rate = IEEE80211_OFDM_RATE_12MB;
370 break;
371 case 0xE:
372 rate = IEEE80211_OFDM_RATE_18MB;
373 break;
374 case 0x9:
375 rate = IEEE80211_OFDM_RATE_24MB;
376 break;
377 case 0xD:
378 rate = IEEE80211_OFDM_RATE_36MB;
379 break;
380 case 0x8:
381 rate = IEEE80211_OFDM_RATE_48MB;
382 break;
383 case 0xC:
384 rate = IEEE80211_OFDM_RATE_54MB;
385 break;
386 default:
387 rate = 0;
388 assert(0);
390 } else {
391 switch (plcp->raw[0]) {
392 case 0x0A:
393 rate = IEEE80211_CCK_RATE_1MB;
394 break;
395 case 0x14:
396 rate = IEEE80211_CCK_RATE_2MB;
397 break;
398 case 0x37:
399 rate = IEEE80211_CCK_RATE_5MB;
400 break;
401 case 0x6E:
402 rate = IEEE80211_CCK_RATE_11MB;
403 break;
404 default:
405 rate = 0;
406 assert(0);
410 return rate;
413 static inline
414 u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
416 switch (bitrate) {
417 case IEEE80211_CCK_RATE_1MB:
418 return 0x0A;
419 case IEEE80211_CCK_RATE_2MB:
420 return 0x14;
421 case IEEE80211_CCK_RATE_5MB:
422 return 0x37;
423 case IEEE80211_CCK_RATE_11MB:
424 return 0x6E;
426 assert(0);
427 return 0;
430 static inline
431 u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
433 switch (bitrate) {
434 case IEEE80211_OFDM_RATE_6MB:
435 return 0xB;
436 case IEEE80211_OFDM_RATE_9MB:
437 return 0xF;
438 case IEEE80211_OFDM_RATE_12MB:
439 return 0xA;
440 case IEEE80211_OFDM_RATE_18MB:
441 return 0xE;
442 case IEEE80211_OFDM_RATE_24MB:
443 return 0x9;
444 case IEEE80211_OFDM_RATE_36MB:
445 return 0xD;
446 case IEEE80211_OFDM_RATE_48MB:
447 return 0x8;
448 case IEEE80211_OFDM_RATE_54MB:
449 return 0xC;
451 assert(0);
452 return 0;
455 static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
456 u16 octets, const u8 bitrate,
457 const int ofdm_modulation)
459 __le32 *data = &(plcp->data);
460 __u8 *raw = plcp->raw;
462 /* Account for hardware-appended FCS. */
463 octets += IEEE80211_FCS_LEN;
465 if (ofdm_modulation) {
466 *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
467 assert(!(octets & 0xF000));
468 *data |= (octets << 5);
469 *data = cpu_to_le32(*data);
470 } else {
471 u32 plen;
473 plen = octets * 16 / bitrate;
474 if ((octets * 16 % bitrate) > 0) {
475 plen++;
476 if ((bitrate == IEEE80211_CCK_RATE_11MB)
477 && ((octets * 8 % 11) < 4)) {
478 raw[1] = 0x84;
479 } else
480 raw[1] = 0x04;
481 } else
482 raw[1] = 0x04;
483 *data |= cpu_to_le32(plen << 16);
484 raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
487 //bcm43xx_printk_bitdump(raw, 4, 0, "PLCP");
490 void fastcall
491 bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
492 struct bcm43xx_txhdr *txhdr,
493 const unsigned char *fragment_data,
494 unsigned int fragment_len,
495 const int is_first_fragment,
496 const u16 cookie)
498 const struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
499 const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data;
500 const struct ieee80211_security *secinfo = &bcm->ieee->sec;
501 u8 bitrate;
502 int ofdm_modulation;
503 u8 fallback_bitrate;
504 int fallback_ofdm_modulation;
505 u16 tmp;
506 u16 encrypt_frame;
508 /* Now construct the TX header. */
509 memset(txhdr, 0, sizeof(*txhdr));
511 //TODO: Some RTS/CTS stuff has to be done.
512 //TODO: Encryption stuff.
513 //TODO: others?
515 bitrate = bcm->softmac->txrates.default_rate;
516 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
517 fallback_bitrate = bcm->softmac->txrates.default_fallback;
518 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
520 /* Set Frame Control from 80211 header. */
521 txhdr->frame_control = wireless_header->frame_ctl;
522 /* Copy address1 from 80211 header. */
523 memcpy(txhdr->mac1, wireless_header->addr1, 6);
524 /* Set the fallback duration ID. */
525 //FIXME: We use the original durid for now.
526 txhdr->fallback_dur_id = wireless_header->duration_id;
528 /* Set the cookie (used as driver internal ID for the frame) */
529 txhdr->cookie = cpu_to_le16(cookie);
531 encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
532 if (encrypt_frame && !bcm->ieee->host_encrypt) {
533 const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
534 if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) {
535 dprintkl(KERN_ERR PFX "invalid packet with PROTECTED"
536 "flag set discarded");
537 return;
539 memcpy(txhdr->wep_iv, hdr->payload, 4);
540 /* Hardware appends ICV. */
541 fragment_len += 4;
544 /* Generate the PLCP header and the fallback PLCP header. */
545 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
546 fragment_len,
547 bitrate, ofdm_modulation);
548 bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len,
549 fallback_bitrate, fallback_ofdm_modulation);
551 /* Set the CONTROL field */
552 tmp = 0;
553 if (ofdm_modulation)
554 tmp |= BCM43xx_TXHDRCTL_OFDM;
555 if (bcm->short_preamble) //FIXME: could be the other way around, please test
556 tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
557 tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
558 & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
559 txhdr->control = cpu_to_le16(tmp);
561 /* Set the FLAGS field */
562 tmp = 0;
563 if (!is_multicast_ether_addr(wireless_header->addr1) &&
564 !is_broadcast_ether_addr(wireless_header->addr1))
565 tmp |= BCM43xx_TXHDRFLAG_EXPECTACK;
566 if (1 /* FIXME: PS poll?? */)
567 tmp |= 0x10; // FIXME: unknown meaning.
568 if (fallback_ofdm_modulation)
569 tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
570 if (is_first_fragment)
571 tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
572 txhdr->flags = cpu_to_le16(tmp);
574 /* Set WSEC/RATE field */
575 if (encrypt_frame && !bcm->ieee->host_encrypt) {
576 tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
577 & BCM43xx_TXHDR_WSEC_ALGO_MASK;
578 tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
579 & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
580 txhdr->wsec_rate = cpu_to_le16(tmp);
583 //bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header");
586 static
587 void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
588 u16 offset,
589 const u8 *mac)
591 u16 data;
593 offset |= 0x0020;
594 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
596 data = mac[0];
597 data |= mac[1] << 8;
598 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
599 data = mac[2];
600 data |= mac[3] << 8;
601 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
602 data = mac[4];
603 data |= mac[5] << 8;
604 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
607 static inline
608 void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
609 u16 offset)
611 const u8 zero_addr[ETH_ALEN] = { 0 };
613 bcm43xx_macfilter_set(bcm, offset, zero_addr);
616 static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
618 const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
619 const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
620 u8 mac_bssid[ETH_ALEN * 2];
621 int i;
623 memcpy(mac_bssid, mac, ETH_ALEN);
624 memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
626 /* Write our MAC address and BSSID to template ram */
627 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
628 bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
629 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
630 bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
631 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
632 bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
635 static inline
636 void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
638 /* slot_time is in usec. */
639 if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G)
640 return;
641 bcm43xx_write16(bcm, 0x684, 510 + slot_time);
642 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
645 static inline
646 void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
648 bcm43xx_set_slot_time(bcm, 9);
651 static inline
652 void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
654 bcm43xx_set_slot_time(bcm, 20);
657 //FIXME: rename this func?
658 static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
660 bcm43xx_mac_suspend(bcm);
661 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
663 bcm43xx_ram_write(bcm, 0x0026, 0x0000);
664 bcm43xx_ram_write(bcm, 0x0028, 0x0000);
665 bcm43xx_ram_write(bcm, 0x007E, 0x0000);
666 bcm43xx_ram_write(bcm, 0x0080, 0x0000);
667 bcm43xx_ram_write(bcm, 0x047E, 0x0000);
668 bcm43xx_ram_write(bcm, 0x0480, 0x0000);
670 if (bcm->current_core->rev < 3) {
671 bcm43xx_write16(bcm, 0x0610, 0x8000);
672 bcm43xx_write16(bcm, 0x060E, 0x0000);
673 } else
674 bcm43xx_write32(bcm, 0x0188, 0x80000000);
676 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
678 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
679 ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
680 bcm43xx_short_slot_timing_enable(bcm);
682 bcm43xx_mac_enable(bcm);
685 //FIXME: rename this func?
686 static void bcm43xx_associate(struct bcm43xx_private *bcm,
687 const u8 *mac)
689 memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
691 bcm43xx_mac_suspend(bcm);
692 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
693 bcm43xx_write_mac_bssid_templates(bcm);
694 bcm43xx_mac_enable(bcm);
697 /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
698 * Returns the _previously_ enabled IRQ mask.
700 static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
702 u32 old_mask;
704 old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
705 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
707 return old_mask;
710 /* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
711 * Returns the _previously_ enabled IRQ mask.
713 static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
715 u32 old_mask;
717 old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
718 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
720 return old_mask;
723 /* Make sure we don't receive more data from the device. */
724 static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
726 u32 old;
727 unsigned long flags;
729 spin_lock_irqsave(&bcm->lock, flags);
730 if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
731 spin_unlock_irqrestore(&bcm->lock, flags);
732 return -EBUSY;
734 old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
735 tasklet_disable(&bcm->isr_tasklet);
736 spin_unlock_irqrestore(&bcm->lock, flags);
737 if (oldstate)
738 *oldstate = old;
740 return 0;
743 static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
745 u32 radio_id;
746 u16 manufact;
747 u16 version;
748 u8 revision;
749 s8 i;
751 if (bcm->chip_id == 0x4317) {
752 if (bcm->chip_rev == 0x00)
753 radio_id = 0x3205017F;
754 else if (bcm->chip_rev == 0x01)
755 radio_id = 0x4205017F;
756 else
757 radio_id = 0x5205017F;
758 } else {
759 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
760 radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
761 radio_id <<= 16;
762 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
763 radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
766 manufact = (radio_id & 0x00000FFF);
767 version = (radio_id & 0x0FFFF000) >> 12;
768 revision = (radio_id & 0xF0000000) >> 28;
770 dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
771 radio_id, manufact, version, revision);
773 switch (bcm->current_core->phy->type) {
774 case BCM43xx_PHYTYPE_A:
775 if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
776 goto err_unsupported_radio;
777 break;
778 case BCM43xx_PHYTYPE_B:
779 if ((version & 0xFFF0) != 0x2050)
780 goto err_unsupported_radio;
781 break;
782 case BCM43xx_PHYTYPE_G:
783 if (version != 0x2050)
784 goto err_unsupported_radio;
785 break;
788 bcm->current_core->radio->manufact = manufact;
789 bcm->current_core->radio->version = version;
790 bcm->current_core->radio->revision = revision;
792 /* Set default attenuation values. */
793 bcm->current_core->radio->txpower[0] = 2;
794 bcm->current_core->radio->txpower[1] = 2;
795 if (revision == 1)
796 bcm->current_core->radio->txpower[2] = 3;
797 else
798 bcm->current_core->radio->txpower[2] = 0;
800 /* Initialize the in-memory nrssi Lookup Table. */
801 for (i = 0; i < 64; i++)
802 bcm->current_core->radio->nrssi_lt[i] = i;
804 return 0;
806 err_unsupported_radio:
807 printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
808 return -ENODEV;
811 static const char * bcm43xx_locale_iso(u8 locale)
813 /* ISO 3166-1 country codes.
814 * Note that there aren't ISO 3166-1 codes for
815 * all or locales. (Not all locales are countries)
817 switch (locale) {
818 case BCM43xx_LOCALE_WORLD:
819 case BCM43xx_LOCALE_ALL:
820 return "XX";
821 case BCM43xx_LOCALE_THAILAND:
822 return "TH";
823 case BCM43xx_LOCALE_ISRAEL:
824 return "IL";
825 case BCM43xx_LOCALE_JORDAN:
826 return "JO";
827 case BCM43xx_LOCALE_CHINA:
828 return "CN";
829 case BCM43xx_LOCALE_JAPAN:
830 case BCM43xx_LOCALE_JAPAN_HIGH:
831 return "JP";
832 case BCM43xx_LOCALE_USA_CANADA_ANZ:
833 case BCM43xx_LOCALE_USA_LOW:
834 return "US";
835 case BCM43xx_LOCALE_EUROPE:
836 return "EU";
837 case BCM43xx_LOCALE_NONE:
838 return " ";
840 assert(0);
841 return " ";
844 static const char * bcm43xx_locale_string(u8 locale)
846 switch (locale) {
847 case BCM43xx_LOCALE_WORLD:
848 return "World";
849 case BCM43xx_LOCALE_THAILAND:
850 return "Thailand";
851 case BCM43xx_LOCALE_ISRAEL:
852 return "Israel";
853 case BCM43xx_LOCALE_JORDAN:
854 return "Jordan";
855 case BCM43xx_LOCALE_CHINA:
856 return "China";
857 case BCM43xx_LOCALE_JAPAN:
858 return "Japan";
859 case BCM43xx_LOCALE_USA_CANADA_ANZ:
860 return "USA/Canada/ANZ";
861 case BCM43xx_LOCALE_EUROPE:
862 return "Europe";
863 case BCM43xx_LOCALE_USA_LOW:
864 return "USAlow";
865 case BCM43xx_LOCALE_JAPAN_HIGH:
866 return "JapanHigh";
867 case BCM43xx_LOCALE_ALL:
868 return "All";
869 case BCM43xx_LOCALE_NONE:
870 return "None";
872 assert(0);
873 return "";
876 static inline u8 bcm43xx_crc8(u8 crc, u8 data)
878 static const u8 t[] = {
879 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
880 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
881 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
882 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
883 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
884 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
885 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
886 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
887 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
888 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
889 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
890 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
891 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
892 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
893 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
894 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
895 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
896 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
897 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
898 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
899 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
900 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
901 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
902 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
903 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
904 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
905 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
906 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
907 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
908 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
909 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
910 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
912 return t[crc ^ data];
915 u8 bcm43xx_sprom_crc(const u16 *sprom)
917 int word;
918 u8 crc = 0xFF;
920 for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
921 crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
922 crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
924 crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
925 crc ^= 0xFF;
927 return crc;
931 static int bcm43xx_read_sprom(struct bcm43xx_private *bcm)
933 int i;
934 u16 value;
935 u16 *sprom;
936 u8 crc, expected_crc;
937 #ifdef CONFIG_BCM947XX
938 char *c;
939 #endif
941 sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
942 GFP_KERNEL);
943 if (!sprom) {
944 printk(KERN_ERR PFX "read_sprom OOM\n");
945 return -ENOMEM;
947 #ifdef CONFIG_BCM947XX
948 sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
949 sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
951 if ((c = nvram_get("il0macaddr")) != NULL)
952 e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
954 if ((c = nvram_get("et1macaddr")) != NULL)
955 e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
957 sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
958 sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
959 sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
961 sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
962 sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
963 sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
965 sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
966 #else
967 for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
968 sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
970 /* CRC-8 check. */
971 crc = bcm43xx_sprom_crc(sprom);
972 expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
973 if (crc != expected_crc) {
974 printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
975 "(0x%02X, expected: 0x%02X)\n",
976 crc, expected_crc);
978 #endif
980 /* boardflags2 */
981 value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
982 bcm->sprom.boardflags2 = value;
984 /* il0macaddr */
985 value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
986 *(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
987 value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
988 *(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
989 value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
990 *(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
992 /* et0macaddr */
993 value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
994 *(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
995 value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
996 *(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
997 value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
998 *(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
1000 /* et1macaddr */
1001 value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
1002 *(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
1003 value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
1004 *(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
1005 value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
1006 *(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
1008 /* ethernet phy settings */
1009 value = sprom[BCM43xx_SPROM_ETHPHY];
1010 bcm->sprom.et0phyaddr = (value & 0x001F);
1011 bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
1012 bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
1013 bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
1015 /* boardrev, antennas, locale */
1016 value = sprom[BCM43xx_SPROM_BOARDREV];
1017 bcm->sprom.boardrev = (value & 0x00FF);
1018 bcm->sprom.locale = (value & 0x0F00) >> 8;
1019 bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
1020 bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
1021 if (modparam_locale != -1) {
1022 if (modparam_locale >= 0 && modparam_locale <= 11) {
1023 bcm->sprom.locale = modparam_locale;
1024 printk(KERN_WARNING PFX "Operating with modified "
1025 "LocaleCode %u (%s)\n",
1026 bcm->sprom.locale,
1027 bcm43xx_locale_string(bcm->sprom.locale));
1028 } else {
1029 printk(KERN_WARNING PFX "Module parameter \"locale\" "
1030 "invalid value. (0 - 11)\n");
1034 /* pa0b* */
1035 value = sprom[BCM43xx_SPROM_PA0B0];
1036 bcm->sprom.pa0b0 = value;
1037 value = sprom[BCM43xx_SPROM_PA0B1];
1038 bcm->sprom.pa0b1 = value;
1039 value = sprom[BCM43xx_SPROM_PA0B2];
1040 bcm->sprom.pa0b2 = value;
1042 /* wl0gpio* */
1043 value = sprom[BCM43xx_SPROM_WL0GPIO0];
1044 if (value == 0x0000)
1045 value = 0xFFFF;
1046 bcm->sprom.wl0gpio0 = value & 0x00FF;
1047 bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
1048 value = sprom[BCM43xx_SPROM_WL0GPIO2];
1049 if (value == 0x0000)
1050 value = 0xFFFF;
1051 bcm->sprom.wl0gpio2 = value & 0x00FF;
1052 bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
1054 /* maxpower */
1055 value = sprom[BCM43xx_SPROM_MAXPWR];
1056 bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
1057 bcm->sprom.maxpower_bgphy = value & 0x00FF;
1059 /* pa1b* */
1060 value = sprom[BCM43xx_SPROM_PA1B0];
1061 bcm->sprom.pa1b0 = value;
1062 value = sprom[BCM43xx_SPROM_PA1B1];
1063 bcm->sprom.pa1b1 = value;
1064 value = sprom[BCM43xx_SPROM_PA1B2];
1065 bcm->sprom.pa1b2 = value;
1067 /* idle tssi target */
1068 value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
1069 bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
1070 bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
1072 /* boardflags */
1073 value = sprom[BCM43xx_SPROM_BOARDFLAGS];
1074 if (value == 0xFFFF)
1075 value = 0x0000;
1076 bcm->sprom.boardflags = value;
1078 /* antenna gain */
1079 value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
1080 if (value == 0x0000 || value == 0xFFFF)
1081 value = 0x0202;
1082 /* convert values to Q5.2 */
1083 bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
1084 bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
1086 kfree(sprom);
1088 return 0;
1091 static int bcm43xx_channel_is_allowed(struct bcm43xx_private *bcm, u8 channel,
1092 u8 *max_power, u8 *flags)
1094 /* THIS FUNCTION DOES _NOT_ ENFORCE REGULATORY DOMAIN COMPLIANCE.
1095 * It is only a helper function to make life easier to
1096 * select legal channels and transmission powers.
1099 u8 phytype = bcm->current_core->phy->type;
1100 int allowed = 0;
1102 *max_power = 0;
1103 *flags = 0;
1105 //FIXME: Set max_power and maybe flags
1106 /*FIXME: Allowed channels are sometimes different for outdoor
1107 * or indoor use. See modparam_outdoor.
1109 /* From b specs Max Power BPHY:
1110 * USA: 1000mW
1111 * Europe: 100mW
1112 * Japan: 10mW/MHz
1115 switch (bcm->sprom.locale) {
1116 case BCM43xx_LOCALE_WORLD:
1117 if (phytype == BCM43xx_PHYTYPE_A) {
1118 allowed = 1;//FIXME
1119 } else if (phytype == BCM43xx_PHYTYPE_B) {
1120 if (channel >= 1 && channel <= 13)
1121 allowed = 1;
1122 } else {
1123 if (channel >= 1 && channel <= 13)
1124 allowed = 1;
1126 break;
1127 case BCM43xx_LOCALE_THAILAND:
1128 if (phytype == BCM43xx_PHYTYPE_A) {
1129 allowed = 1;//FIXME
1130 } else if (phytype == BCM43xx_PHYTYPE_B) {
1131 if (channel >= 1 && channel <= 14)
1132 allowed = 1;
1133 } else {
1134 if (channel >= 1 && channel <= 14)
1135 allowed = 1;
1137 break;
1138 case BCM43xx_LOCALE_ISRAEL:
1139 if (phytype == BCM43xx_PHYTYPE_A) {
1140 allowed = 1;//FIXME
1141 } else if (phytype == BCM43xx_PHYTYPE_B) {
1142 if (channel >= 5 && channel <= 7)
1143 allowed = 1;
1144 } else {
1145 if (channel >= 5 && channel <= 7)
1146 allowed = 1;
1148 break;
1149 case BCM43xx_LOCALE_JORDAN:
1150 if (phytype == BCM43xx_PHYTYPE_A) {
1151 allowed = 1;//FIXME
1152 } else if (phytype == BCM43xx_PHYTYPE_B) {
1153 if (channel >= 10 && channel <= 13)
1154 allowed = 1;
1155 } else {
1156 if (channel >= 10 && channel <= 13)
1157 allowed = 1;
1159 break;
1160 case BCM43xx_LOCALE_CHINA:
1161 if (phytype == BCM43xx_PHYTYPE_A) {
1162 allowed = 1;//FIXME
1163 } else if (phytype == BCM43xx_PHYTYPE_B) {
1164 if (channel >= 1 && channel <= 13)
1165 allowed = 1;
1166 } else {
1167 if (channel >= 1 && channel <= 13)
1168 allowed = 1;
1170 break;
1171 case BCM43xx_LOCALE_JAPAN:
1172 if (phytype == BCM43xx_PHYTYPE_A) {
1173 allowed = 1;//FIXME
1174 } else if (phytype == BCM43xx_PHYTYPE_B) {
1175 //FIXME: This seems to be wrong.
1176 if (channel >= 1 && channel <= 14)
1177 allowed = 1;
1178 } else {
1179 //FIXME: This seems to be wrong.
1180 if (channel >= 1 && channel <= 14)
1181 allowed = 1;
1183 break;
1184 case BCM43xx_LOCALE_USA_CANADA_ANZ:
1185 if (phytype == BCM43xx_PHYTYPE_A) {
1186 allowed = 1;//FIXME
1187 } else if (phytype == BCM43xx_PHYTYPE_B) {
1188 if (channel >= 1 && channel <= 13)
1189 allowed = 1;
1190 } else {
1191 if (channel >= 1 && channel <= 11)
1192 allowed = 1;
1194 break;
1195 case BCM43xx_LOCALE_EUROPE:
1196 if (phytype == BCM43xx_PHYTYPE_A) {
1197 allowed = 1;//FIXME
1198 } else if (phytype == BCM43xx_PHYTYPE_B) {
1199 if (channel >= 1 && channel <= 13)
1200 allowed = 1;
1201 } else {
1202 if (channel >= 1 && channel <= 13)
1203 allowed = 1;
1205 break;
1206 case BCM43xx_LOCALE_USA_LOW:
1207 if (phytype == BCM43xx_PHYTYPE_A) {
1208 allowed = 1;//FIXME
1209 } else if (phytype == BCM43xx_PHYTYPE_B) {
1210 if (channel >= 1 && channel <= 13)
1211 allowed = 1;
1212 } else {
1213 if (channel >= 1 && channel <= 11)
1214 allowed = 1;
1216 break;
1217 case BCM43xx_LOCALE_JAPAN_HIGH:
1218 if (phytype == BCM43xx_PHYTYPE_A) {
1219 allowed = 1;//FIXME
1220 } else if (phytype == BCM43xx_PHYTYPE_B) {
1221 //FIXME?
1222 if (channel >= 1 && channel <= 14)
1223 allowed = 1;
1224 } else {
1225 if (channel >= 1 && channel <= 14)
1226 allowed = 1;
1228 break;
1229 case BCM43xx_LOCALE_ALL:
1230 allowed = 1;
1231 break;
1232 case BCM43xx_LOCALE_NONE:
1233 break;
1234 default:
1235 assert(0);
1238 return allowed;
1241 static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
1243 struct ieee80211_geo geo;
1244 struct ieee80211_channel *chan;
1245 int have_a = 0, have_bg = 0;
1246 int i, num80211;
1247 u8 channel, flags, max_power;
1248 struct bcm43xx_phyinfo *phy;
1249 const char *iso_country;
1251 memset(&geo, 0, sizeof(geo));
1252 num80211 = bcm43xx_num_80211_cores(bcm);
1253 for (i = 0; i < num80211; i++) {
1254 phy = bcm->phy + i;
1255 switch (phy->type) {
1256 case BCM43xx_PHYTYPE_B:
1257 case BCM43xx_PHYTYPE_G:
1258 have_bg = 1;
1259 break;
1260 case BCM43xx_PHYTYPE_A:
1261 have_a = 1;
1262 break;
1263 default:
1264 assert(0);
1267 iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
1269 if (have_a) {
1270 for (i = 0, channel = 0; channel < 201; channel++) {
1271 if (!bcm43xx_channel_is_allowed(bcm, channel,
1272 &max_power, &flags))
1273 continue;
1274 chan = &geo.a[i++];
1275 chan->freq = bcm43xx_channel_to_freq(bcm, channel);
1276 chan->channel = channel;
1277 chan->flags = flags;
1278 chan->max_power = max_power;
1280 geo.a_channels = i;
1282 if (have_bg) {
1283 for (i = 0, channel = 1; channel < 15; channel++) {
1284 if (!bcm43xx_channel_is_allowed(bcm, channel,
1285 &max_power, &flags))
1286 continue;
1287 chan = &geo.bg[i++];
1288 chan->freq = bcm43xx_channel_to_freq(bcm, channel);
1289 chan->channel = channel;
1290 chan->flags = flags;
1291 chan->max_power = max_power;
1293 geo.bg_channels = i;
1295 memcpy(geo.name, iso_country, 2);
1296 if (0 /*TODO: Outdoor use only */)
1297 geo.name[2] = 'O';
1298 else if (0 /*TODO: Indoor use only */)
1299 geo.name[2] = 'I';
1300 else
1301 geo.name[2] = ' ';
1302 geo.name[3] = '\0';
1304 ieee80211_set_geo(bcm->ieee, &geo);
1307 /* DummyTransmission function, as documented on
1308 * http://bcm-specs.sipsolutions.net/DummyTransmission
1310 void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
1312 unsigned int i, max_loop;
1313 u16 value = 0;
1314 u32 buffer[5] = {
1315 0x00000000,
1316 0x0000D400,
1317 0x00000000,
1318 0x00000001,
1319 0x00000000,
1322 switch (bcm->current_core->phy->type) {
1323 case BCM43xx_PHYTYPE_A:
1324 max_loop = 0x1E;
1325 buffer[0] = 0xCC010200;
1326 break;
1327 case BCM43xx_PHYTYPE_B:
1328 case BCM43xx_PHYTYPE_G:
1329 max_loop = 0xFA;
1330 buffer[0] = 0x6E840B00;
1331 break;
1332 default:
1333 assert(0);
1334 return;
1337 for (i = 0; i < 5; i++)
1338 bcm43xx_ram_write(bcm, i * 4, buffer[i]);
1340 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
1342 bcm43xx_write16(bcm, 0x0568, 0x0000);
1343 bcm43xx_write16(bcm, 0x07C0, 0x0000);
1344 bcm43xx_write16(bcm, 0x050C, ((bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
1345 bcm43xx_write16(bcm, 0x0508, 0x0000);
1346 bcm43xx_write16(bcm, 0x050A, 0x0000);
1347 bcm43xx_write16(bcm, 0x054C, 0x0000);
1348 bcm43xx_write16(bcm, 0x056A, 0x0014);
1349 bcm43xx_write16(bcm, 0x0568, 0x0826);
1350 bcm43xx_write16(bcm, 0x0500, 0x0000);
1351 bcm43xx_write16(bcm, 0x0502, 0x0030);
1353 for (i = 0x00; i < max_loop; i++) {
1354 value = bcm43xx_read16(bcm, 0x050E);
1355 if ((value & 0x0080) != 0)
1356 break;
1357 udelay(10);
1359 for (i = 0x00; i < 0x0A; i++) {
1360 value = bcm43xx_read16(bcm, 0x050E);
1361 if ((value & 0x0400) != 0)
1362 break;
1363 udelay(10);
1365 for (i = 0x00; i < 0x0A; i++) {
1366 value = bcm43xx_read16(bcm, 0x0690);
1367 if ((value & 0x0100) == 0)
1368 break;
1369 udelay(10);
1373 static void key_write(struct bcm43xx_private *bcm,
1374 u8 index, u8 algorithm, const u16 *key)
1376 unsigned int i, basic_wep = 0;
1377 u32 offset;
1378 u16 value;
1380 /* Write associated key information */
1381 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
1382 ((index << 4) | (algorithm & 0x0F)));
1384 /* The first 4 WEP keys need extra love */
1385 if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
1386 (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
1387 basic_wep = 1;
1389 /* Write key payload, 8 little endian words */
1390 offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
1391 for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
1392 value = cpu_to_le16(key[i]);
1393 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1394 offset + (i * 2), value);
1396 if (!basic_wep)
1397 continue;
1399 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1400 offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
1401 value);
1405 static void keymac_write(struct bcm43xx_private *bcm,
1406 u8 index, const u32 *addr)
1408 /* for keys 0-3 there is no associated mac address */
1409 if (index < 4)
1410 return;
1412 index -= 4;
1413 if (bcm->current_core->rev >= 5) {
1414 bcm43xx_shm_write32(bcm,
1415 BCM43xx_SHM_HWMAC,
1416 index * 2,
1417 cpu_to_be32(*addr));
1418 bcm43xx_shm_write16(bcm,
1419 BCM43xx_SHM_HWMAC,
1420 (index * 2) + 1,
1421 cpu_to_be16(*((u16 *)(addr + 1))));
1422 } else {
1423 if (index < 8) {
1424 TODO(); /* Put them in the macaddress filter */
1425 } else {
1426 TODO();
1427 /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
1428 Keep in mind to update the count of keymacs in 0x003E as well! */
1433 static int bcm43xx_key_write(struct bcm43xx_private *bcm,
1434 u8 index, u8 algorithm,
1435 const u8 *_key, int key_len,
1436 const u8 *mac_addr)
1438 u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
1440 if (index >= ARRAY_SIZE(bcm->key))
1441 return -EINVAL;
1442 if (key_len > ARRAY_SIZE(key))
1443 return -EINVAL;
1444 if (algorithm < 1 || algorithm > 5)
1445 return -EINVAL;
1447 memcpy(key, _key, key_len);
1448 key_write(bcm, index, algorithm, (const u16 *)key);
1449 keymac_write(bcm, index, (const u32 *)mac_addr);
1451 bcm->key[index].algorithm = algorithm;
1453 return 0;
1456 static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
1458 static const u32 zero_mac[2] = { 0 };
1459 unsigned int i,j, nr_keys = 54;
1460 u16 offset;
1462 if (bcm->current_core->rev < 5)
1463 nr_keys = 16;
1464 assert(nr_keys <= ARRAY_SIZE(bcm->key));
1466 for (i = 0; i < nr_keys; i++) {
1467 bcm->key[i].enabled = 0;
1468 /* returns for i < 4 immediately */
1469 keymac_write(bcm, i, zero_mac);
1470 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1471 0x100 + (i * 2), 0x0000);
1472 for (j = 0; j < 8; j++) {
1473 offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
1474 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1475 offset, 0x0000);
1478 dprintk(KERN_INFO PFX "Keys cleared\n");
1481 /* Puts the index of the current core into user supplied core variable.
1482 * This function reads the value from the device.
1483 * Almost always you don't want to call this, but use bcm->current_core
1485 static inline
1486 int _get_current_core(struct bcm43xx_private *bcm, int *core)
1488 int err;
1490 err = bcm43xx_pci_read_config32(bcm, BCM43xx_REG_ACTIVE_CORE, core);
1491 if (unlikely(err)) {
1492 dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE read failed!\n");
1493 return -ENODEV;
1495 *core = (*core - 0x18000000) / 0x1000;
1497 return 0;
1500 /* Lowlevel core-switch function. This is only to be used in
1501 * bcm43xx_switch_core() and bcm43xx_probe_cores()
1503 static int _switch_core(struct bcm43xx_private *bcm, int core)
1505 int err;
1506 int attempts = 0;
1507 int current_core = -1;
1509 assert(core >= 0);
1511 err = _get_current_core(bcm, &current_core);
1512 if (unlikely(err))
1513 goto out;
1515 /* Write the computed value to the register. This doesn't always
1516 succeed so we retry BCM43xx_SWITCH_CORE_MAX_RETRIES times */
1517 while (current_core != core) {
1518 if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) {
1519 err = -ENODEV;
1520 printk(KERN_ERR PFX
1521 "unable to switch to core %u, retried %i times\n",
1522 core, attempts);
1523 goto out;
1525 err = bcm43xx_pci_write_config32(bcm, BCM43xx_REG_ACTIVE_CORE,
1526 (core * 0x1000) + 0x18000000);
1527 if (unlikely(err)) {
1528 dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE write failed!\n");
1529 continue;
1531 _get_current_core(bcm, &current_core);
1532 #ifdef CONFIG_BCM947XX
1533 if (bcm->pci_dev->bus->number == 0)
1534 bcm->current_core_offset = 0x1000 * core;
1535 else
1536 bcm->current_core_offset = 0;
1537 #endif
1540 assert(err == 0);
1541 out:
1542 return err;
1545 int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
1547 int err;
1549 if (!new_core)
1550 return 0;
1552 if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE))
1553 return -ENODEV;
1554 if (bcm->current_core == new_core)
1555 return 0;
1556 err = _switch_core(bcm, new_core->index);
1557 if (!err)
1558 bcm->current_core = new_core;
1560 return err;
1563 static inline int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
1565 u32 value;
1567 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1568 value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
1569 | BCM43xx_SBTMSTATELOW_REJECT;
1571 return (value == BCM43xx_SBTMSTATELOW_CLOCK);
1574 /* disable current core */
1575 static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
1577 u32 sbtmstatelow;
1578 u32 sbtmstatehigh;
1579 int i;
1581 /* fetch sbtmstatelow from core information registers */
1582 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1584 /* core is already in reset */
1585 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
1586 goto out;
1588 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
1589 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1590 BCM43xx_SBTMSTATELOW_REJECT;
1591 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1593 for (i = 0; i < 1000; i++) {
1594 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1595 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
1596 i = -1;
1597 break;
1599 udelay(10);
1601 if (i != -1) {
1602 printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
1603 return -EBUSY;
1606 for (i = 0; i < 1000; i++) {
1607 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1608 if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
1609 i = -1;
1610 break;
1612 udelay(10);
1614 if (i != -1) {
1615 printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
1616 return -EBUSY;
1619 sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1620 BCM43xx_SBTMSTATELOW_REJECT |
1621 BCM43xx_SBTMSTATELOW_RESET |
1622 BCM43xx_SBTMSTATELOW_CLOCK |
1623 core_flags;
1624 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1625 udelay(10);
1628 sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
1629 BCM43xx_SBTMSTATELOW_REJECT |
1630 core_flags;
1631 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1633 out:
1634 bcm->current_core->flags &= ~ BCM43xx_COREFLAG_ENABLED;
1635 return 0;
1638 /* enable (reset) current core */
1639 static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
1641 u32 sbtmstatelow;
1642 u32 sbtmstatehigh;
1643 u32 sbimstate;
1644 int err;
1646 err = bcm43xx_core_disable(bcm, core_flags);
1647 if (err)
1648 goto out;
1650 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1651 BCM43xx_SBTMSTATELOW_RESET |
1652 BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1653 core_flags;
1654 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1655 udelay(1);
1657 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1658 if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
1659 sbtmstatehigh = 0x00000000;
1660 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
1663 sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
1664 if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
1665 sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
1666 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
1669 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1670 BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1671 core_flags;
1672 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1673 udelay(1);
1675 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
1676 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1677 udelay(1);
1679 bcm->current_core->flags |= BCM43xx_COREFLAG_ENABLED;
1680 assert(err == 0);
1681 out:
1682 return err;
1685 /* http://bcm-specs.sipsolutions.net/80211CoreReset */
1686 void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
1688 u32 flags = 0x00040000;
1690 if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) {
1691 //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
1692 #ifndef CONFIG_BCM947XX
1693 /* reset all used DMA controllers. */
1694 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
1695 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
1696 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
1697 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
1698 bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
1699 if (bcm->current_core->rev < 5)
1700 bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
1701 #endif
1703 if (bcm->shutting_down) {
1704 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1705 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1706 & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
1707 } else {
1708 if (connect_phy)
1709 flags |= 0x20000000;
1710 bcm43xx_phy_connect(bcm, connect_phy);
1711 bcm43xx_core_enable(bcm, flags);
1712 bcm43xx_write16(bcm, 0x03E6, 0x0000);
1713 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1714 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1715 | BCM43xx_SBF_400);
1719 static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
1721 bcm43xx_radio_turn_off(bcm);
1722 bcm43xx_write16(bcm, 0x03E6, 0x00F4);
1723 bcm43xx_core_disable(bcm, 0);
1726 /* Mark the current 80211 core inactive.
1727 * "active_80211_core" is the other 80211 core, which is used.
1729 static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
1730 struct bcm43xx_coreinfo *active_80211_core)
1732 u32 sbtmstatelow;
1733 struct bcm43xx_coreinfo *old_core;
1734 int err = 0;
1736 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1737 bcm43xx_radio_turn_off(bcm);
1738 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1739 sbtmstatelow &= ~0x200a0000;
1740 sbtmstatelow |= 0xa0000;
1741 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1742 udelay(1);
1743 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1744 sbtmstatelow &= ~0xa0000;
1745 sbtmstatelow |= 0x80000;
1746 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1747 udelay(1);
1749 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) {
1750 old_core = bcm->current_core;
1751 err = bcm43xx_switch_core(bcm, active_80211_core);
1752 if (err)
1753 goto out;
1754 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1755 sbtmstatelow &= ~0x20000000;
1756 sbtmstatelow |= 0x20000000;
1757 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1758 err = bcm43xx_switch_core(bcm, old_core);
1761 out:
1762 return err;
1765 static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm)
1767 u32 v0, v1;
1768 u16 tmp;
1769 struct bcm43xx_xmitstatus stat;
1771 assert(bcm->current_core->id == BCM43xx_COREID_80211);
1772 assert(bcm->current_core->rev >= 5);
1774 while (1) {
1775 v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
1776 if (!v0)
1777 break;
1778 v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
1780 stat.cookie = (v0 >> 16) & 0x0000FFFF;
1781 tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
1782 stat.flags = tmp & 0xFF;
1783 stat.cnt1 = (tmp & 0x0F00) >> 8;
1784 stat.cnt2 = (tmp & 0xF000) >> 12;
1785 stat.seq = (u16)(v1 & 0xFFFF);
1786 stat.unknown = (u16)((v1 >> 16) & 0xFF);
1788 bcm43xx_debugfs_log_txstat(bcm, &stat);
1790 if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
1791 continue;
1792 if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
1793 //TODO: packet was not acked (was lost)
1795 //TODO: There are more (unknown) flags to test. see bcm43xx_main.h
1797 if (bcm->pio_mode)
1798 bcm43xx_pio_handle_xmitstatus(bcm, &stat);
1799 else
1800 bcm43xx_dma_handle_xmitstatus(bcm, &stat);
1804 static inline void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
1806 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
1807 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
1808 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
1809 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
1810 assert(bcm->noisecalc.core_at_start == bcm->current_core);
1811 assert(bcm->noisecalc.channel_at_start == bcm->current_core->radio->channel);
1814 static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
1816 /* Top half of Link Quality calculation. */
1818 if (bcm->noisecalc.calculation_running)
1819 return;
1820 bcm->noisecalc.core_at_start = bcm->current_core;
1821 bcm->noisecalc.channel_at_start = bcm->current_core->radio->channel;
1822 bcm->noisecalc.calculation_running = 1;
1823 bcm->noisecalc.nr_samples = 0;
1825 bcm43xx_generate_noise_sample(bcm);
1828 static inline void handle_irq_noise(struct bcm43xx_private *bcm)
1830 struct bcm43xx_radioinfo *radio = bcm->current_core->radio;
1831 u16 tmp;
1832 u8 noise[4];
1833 u8 i, j;
1834 s32 average;
1836 /* Bottom half of Link Quality calculation. */
1838 assert(bcm->noisecalc.calculation_running);
1839 if (bcm->noisecalc.core_at_start != bcm->current_core ||
1840 bcm->noisecalc.channel_at_start != radio->channel)
1841 goto drop_calculation;
1842 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
1843 noise[0] = (tmp & 0x00FF);
1844 noise[1] = (tmp & 0xFF00) >> 8;
1845 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
1846 noise[2] = (tmp & 0x00FF);
1847 noise[3] = (tmp & 0xFF00) >> 8;
1848 if (noise[0] == 0x7F || noise[1] == 0x7F ||
1849 noise[2] == 0x7F || noise[3] == 0x7F)
1850 goto generate_new;
1852 /* Get the noise samples. */
1853 assert(bcm->noisecalc.nr_samples <= 8);
1854 i = bcm->noisecalc.nr_samples;
1855 noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1856 noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1857 noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1858 noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1859 bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
1860 bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
1861 bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
1862 bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
1863 bcm->noisecalc.nr_samples++;
1864 if (bcm->noisecalc.nr_samples == 8) {
1865 /* Calculate the Link Quality by the noise samples. */
1866 average = 0;
1867 for (i = 0; i < 8; i++) {
1868 for (j = 0; j < 4; j++)
1869 average += bcm->noisecalc.samples[i][j];
1871 average /= (8 * 4);
1872 average *= 125;
1873 average += 64;
1874 average /= 128;
1875 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
1876 tmp = (tmp / 128) & 0x1F;
1877 if (tmp >= 8)
1878 average += 2;
1879 else
1880 average -= 25;
1881 if (tmp == 8)
1882 average -= 72;
1883 else
1884 average -= 48;
1886 if (average > -65)
1887 bcm->stats.link_quality = 0;
1888 else if (average > -75)
1889 bcm->stats.link_quality = 1;
1890 else if (average > -85)
1891 bcm->stats.link_quality = 2;
1892 else
1893 bcm->stats.link_quality = 3;
1894 // dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average);
1895 drop_calculation:
1896 bcm->noisecalc.calculation_running = 0;
1897 return;
1899 generate_new:
1900 bcm43xx_generate_noise_sample(bcm);
1903 static inline
1904 void handle_irq_ps(struct bcm43xx_private *bcm)
1906 if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
1907 ///TODO: PS TBTT
1908 } else {
1909 if (1/*FIXME: the last PSpoll frame was sent successfully */)
1910 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
1912 if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
1913 bcm->reg124_set_0x4 = 1;
1914 //FIXME else set to false?
1917 static inline
1918 void handle_irq_reg124(struct bcm43xx_private *bcm)
1920 if (!bcm->reg124_set_0x4)
1921 return;
1922 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
1923 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
1924 | 0x4);
1925 //FIXME: reset reg124_set_0x4 to false?
1928 static inline
1929 void handle_irq_pmq(struct bcm43xx_private *bcm)
1931 u32 tmp;
1933 //TODO: AP mode.
1935 while (1) {
1936 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
1937 if (!(tmp & 0x00000008))
1938 break;
1940 /* 16bit write is odd, but correct. */
1941 bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
1944 static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
1945 u16 ram_offset, u16 shm_size_offset)
1947 u32 value;
1948 u16 size = 0;
1950 /* Timestamp. */
1951 //FIXME: assumption: The chip sets the timestamp
1952 value = 0;
1953 bcm43xx_ram_write(bcm, ram_offset++, value);
1954 bcm43xx_ram_write(bcm, ram_offset++, value);
1955 size += 8;
1957 /* Beacon Interval / Capability Information */
1958 value = 0x0000;//FIXME: Which interval?
1959 value |= (1 << 0) << 16; /* ESS */
1960 value |= (1 << 2) << 16; /* CF Pollable */ //FIXME?
1961 value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME?
1962 if (!bcm->ieee->open_wep)
1963 value |= (1 << 4) << 16; /* Privacy */
1964 bcm43xx_ram_write(bcm, ram_offset++, value);
1965 size += 4;
1967 /* SSID */
1968 //TODO
1970 /* FH Parameter Set */
1971 //TODO
1973 /* DS Parameter Set */
1974 //TODO
1976 /* CF Parameter Set */
1977 //TODO
1979 /* TIM */
1980 //TODO
1982 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
1985 static inline
1986 void handle_irq_beacon(struct bcm43xx_private *bcm)
1988 u32 status;
1990 bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
1991 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
1993 if ((status & 0x1) && (status & 0x2)) {
1994 /* ACK beacon IRQ. */
1995 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
1996 BCM43xx_IRQ_BEACON);
1997 bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
1998 return;
2000 if (!(status & 0x1)) {
2001 bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
2002 status |= 0x1;
2003 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
2005 if (!(status & 0x2)) {
2006 bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
2007 status |= 0x2;
2008 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
2012 /* Debug helper for irq bottom-half to print all reason registers. */
2013 #define bcmirq_print_reasons(description) \
2014 do { \
2015 dprintkl(KERN_ERR PFX description "\n" \
2016 KERN_ERR PFX " Generic Reason: 0x%08x\n" \
2017 KERN_ERR PFX " DMA reasons: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n" \
2018 KERN_ERR PFX " DMA TX status: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", \
2019 reason, \
2020 dma_reason[0], dma_reason[1], \
2021 dma_reason[2], dma_reason[3], \
2022 bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_BASE + BCM43xx_DMA_TX_STATUS), \
2023 bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_BASE + BCM43xx_DMA_TX_STATUS), \
2024 bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_BASE + BCM43xx_DMA_TX_STATUS), \
2025 bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_BASE + BCM43xx_DMA_TX_STATUS)); \
2026 } while (0)
2028 /* Interrupt handler bottom-half */
2029 static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
2031 u32 reason;
2032 u32 dma_reason[4];
2033 int activity = 0;
2034 unsigned long flags;
2036 #ifdef CONFIG_BCM43XX_DEBUG
2037 u32 _handled = 0x00000000;
2038 # define bcmirq_handled(irq) do { _handled |= (irq); } while (0)
2039 #else
2040 # define bcmirq_handled(irq) do { /* nothing */ } while (0)
2041 #endif /* CONFIG_BCM43XX_DEBUG*/
2043 spin_lock_irqsave(&bcm->lock, flags);
2044 reason = bcm->irq_reason;
2045 dma_reason[0] = bcm->dma_reason[0];
2046 dma_reason[1] = bcm->dma_reason[1];
2047 dma_reason[2] = bcm->dma_reason[2];
2048 dma_reason[3] = bcm->dma_reason[3];
2050 if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
2051 /* TX error. We get this when Template Ram is written in wrong endianess
2052 * in dummy_tx(). We also get this if something is wrong with the TX header
2053 * on DMA or PIO queues.
2054 * Maybe we get this in other error conditions, too.
2056 bcmirq_print_reasons("XMIT ERROR");
2057 bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
2060 if (reason & BCM43xx_IRQ_PS) {
2061 handle_irq_ps(bcm);
2062 bcmirq_handled(BCM43xx_IRQ_PS);
2065 if (reason & BCM43xx_IRQ_REG124) {
2066 handle_irq_reg124(bcm);
2067 bcmirq_handled(BCM43xx_IRQ_REG124);
2070 if (reason & BCM43xx_IRQ_BEACON) {
2071 if (bcm->ieee->iw_mode == IW_MODE_MASTER)
2072 handle_irq_beacon(bcm);
2073 bcmirq_handled(BCM43xx_IRQ_BEACON);
2076 if (reason & BCM43xx_IRQ_PMQ) {
2077 handle_irq_pmq(bcm);
2078 bcmirq_handled(BCM43xx_IRQ_PMQ);
2081 if (reason & BCM43xx_IRQ_SCAN) {
2082 /*TODO*/
2083 //bcmirq_handled(BCM43xx_IRQ_SCAN);
2086 if (reason & BCM43xx_IRQ_NOISE) {
2087 handle_irq_noise(bcm);
2088 bcmirq_handled(BCM43xx_IRQ_NOISE);
2091 /* Check the DMA reason registers for received data. */
2092 assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
2093 assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
2094 if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
2095 if (bcm->pio_mode)
2096 bcm43xx_pio_rx(bcm->current_core->pio->queue0);
2097 else
2098 bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0);
2099 activity = 1;
2101 if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
2102 if (likely(bcm->current_core->rev < 5)) {
2103 if (bcm->pio_mode)
2104 bcm43xx_pio_rx(bcm->current_core->pio->queue3);
2105 else
2106 bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1);
2107 activity = 1;
2108 } else
2109 assert(0);
2111 bcmirq_handled(BCM43xx_IRQ_RX);
2113 if (reason & BCM43xx_IRQ_XMIT_STATUS) {
2114 if (bcm->current_core->rev >= 5) {
2115 handle_irq_transmit_status(bcm);
2116 activity = 1;
2118 //TODO: In AP mode, this also causes sending of powersave responses.
2119 bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
2122 /* We get spurious IRQs, althought they are masked.
2123 * Assume they are void and ignore them.
2125 bcmirq_handled(~(bcm->irq_savedstate));
2126 /* IRQ_PIO_WORKAROUND is handled in the top-half. */
2127 bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
2128 #ifdef CONFIG_BCM43XX_DEBUG
2129 if (unlikely(reason & ~_handled)) {
2130 printkl(KERN_WARNING PFX
2131 "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, "
2132 "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
2133 reason, (reason & ~_handled),
2134 dma_reason[0], dma_reason[1],
2135 dma_reason[2], dma_reason[3]);
2137 #endif
2138 #undef bcmirq_handled
2140 if (!modparam_noleds)
2141 bcm43xx_leds_update(bcm, activity);
2142 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
2143 spin_unlock_irqrestore(&bcm->lock, flags);
2146 #undef bcmirq_print_reasons
2148 static inline
2149 void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm,
2150 u32 reason, u32 mask)
2152 bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
2153 & 0x0001dc00;
2154 bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
2155 & 0x0000dc00;
2156 bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
2157 & 0x0000dc00;
2158 bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
2159 & 0x0001dc00;
2161 if ((bcm->pio_mode) &&
2162 (bcm->current_core->rev < 3) &&
2163 (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
2164 /* Apply a PIO specific workaround to the dma_reasons */
2166 #define apply_pio_workaround(BASE, QNUM) \
2167 do { \
2168 if (bcm43xx_read16(bcm, BASE + BCM43xx_PIO_RXCTL) & BCM43xx_PIO_RXCTL_DATAAVAILABLE) \
2169 bcm->dma_reason[QNUM] |= 0x00010000; \
2170 else \
2171 bcm->dma_reason[QNUM] &= ~0x00010000; \
2172 } while (0)
2174 apply_pio_workaround(BCM43xx_MMIO_PIO1_BASE, 0);
2175 apply_pio_workaround(BCM43xx_MMIO_PIO2_BASE, 1);
2176 apply_pio_workaround(BCM43xx_MMIO_PIO3_BASE, 2);
2177 apply_pio_workaround(BCM43xx_MMIO_PIO4_BASE, 3);
2179 #undef apply_pio_workaround
2182 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
2183 reason & mask);
2185 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
2186 bcm->dma_reason[0]);
2187 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
2188 bcm->dma_reason[1]);
2189 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
2190 bcm->dma_reason[2]);
2191 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
2192 bcm->dma_reason[3]);
2195 /* Interrupt handler top-half */
2196 static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
2198 struct bcm43xx_private *bcm = dev_id;
2199 u32 reason, mask;
2201 if (!bcm)
2202 return IRQ_NONE;
2204 spin_lock(&bcm->lock);
2206 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2207 if (reason == 0xffffffff) {
2208 /* irq not for us (shared irq) */
2209 spin_unlock(&bcm->lock);
2210 return IRQ_NONE;
2212 mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
2213 if (!(reason & mask)) {
2214 spin_unlock(&bcm->lock);
2215 return IRQ_HANDLED;
2218 bcm43xx_interrupt_ack(bcm, reason, mask);
2220 /* disable all IRQs. They are enabled again in the bottom half. */
2221 bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
2223 /* save the reason code and call our bottom half. */
2224 bcm->irq_reason = reason;
2225 tasklet_schedule(&bcm->isr_tasklet);
2227 spin_unlock(&bcm->lock);
2229 return IRQ_HANDLED;
2232 static void bcm43xx_release_firmware(struct bcm43xx_private *bcm)
2234 if (bcm->firmware_norelease)
2235 return; /* Suspending or controller reset. */
2236 release_firmware(bcm->ucode);
2237 bcm->ucode = NULL;
2238 release_firmware(bcm->pcm);
2239 bcm->pcm = NULL;
2240 release_firmware(bcm->initvals0);
2241 bcm->initvals0 = NULL;
2242 release_firmware(bcm->initvals1);
2243 bcm->initvals1 = NULL;
2246 static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
2248 struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
2249 u8 rev = bcm->current_core->rev;
2250 int err = 0;
2251 int nr;
2252 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
2254 if (!bcm->ucode) {
2255 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
2256 (rev >= 5 ? 5 : rev),
2257 modparam_fwpostfix);
2258 err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev);
2259 if (err) {
2260 printk(KERN_ERR PFX
2261 "Error: Microcode \"%s\" not available or load failed.\n",
2262 buf);
2263 goto error;
2267 if (!bcm->pcm) {
2268 snprintf(buf, ARRAY_SIZE(buf),
2269 "bcm43xx_pcm%d%s.fw",
2270 (rev < 5 ? 4 : 5),
2271 modparam_fwpostfix);
2272 err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev);
2273 if (err) {
2274 printk(KERN_ERR PFX
2275 "Error: PCM \"%s\" not available or load failed.\n",
2276 buf);
2277 goto error;
2281 if (!bcm->initvals0) {
2282 if (rev == 2 || rev == 4) {
2283 switch (phy->type) {
2284 case BCM43xx_PHYTYPE_A:
2285 nr = 3;
2286 break;
2287 case BCM43xx_PHYTYPE_B:
2288 case BCM43xx_PHYTYPE_G:
2289 nr = 1;
2290 break;
2291 default:
2292 goto err_noinitval;
2295 } else if (rev >= 5) {
2296 switch (phy->type) {
2297 case BCM43xx_PHYTYPE_A:
2298 nr = 7;
2299 break;
2300 case BCM43xx_PHYTYPE_B:
2301 case BCM43xx_PHYTYPE_G:
2302 nr = 5;
2303 break;
2304 default:
2305 goto err_noinitval;
2307 } else
2308 goto err_noinitval;
2309 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2310 nr, modparam_fwpostfix);
2312 err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev);
2313 if (err) {
2314 printk(KERN_ERR PFX
2315 "Error: InitVals \"%s\" not available or load failed.\n",
2316 buf);
2317 goto error;
2319 if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) {
2320 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2321 goto error;
2325 if (!bcm->initvals1) {
2326 if (rev >= 5) {
2327 u32 sbtmstatehigh;
2329 switch (phy->type) {
2330 case BCM43xx_PHYTYPE_A:
2331 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
2332 if (sbtmstatehigh & 0x00010000)
2333 nr = 9;
2334 else
2335 nr = 10;
2336 break;
2337 case BCM43xx_PHYTYPE_B:
2338 case BCM43xx_PHYTYPE_G:
2339 nr = 6;
2340 break;
2341 default:
2342 goto err_noinitval;
2344 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2345 nr, modparam_fwpostfix);
2347 err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev);
2348 if (err) {
2349 printk(KERN_ERR PFX
2350 "Error: InitVals \"%s\" not available or load failed.\n",
2351 buf);
2352 goto error;
2354 if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) {
2355 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2356 goto error;
2361 out:
2362 return err;
2363 error:
2364 bcm43xx_release_firmware(bcm);
2365 goto out;
2366 err_noinitval:
2367 printk(KERN_ERR PFX "Error: No InitVals available!\n");
2368 err = -ENOENT;
2369 goto error;
2372 static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2374 const u32 *data;
2375 unsigned int i, len;
2377 #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT
2378 bcm43xx_mmioprint_enable(bcm);
2379 #else
2380 bcm43xx_mmioprint_disable(bcm);
2381 #endif
2383 /* Upload Microcode. */
2384 data = (u32 *)(bcm->ucode->data);
2385 len = bcm->ucode->size / sizeof(u32);
2386 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
2387 for (i = 0; i < len; i++) {
2388 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
2389 be32_to_cpu(data[i]));
2390 udelay(10);
2393 /* Upload PCM data. */
2394 data = (u32 *)(bcm->pcm->data);
2395 len = bcm->pcm->size / sizeof(u32);
2396 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
2397 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
2398 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
2399 for (i = 0; i < len; i++) {
2400 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
2401 be32_to_cpu(data[i]));
2402 udelay(10);
2405 #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT
2406 bcm43xx_mmioprint_disable(bcm);
2407 #else
2408 bcm43xx_mmioprint_enable(bcm);
2409 #endif
2412 static void bcm43xx_write_initvals(struct bcm43xx_private *bcm,
2413 const struct bcm43xx_initval *data,
2414 const unsigned int len)
2416 u16 offset, size;
2417 u32 value;
2418 unsigned int i;
2420 for (i = 0; i < len; i++) {
2421 offset = be16_to_cpu(data[i].offset);
2422 size = be16_to_cpu(data[i].size);
2423 value = be32_to_cpu(data[i].value);
2425 if (size == 2)
2426 bcm43xx_write16(bcm, offset, value);
2427 else if (size == 4)
2428 bcm43xx_write32(bcm, offset, value);
2429 else
2430 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2434 static void bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
2436 #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT
2437 bcm43xx_mmioprint_enable(bcm);
2438 #else
2439 bcm43xx_mmioprint_disable(bcm);
2440 #endif
2442 bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
2443 bcm->initvals0->size / sizeof(struct bcm43xx_initval));
2444 if (bcm->initvals1) {
2445 bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
2446 bcm->initvals1->size / sizeof(struct bcm43xx_initval));
2449 #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT
2450 bcm43xx_mmioprint_disable(bcm);
2451 #else
2452 bcm43xx_mmioprint_enable(bcm);
2453 #endif
2456 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2458 int res;
2459 unsigned int i;
2460 u32 data;
2462 bcm->irq = bcm->pci_dev->irq;
2463 #ifdef CONFIG_BCM947XX
2464 if (bcm->pci_dev->bus->number == 0) {
2465 struct pci_dev *d = NULL;
2466 /* FIXME: we will probably need more device IDs here... */
2467 d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
2468 if (d != NULL) {
2469 bcm->irq = d->irq;
2472 #endif
2473 res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
2474 SA_SHIRQ, DRV_NAME, bcm);
2475 if (res) {
2476 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
2477 return -EFAULT;
2479 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
2480 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2481 i = 0;
2482 while (1) {
2483 data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2484 if (data == BCM43xx_IRQ_READY)
2485 break;
2486 i++;
2487 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2488 printk(KERN_ERR PFX "Card IRQ register not responding. "
2489 "Giving up.\n");
2490 free_irq(bcm->irq, bcm);
2491 return -ENODEV;
2493 udelay(10);
2495 // dummy read
2496 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2498 return 0;
2501 /* Switch to the core used to write the GPIO register.
2502 * This is either the ChipCommon, or the PCI core.
2504 static inline int switch_to_gpio_core(struct bcm43xx_private *bcm)
2506 int err;
2508 /* Where to find the GPIO register depends on the chipset.
2509 * If it has a ChipCommon, its register at offset 0x6c is the GPIO
2510 * control register. Otherwise the register at offset 0x6c in the
2511 * PCI core is the GPIO control register.
2513 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
2514 if (err == -ENODEV) {
2515 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
2516 if (err == -ENODEV) {
2517 printk(KERN_ERR PFX "gpio error: "
2518 "Neither ChipCommon nor PCI core available!\n");
2519 return -ENODEV;
2520 } else if (err != 0)
2521 return -ENODEV;
2522 } else if (err != 0)
2523 return -ENODEV;
2525 return 0;
2528 /* Initialize the GPIOs
2529 * http://bcm-specs.sipsolutions.net/GPIO
2531 static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
2533 struct bcm43xx_coreinfo *old_core;
2534 int err;
2535 u32 mask, value;
2537 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2538 value &= ~0xc000;
2539 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
2541 mask = 0x0000001F;
2542 value = 0x0000000F;
2543 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL,
2544 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL) & 0xFFF0);
2545 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2546 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
2548 old_core = bcm->current_core;
2550 err = switch_to_gpio_core(bcm);
2551 if (err)
2552 return err;
2554 if (bcm->current_core->rev >= 2){
2555 mask |= 0x10;
2556 value |= 0x10;
2558 if (bcm->chip_id == 0x4301) {
2559 mask |= 0x60;
2560 value |= 0x60;
2562 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
2563 mask |= 0x200;
2564 value |= 0x200;
2567 bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
2568 (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | value);
2570 err = bcm43xx_switch_core(bcm, old_core);
2571 assert(err == 0);
2573 return 0;
2576 /* Turn off all GPIO stuff. Call this on module unload, for example. */
2577 static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
2579 struct bcm43xx_coreinfo *old_core;
2580 int err;
2582 old_core = bcm->current_core;
2583 err = switch_to_gpio_core(bcm);
2584 if (err)
2585 return err;
2586 bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
2587 err = bcm43xx_switch_core(bcm, old_core);
2588 assert(err == 0);
2590 return 0;
2593 /* http://bcm-specs.sipsolutions.net/EnableMac */
2594 void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
2596 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2597 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2598 | BCM43xx_SBF_MAC_ENABLED);
2599 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
2600 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
2601 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2602 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
2605 /* http://bcm-specs.sipsolutions.net/SuspendMAC */
2606 void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
2608 int i;
2609 u32 tmp;
2611 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
2612 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2613 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2614 & ~BCM43xx_SBF_MAC_ENABLED);
2615 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2616 for (i = 1000; i > 0; i--) {
2617 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2618 if (tmp & BCM43xx_IRQ_READY) {
2619 i = -1;
2620 break;
2622 udelay(10);
2624 if (!i)
2625 printkl(KERN_ERR PFX "Failed to suspend mac!\n");
2628 void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
2629 int iw_mode)
2631 unsigned long flags;
2632 u32 status;
2634 spin_lock_irqsave(&bcm->ieee->lock, flags);
2635 bcm->ieee->iw_mode = iw_mode;
2636 spin_unlock_irqrestore(&bcm->ieee->lock, flags);
2637 if (iw_mode == IW_MODE_MONITOR)
2638 bcm->net_dev->type = ARPHRD_IEEE80211;
2639 else
2640 bcm->net_dev->type = ARPHRD_ETHER;
2642 if (!bcm->initialized)
2643 return;
2645 bcm43xx_mac_suspend(bcm);
2646 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2647 /* Reset status to infrastructured mode */
2648 status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
2649 /*FIXME: We actually set promiscuous mode as well, until we don't
2650 * get the HW mac filter working */
2651 status |= BCM43xx_SBF_MODE_NOTADHOC | BCM43xx_SBF_MODE_PROMISC;
2653 switch (iw_mode) {
2654 case IW_MODE_MONITOR:
2655 status |= (BCM43xx_SBF_MODE_PROMISC |
2656 BCM43xx_SBF_MODE_MONITOR);
2657 break;
2658 case IW_MODE_ADHOC:
2659 status &= ~BCM43xx_SBF_MODE_NOTADHOC;
2660 break;
2661 case IW_MODE_MASTER:
2662 case IW_MODE_SECOND:
2663 case IW_MODE_REPEAT:
2664 /* TODO: No AP/Repeater mode for now :-/ */
2665 TODO();
2666 break;
2667 case IW_MODE_INFRA:
2668 /* nothing to be done here... */
2669 break;
2670 default:
2671 printk(KERN_ERR PFX "Unknown iwmode %d\n", iw_mode);
2674 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
2675 bcm43xx_mac_enable(bcm);
2678 /* This is the opposite of bcm43xx_chip_init() */
2679 static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
2681 bcm43xx_radio_turn_off(bcm);
2682 if (!modparam_noleds)
2683 bcm43xx_leds_exit(bcm);
2684 bcm43xx_gpio_cleanup(bcm);
2685 free_irq(bcm->irq, bcm);
2686 bcm43xx_release_firmware(bcm);
2689 /* Initialize the chip
2690 * http://bcm-specs.sipsolutions.net/ChipInit
2692 static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2694 int err;
2695 int iw_mode = bcm->ieee->iw_mode;
2696 int tmp;
2697 u32 value32;
2698 u16 value16;
2700 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2701 BCM43xx_SBF_CORE_READY
2702 | BCM43xx_SBF_400);
2704 err = bcm43xx_request_firmware(bcm);
2705 if (err)
2706 goto out;
2707 bcm43xx_upload_microcode(bcm);
2709 err = bcm43xx_initialize_irq(bcm);
2710 if (err)
2711 goto out;
2713 err = bcm43xx_gpio_init(bcm);
2714 if (err)
2715 goto err_free_irq;
2717 bcm43xx_upload_initvals(bcm);
2718 bcm43xx_radio_turn_on(bcm);
2720 if (modparam_noleds)
2721 bcm43xx_leds_turn_off(bcm);
2722 else
2723 bcm43xx_leds_update(bcm, 0);
2725 bcm43xx_write16(bcm, 0x03E6, 0x0000);
2726 err = bcm43xx_phy_init(bcm);
2727 if (err)
2728 goto err_radio_off;
2730 /* Select initial Interference Mitigation. */
2731 tmp = bcm->current_core->radio->interfmode;
2732 bcm->current_core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2733 bcm43xx_radio_set_interference_mitigation(bcm, tmp);
2735 bcm43xx_phy_set_antenna_diversity(bcm);
2736 bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
2737 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) {
2738 value16 = bcm43xx_read16(bcm, 0x005E);
2739 value16 |= 0x0004;
2740 bcm43xx_write16(bcm, 0x005E, value16);
2742 bcm43xx_write32(bcm, 0x0100, 0x01000000);
2743 if (bcm->current_core->rev < 5)
2744 bcm43xx_write32(bcm, 0x010C, 0x01000000);
2746 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2747 value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
2748 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2749 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2750 value32 |= BCM43xx_SBF_MODE_NOTADHOC;
2751 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2752 /*FIXME: For now, use promiscuous mode at all times; otherwise we don't
2753 get broadcast or multicast packets */
2754 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2755 value32 |= BCM43xx_SBF_MODE_PROMISC;
2756 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2758 if (iw_mode == IW_MODE_MONITOR) {
2759 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2760 value32 |= BCM43xx_SBF_MODE_PROMISC;
2761 value32 |= BCM43xx_SBF_MODE_MONITOR;
2762 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2764 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2765 value32 |= 0x100000; //FIXME: What's this? Is this correct?
2766 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2768 if (bcm->pio_mode) {
2769 bcm43xx_write32(bcm, 0x0210, 0x00000100);
2770 bcm43xx_write32(bcm, 0x0230, 0x00000100);
2771 bcm43xx_write32(bcm, 0x0250, 0x00000100);
2772 bcm43xx_write32(bcm, 0x0270, 0x00000100);
2773 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
2776 /* Probe Response Timeout value */
2777 /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
2778 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
2780 if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
2781 if ((bcm->chip_id == 0x4306) && (bcm->chip_rev == 3))
2782 bcm43xx_write16(bcm, 0x0612, 0x0064);
2783 else
2784 bcm43xx_write16(bcm, 0x0612, 0x0032);
2785 } else
2786 bcm43xx_write16(bcm, 0x0612, 0x0002);
2788 if (bcm->current_core->rev < 3) {
2789 bcm43xx_write16(bcm, 0x060E, 0x0000);
2790 bcm43xx_write16(bcm, 0x0610, 0x8000);
2791 bcm43xx_write16(bcm, 0x0604, 0x0000);
2792 bcm43xx_write16(bcm, 0x0606, 0x0200);
2793 } else {
2794 bcm43xx_write32(bcm, 0x0188, 0x80000000);
2795 bcm43xx_write32(bcm, 0x018C, 0x02000000);
2797 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
2798 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00);
2799 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
2800 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00);
2801 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00);
2803 value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
2804 value32 |= 0x00100000;
2805 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
2807 bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
2809 assert(err == 0);
2810 dprintk(KERN_INFO PFX "Chip initialized\n");
2811 out:
2812 return err;
2814 err_radio_off:
2815 bcm43xx_radio_turn_off(bcm);
2816 bcm43xx_gpio_cleanup(bcm);
2817 err_free_irq:
2818 free_irq(bcm->irq, bcm);
2819 goto out;
2822 /* Validate chip access
2823 * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
2824 static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
2826 int err = -ENODEV;
2827 u32 value;
2828 u32 shm_backup;
2830 shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
2831 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
2832 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) {
2833 printk(KERN_ERR PFX "Error: SHM mismatch (1) validating chip\n");
2834 goto out;
2837 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
2838 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) {
2839 printk(KERN_ERR PFX "Error: SHM mismatch (2) validating chip\n");
2840 goto out;
2843 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
2845 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2846 if ((value | 0x80000000) != 0x80000400) {
2847 printk(KERN_ERR PFX "Error: Bad Status Bitfield while validating chip\n");
2848 goto out;
2851 value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2852 if (value != 0x00000000) {
2853 printk(KERN_ERR PFX "Error: Bad interrupt reason code while validating chip\n");
2854 goto out;
2857 err = 0;
2858 out:
2859 return err;
2862 static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2864 int err, i;
2865 int current_core;
2866 u32 core_vendor, core_id, core_rev;
2867 u32 sb_id_hi, chip_id_32 = 0;
2868 u16 pci_device, chip_id_16;
2869 u8 core_count;
2871 memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
2872 memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
2873 memset(&bcm->core_v90, 0, sizeof(struct bcm43xx_coreinfo));
2874 memset(&bcm->core_pcmcia, 0, sizeof(struct bcm43xx_coreinfo));
2875 memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
2876 * BCM43xx_MAX_80211_CORES);
2878 memset(&bcm->phy, 0, sizeof(struct bcm43xx_phyinfo)
2879 * BCM43xx_MAX_80211_CORES);
2880 memset(&bcm->radio, 0, sizeof(struct bcm43xx_radioinfo)
2881 * BCM43xx_MAX_80211_CORES);
2883 /* map core 0 */
2884 err = _switch_core(bcm, 0);
2885 if (err)
2886 goto out;
2888 /* fetch sb_id_hi from core information registers */
2889 sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
2891 core_id = (sb_id_hi & 0xFFF0) >> 4;
2892 core_rev = (sb_id_hi & 0xF);
2893 core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
2895 /* if present, chipcommon is always core 0; read the chipid from it */
2896 if (core_id == BCM43xx_COREID_CHIPCOMMON) {
2897 chip_id_32 = bcm43xx_read32(bcm, 0);
2898 chip_id_16 = chip_id_32 & 0xFFFF;
2899 bcm->core_chipcommon.flags |= BCM43xx_COREFLAG_AVAILABLE;
2900 bcm->core_chipcommon.id = core_id;
2901 bcm->core_chipcommon.rev = core_rev;
2902 bcm->core_chipcommon.index = 0;
2903 /* While we are at it, also read the capabilities. */
2904 bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
2905 } else {
2906 /* without a chipCommon, use a hard coded table. */
2907 pci_device = bcm->pci_dev->device;
2908 if (pci_device == 0x4301)
2909 chip_id_16 = 0x4301;
2910 else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
2911 chip_id_16 = 0x4307;
2912 else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
2913 chip_id_16 = 0x4402;
2914 else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
2915 chip_id_16 = 0x4610;
2916 else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
2917 chip_id_16 = 0x4710;
2918 #ifdef CONFIG_BCM947XX
2919 else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
2920 chip_id_16 = 0x4309;
2921 #endif
2922 else {
2923 printk(KERN_ERR PFX "Could not determine Chip ID\n");
2924 return -ENODEV;
2928 /* ChipCommon with Core Rev >=4 encodes number of cores,
2929 * otherwise consult hardcoded table */
2930 if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
2931 core_count = (chip_id_32 & 0x0F000000) >> 24;
2932 } else {
2933 switch (chip_id_16) {
2934 case 0x4610:
2935 case 0x4704:
2936 case 0x4710:
2937 core_count = 9;
2938 break;
2939 case 0x4310:
2940 core_count = 8;
2941 break;
2942 case 0x5365:
2943 core_count = 7;
2944 break;
2945 case 0x4306:
2946 core_count = 6;
2947 break;
2948 case 0x4301:
2949 case 0x4307:
2950 core_count = 5;
2951 break;
2952 case 0x4402:
2953 core_count = 3;
2954 break;
2955 default:
2956 /* SOL if we get here */
2957 assert(0);
2958 core_count = 1;
2962 bcm->chip_id = chip_id_16;
2963 bcm->chip_rev = (chip_id_32 & 0x000f0000) >> 16;
2965 dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
2966 bcm->chip_id, bcm->chip_rev);
2967 dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
2968 if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) {
2969 dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
2970 core_id, core_rev, core_vendor,
2971 bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
2974 if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE)
2975 current_core = 1;
2976 else
2977 current_core = 0;
2978 for ( ; current_core < core_count; current_core++) {
2979 struct bcm43xx_coreinfo *core;
2981 err = _switch_core(bcm, current_core);
2982 if (err)
2983 goto out;
2984 /* Gather information */
2985 /* fetch sb_id_hi from core information registers */
2986 sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
2988 /* extract core_id, core_rev, core_vendor */
2989 core_id = (sb_id_hi & 0xFFF0) >> 4;
2990 core_rev = (sb_id_hi & 0xF);
2991 core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
2993 dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
2994 current_core, core_id, core_rev, core_vendor,
2995 bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
2997 core = NULL;
2998 switch (core_id) {
2999 case BCM43xx_COREID_PCI:
3000 core = &bcm->core_pci;
3001 if (core->flags & BCM43xx_COREFLAG_AVAILABLE) {
3002 printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
3003 continue;
3005 break;
3006 case BCM43xx_COREID_V90:
3007 core = &bcm->core_v90;
3008 if (core->flags & BCM43xx_COREFLAG_AVAILABLE) {
3009 printk(KERN_WARNING PFX "Multiple V90 cores found.\n");
3010 continue;
3012 break;
3013 case BCM43xx_COREID_PCMCIA:
3014 core = &bcm->core_pcmcia;
3015 if (core->flags & BCM43xx_COREFLAG_AVAILABLE) {
3016 printk(KERN_WARNING PFX "Multiple PCMCIA cores found.\n");
3017 continue;
3019 break;
3020 case BCM43xx_COREID_ETHERNET:
3021 core = &bcm->core_ethernet;
3022 if (core->flags & BCM43xx_COREFLAG_AVAILABLE) {
3023 printk(KERN_WARNING PFX "Multiple Ethernet cores found.\n");
3024 continue;
3026 break;
3027 case BCM43xx_COREID_80211:
3028 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3029 core = &(bcm->core_80211[i]);
3030 if (!(core->flags & BCM43xx_COREFLAG_AVAILABLE))
3031 break;
3032 core = NULL;
3034 if (!core) {
3035 printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
3036 BCM43xx_MAX_80211_CORES);
3037 continue;
3039 if (i != 0) {
3040 /* More than one 80211 core is only supported
3041 * by special chips.
3042 * There are chips with two 80211 cores, but with
3043 * dangling pins on the second core. Be careful
3044 * and ignore these cores here.
3046 if (bcm->pci_dev->device != 0x4324) {
3047 dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n");
3048 continue;
3051 switch (core_rev) {
3052 case 2:
3053 case 4:
3054 case 5:
3055 case 6:
3056 case 7:
3057 case 9:
3058 break;
3059 default:
3060 printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
3061 core_rev);
3062 err = -ENODEV;
3063 goto out;
3065 core->phy = &bcm->phy[i];
3066 core->phy->antenna_diversity = 0xffff;
3067 core->phy->savedpctlreg = 0xFFFF;
3068 core->phy->minlowsig[0] = 0xFFFF;
3069 core->phy->minlowsig[1] = 0xFFFF;
3070 core->phy->minlowsigpos[0] = 0;
3071 core->phy->minlowsigpos[1] = 0;
3072 spin_lock_init(&core->phy->lock);
3073 core->radio = &bcm->radio[i];
3074 core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
3075 core->radio->channel = 0xFF;
3076 core->radio->initial_channel = 0xFF;
3077 core->radio->lofcal = 0xFFFF;
3078 core->radio->initval = 0xFFFF;
3079 core->radio->nrssi[0] = -1000;
3080 core->radio->nrssi[1] = -1000;
3081 core->dma = &bcm->dma[i];
3082 core->pio = &bcm->pio[i];
3083 break;
3084 case BCM43xx_COREID_CHIPCOMMON:
3085 printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
3086 break;
3087 default:
3088 printk(KERN_WARNING PFX "Unknown core found (ID 0x%x)\n", core_id);
3090 if (core) {
3091 core->flags |= BCM43xx_COREFLAG_AVAILABLE;
3092 core->id = core_id;
3093 core->rev = core_rev;
3094 core->index = current_core;
3098 if (!(bcm->core_80211[0].flags & BCM43xx_COREFLAG_AVAILABLE)) {
3099 printk(KERN_ERR PFX "Error: No 80211 core found!\n");
3100 err = -ENODEV;
3101 goto out;
3104 err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
3106 assert(err == 0);
3107 out:
3108 return err;
3111 static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
3113 const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
3114 u8 *bssid = bcm->ieee->bssid;
3116 switch (bcm->ieee->iw_mode) {
3117 case IW_MODE_ADHOC:
3118 random_ether_addr(bssid);
3119 break;
3120 case IW_MODE_MASTER:
3121 case IW_MODE_INFRA:
3122 case IW_MODE_REPEAT:
3123 case IW_MODE_SECOND:
3124 case IW_MODE_MONITOR:
3125 memcpy(bssid, mac, ETH_ALEN);
3126 break;
3127 default:
3128 assert(0);
3132 static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
3133 u16 rate,
3134 int is_ofdm)
3136 u16 offset;
3138 if (is_ofdm) {
3139 offset = 0x480;
3140 offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
3142 else {
3143 offset = 0x4C0;
3144 offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
3146 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
3147 bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
3150 static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
3152 switch (bcm->current_core->phy->type) {
3153 case BCM43xx_PHYTYPE_A:
3154 case BCM43xx_PHYTYPE_G:
3155 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
3156 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
3157 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
3158 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
3159 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
3160 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
3161 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
3162 case BCM43xx_PHYTYPE_B:
3163 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
3164 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
3165 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
3166 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
3167 break;
3168 default:
3169 assert(0);
3173 static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
3175 bcm43xx_chip_cleanup(bcm);
3176 bcm43xx_pio_free(bcm);
3177 bcm43xx_dma_free(bcm);
3179 bcm->current_core->flags &= ~ BCM43xx_COREFLAG_INITIALIZED;
3182 /* http://bcm-specs.sipsolutions.net/80211Init */
3183 static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
3185 u32 ucodeflags;
3186 int err;
3187 u32 sbimconfiglow;
3188 u8 limit;
3190 if (bcm->chip_rev < 5) {
3191 sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
3192 sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
3193 sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
3194 if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
3195 sbimconfiglow |= 0x32;
3196 else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
3197 sbimconfiglow |= 0x53;
3198 else
3199 assert(0);
3200 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
3203 bcm43xx_phy_calibrate(bcm);
3204 err = bcm43xx_chip_init(bcm);
3205 if (err)
3206 goto out;
3208 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
3209 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
3211 if (0 /*FIXME: which condition has to be used here? */)
3212 ucodeflags |= 0x00000010;
3214 /* HW decryption needs to be set now */
3215 ucodeflags |= 0x40000000;
3217 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) {
3218 ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
3219 if (bcm->current_core->phy->rev == 1)
3220 ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
3221 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
3222 ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
3223 } else if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) {
3224 ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
3225 if ((bcm->current_core->phy->rev >= 2) &&
3226 (bcm->current_core->radio->version == 0x2050))
3227 ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
3230 if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
3231 BCM43xx_UCODEFLAGS_OFFSET)) {
3232 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
3233 BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
3236 /* Short/Long Retry Limit.
3237 * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
3238 * the chip-internal counter.
3240 limit = limit_value(modparam_short_retry, 0, 0xF);
3241 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
3242 limit = limit_value(modparam_long_retry, 0, 0xF);
3243 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
3245 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
3246 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
3248 bcm43xx_rate_memory_init(bcm);
3250 /* Minimum Contention Window */
3251 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B)
3252 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
3253 else
3254 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
3255 /* Maximum Contention Window */
3256 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
3258 bcm43xx_gen_bssid(bcm);
3259 bcm43xx_write_mac_bssid_templates(bcm);
3261 if (bcm->current_core->rev >= 5)
3262 bcm43xx_write16(bcm, 0x043C, 0x000C);
3264 if (!bcm->pio_mode) {
3265 err = bcm43xx_dma_init(bcm);
3266 if (err)
3267 goto err_chip_cleanup;
3268 } else {
3269 err = bcm43xx_pio_init(bcm);
3270 if (err)
3271 goto err_chip_cleanup;
3273 bcm43xx_write16(bcm, 0x0612, 0x0050);
3274 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
3275 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
3277 bcm43xx_mac_enable(bcm);
3278 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
3280 bcm->current_core->flags |= BCM43xx_COREFLAG_INITIALIZED;
3281 out:
3282 return err;
3284 err_chip_cleanup:
3285 bcm43xx_chip_cleanup(bcm);
3286 goto out;
3289 static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
3291 int err;
3292 u16 pci_status;
3294 err = bcm43xx_pctl_set_crystal(bcm, 1);
3295 if (err)
3296 goto out;
3297 bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
3298 bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
3300 out:
3301 return err;
3304 static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
3306 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
3307 bcm43xx_pctl_set_crystal(bcm, 0);
3310 static inline void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
3311 u32 address,
3312 u32 data)
3314 bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
3315 bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
3318 static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
3320 int err;
3321 struct bcm43xx_coreinfo *old_core;
3323 old_core = bcm->current_core;
3324 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
3325 if (err)
3326 goto out;
3328 bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
3330 bcm43xx_switch_core(bcm, old_core);
3331 assert(err == 0);
3332 out:
3333 return err;
3336 /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
3337 * To enable core 0, pass a core_mask of 1<<0
3339 static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
3340 u32 core_mask)
3342 u32 backplane_flag_nr;
3343 u32 value;
3344 struct bcm43xx_coreinfo *old_core;
3345 int err = 0;
3347 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
3348 backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
3350 old_core = bcm->current_core;
3351 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
3352 if (err)
3353 goto out;
3355 if (bcm->core_pci.rev < 6) {
3356 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
3357 value |= (1 << backplane_flag_nr);
3358 bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
3359 } else {
3360 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
3361 if (err) {
3362 printk(KERN_ERR PFX "Error: ICR setup failure!\n");
3363 goto out_switch_back;
3365 value |= core_mask << 8;
3366 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
3367 if (err) {
3368 printk(KERN_ERR PFX "Error: ICR setup failure!\n");
3369 goto out_switch_back;
3373 value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
3374 value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
3375 bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
3377 if (bcm->core_pci.rev < 5) {
3378 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
3379 value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
3380 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
3381 value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
3382 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
3383 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
3384 err = bcm43xx_pcicore_commit_settings(bcm);
3385 assert(err == 0);
3388 out_switch_back:
3389 err = bcm43xx_switch_core(bcm, old_core);
3390 out:
3391 return err;
3394 static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
3396 ieee80211softmac_start(bcm->net_dev);
3399 static void bcm43xx_periodic_work0_handler(void *d)
3401 struct bcm43xx_private *bcm = d;
3402 unsigned long flags;
3403 //TODO: unsigned int aci_average;
3405 spin_lock_irqsave(&bcm->lock, flags);
3407 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) {
3408 //FIXME: aci_average = bcm43xx_update_aci_average(bcm);
3409 if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) {
3410 bcm43xx_mac_suspend(bcm);
3411 if (!bcm->current_core->radio->aci_enable &&
3412 1 /*FIXME: We are not scanning? */) {
3413 /*FIXME: First add bcm43xx_update_aci_average() before
3414 * uncommenting this: */
3415 //if (bcm43xx_radio_aci_scan)
3416 // bcm43xx_radio_set_interference_mitigation(bcm,
3417 // BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3418 } else if (1/*FIXME*/) {
3419 //if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm)))
3420 // bcm43xx_radio_set_interference_mitigation(bcm,
3421 // BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3423 bcm43xx_mac_enable(bcm);
3424 } else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
3425 if (bcm->current_core->phy->rev == 1) {
3426 //FIXME: implement rev1 workaround
3430 bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
3431 //TODO for APHY (temperature?)
3433 if (likely(!bcm->shutting_down)) {
3434 queue_delayed_work(bcm->workqueue, &bcm->periodic_work0,
3435 BCM43xx_PERIODIC_0_DELAY);
3437 spin_unlock_irqrestore(&bcm->lock, flags);
3440 static void bcm43xx_periodic_work1_handler(void *d)
3442 struct bcm43xx_private *bcm = d;
3443 unsigned long flags;
3445 spin_lock_irqsave(&bcm->lock, flags);
3447 bcm43xx_phy_lo_mark_all_unused(bcm);
3448 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
3449 bcm43xx_mac_suspend(bcm);
3450 bcm43xx_calc_nrssi_slope(bcm);
3451 bcm43xx_mac_enable(bcm);
3454 if (likely(!bcm->shutting_down)) {
3455 queue_delayed_work(bcm->workqueue, &bcm->periodic_work1,
3456 BCM43xx_PERIODIC_1_DELAY);
3458 spin_unlock_irqrestore(&bcm->lock, flags);
3461 static void bcm43xx_periodic_work2_handler(void *d)
3463 struct bcm43xx_private *bcm = d;
3464 unsigned long flags;
3466 spin_lock_irqsave(&bcm->lock, flags);
3468 assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G);
3469 assert(bcm->current_core->phy->rev >= 2);
3471 bcm43xx_mac_suspend(bcm);
3472 bcm43xx_phy_lo_g_measure(bcm);
3473 bcm43xx_mac_enable(bcm);
3475 if (likely(!bcm->shutting_down)) {
3476 queue_delayed_work(bcm->workqueue, &bcm->periodic_work2,
3477 BCM43xx_PERIODIC_2_DELAY);
3479 spin_unlock_irqrestore(&bcm->lock, flags);
3482 static void bcm43xx_periodic_work3_handler(void *d)
3484 struct bcm43xx_private *bcm = d;
3485 unsigned long flags;
3487 spin_lock_irqsave(&bcm->lock, flags);
3489 /* Update device statistics. */
3490 bcm43xx_calculate_link_quality(bcm);
3492 if (likely(!bcm->shutting_down)) {
3493 queue_delayed_work(bcm->workqueue, &bcm->periodic_work3,
3494 BCM43xx_PERIODIC_3_DELAY);
3496 spin_unlock_irqrestore(&bcm->lock, flags);
3499 /* Delete all periodic tasks and make
3500 * sure they are not running any longer
3502 static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
3504 cancel_delayed_work(&bcm->periodic_work0);
3505 cancel_delayed_work(&bcm->periodic_work1);
3506 cancel_delayed_work(&bcm->periodic_work2);
3507 cancel_delayed_work(&bcm->periodic_work3);
3508 flush_workqueue(bcm->workqueue);
3511 /* Setup all periodic tasks. */
3512 static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
3514 INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm);
3515 INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm);
3516 INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm);
3517 INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm);
3519 /* Periodic task 0: Delay ~15sec */
3520 queue_delayed_work(bcm->workqueue, &bcm->periodic_work0,
3521 BCM43xx_PERIODIC_0_DELAY);
3523 /* Periodic task 1: Delay ~60sec */
3524 queue_delayed_work(bcm->workqueue, &bcm->periodic_work1,
3525 BCM43xx_PERIODIC_1_DELAY);
3527 /* Periodic task 2: Delay ~120sec */
3528 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
3529 bcm->current_core->phy->rev >= 2) {
3530 queue_delayed_work(bcm->workqueue, &bcm->periodic_work2,
3531 BCM43xx_PERIODIC_2_DELAY);
3534 /* Periodic task 3: Delay ~30sec */
3535 queue_delayed_work(bcm->workqueue, &bcm->periodic_work3,
3536 BCM43xx_PERIODIC_3_DELAY);
3539 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
3541 bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
3542 0x0056) * 2;
3543 bcm43xx_clear_keys(bcm);
3546 /* This is the opposite of bcm43xx_init_board() */
3547 static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3549 int i, err;
3550 unsigned long flags;
3552 spin_lock_irqsave(&bcm->lock, flags);
3553 bcm->initialized = 0;
3554 bcm->shutting_down = 1;
3555 spin_unlock_irqrestore(&bcm->lock, flags);
3557 bcm43xx_periodic_tasks_delete(bcm);
3559 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3560 if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE))
3561 continue;
3562 if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED))
3563 continue;
3565 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3566 assert(err == 0);
3567 bcm43xx_wireless_core_cleanup(bcm);
3570 bcm43xx_pctl_set_crystal(bcm, 0);
3572 spin_lock_irqsave(&bcm->lock, flags);
3573 bcm->shutting_down = 0;
3574 spin_unlock_irqrestore(&bcm->lock, flags);
3577 static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3579 int i, err;
3580 int num_80211_cores;
3581 int connect_phy;
3582 unsigned long flags;
3584 might_sleep();
3586 spin_lock_irqsave(&bcm->lock, flags);
3587 bcm->initialized = 0;
3588 bcm->shutting_down = 0;
3589 spin_unlock_irqrestore(&bcm->lock, flags);
3591 err = bcm43xx_pctl_set_crystal(bcm, 1);
3592 if (err)
3593 goto out;
3594 err = bcm43xx_pctl_init(bcm);
3595 if (err)
3596 goto err_crystal_off;
3597 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
3598 if (err)
3599 goto err_crystal_off;
3601 tasklet_enable(&bcm->isr_tasklet);
3602 num_80211_cores = bcm43xx_num_80211_cores(bcm);
3603 for (i = 0; i < num_80211_cores; i++) {
3604 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3605 assert(err != -ENODEV);
3606 if (err)
3607 goto err_80211_unwind;
3609 /* Enable the selected wireless core.
3610 * Connect PHY only on the first core.
3612 if (!bcm43xx_core_enabled(bcm)) {
3613 if (num_80211_cores == 1) {
3614 connect_phy = bcm->current_core->phy->connected;
3615 } else {
3616 if (i == 0)
3617 connect_phy = 1;
3618 else
3619 connect_phy = 0;
3621 bcm43xx_wireless_core_reset(bcm, connect_phy);
3624 if (i != 0)
3625 bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]);
3627 err = bcm43xx_wireless_core_init(bcm);
3628 if (err)
3629 goto err_80211_unwind;
3631 if (i != 0) {
3632 bcm43xx_mac_suspend(bcm);
3633 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3634 bcm43xx_radio_turn_off(bcm);
3637 bcm->active_80211_core = &bcm->core_80211[0];
3638 if (num_80211_cores >= 2) {
3639 bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
3640 bcm43xx_mac_enable(bcm);
3642 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3643 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
3644 dprintk(KERN_INFO PFX "80211 cores initialized\n");
3645 bcm43xx_security_init(bcm);
3646 bcm43xx_softmac_init(bcm);
3648 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
3650 spin_lock_irqsave(&bcm->lock, flags);
3651 bcm->initialized = 1;
3652 spin_unlock_irqrestore(&bcm->lock, flags);
3654 if (bcm->current_core->radio->initial_channel != 0xFF) {
3655 bcm43xx_mac_suspend(bcm);
3656 bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0);
3657 bcm43xx_mac_enable(bcm);
3659 bcm43xx_periodic_tasks_setup(bcm);
3661 assert(err == 0);
3662 out:
3663 return err;
3665 err_80211_unwind:
3666 tasklet_disable(&bcm->isr_tasklet);
3667 /* unwind all 80211 initialization */
3668 for (i = 0; i < num_80211_cores; i++) {
3669 if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED))
3670 continue;
3671 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3672 bcm43xx_wireless_core_cleanup(bcm);
3674 err_crystal_off:
3675 bcm43xx_pctl_set_crystal(bcm, 0);
3676 goto out;
3679 static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
3681 struct pci_dev *pci_dev = bcm->pci_dev;
3682 int i;
3684 bcm43xx_chipset_detach(bcm);
3685 /* Do _not_ access the chip, after it is detached. */
3686 iounmap(bcm->mmio_addr);
3688 pci_release_regions(pci_dev);
3689 pci_disable_device(pci_dev);
3691 /* Free allocated structures/fields */
3692 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3693 kfree(bcm->phy[i]._lo_pairs);
3694 if (bcm->phy[i].dyn_tssi_tbl)
3695 kfree(bcm->phy[i].tssi2dbm);
3699 static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
3701 u16 value;
3702 u8 phy_version;
3703 u8 phy_type;
3704 u8 phy_rev;
3705 int phy_rev_ok = 1;
3706 void *p;
3708 value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
3710 phy_version = (value & 0xF000) >> 12;
3711 phy_type = (value & 0x0F00) >> 8;
3712 phy_rev = (value & 0x000F);
3714 dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
3715 phy_version, phy_type, phy_rev);
3717 switch (phy_type) {
3718 case BCM43xx_PHYTYPE_A:
3719 if (phy_rev >= 4)
3720 phy_rev_ok = 0;
3721 /*FIXME: We need to switch the ieee->modulation, etc.. flags,
3722 * if we switch 80211 cores after init is done.
3723 * As we do not implement on the fly switching between
3724 * wireless cores, I will leave this as a future task.
3726 bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
3727 bcm->ieee->mode = IEEE_A;
3728 bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
3729 IEEE80211_24GHZ_BAND;
3730 break;
3731 case BCM43xx_PHYTYPE_B:
3732 if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
3733 phy_rev_ok = 0;
3734 bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
3735 bcm->ieee->mode = IEEE_B;
3736 bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
3737 break;
3738 case BCM43xx_PHYTYPE_G:
3739 if (phy_rev > 7)
3740 phy_rev_ok = 0;
3741 bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
3742 IEEE80211_CCK_MODULATION;
3743 bcm->ieee->mode = IEEE_G;
3744 bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
3745 break;
3746 default:
3747 printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
3748 phy_type);
3749 return -ENODEV;
3751 if (!phy_rev_ok) {
3752 printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
3753 phy_rev);
3756 bcm->current_core->phy->version = phy_version;
3757 bcm->current_core->phy->type = phy_type;
3758 bcm->current_core->phy->rev = phy_rev;
3759 if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
3760 p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
3761 GFP_KERNEL);
3762 if (!p)
3763 return -ENOMEM;
3764 bcm->current_core->phy->_lo_pairs = p;
3767 return 0;
3770 static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
3772 struct pci_dev *pci_dev = bcm->pci_dev;
3773 struct net_device *net_dev = bcm->net_dev;
3774 int err;
3775 int i;
3776 void __iomem *ioaddr;
3777 unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
3778 int num_80211_cores;
3779 u32 coremask;
3781 err = pci_enable_device(pci_dev);
3782 if (err) {
3783 printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err);
3784 err = -ENODEV;
3785 goto out;
3788 mmio_start = pci_resource_start(pci_dev, 0);
3789 mmio_end = pci_resource_end(pci_dev, 0);
3790 mmio_flags = pci_resource_flags(pci_dev, 0);
3791 mmio_len = pci_resource_len(pci_dev, 0);
3793 /* make sure PCI base addr is MMIO */
3794 if (!(mmio_flags & IORESOURCE_MEM)) {
3795 printk(KERN_ERR PFX
3796 "%s, region #0 not an MMIO resource, aborting\n",
3797 pci_name(pci_dev));
3798 err = -ENODEV;
3799 goto err_pci_disable;
3801 //FIXME: Why is this check disabled for BCM947XX? What is the IO_SIZE there?
3802 #ifndef CONFIG_BCM947XX
3803 if (mmio_len != BCM43xx_IO_SIZE) {
3804 printk(KERN_ERR PFX
3805 "%s: invalid PCI mem region size(s), aborting\n",
3806 pci_name(pci_dev));
3807 err = -ENODEV;
3808 goto err_pci_disable;
3810 #endif
3812 err = pci_request_regions(pci_dev, DRV_NAME);
3813 if (err) {
3814 printk(KERN_ERR PFX
3815 "could not access PCI resources (%i)\n", err);
3816 goto err_pci_disable;
3819 /* enable PCI bus-mastering */
3820 pci_set_master(pci_dev);
3822 /* ioremap MMIO region */
3823 ioaddr = ioremap(mmio_start, mmio_len);
3824 if (!ioaddr) {
3825 printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n",
3826 pci_name(pci_dev));
3827 err = -EIO;
3828 goto err_pci_release;
3831 net_dev->base_addr = (unsigned long)ioaddr;
3832 bcm->mmio_addr = ioaddr;
3833 bcm->mmio_len = mmio_len;
3835 bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
3836 &bcm->board_vendor);
3837 bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
3838 &bcm->board_type);
3839 bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
3840 &bcm->board_revision);
3842 err = bcm43xx_chipset_attach(bcm);
3843 if (err)
3844 goto err_iounmap;
3845 err = bcm43xx_pctl_init(bcm);
3846 if (err)
3847 goto err_chipset_detach;
3848 err = bcm43xx_probe_cores(bcm);
3849 if (err)
3850 goto err_chipset_detach;
3852 num_80211_cores = bcm43xx_num_80211_cores(bcm);
3854 /* Attach all IO cores to the backplane. */
3855 coremask = 0;
3856 for (i = 0; i < num_80211_cores; i++)
3857 coremask |= (1 << bcm->core_80211[i].index);
3858 //FIXME: Also attach some non80211 cores?
3859 err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
3860 if (err) {
3861 printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
3862 goto err_chipset_detach;
3865 err = bcm43xx_read_sprom(bcm);
3866 if (err)
3867 goto err_chipset_detach;
3868 err = bcm43xx_leds_init(bcm);
3869 if (err)
3870 goto err_chipset_detach;
3872 for (i = 0; i < num_80211_cores; i++) {
3873 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3874 assert(err != -ENODEV);
3875 if (err)
3876 goto err_80211_unwind;
3878 /* Enable the selected wireless core.
3879 * Connect PHY only on the first core.
3881 bcm43xx_wireless_core_reset(bcm, (i == 0));
3883 err = bcm43xx_read_phyinfo(bcm);
3884 if (err && (i == 0))
3885 goto err_80211_unwind;
3887 err = bcm43xx_read_radioinfo(bcm);
3888 if (err && (i == 0))
3889 goto err_80211_unwind;
3891 err = bcm43xx_validate_chip(bcm);
3892 if (err && (i == 0))
3893 goto err_80211_unwind;
3895 bcm43xx_radio_turn_off(bcm);
3896 err = bcm43xx_phy_init_tssi2dbm_table(bcm);
3897 if (err)
3898 goto err_80211_unwind;
3899 bcm43xx_wireless_core_disable(bcm);
3901 bcm43xx_pctl_set_crystal(bcm, 0);
3903 /* Set the MAC address in the networking subsystem */
3904 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A)
3905 memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
3906 else
3907 memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
3909 bcm43xx_geo_init(bcm);
3911 snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
3912 "Broadcom %04X", bcm->chip_id);
3914 assert(err == 0);
3915 out:
3916 return err;
3918 err_80211_unwind:
3919 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3920 kfree(bcm->phy[i]._lo_pairs);
3921 if (bcm->phy[i].dyn_tssi_tbl)
3922 kfree(bcm->phy[i].tssi2dbm);
3924 err_chipset_detach:
3925 bcm43xx_chipset_detach(bcm);
3926 err_iounmap:
3927 iounmap(bcm->mmio_addr);
3928 err_pci_release:
3929 pci_release_regions(pci_dev);
3930 err_pci_disable:
3931 pci_disable_device(pci_dev);
3932 goto out;
3935 static inline
3936 s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi,
3937 int ofdm, int adjust_2053, int adjust_2050)
3939 s32 tmp;
3941 switch (bcm->current_core->radio->version) {
3942 case 0x2050:
3943 if (ofdm) {
3944 tmp = in_rssi;
3945 if (tmp > 127)
3946 tmp -= 256;
3947 tmp *= 73;
3948 tmp /= 64;
3949 if (adjust_2050)
3950 tmp += 25;
3951 else
3952 tmp -= 3;
3953 } else {
3954 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
3955 if (in_rssi > 63)
3956 in_rssi = 63;
3957 tmp = bcm->current_core->radio->nrssi_lt[in_rssi];
3958 tmp = 31 - tmp;
3959 tmp *= -131;
3960 tmp /= 128;
3961 tmp -= 57;
3962 } else {
3963 tmp = in_rssi;
3964 tmp = 31 - tmp;
3965 tmp *= -149;
3966 tmp /= 128;
3967 tmp -= 68;
3969 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
3970 adjust_2050)
3971 tmp += 25;
3973 break;
3974 case 0x2060:
3975 if (in_rssi > 127)
3976 tmp = in_rssi - 256;
3977 else
3978 tmp = in_rssi;
3979 break;
3980 default:
3981 tmp = in_rssi;
3982 tmp -= 11;
3983 tmp *= 103;
3984 tmp /= 64;
3985 if (adjust_2053)
3986 tmp -= 109;
3987 else
3988 tmp -= 83;
3991 return (s8)tmp;
3994 static inline
3995 s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi)
3997 s8 ret;
3999 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) {
4000 //TODO: Incomplete specs.
4001 ret = 0;
4002 } else
4003 ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
4005 return ret;
4008 static inline
4009 int bcm43xx_rx_packet(struct bcm43xx_private *bcm,
4010 struct sk_buff *skb,
4011 struct ieee80211_rx_stats *stats)
4013 int err;
4015 err = ieee80211_rx(bcm->ieee, skb, stats);
4016 if (unlikely(err == 0))
4017 return -EINVAL;
4018 return 0;
4021 int fastcall bcm43xx_rx(struct bcm43xx_private *bcm,
4022 struct sk_buff *skb,
4023 struct bcm43xx_rxhdr *rxhdr)
4025 struct bcm43xx_plcp_hdr4 *plcp;
4026 struct ieee80211_rx_stats stats;
4027 struct ieee80211_hdr_4addr *wlhdr;
4028 u16 frame_ctl;
4029 int is_packet_for_us = 0;
4030 int err = -EINVAL;
4031 const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
4032 const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
4033 const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
4034 const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
4036 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
4037 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
4038 /* Skip two unknown bytes and the PLCP header. */
4039 skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
4040 } else {
4041 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
4042 /* Skip the PLCP header. */
4043 skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
4045 /* The SKB contains the PAYLOAD (wireless header + data)
4046 * at this point. The FCS at the end is stripped.
4049 memset(&stats, 0, sizeof(stats));
4050 stats.mac_time = le16_to_cpu(rxhdr->mactime);
4051 stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
4052 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
4053 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
4054 stats.signal = rxhdr->signal_quality; //FIXME
4055 //TODO stats.noise =
4056 stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm);
4057 //printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
4058 stats.received_channel = bcm->current_core->radio->channel;
4059 //TODO stats.control =
4060 stats.mask = IEEE80211_STATMASK_SIGNAL |
4061 //TODO IEEE80211_STATMASK_NOISE |
4062 IEEE80211_STATMASK_RATE |
4063 IEEE80211_STATMASK_RSSI;
4064 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A)
4065 stats.freq = IEEE80211_52GHZ_BAND;
4066 else
4067 stats.freq = IEEE80211_24GHZ_BAND;
4068 stats.len = skb->len;
4070 bcm->stats.last_rx = jiffies;
4071 if (bcm->ieee->iw_mode == IW_MODE_MONITOR)
4072 return bcm43xx_rx_packet(bcm, skb, &stats);
4074 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
4076 switch (bcm->ieee->iw_mode) {
4077 case IW_MODE_ADHOC:
4078 if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
4079 memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
4080 is_broadcast_ether_addr(wlhdr->addr1) ||
4081 is_multicast_ether_addr(wlhdr->addr1) ||
4082 bcm->net_dev->flags & IFF_PROMISC)
4083 is_packet_for_us = 1;
4084 break;
4085 case IW_MODE_INFRA:
4086 default:
4087 /* When receiving multicast or broadcast packets, filter out
4088 the packets we send ourself; we shouldn't see those */
4089 if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
4090 memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
4091 (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
4092 (is_broadcast_ether_addr(wlhdr->addr1) ||
4093 is_multicast_ether_addr(wlhdr->addr1) ||
4094 bcm->net_dev->flags & IFF_PROMISC)))
4095 is_packet_for_us = 1;
4096 break;
4099 frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
4100 if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
4101 frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
4102 wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
4103 /* trim IV and ICV */
4104 /* FIXME: this must be done only for WEP encrypted packets */
4105 if (skb->len < 32) {
4106 dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
4107 "set and length < 32)\n");
4108 return -EINVAL;
4109 } else {
4110 memmove(skb->data + 4, skb->data, 24);
4111 skb_pull(skb, 4);
4112 skb_trim(skb, skb->len - 4);
4113 stats.len -= 8;
4115 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
4118 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
4119 case IEEE80211_FTYPE_MGMT:
4120 ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
4121 break;
4122 case IEEE80211_FTYPE_DATA:
4123 if (is_packet_for_us)
4124 err = bcm43xx_rx_packet(bcm, skb, &stats);
4125 break;
4126 case IEEE80211_FTYPE_CTL:
4127 break;
4128 default:
4129 assert(0);
4130 return -EINVAL;
4133 return err;
4136 /* Do the Hardware IO operations to send the txb */
4137 static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
4138 struct ieee80211_txb *txb)
4140 int err = -ENODEV;
4142 if (bcm->pio_mode)
4143 err = bcm43xx_pio_transfer_txb(bcm, txb);
4144 else
4145 err = bcm43xx_dma_tx(bcm, txb);
4147 return err;
4150 static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
4151 u8 channel)
4153 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4154 unsigned long flags;
4156 spin_lock_irqsave(&bcm->lock, flags);
4157 bcm43xx_mac_suspend(bcm);
4158 bcm43xx_radio_selectchannel(bcm, channel, 0);
4159 bcm43xx_mac_enable(bcm);
4160 spin_unlock_irqrestore(&bcm->lock, flags);
4163 /* set_security() callback in struct ieee80211_device */
4164 static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
4165 struct ieee80211_security *sec)
4167 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4168 struct ieee80211_security *secinfo = &bcm->ieee->sec;
4169 unsigned long flags;
4170 int keyidx;
4172 dprintk(KERN_INFO PFX "set security called\n");
4174 spin_lock_irqsave(&bcm->lock, flags);
4176 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
4177 if (sec->flags & (1<<keyidx)) {
4178 secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
4179 secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
4180 memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
4183 if (sec->flags & SEC_ACTIVE_KEY) {
4184 secinfo->active_key = sec->active_key;
4185 dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key);
4187 if (sec->flags & SEC_UNICAST_GROUP) {
4188 secinfo->unicast_uses_group = sec->unicast_uses_group;
4189 dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group);
4191 if (sec->flags & SEC_LEVEL) {
4192 secinfo->level = sec->level;
4193 dprintk(KERN_INFO PFX " .level = %d\n", sec->level);
4195 if (sec->flags & SEC_ENABLED) {
4196 secinfo->enabled = sec->enabled;
4197 dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled);
4199 if (sec->flags & SEC_ENCRYPT) {
4200 secinfo->encrypt = sec->encrypt;
4201 dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt);
4203 if (bcm->initialized && !bcm->ieee->host_encrypt) {
4204 if (secinfo->enabled) {
4205 /* upload WEP keys to hardware */
4206 char null_address[6] = { 0 };
4207 u8 algorithm = 0;
4208 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
4209 if (!(sec->flags & (1<<keyidx)))
4210 continue;
4211 switch (sec->encode_alg[keyidx]) {
4212 case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
4213 case SEC_ALG_WEP:
4214 algorithm = BCM43xx_SEC_ALGO_WEP;
4215 if (secinfo->key_sizes[keyidx] == 13)
4216 algorithm = BCM43xx_SEC_ALGO_WEP104;
4217 break;
4218 case SEC_ALG_TKIP:
4219 FIXME();
4220 algorithm = BCM43xx_SEC_ALGO_TKIP;
4221 break;
4222 case SEC_ALG_CCMP:
4223 FIXME();
4224 algorithm = BCM43xx_SEC_ALGO_AES;
4225 break;
4226 default:
4227 assert(0);
4228 break;
4230 bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
4231 bcm->key[keyidx].enabled = 1;
4232 bcm->key[keyidx].algorithm = algorithm;
4234 } else
4235 bcm43xx_clear_keys(bcm);
4237 spin_unlock_irqrestore(&bcm->lock, flags);
4240 /* hard_start_xmit() callback in struct ieee80211_device */
4241 static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
4242 struct net_device *net_dev,
4243 int pri)
4245 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4246 int err = -ENODEV;
4247 unsigned long flags;
4249 spin_lock_irqsave(&bcm->lock, flags);
4250 if (likely(bcm->initialized))
4251 err = bcm43xx_tx(bcm, txb);
4252 spin_unlock_irqrestore(&bcm->lock, flags);
4254 return err;
4257 static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
4259 return &(bcm43xx_priv(net_dev)->ieee->stats);
4262 static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
4264 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4266 bcm43xx_controller_restart(bcm, "TX timeout");
4269 #ifdef CONFIG_NET_POLL_CONTROLLER
4270 static void bcm43xx_net_poll_controller(struct net_device *net_dev)
4272 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4273 unsigned long flags;
4275 local_irq_save(flags);
4276 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
4277 local_irq_restore(flags);
4279 #endif /* CONFIG_NET_POLL_CONTROLLER */
4281 static int bcm43xx_net_open(struct net_device *net_dev)
4283 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4285 return bcm43xx_init_board(bcm);
4288 static int bcm43xx_net_stop(struct net_device *net_dev)
4290 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4292 ieee80211softmac_stop(net_dev);
4293 bcm43xx_disable_interrupts_sync(bcm, NULL);
4294 bcm43xx_free_board(bcm);
4296 return 0;
4299 static void bcm43xx_init_private(struct bcm43xx_private *bcm,
4300 struct net_device *net_dev,
4301 struct pci_dev *pci_dev,
4302 struct workqueue_struct *wq)
4304 bcm->ieee = netdev_priv(net_dev);
4305 bcm->softmac = ieee80211_priv(net_dev);
4306 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
4307 bcm->workqueue = wq;
4309 #ifdef DEBUG_ENABLE_MMIO_PRINT
4310 bcm43xx_mmioprint_initial(bcm, 1);
4311 #else
4312 bcm43xx_mmioprint_initial(bcm, 0);
4313 #endif
4314 #ifdef DEBUG_ENABLE_PCILOG
4315 bcm43xx_pciprint_initial(bcm, 1);
4316 #else
4317 bcm43xx_pciprint_initial(bcm, 0);
4318 #endif
4320 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
4321 bcm->pci_dev = pci_dev;
4322 bcm->net_dev = net_dev;
4323 if (modparam_bad_frames_preempt)
4324 bcm->bad_frames_preempt = 1;
4325 spin_lock_init(&bcm->lock);
4326 tasklet_init(&bcm->isr_tasklet,
4327 (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
4328 (unsigned long)bcm);
4329 tasklet_disable_nosync(&bcm->isr_tasklet);
4330 if (modparam_pio) {
4331 bcm->pio_mode = 1;
4332 } else {
4333 if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK) == 0) {
4334 bcm->pio_mode = 0;
4335 } else {
4336 printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
4337 bcm->pio_mode = 1;
4340 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
4342 /* default to sw encryption for now */
4343 bcm->ieee->host_build_iv = 0;
4344 bcm->ieee->host_encrypt = 1;
4345 bcm->ieee->host_decrypt = 1;
4347 bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
4348 bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
4349 bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
4350 bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
4353 static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
4354 const struct pci_device_id *ent)
4356 struct net_device *net_dev;
4357 struct bcm43xx_private *bcm;
4358 struct workqueue_struct *wq;
4359 int err;
4361 #ifdef CONFIG_BCM947XX
4362 if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
4363 return -ENODEV;
4364 #endif
4366 #ifdef DEBUG_SINGLE_DEVICE_ONLY
4367 if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
4368 return -ENODEV;
4369 #endif
4371 net_dev = alloc_ieee80211softmac(sizeof(*bcm));
4372 if (!net_dev) {
4373 printk(KERN_ERR PFX
4374 "could not allocate ieee80211 device %s\n",
4375 pci_name(pdev));
4376 err = -ENOMEM;
4377 goto out;
4379 /* initialize the net_device struct */
4380 SET_MODULE_OWNER(net_dev);
4381 SET_NETDEV_DEV(net_dev, &pdev->dev);
4383 net_dev->open = bcm43xx_net_open;
4384 net_dev->stop = bcm43xx_net_stop;
4385 net_dev->get_stats = bcm43xx_net_get_stats;
4386 net_dev->tx_timeout = bcm43xx_net_tx_timeout;
4387 #ifdef CONFIG_NET_POLL_CONTROLLER
4388 net_dev->poll_controller = bcm43xx_net_poll_controller;
4389 #endif
4390 net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
4391 net_dev->irq = pdev->irq;
4392 net_dev->watchdog_timeo = BCM43xx_TX_TIMEOUT;
4394 /* initialize the bcm43xx_private struct */
4395 bcm = bcm43xx_priv(net_dev);
4396 memset(bcm, 0, sizeof(*bcm));
4397 wq = create_workqueue(DRV_NAME "_wq");
4398 if (!wq) {
4399 err = -ENOMEM;
4400 goto err_free_netdev;
4402 bcm43xx_init_private(bcm, net_dev, pdev, wq);
4404 pci_set_drvdata(pdev, net_dev);
4406 err = bcm43xx_attach_board(bcm);
4407 if (err)
4408 goto err_destroy_wq;
4410 err = register_netdev(net_dev);
4411 if (err) {
4412 printk(KERN_ERR PFX "Cannot register net device, "
4413 "aborting.\n");
4414 err = -ENOMEM;
4415 goto err_detach_board;
4418 bcm43xx_debugfs_add_device(bcm);
4420 assert(err == 0);
4421 out:
4422 return err;
4424 err_detach_board:
4425 bcm43xx_detach_board(bcm);
4426 err_destroy_wq:
4427 destroy_workqueue(wq);
4428 err_free_netdev:
4429 free_ieee80211softmac(net_dev);
4430 goto out;
4433 static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
4435 struct net_device *net_dev = pci_get_drvdata(pdev);
4436 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4438 bcm43xx_debugfs_remove_device(bcm);
4439 unregister_netdev(net_dev);
4440 bcm43xx_detach_board(bcm);
4441 assert(bcm->ucode == NULL);
4442 destroy_workqueue(bcm->workqueue);
4443 free_ieee80211softmac(net_dev);
4446 /* Hard-reset the chip. Do not call this directly.
4447 * Use bcm43xx_controller_restart()
4449 static void bcm43xx_chip_reset(void *_bcm)
4451 struct bcm43xx_private *bcm = _bcm;
4452 struct net_device *net_dev = bcm->net_dev;
4453 struct pci_dev *pci_dev = bcm->pci_dev;
4454 struct workqueue_struct *wq = bcm->workqueue;
4455 int err;
4456 int was_initialized = bcm->initialized;
4458 netif_stop_queue(bcm->net_dev);
4459 tasklet_disable(&bcm->isr_tasklet);
4461 bcm->firmware_norelease = 1;
4462 if (was_initialized)
4463 bcm43xx_free_board(bcm);
4464 bcm->firmware_norelease = 0;
4465 bcm43xx_detach_board(bcm);
4466 bcm43xx_init_private(bcm, net_dev, pci_dev, wq);
4467 err = bcm43xx_attach_board(bcm);
4468 if (err)
4469 goto failure;
4470 if (was_initialized) {
4471 err = bcm43xx_init_board(bcm);
4472 if (err)
4473 goto failure;
4475 netif_wake_queue(bcm->net_dev);
4476 printk(KERN_INFO PFX "Controller restarted\n");
4478 return;
4479 failure:
4480 printk(KERN_ERR PFX "Controller restart failed\n");
4483 /* Hard-reset the chip.
4484 * This can be called from interrupt or process context.
4485 * Make sure to _not_ re-enable device interrupts after this has been called.
4487 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
4489 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
4490 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
4491 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
4492 queue_work(bcm->workqueue, &bcm->restart_work);
4495 #ifdef CONFIG_PM
4497 static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
4499 struct net_device *net_dev = pci_get_drvdata(pdev);
4500 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4501 unsigned long flags;
4502 int try_to_shutdown = 0, err;
4504 dprintk(KERN_INFO PFX "Suspending...\n");
4506 spin_lock_irqsave(&bcm->lock, flags);
4507 bcm->was_initialized = bcm->initialized;
4508 if (bcm->initialized)
4509 try_to_shutdown = 1;
4510 spin_unlock_irqrestore(&bcm->lock, flags);
4512 netif_device_detach(net_dev);
4513 if (try_to_shutdown) {
4514 ieee80211softmac_stop(net_dev);
4515 err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate);
4516 if (unlikely(err)) {
4517 dprintk(KERN_ERR PFX "Suspend failed.\n");
4518 return -EAGAIN;
4520 bcm->firmware_norelease = 1;
4521 bcm43xx_free_board(bcm);
4522 bcm->firmware_norelease = 0;
4524 bcm43xx_chipset_detach(bcm);
4526 pci_save_state(pdev);
4527 pci_disable_device(pdev);
4528 pci_set_power_state(pdev, pci_choose_state(pdev, state));
4530 dprintk(KERN_INFO PFX "Device suspended.\n");
4532 return 0;
4535 static int bcm43xx_resume(struct pci_dev *pdev)
4537 struct net_device *net_dev = pci_get_drvdata(pdev);
4538 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4539 int err = 0;
4541 dprintk(KERN_INFO PFX "Resuming...\n");
4543 pci_set_power_state(pdev, 0);
4544 pci_enable_device(pdev);
4545 pci_restore_state(pdev);
4547 bcm43xx_chipset_attach(bcm);
4548 if (bcm->was_initialized) {
4549 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
4550 err = bcm43xx_init_board(bcm);
4552 if (err) {
4553 printk(KERN_ERR PFX "Resume failed!\n");
4554 return err;
4557 netif_device_attach(net_dev);
4559 /*FIXME: This should be handled by softmac instead. */
4560 schedule_work(&bcm->softmac->associnfo.work);
4562 dprintk(KERN_INFO PFX "Device resumed.\n");
4564 return 0;
4567 #endif /* CONFIG_PM */
4569 static struct pci_driver bcm43xx_pci_driver = {
4570 .name = BCM43xx_DRIVER_NAME,
4571 .id_table = bcm43xx_pci_tbl,
4572 .probe = bcm43xx_init_one,
4573 .remove = __devexit_p(bcm43xx_remove_one),
4574 #ifdef CONFIG_PM
4575 .suspend = bcm43xx_suspend,
4576 .resume = bcm43xx_resume,
4577 #endif /* CONFIG_PM */
4580 static int __init bcm43xx_init(void)
4582 printk(KERN_INFO BCM43xx_DRIVER_NAME "\n");
4583 bcm43xx_debugfs_init();
4584 return pci_register_driver(&bcm43xx_pci_driver);
4587 static void __exit bcm43xx_exit(void)
4589 pci_unregister_driver(&bcm43xx_pci_driver);
4590 bcm43xx_debugfs_exit();
4593 module_init(bcm43xx_init)
4594 module_exit(bcm43xx_exit)
4596 /* vim: set ts=8 sw=8 sts=8: */