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