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