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