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