aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@kernel.org>2008-03-04 18:26:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-13 16:01:04 -0400
commit2079fcdc06ea01c084044c348dbcd7b3e335ad49 (patch)
tree5571610add4241c6184dbe327c42ad6a0a8ca06a /drivers/net
parentaffe0a02189eeec43757993b1ccb65f24e39afa5 (diff)
the scheduled bcm43xx removal
Signed-off-by: Adrian Bunk <bunk@kernel.org> Cc: <Larry.Finger@lwfinger.net> Cc: <stefano.brivio@polimi.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/bcm43xx/Kconfig70
-rw-r--r--drivers/net/wireless/bcm43xx/Makefile12
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h997
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c556
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h118
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c1263
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h386
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c50
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ilt.c352
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ilt.h33
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.c307
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.h62
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c4281
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h133
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2346
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.h78
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c674
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.h163
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.c393
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.h56
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.c2170
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.h115
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c471
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h9
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c1035
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.h36
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c565
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.h150
31 files changed, 0 insertions, 16891 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 3c3ef966c95b..f4ca6fd4a29f 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -741,7 +741,6 @@ config P54_PCI
741source "drivers/net/wireless/ath5k/Kconfig" 741source "drivers/net/wireless/ath5k/Kconfig"
742source "drivers/net/wireless/iwlwifi/Kconfig" 742source "drivers/net/wireless/iwlwifi/Kconfig"
743source "drivers/net/wireless/hostap/Kconfig" 743source "drivers/net/wireless/hostap/Kconfig"
744source "drivers/net/wireless/bcm43xx/Kconfig"
745source "drivers/net/wireless/b43/Kconfig" 744source "drivers/net/wireless/b43/Kconfig"
746source "drivers/net/wireless/b43legacy/Kconfig" 745source "drivers/net/wireless/b43legacy/Kconfig"
747source "drivers/net/wireless/zd1211rw/Kconfig" 746source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 091dfe2e574e..dd3899747b5c 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
35obj-$(CONFIG_PRISM54) += prism54/ 35obj-$(CONFIG_PRISM54) += prism54/
36 36
37obj-$(CONFIG_HOSTAP) += hostap/ 37obj-$(CONFIG_HOSTAP) += hostap/
38obj-$(CONFIG_BCM43XX) += bcm43xx/
39obj-$(CONFIG_B43) += b43/ 38obj-$(CONFIG_B43) += b43/
40obj-$(CONFIG_B43LEGACY) += b43legacy/ 39obj-$(CONFIG_B43LEGACY) += b43legacy/
41obj-$(CONFIG_ZD1211RW) += zd1211rw/ 40obj-$(CONFIG_ZD1211RW) += zd1211rw/
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
deleted file mode 100644
index afb8f4305c24..000000000000
--- a/drivers/net/wireless/bcm43xx/Kconfig
+++ /dev/null
@@ -1,70 +0,0 @@
1config BCM43XX
2 tristate "Broadcom BCM43xx wireless support (DEPRECATED)"
3 depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL
4 select WIRELESS_EXT
5 select FW_LOADER
6 select HW_RANDOM
7 ---help---
8 This is an experimental driver for the Broadcom 43xx wireless
9 chip, found in the Apple Airport Extreme and various other
10 devices. This driver is deprecated and will be removed
11 from the kernel in the near future. It has been replaced
12 by the b43 and b43legacy drivers.
13
14config BCM43XX_DEBUG
15 bool "Broadcom BCM43xx debugging (RECOMMENDED)"
16 depends on BCM43XX
17 default y
18 ---help---
19 Broadcom 43xx debugging messages.
20 Say Y, because the driver is still very experimental and
21 this will help you get it running.
22
23config BCM43XX_DMA
24 bool
25 depends on BCM43XX
26
27config BCM43XX_PIO
28 bool
29 depends on BCM43XX
30
31choice
32 prompt "BCM43xx data transfer mode"
33 depends on BCM43XX
34 default BCM43XX_DMA_AND_PIO_MODE
35
36config BCM43XX_DMA_AND_PIO_MODE
37 bool "DMA + PIO"
38 select BCM43XX_DMA
39 select BCM43XX_PIO
40 ---help---
41 Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
42 data transfer modes.
43 The actually used mode is selectable through the module
44 parameter "pio". If the module parameter is pio=0, DMA is used.
45 Otherwise PIO is used. DMA is default.
46
47 If unsure, choose this option.
48
49config BCM43XX_DMA_MODE
50 bool "DMA (Direct Memory Access) only"
51 select BCM43XX_DMA
52 ---help---
53 Only include Direct Memory Access (DMA).
54 This reduces the size of the driver module, by omitting the PIO code.
55
56config BCM43XX_PIO_MODE
57 bool "PIO (Programmed I/O) only"
58 select BCM43XX_PIO
59 ---help---
60 Only include Programmed I/O (PIO).
61 This reduces the size of the driver module, by omitting the DMA code.
62 Please note that PIO transfers are slow (compared to DMA).
63
64 Also note that not all devices of the 43xx series support PIO.
65 The 4306 (Apple Airport Extreme and others) supports PIO, while
66 the 4318 is known to _not_ support PIO.
67
68 Only use PIO, if DMA does not work for you.
69
70endchoice
diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
deleted file mode 100644
index bb5220c629d2..000000000000
--- a/drivers/net/wireless/bcm43xx/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
1obj-$(CONFIG_BCM43XX) += bcm43xx.o
2bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
3
4bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
5bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
6
7bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
8 bcm43xx_radio.o bcm43xx_phy.o \
9 bcm43xx_power.o bcm43xx_wx.o \
10 bcm43xx_leds.o bcm43xx_ethtool.o \
11 bcm43xx_xmit.o bcm43xx_sysfs.o \
12 $(bcm43xx-obj-y)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
deleted file mode 100644
index 2ebd2edf5862..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ /dev/null
@@ -1,997 +0,0 @@
1#ifndef BCM43xx_H_
2#define BCM43xx_H_
3
4#include <linux/hw_random.h>
5#include <linux/version.h>
6#include <linux/kernel.h>
7#include <linux/spinlock.h>
8#include <linux/interrupt.h>
9#include <linux/stringify.h>
10#include <linux/pci.h>
11#include <net/ieee80211.h>
12#include <net/ieee80211softmac.h>
13#include <asm/atomic.h>
14#include <asm/io.h>
15
16
17#include "bcm43xx_debugfs.h"
18#include "bcm43xx_leds.h"
19
20
21#define PFX KBUILD_MODNAME ": "
22
23#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50
24#define BCM43xx_IRQWAIT_MAX_RETRIES 100
25
26#define BCM43xx_IO_SIZE 8192
27
28/* Active Core PCI Configuration Register. */
29#define BCM43xx_PCICFG_ACTIVE_CORE 0x80
30/* SPROM control register. */
31#define BCM43xx_PCICFG_SPROMCTL 0x88
32/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
33#define BCM43xx_PCICFG_ICR 0x94
34
35/* MMIO offsets */
36#define BCM43xx_MMIO_DMA0_REASON 0x20
37#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24
38#define BCM43xx_MMIO_DMA1_REASON 0x28
39#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C
40#define BCM43xx_MMIO_DMA2_REASON 0x30
41#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34
42#define BCM43xx_MMIO_DMA3_REASON 0x38
43#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C
44#define BCM43xx_MMIO_DMA4_REASON 0x40
45#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44
46#define BCM43xx_MMIO_DMA5_REASON 0x48
47#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C
48#define BCM43xx_MMIO_STATUS_BITFIELD 0x120
49#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124
50#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128
51#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C
52#define BCM43xx_MMIO_RAM_CONTROL 0x130
53#define BCM43xx_MMIO_RAM_DATA 0x134
54#define BCM43xx_MMIO_PS_STATUS 0x140
55#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158
56#define BCM43xx_MMIO_SHM_CONTROL 0x160
57#define BCM43xx_MMIO_SHM_DATA 0x164
58#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166
59#define BCM43xx_MMIO_XMITSTAT_0 0x170
60#define BCM43xx_MMIO_XMITSTAT_1 0x174
61#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
62#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
63
64/* 32-bit DMA */
65#define BCM43xx_MMIO_DMA32_BASE0 0x200
66#define BCM43xx_MMIO_DMA32_BASE1 0x220
67#define BCM43xx_MMIO_DMA32_BASE2 0x240
68#define BCM43xx_MMIO_DMA32_BASE3 0x260
69#define BCM43xx_MMIO_DMA32_BASE4 0x280
70#define BCM43xx_MMIO_DMA32_BASE5 0x2A0
71/* 64-bit DMA */
72#define BCM43xx_MMIO_DMA64_BASE0 0x200
73#define BCM43xx_MMIO_DMA64_BASE1 0x240
74#define BCM43xx_MMIO_DMA64_BASE2 0x280
75#define BCM43xx_MMIO_DMA64_BASE3 0x2C0
76#define BCM43xx_MMIO_DMA64_BASE4 0x300
77#define BCM43xx_MMIO_DMA64_BASE5 0x340
78/* PIO */
79#define BCM43xx_MMIO_PIO1_BASE 0x300
80#define BCM43xx_MMIO_PIO2_BASE 0x310
81#define BCM43xx_MMIO_PIO3_BASE 0x320
82#define BCM43xx_MMIO_PIO4_BASE 0x330
83
84#define BCM43xx_MMIO_PHY_VER 0x3E0
85#define BCM43xx_MMIO_PHY_RADIO 0x3E2
86#define BCM43xx_MMIO_ANTENNA 0x3E8
87#define BCM43xx_MMIO_CHANNEL 0x3F0
88#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4
89#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6
90#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8
91#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA
92#define BCM43xx_MMIO_PHY_CONTROL 0x3FC
93#define BCM43xx_MMIO_PHY_DATA 0x3FE
94#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420
95#define BCM43xx_MMIO_MACFILTER_DATA 0x422
96#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A
97#define BCM43xx_MMIO_GPIO_CONTROL 0x49C
98#define BCM43xx_MMIO_GPIO_MASK 0x49E
99#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */
100#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */
101#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */
102#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */
103#define BCM43xx_MMIO_RNG 0x65A
104#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8
105
106/* SPROM offsets. */
107#define BCM43xx_SPROM_BASE 0x1000
108#define BCM43xx_SPROM_BOARDFLAGS2 0x1c
109#define BCM43xx_SPROM_IL0MACADDR 0x24
110#define BCM43xx_SPROM_ET0MACADDR 0x27
111#define BCM43xx_SPROM_ET1MACADDR 0x2a
112#define BCM43xx_SPROM_ETHPHY 0x2d
113#define BCM43xx_SPROM_BOARDREV 0x2e
114#define BCM43xx_SPROM_PA0B0 0x2f
115#define BCM43xx_SPROM_PA0B1 0x30
116#define BCM43xx_SPROM_PA0B2 0x31
117#define BCM43xx_SPROM_WL0GPIO0 0x32
118#define BCM43xx_SPROM_WL0GPIO2 0x33
119#define BCM43xx_SPROM_MAXPWR 0x34
120#define BCM43xx_SPROM_PA1B0 0x35
121#define BCM43xx_SPROM_PA1B1 0x36
122#define BCM43xx_SPROM_PA1B2 0x37
123#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38
124#define BCM43xx_SPROM_BOARDFLAGS 0x39
125#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a
126#define BCM43xx_SPROM_VERSION 0x3f
127
128/* BCM43xx_SPROM_BOARDFLAGS values */
129#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
130#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
131#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */
132#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */
133#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */
134#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */
135#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */
136#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */
137#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */
138#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */
139#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */
140#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */
141#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */
142#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */
143#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
144#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
145
146/* GPIO register offset, in both ChipCommon and PCI core. */
147#define BCM43xx_GPIO_CONTROL 0x6c
148
149/* SHM Routing */
150#define BCM43xx_SHM_SHARED 0x0001
151#define BCM43xx_SHM_WIRELESS 0x0002
152#define BCM43xx_SHM_PCM 0x0003
153#define BCM43xx_SHM_HWMAC 0x0004
154#define BCM43xx_SHM_UCODE 0x0300
155
156/* MacFilter offsets. */
157#define BCM43xx_MACFILTER_SELF 0x0000
158#define BCM43xx_MACFILTER_ASSOC 0x0003
159
160/* Chipcommon registers. */
161#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
162#define BCM43xx_CHIPCOMMON_CTL 0x28
163#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
164#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
165#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
166#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0
167
168/* PCI core specific registers. */
169#define BCM43xx_PCICORE_BCAST_ADDR 0x50
170#define BCM43xx_PCICORE_BCAST_DATA 0x54
171#define BCM43xx_PCICORE_SBTOPCI2 0x108
172
173/* SBTOPCI2 values. */
174#define BCM43xx_SBTOPCI2_PREFETCH 0x4
175#define BCM43xx_SBTOPCI2_BURST 0x8
176#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20
177
178/* PCI-E core registers. */
179#define BCM43xx_PCIECORE_REG_ADDR 0x0130
180#define BCM43xx_PCIECORE_REG_DATA 0x0134
181#define BCM43xx_PCIECORE_MDIO_CTL 0x0128
182#define BCM43xx_PCIECORE_MDIO_DATA 0x012C
183
184/* PCI-E registers. */
185#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004
186#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100
187
188/* PCI-E MDIO bits. */
189#define BCM43xx_PCIE_MDIO_ST 0x40000000
190#define BCM43xx_PCIE_MDIO_WT 0x10000000
191#define BCM43xx_PCIE_MDIO_DEV 22
192#define BCM43xx_PCIE_MDIO_REG 18
193#define BCM43xx_PCIE_MDIO_TA 0x00020000
194#define BCM43xx_PCIE_MDIO_TC 0x0100
195
196/* MDIO devices. */
197#define BCM43xx_MDIO_SERDES_RX 0x1F
198
199/* SERDES RX registers. */
200#define BCM43xx_SERDES_RXTIMER 0x2
201#define BCM43xx_SERDES_CDR 0x6
202#define BCM43xx_SERDES_CDR_BW 0x7
203
204/* Chipcommon capabilities. */
205#define BCM43xx_CAPABILITIES_PCTL 0x00040000
206#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000
207#define BCM43xx_CAPABILITIES_PLLSHIFT 16
208#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700
209#define BCM43xx_CAPABILITIES_FLASHSHIFT 8
210#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040
211#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020
212#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018
213#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3
214#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004
215#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003
216
217/* PowerControl */
218#define BCM43xx_PCTL_IN 0xB0
219#define BCM43xx_PCTL_OUT 0xB4
220#define BCM43xx_PCTL_OUTENABLE 0xB8
221#define BCM43xx_PCTL_XTAL_POWERUP 0x40
222#define BCM43xx_PCTL_PLL_POWERDOWN 0x80
223
224/* PowerControl Clock Modes */
225#define BCM43xx_PCTL_CLK_FAST 0x00
226#define BCM43xx_PCTL_CLK_SLOW 0x01
227#define BCM43xx_PCTL_CLK_DYNAMIC 0x02
228
229#define BCM43xx_PCTL_FORCE_SLOW 0x0800
230#define BCM43xx_PCTL_FORCE_PLL 0x1000
231#define BCM43xx_PCTL_DYN_XTAL 0x2000
232
233/* COREIDs */
234#define BCM43xx_COREID_CHIPCOMMON 0x800
235#define BCM43xx_COREID_ILINE20 0x801
236#define BCM43xx_COREID_SDRAM 0x803
237#define BCM43xx_COREID_PCI 0x804
238#define BCM43xx_COREID_MIPS 0x805
239#define BCM43xx_COREID_ETHERNET 0x806
240#define BCM43xx_COREID_V90 0x807
241#define BCM43xx_COREID_USB11_HOSTDEV 0x80a
242#define BCM43xx_COREID_IPSEC 0x80b
243#define BCM43xx_COREID_PCMCIA 0x80d
244#define BCM43xx_COREID_EXT_IF 0x80f
245#define BCM43xx_COREID_80211 0x812
246#define BCM43xx_COREID_MIPS_3302 0x816
247#define BCM43xx_COREID_USB11_HOST 0x817
248#define BCM43xx_COREID_USB11_DEV 0x818
249#define BCM43xx_COREID_USB20_HOST 0x819
250#define BCM43xx_COREID_USB20_DEV 0x81a
251#define BCM43xx_COREID_SDIO_HOST 0x81b
252#define BCM43xx_COREID_PCIE 0x820
253
254/* Core Information Registers */
255#define BCM43xx_CIR_BASE 0xf00
256#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18)
257#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90)
258#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94)
259#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98)
260#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c)
261#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8)
262#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc)
263
264/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
265#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f
266
267/* SBIMCONFIGLOW values/masks. */
268#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007
269#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0
270#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070
271#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4
272#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000
273#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16
274
275/* sbtmstatelow state flags */
276#define BCM43xx_SBTMSTATELOW_RESET 0x01
277#define BCM43xx_SBTMSTATELOW_REJECT 0x02
278#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000
279#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000
280#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE 0x20000000
281
282/* sbtmstatehigh state flags */
283#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001
284#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004
285#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020
286#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL 0x00010000
287#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL 0x00020000
288#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000
289#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000
290#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000
291#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000
292#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000
293
294/* sbimstate flags */
295#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000
296#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000
297
298/* PHYVersioning */
299#define BCM43xx_PHYTYPE_A 0x00
300#define BCM43xx_PHYTYPE_B 0x01
301#define BCM43xx_PHYTYPE_G 0x02
302
303/* PHYRegisters */
304#define BCM43xx_PHY_ILT_A_CTRL 0x0072
305#define BCM43xx_PHY_ILT_A_DATA1 0x0073
306#define BCM43xx_PHY_ILT_A_DATA2 0x0074
307#define BCM43xx_PHY_G_LO_CONTROL 0x0810
308#define BCM43xx_PHY_ILT_G_CTRL 0x0472
309#define BCM43xx_PHY_ILT_G_DATA1 0x0473
310#define BCM43xx_PHY_ILT_G_DATA2 0x0474
311#define BCM43xx_PHY_A_PCTL 0x007B
312#define BCM43xx_PHY_G_PCTL 0x0029
313#define BCM43xx_PHY_A_CRS 0x0029
314#define BCM43xx_PHY_RADIO_BITFIELD 0x0401
315#define BCM43xx_PHY_G_CRS 0x0429
316#define BCM43xx_PHY_NRSSILT_CTRL 0x0803
317#define BCM43xx_PHY_NRSSILT_DATA 0x0804
318
319/* RadioRegisters */
320#define BCM43xx_RADIOCTL_ID 0x01
321
322/* StatusBitField */
323#define BCM43xx_SBF_MAC_ENABLED 0x00000001
324#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/
325#define BCM43xx_SBF_CORE_READY 0x00000004
326#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/
327#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/
328#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/
329#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000
330#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000
331#define BCM43xx_SBF_MODE_AP 0x00040000
332#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000
333#define BCM43xx_SBF_MODE_MONITOR 0x00400000
334#define BCM43xx_SBF_MODE_PROMISC 0x01000000
335#define BCM43xx_SBF_PS1 0x02000000
336#define BCM43xx_SBF_PS2 0x04000000
337#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000
338#define BCM43xx_SBF_TIME_UPDATE 0x10000000
339#define BCM43xx_SBF_MODE_G 0x80000000
340
341/* Microcode */
342#define BCM43xx_UCODE_REVISION 0x0000
343#define BCM43xx_UCODE_PATCHLEVEL 0x0002
344#define BCM43xx_UCODE_DATE 0x0004
345#define BCM43xx_UCODE_TIME 0x0006
346#define BCM43xx_UCODE_STATUS 0x0040
347
348/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
349#define BCM43xx_UCODEFLAGS_OFFSET 0x005E
350
351#define BCM43xx_UCODEFLAG_AUTODIV 0x0001
352#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002
353#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004
354#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020
355#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040
356#define BCM43xx_UCODEFLAG_JAPAN 0x0080
357
358/* Hardware Radio Enable masks */
359#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
360#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
361
362/* Generic-Interrupt reasons. */
363#define BCM43xx_IRQ_READY (1 << 0)
364#define BCM43xx_IRQ_BEACON (1 << 1)
365#define BCM43xx_IRQ_PS (1 << 2)
366#define BCM43xx_IRQ_REG124 (1 << 5)
367#define BCM43xx_IRQ_PMQ (1 << 6)
368#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8)
369#define BCM43xx_IRQ_XMIT_ERROR (1 << 11)
370#define BCM43xx_IRQ_RX (1 << 15)
371#define BCM43xx_IRQ_SCAN (1 << 16)
372#define BCM43xx_IRQ_NOISE (1 << 18)
373#define BCM43xx_IRQ_XMIT_STATUS (1 << 29)
374
375#define BCM43xx_IRQ_ALL 0xffffffff
376#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \
377 BCM43xx_IRQ_REG124 | \
378 BCM43xx_IRQ_PMQ | \
379 BCM43xx_IRQ_XMIT_ERROR | \
380 BCM43xx_IRQ_RX | \
381 BCM43xx_IRQ_SCAN | \
382 BCM43xx_IRQ_NOISE | \
383 BCM43xx_IRQ_XMIT_STATUS)
384
385
386/* Initial default iw_mode */
387#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA
388
389/* Bus type PCI. */
390#define BCM43xx_BUSTYPE_PCI 0
391/* Bus type Silicone Backplane Bus. */
392#define BCM43xx_BUSTYPE_SB 1
393/* Bus type PCMCIA. */
394#define BCM43xx_BUSTYPE_PCMCIA 2
395
396/* Threshold values. */
397#define BCM43xx_MIN_RTS_THRESHOLD 1U
398#define BCM43xx_MAX_RTS_THRESHOLD 2304U
399#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD
400
401#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7
402#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4
403
404/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
405#define RX_RSSI_MAX 60
406
407/* Max size of a security key */
408#define BCM43xx_SEC_KEYSIZE 16
409/* Security algorithms. */
410enum {
411 BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
412 BCM43xx_SEC_ALGO_WEP,
413 BCM43xx_SEC_ALGO_UNKNOWN,
414 BCM43xx_SEC_ALGO_AES,
415 BCM43xx_SEC_ALGO_WEP104,
416 BCM43xx_SEC_ALGO_TKIP,
417};
418
419#ifdef assert
420# undef assert
421#endif
422#ifdef CONFIG_BCM43XX_DEBUG
423#define assert(expr) \
424 do { \
425 if (unlikely(!(expr))) { \
426 printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \
427 #expr, __FILE__, __LINE__, __FUNCTION__); \
428 } \
429 } while (0)
430#else
431#define assert(expr) do { /* nothing */ } while (0)
432#endif
433
434/* rate limited printk(). */
435#ifdef printkl
436# undef printkl
437#endif
438#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
439/* rate limited printk() for debugging */
440#ifdef dprintkl
441# undef dprintkl
442#endif
443#ifdef CONFIG_BCM43XX_DEBUG
444# define dprintkl printkl
445#else
446# define dprintkl(f, x...) do { /* nothing */ } while (0)
447#endif
448
449/* Helper macro for if branches.
450 * An if branch marked with this macro is only taken in DEBUG mode.
451 * Example:
452 * if (DEBUG_ONLY(foo == bar)) {
453 * do something
454 * }
455 * In DEBUG mode, the branch will be taken if (foo == bar).
456 * In non-DEBUG mode, the branch will never be taken.
457 */
458#ifdef DEBUG_ONLY
459# undef DEBUG_ONLY
460#endif
461#ifdef CONFIG_BCM43XX_DEBUG
462# define DEBUG_ONLY(x) (x)
463#else
464# define DEBUG_ONLY(x) 0
465#endif
466
467/* debugging printk() */
468#ifdef dprintk
469# undef dprintk
470#endif
471#ifdef CONFIG_BCM43XX_DEBUG
472# define dprintk(f, x...) do { printk(f ,##x); } while (0)
473#else
474# define dprintk(f, x...) do { /* nothing */ } while (0)
475#endif
476
477
478struct net_device;
479struct pci_dev;
480struct bcm43xx_dmaring;
481struct bcm43xx_pioqueue;
482
483struct bcm43xx_initval {
484 __be16 offset;
485 __be16 size;
486 __be32 value;
487} __attribute__((__packed__));
488
489/* Values for bcm430x_sprominfo.locale */
490enum {
491 BCM43xx_LOCALE_WORLD = 0,
492 BCM43xx_LOCALE_THAILAND,
493 BCM43xx_LOCALE_ISRAEL,
494 BCM43xx_LOCALE_JORDAN,
495 BCM43xx_LOCALE_CHINA,
496 BCM43xx_LOCALE_JAPAN,
497 BCM43xx_LOCALE_USA_CANADA_ANZ,
498 BCM43xx_LOCALE_EUROPE,
499 BCM43xx_LOCALE_USA_LOW,
500 BCM43xx_LOCALE_JAPAN_HIGH,
501 BCM43xx_LOCALE_ALL,
502 BCM43xx_LOCALE_NONE,
503};
504
505#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */
506struct bcm43xx_sprominfo {
507 u16 boardflags2;
508 u8 il0macaddr[6];
509 u8 et0macaddr[6];
510 u8 et1macaddr[6];
511 u8 et0phyaddr:5;
512 u8 et1phyaddr:5;
513 u8 boardrev;
514 u8 locale:4;
515 u8 antennas_aphy:2;
516 u8 antennas_bgphy:2;
517 u16 pa0b0;
518 u16 pa0b1;
519 u16 pa0b2;
520 u8 wl0gpio0;
521 u8 wl0gpio1;
522 u8 wl0gpio2;
523 u8 wl0gpio3;
524 u8 maxpower_aphy;
525 u8 maxpower_bgphy;
526 u16 pa1b0;
527 u16 pa1b1;
528 u16 pa1b2;
529 u8 idle_tssi_tgt_aphy;
530 u8 idle_tssi_tgt_bgphy;
531 u16 boardflags;
532 u16 antennagain_aphy;
533 u16 antennagain_bgphy;
534};
535
536/* Value pair to measure the LocalOscillator. */
537struct bcm43xx_lopair {
538 s8 low;
539 s8 high;
540 u8 used:1;
541};
542#define BCM43xx_LO_COUNT (14*4)
543
544struct bcm43xx_phyinfo {
545 /* Hardware Data */
546 u8 analog;
547 u8 type;
548 u8 rev;
549 u16 antenna_diversity;
550 u16 savedpctlreg;
551 u16 minlowsig[2];
552 u16 minlowsigpos[2];
553 u8 connected:1,
554 calibrated:1,
555 is_locked:1, /* used in bcm43xx_phy_{un}lock() */
556 dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
557 /* LO Measurement Data.
558 * Use bcm43xx_get_lopair() to get a value.
559 */
560 struct bcm43xx_lopair *_lo_pairs;
561
562 /* TSSI to dBm table in use */
563 const s8 *tssi2dbm;
564 /* idle TSSI value */
565 s8 idle_tssi;
566
567 /* Values from bcm43xx_calc_loopback_gain() */
568 u16 loopback_gain[2];
569
570 /* PHY lock for core.rev < 3
571 * This lock is only used by bcm43xx_phy_{un}lock()
572 */
573 spinlock_t lock;
574
575 /* Firmware. */
576 const struct firmware *ucode;
577 const struct firmware *pcm;
578 const struct firmware *initvals0;
579 const struct firmware *initvals1;
580};
581
582
583struct bcm43xx_radioinfo {
584 u16 manufact;
585 u16 version;
586 u8 revision;
587
588 /* Desired TX power in dBm Q5.2 */
589 u16 txpower_desired;
590 /* TX Power control values. */
591 union {
592 /* B/G PHY */
593 struct {
594 u16 baseband_atten;
595 u16 radio_atten;
596 u16 txctl1;
597 u16 txctl2;
598 };
599 /* A PHY */
600 struct {
601 u16 txpwr_offset;
602 };
603 };
604
605 /* Current Interference Mitigation mode */
606 int interfmode;
607 /* Stack of saved values from the Interference Mitigation code.
608 * Each value in the stack is layed out as follows:
609 * bit 0-11: offset
610 * bit 12-15: register ID
611 * bit 16-32: value
612 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
613 */
614#define BCM43xx_INTERFSTACK_SIZE 26
615 u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
616
617 /* Saved values from the NRSSI Slope calculation */
618 s16 nrssi[2];
619 s32 nrssislope;
620 /* In memory nrssi lookup table. */
621 s8 nrssi_lt[64];
622
623 /* current channel */
624 u8 channel;
625 u8 initial_channel;
626
627 u16 lofcal;
628
629 u16 initval;
630
631 u8 enabled:1;
632 /* ACI (adjacent channel interference) flags. */
633 u8 aci_enable:1,
634 aci_wlan_automatic:1,
635 aci_hw_rssi:1;
636};
637
638/* Data structures for DMA transmission, per 80211 core. */
639struct bcm43xx_dma {
640 struct bcm43xx_dmaring *tx_ring0;
641 struct bcm43xx_dmaring *tx_ring1;
642 struct bcm43xx_dmaring *tx_ring2;
643 struct bcm43xx_dmaring *tx_ring3;
644 struct bcm43xx_dmaring *tx_ring4;
645 struct bcm43xx_dmaring *tx_ring5;
646
647 struct bcm43xx_dmaring *rx_ring0;
648 struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */
649};
650
651/* Data structures for PIO transmission, per 80211 core. */
652struct bcm43xx_pio {
653 struct bcm43xx_pioqueue *queue0;
654 struct bcm43xx_pioqueue *queue1;
655 struct bcm43xx_pioqueue *queue2;
656 struct bcm43xx_pioqueue *queue3;
657};
658
659#define BCM43xx_MAX_80211_CORES 2
660
661/* Generic information about a core. */
662struct bcm43xx_coreinfo {
663 u8 available:1,
664 enabled:1,
665 initialized:1;
666 /** core_rev revision number */
667 u8 rev;
668 /** Index number for _switch_core() */
669 u8 index;
670 /** core_id ID number */
671 u16 id;
672 /** Core-specific data. */
673 void *priv;
674};
675
676/* Additional information for each 80211 core. */
677struct bcm43xx_coreinfo_80211 {
678 /* PHY device. */
679 struct bcm43xx_phyinfo phy;
680 /* Radio device. */
681 struct bcm43xx_radioinfo radio;
682 union {
683 /* DMA context. */
684 struct bcm43xx_dma dma;
685 /* PIO context. */
686 struct bcm43xx_pio pio;
687 };
688};
689
690/* Context information for a noise calculation (Link Quality). */
691struct bcm43xx_noise_calculation {
692 struct bcm43xx_coreinfo *core_at_start;
693 u8 channel_at_start;
694 u8 calculation_running:1;
695 u8 nr_samples;
696 s8 samples[8][4];
697};
698
699struct bcm43xx_stats {
700 u8 noise;
701 struct iw_statistics wstats;
702 /* Store the last TX/RX times here for updating the leds. */
703 unsigned long last_tx;
704 unsigned long last_rx;
705};
706
707struct bcm43xx_key {
708 u8 enabled:1;
709 u8 algorithm;
710};
711
712/* Driver initialization status. */
713enum {
714 BCM43xx_STAT_UNINIT, /* Uninitialized. */
715 BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */
716 BCM43xx_STAT_INITIALIZED, /* Fully operational. */
717 BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */
718 BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
719};
720#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
721#define bcm43xx_set_status(bcm, stat) do { \
722 atomic_set(&(bcm)->init_status, (stat)); \
723 smp_wmb(); \
724 } while (0)
725
726/* *** THEORY OF LOCKING ***
727 *
728 * We have two different locks in the bcm43xx driver.
729 * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
730 * and the device registers. This mutex does _not_ protect
731 * against concurrency from the IRQ handler.
732 * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
733 *
734 * Please note that, if you only take the irq_lock, you are not protected
735 * against concurrency from the periodic work handlers.
736 * Most times you want to take _both_ locks.
737 */
738
739struct bcm43xx_private {
740 struct ieee80211_device *ieee;
741 struct ieee80211softmac_device *softmac;
742
743 struct net_device *net_dev;
744 struct pci_dev *pci_dev;
745 unsigned int irq;
746
747 void __iomem *mmio_addr;
748
749 spinlock_t irq_lock;
750 struct mutex mutex;
751
752 /* Driver initialization status BCM43xx_STAT_*** */
753 atomic_t init_status;
754
755 u16 was_initialized:1, /* for PCI suspend/resume. */
756 __using_pio:1, /* Internal, use bcm43xx_using_pio(). */
757 bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
758 reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
759 short_preamble:1, /* TRUE, if short preamble is enabled. */
760 firmware_norelease:1, /* Do not release the firmware. Used on suspend. */
761 radio_hw_enable:1; /* TRUE if radio is hardware enabled */
762
763 struct bcm43xx_stats stats;
764
765 /* Bus type we are connected to.
766 * This is currently always BCM43xx_BUSTYPE_PCI
767 */
768 u8 bustype;
769 u64 dma_mask;
770
771 u16 board_vendor;
772 u16 board_type;
773 u16 board_revision;
774
775 u16 chip_id;
776 u8 chip_rev;
777 u8 chip_package;
778
779 struct bcm43xx_sprominfo sprom;
780#define BCM43xx_NR_LEDS 4
781 struct bcm43xx_led leds[BCM43xx_NR_LEDS];
782 spinlock_t leds_lock;
783
784 /* The currently active core. */
785 struct bcm43xx_coreinfo *current_core;
786 struct bcm43xx_coreinfo *active_80211_core;
787 /* coreinfo structs for all possible cores follow.
788 * Note that a core might not exist.
789 * So check the coreinfo flags before using it.
790 */
791 struct bcm43xx_coreinfo core_chipcommon;
792 struct bcm43xx_coreinfo core_pci;
793 struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
794 /* Additional information, specific to the 80211 cores. */
795 struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
796 /* Number of available 80211 cores. */
797 int nr_80211_available;
798
799 u32 chipcommon_capabilities;
800
801 /* Reason code of the last interrupt. */
802 u32 irq_reason;
803 u32 dma_reason[6];
804 /* saved irq enable/disable state bitfield. */
805 u32 irq_savedstate;
806 /* Link Quality calculation context. */
807 struct bcm43xx_noise_calculation noisecalc;
808 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
809 int mac_suspended;
810
811 /* Threshold values. */
812 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
813 u32 rts_threshold;
814
815 /* Interrupt Service Routine tasklet (bottom-half) */
816 struct tasklet_struct isr_tasklet;
817
818 /* Periodic tasks */
819 struct delayed_work periodic_work;
820 unsigned int periodic_state;
821
822 struct work_struct restart_work;
823
824 /* Informational stuff. */
825 char nick[IW_ESSID_MAX_SIZE + 1];
826
827 /* encryption/decryption */
828 u16 security_offset;
829 struct bcm43xx_key key[54];
830 u8 default_key_idx;
831
832 /* Random Number Generator. */
833 struct hwrng rng;
834 char rng_name[20 + 1];
835
836 /* Debugging stuff follows. */
837#ifdef CONFIG_BCM43XX_DEBUG
838 struct bcm43xx_dfsentry *dfsentry;
839#endif
840};
841
842
843static inline
844struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
845{
846 return ieee80211softmac_priv(dev);
847}
848
849struct device;
850
851static inline
852struct bcm43xx_private * dev_to_bcm(struct device *dev)
853{
854 struct net_device *net_dev;
855 struct bcm43xx_private *bcm;
856
857 net_dev = dev_get_drvdata(dev);
858 bcm = bcm43xx_priv(net_dev);
859
860 return bcm;
861}
862
863
864/* Helper function, which returns a boolean.
865 * TRUE, if PIO is used; FALSE, if DMA is used.
866 */
867#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
868static inline
869int bcm43xx_using_pio(struct bcm43xx_private *bcm)
870{
871 return bcm->__using_pio;
872}
873#elif defined(CONFIG_BCM43XX_DMA)
874static inline
875int bcm43xx_using_pio(struct bcm43xx_private *bcm)
876{
877 return 0;
878}
879#elif defined(CONFIG_BCM43XX_PIO)
880static inline
881int bcm43xx_using_pio(struct bcm43xx_private *bcm)
882{
883 return 1;
884}
885#else
886# error "Using neither DMA nor PIO? Confused..."
887#endif
888
889/* Helper functions to access data structures private to the 80211 cores.
890 * Note that we _must_ have an 80211 core mapped when calling
891 * any of these functions.
892 */
893static inline
894struct bcm43xx_coreinfo_80211 *
895bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
896{
897 assert(bcm->current_core->id == BCM43xx_COREID_80211);
898 return bcm->current_core->priv;
899}
900static inline
901struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
902{
903 assert(bcm43xx_using_pio(bcm));
904 return &(bcm43xx_current_80211_priv(bcm)->pio);
905}
906static inline
907struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
908{
909 assert(!bcm43xx_using_pio(bcm));
910 return &(bcm43xx_current_80211_priv(bcm)->dma);
911}
912static inline
913struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
914{
915 return &(bcm43xx_current_80211_priv(bcm)->phy);
916}
917static inline
918struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
919{
920 return &(bcm43xx_current_80211_priv(bcm)->radio);
921}
922
923
924static inline
925struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
926 u16 radio_attenuation,
927 u16 baseband_attenuation)
928{
929 return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
930}
931
932
933static inline
934u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
935{
936 return ioread16(bcm->mmio_addr + offset);
937}
938
939static inline
940void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
941{
942 iowrite16(value, bcm->mmio_addr + offset);
943}
944
945static inline
946u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
947{
948 return ioread32(bcm->mmio_addr + offset);
949}
950
951static inline
952void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
953{
954 iowrite32(value, bcm->mmio_addr + offset);
955}
956
957static inline
958int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
959{
960 return pci_read_config_word(bcm->pci_dev, offset, value);
961}
962
963static inline
964int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
965{
966 return pci_read_config_dword(bcm->pci_dev, offset, value);
967}
968
969static inline
970int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
971{
972 return pci_write_config_word(bcm->pci_dev, offset, value);
973}
974
975static inline
976int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
977{
978 return pci_write_config_dword(bcm->pci_dev, offset, value);
979}
980
981/** Limit a value between two limits */
982#ifdef limit_value
983# undef limit_value
984#endif
985#define limit_value(value, min, max) \
986 ({ \
987 typeof(value) __value = (value); \
988 typeof(value) __min = (min); \
989 typeof(value) __max = (max); \
990 if (__value < __min) \
991 __value = __min; \
992 else if (__value > __max) \
993 __value = __max; \
994 __value; \
995 })
996
997#endif /* BCM43xx_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
deleted file mode 100644
index 76e9dd843faa..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ /dev/null
@@ -1,556 +0,0 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 debugfs driver debugging code
6
7 Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26
27
28#include <linux/fs.h>
29#include <linux/debugfs.h>
30#include <linux/slab.h>
31#include <linux/netdevice.h>
32#include <linux/pci.h>
33#include <asm/io.h>
34
35#include "bcm43xx.h"
36#include "bcm43xx_main.h"
37#include "bcm43xx_debugfs.h"
38#include "bcm43xx_dma.h"
39#include "bcm43xx_pio.h"
40#include "bcm43xx_xmit.h"
41
42#define REALLY_BIG_BUFFER_SIZE (1024*256)
43
44static struct bcm43xx_debugfs fs;
45static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
46static DECLARE_MUTEX(big_buffer_sem);
47
48
49static ssize_t write_file_dummy(struct file *file, const char __user *buf,
50 size_t count, loff_t *ppos)
51{
52 return count;
53}
54
55static int open_file_generic(struct inode *inode, struct file *file)
56{
57 file->private_data = inode->i_private;
58 return 0;
59}
60
61#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x)
62
63static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
64 size_t count, loff_t *ppos)
65{
66 const size_t len = REALLY_BIG_BUFFER_SIZE;
67
68 struct bcm43xx_private *bcm = file->private_data;
69 char *buf = really_big_buffer;
70 size_t pos = 0;
71 ssize_t res;
72 struct net_device *net_dev;
73 struct pci_dev *pci_dev;
74 unsigned long flags;
75 u16 tmp16;
76 int i;
77
78 down(&big_buffer_sem);
79
80 mutex_lock(&bcm->mutex);
81 spin_lock_irqsave(&bcm->irq_lock, flags);
82 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
83 fappend("Board not initialized.\n");
84 goto out;
85 }
86 net_dev = bcm->net_dev;
87 pci_dev = bcm->pci_dev;
88
89 /* This is where the information is written to the "devinfo" file */
90 fappend("*** %s devinfo ***\n", net_dev->name);
91 fappend("vendor: 0x%04x device: 0x%04x\n",
92 pci_dev->vendor, pci_dev->device);
93 fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n",
94 pci_dev->subsystem_vendor, pci_dev->subsystem_device);
95 fappend("IRQ: %d\n", bcm->irq);
96 fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
97 fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
98 if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
99 fappend("Radio disabled by hardware!\n");
100 if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
101 fappend("Radio disabled by hardware!\n");
102 fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor,
103 bcm->board_type);
104
105 fappend("\nCores:\n");
106#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \
107 "rev: 0x%02x, index: 0x%02x\n", \
108 (info).available \
109 ? "available" : "nonavailable", \
110 (info).enabled \
111 ? "enabled" : "disabled", \
112 (info).id, (info).rev, (info).index)
113 fappend_core("CHIPCOMMON", bcm->core_chipcommon);
114 fappend_core("PCI", bcm->core_pci);
115 fappend_core("first 80211", bcm->core_80211[0]);
116 fappend_core("second 80211", bcm->core_80211[1]);
117#undef fappend_core
118 tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
119 fappend("LEDs: ");
120 for (i = 0; i < BCM43xx_NR_LEDS; i++)
121 fappend("%d ", !!(tmp16 & (1 << i)));
122 fappend("\n");
123
124out:
125 spin_unlock_irqrestore(&bcm->irq_lock, flags);
126 mutex_unlock(&bcm->mutex);
127 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
128 up(&big_buffer_sem);
129 return res;
130}
131
132static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
133 size_t count, loff_t *ppos)
134{
135 const size_t len = REALLY_BIG_BUFFER_SIZE;
136
137 char *buf = really_big_buffer;
138 size_t pos = 0;
139 ssize_t res;
140
141 down(&big_buffer_sem);
142
143 /* This is where the information is written to the "driver" file */
144 fappend(KBUILD_MODNAME " driver\n");
145 fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
146
147 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
148 up(&big_buffer_sem);
149 return res;
150}
151
152static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
153 size_t count, loff_t *ppos)
154{
155 const size_t len = REALLY_BIG_BUFFER_SIZE;
156
157 struct bcm43xx_private *bcm = file->private_data;
158 char *buf = really_big_buffer;
159 size_t pos = 0;
160 ssize_t res;
161 unsigned long flags;
162
163 down(&big_buffer_sem);
164 mutex_lock(&bcm->mutex);
165 spin_lock_irqsave(&bcm->irq_lock, flags);
166 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
167 fappend("Board not initialized.\n");
168 goto out;
169 }
170
171 /* This is where the information is written to the "sprom_dump" file */
172 fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
173
174out:
175 spin_unlock_irqrestore(&bcm->irq_lock, flags);
176 mutex_unlock(&bcm->mutex);
177 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
178 up(&big_buffer_sem);
179 return res;
180}
181
182static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
183 size_t count, loff_t *ppos)
184{
185 const size_t len = REALLY_BIG_BUFFER_SIZE;
186
187 struct bcm43xx_private *bcm = file->private_data;
188 char *buf = really_big_buffer;
189 size_t pos = 0;
190 ssize_t res;
191 unsigned long flags;
192 u64 tsf;
193
194 down(&big_buffer_sem);
195 mutex_lock(&bcm->mutex);
196 spin_lock_irqsave(&bcm->irq_lock, flags);
197 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
198 fappend("Board not initialized.\n");
199 goto out;
200 }
201 bcm43xx_tsf_read(bcm, &tsf);
202 fappend("0x%08x%08x\n",
203 (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
204 (unsigned int)(tsf & 0xFFFFFFFFULL));
205
206out:
207 spin_unlock_irqrestore(&bcm->irq_lock, flags);
208 mutex_unlock(&bcm->mutex);
209 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
210 up(&big_buffer_sem);
211 return res;
212}
213
214static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
215 size_t count, loff_t *ppos)
216{
217 struct bcm43xx_private *bcm = file->private_data;
218 char *buf = really_big_buffer;
219 ssize_t buf_size;
220 ssize_t res;
221 unsigned long flags;
222 unsigned long long tsf;
223
224 buf_size = min(count, sizeof (really_big_buffer) - 1);
225 down(&big_buffer_sem);
226 if (copy_from_user(buf, user_buf, buf_size)) {
227 res = -EFAULT;
228 goto out_up;
229 }
230 mutex_lock(&bcm->mutex);
231 spin_lock_irqsave(&bcm->irq_lock, flags);
232 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
233 printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
234 res = -EFAULT;
235 goto out_unlock;
236 }
237 if (sscanf(buf, "%lli", &tsf) != 1) {
238 printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
239 res = -EINVAL;
240 goto out_unlock;
241 }
242 bcm43xx_tsf_write(bcm, tsf);
243 mmiowb();
244 res = buf_size;
245
246out_unlock:
247 spin_unlock_irqrestore(&bcm->irq_lock, flags);
248 mutex_unlock(&bcm->mutex);
249out_up:
250 up(&big_buffer_sem);
251 return res;
252}
253
254static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
255 size_t count, loff_t *ppos)
256{
257 const size_t len = REALLY_BIG_BUFFER_SIZE;
258
259 struct bcm43xx_private *bcm = file->private_data;
260 char *buf = really_big_buffer;
261 size_t pos = 0;
262 ssize_t res;
263 unsigned long flags;
264 struct bcm43xx_dfsentry *e;
265 struct bcm43xx_xmitstatus *status;
266 int i, cnt, j = 0;
267
268 down(&big_buffer_sem);
269 mutex_lock(&bcm->mutex);
270 spin_lock_irqsave(&bcm->irq_lock, flags);
271
272 fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
273 BCM43xx_NR_LOGGED_XMITSTATUS);
274 e = bcm->dfsentry;
275 if (e->xmitstatus_printing == 0) {
276 /* At the beginning, make a copy of all data to avoid
277 * concurrency, as this function is called multiple
278 * times for big logs. Without copying, the data might
279 * change between reads. This would result in total trash.
280 */
281 e->xmitstatus_printing = 1;
282 e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
283 e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
284 memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
285 BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
286 }
287 i = e->saved_xmitstatus_ptr - 1;
288 if (i < 0)
289 i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
290 cnt = e->saved_xmitstatus_cnt;
291 while (cnt) {
292 status = e->xmitstatus_print_buffer + i;
293 fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, "
294 "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, "
295 "unk: 0x%04x\n", j,
296 status->cookie, status->flags,
297 status->cnt1, status->cnt2, status->seq,
298 status->unknown);
299 j++;
300 cnt--;
301 i--;
302 if (i < 0)
303 i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
304 }
305
306 spin_unlock_irqrestore(&bcm->irq_lock, flags);
307 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
308 spin_lock_irqsave(&bcm->irq_lock, flags);
309 if (*ppos == pos) {
310 /* Done. Drop the copied data. */
311 e->xmitstatus_printing = 0;
312 }
313 spin_unlock_irqrestore(&bcm->irq_lock, flags);
314 mutex_unlock(&bcm->mutex);
315 up(&big_buffer_sem);
316 return res;
317}
318
319static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
320 size_t count, loff_t *ppos)
321{
322 struct bcm43xx_private *bcm = file->private_data;
323 char *buf = really_big_buffer;
324 ssize_t buf_size;
325 ssize_t res;
326 unsigned long flags;
327
328 buf_size = min(count, sizeof (really_big_buffer) - 1);
329 down(&big_buffer_sem);
330 if (copy_from_user(buf, user_buf, buf_size)) {
331 res = -EFAULT;
332 goto out_up;
333 }
334 mutex_lock(&(bcm)->mutex);
335 spin_lock_irqsave(&(bcm)->irq_lock, flags);
336 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
337 printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
338 res = -EFAULT;
339 goto out_unlock;
340 }
341 if (count > 0 && buf[0] == '1') {
342 bcm43xx_controller_restart(bcm, "manually restarted");
343 res = count;
344 } else
345 res = -EINVAL;
346
347out_unlock:
348 spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
349 mutex_unlock(&(bcm)->mutex);
350out_up:
351 up(&big_buffer_sem);
352 return res;
353}
354
355#undef fappend
356
357
358static const struct file_operations devinfo_fops = {
359 .read = devinfo_read_file,
360 .write = write_file_dummy,
361 .open = open_file_generic,
362};
363
364static const struct file_operations spromdump_fops = {
365 .read = spromdump_read_file,
366 .write = write_file_dummy,
367 .open = open_file_generic,
368};
369
370static const struct file_operations drvinfo_fops = {
371 .read = drvinfo_read_file,
372 .write = write_file_dummy,
373 .open = open_file_generic,
374};
375
376static const struct file_operations tsf_fops = {
377 .read = tsf_read_file,
378 .write = tsf_write_file,
379 .open = open_file_generic,
380};
381
382static const struct file_operations txstat_fops = {
383 .read = txstat_read_file,
384 .write = write_file_dummy,
385 .open = open_file_generic,
386};
387
388static const struct file_operations restart_fops = {
389 .write = restart_write_file,
390 .open = open_file_generic,
391};
392
393
394void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
395{
396 struct bcm43xx_dfsentry *e;
397 char devdir[IFNAMSIZ];
398
399 assert(bcm);
400 e = kzalloc(sizeof(*e), GFP_KERNEL);
401 if (!e) {
402 printk(KERN_ERR PFX "out of memory\n");
403 return;
404 }
405 e->bcm = bcm;
406 e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
407 * sizeof(*(e->xmitstatus_buffer)),
408 GFP_KERNEL);
409 if (!e->xmitstatus_buffer) {
410 printk(KERN_ERR PFX "out of memory\n");
411 kfree(e);
412 return;
413 }
414 e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
415 * sizeof(*(e->xmitstatus_buffer)),
416 GFP_KERNEL);
417 if (!e->xmitstatus_print_buffer) {
418 printk(KERN_ERR PFX "out of memory\n");
419 kfree(e);
420 return;
421 }
422
423
424 bcm->dfsentry = e;
425
426 strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
427 e->subdir = debugfs_create_dir(devdir, fs.root);
428 e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
429 bcm, &devinfo_fops);
430 if (!e->dentry_devinfo)
431 printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
432 e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
433 bcm, &spromdump_fops);
434 if (!e->dentry_spromdump)
435 printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
436 e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
437 bcm, &tsf_fops);
438 if (!e->dentry_tsf)
439 printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
440 e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
441 bcm, &txstat_fops);
442 if (!e->dentry_txstat)
443 printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
444 e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
445 bcm, &restart_fops);
446 if (!e->dentry_restart)
447 printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
448}
449
450void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
451{
452 struct bcm43xx_dfsentry *e;
453
454 if (!bcm)
455 return;
456
457 e = bcm->dfsentry;
458 assert(e);
459 debugfs_remove(e->dentry_spromdump);
460 debugfs_remove(e->dentry_devinfo);
461 debugfs_remove(e->dentry_tsf);
462 debugfs_remove(e->dentry_txstat);
463 debugfs_remove(e->dentry_restart);
464 debugfs_remove(e->subdir);
465 kfree(e->xmitstatus_buffer);
466 kfree(e->xmitstatus_print_buffer);
467 kfree(e);
468}
469
470void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
471 struct bcm43xx_xmitstatus *status)
472{
473 struct bcm43xx_dfsentry *e;
474 struct bcm43xx_xmitstatus *savedstatus;
475
476 /* This is protected by bcm->_lock */
477 e = bcm->dfsentry;
478 assert(e);
479 savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
480 memcpy(savedstatus, status, sizeof(*status));
481 e->xmitstatus_ptr++;
482 if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
483 e->xmitstatus_ptr = 0;
484 if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
485 e->xmitstatus_cnt++;
486}
487
488void bcm43xx_debugfs_init(void)
489{
490 memset(&fs, 0, sizeof(fs));
491 fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
492 if (!fs.root)
493 printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
494 fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
495 if (!fs.dentry_driverinfo)
496 printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
497}
498
499void bcm43xx_debugfs_exit(void)
500{
501 debugfs_remove(fs.dentry_driverinfo);
502 debugfs_remove(fs.root);
503}
504
505void bcm43xx_printk_dump(const char *data,
506 size_t size,
507 const char *description)
508{
509 size_t i;
510 char c;
511
512 printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
513 description, size);
514 for (i = 0; i < size; i++) {
515 c = data[i];
516 if (i % 8 == 0)
517 printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff);
518 else
519 printk("0x%02x, ", c & 0xff);
520 }
521 printk("\n");
522}
523
524void bcm43xx_printk_bitdump(const unsigned char *data,
525 size_t bytes, int msb_to_lsb,
526 const char *description)
527{
528 size_t i;
529 int j;
530 const unsigned char *d;
531
532 printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
533 description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
534 for (i = 0; i < bytes; i++) {
535 d = data + i;
536 if (i % 8 == 0)
537 printk("\n" KERN_INFO PFX "0x%08zx: ", i);
538 if (msb_to_lsb) {
539 for (j = 7; j >= 0; j--) {
540 if (*d & (1 << j))
541 printk("1");
542 else
543 printk("0");
544 }
545 } else {
546 for (j = 0; j < 8; j++) {
547 if (*d & (1 << j))
548 printk("1");
549 else
550 printk("0");
551 }
552 }
553 printk(" ");
554 }
555 printk("\n");
556}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
deleted file mode 100644
index a40d1af35545..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
+++ /dev/null
@@ -1,118 +0,0 @@
1#ifndef BCM43xx_DEBUGFS_H_
2#define BCM43xx_DEBUGFS_H_
3
4struct bcm43xx_private;
5struct bcm43xx_xmitstatus;
6
7#ifdef CONFIG_BCM43XX_DEBUG
8
9#include <linux/list.h>
10#include <asm/semaphore.h>
11
12struct dentry;
13
14/* limited by the size of the "really_big_buffer" */
15#define BCM43xx_NR_LOGGED_XMITSTATUS 100
16
17struct bcm43xx_dfsentry {
18 struct dentry *subdir;
19 struct dentry *dentry_devinfo;
20 struct dentry *dentry_spromdump;
21 struct dentry *dentry_tsf;
22 struct dentry *dentry_txstat;
23 struct dentry *dentry_restart;
24
25 struct bcm43xx_private *bcm;
26
27 /* saved xmitstatus. */
28 struct bcm43xx_xmitstatus *xmitstatus_buffer;
29 int xmitstatus_ptr;
30 int xmitstatus_cnt;
31 /* We need a seperate buffer while printing to avoid
32 * concurrency issues. (New xmitstatus can arrive
33 * while we are printing).
34 */
35 struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
36 int saved_xmitstatus_ptr;
37 int saved_xmitstatus_cnt;
38 int xmitstatus_printing;
39};
40
41struct bcm43xx_debugfs {
42 struct dentry *root;
43 struct dentry *dentry_driverinfo;
44};
45
46void bcm43xx_debugfs_init(void);
47void bcm43xx_debugfs_exit(void);
48void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
49void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
50void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
51 struct bcm43xx_xmitstatus *status);
52
53/* Debug helper: Dump binary data through printk. */
54void bcm43xx_printk_dump(const char *data,
55 size_t size,
56 const char *description);
57/* Debug helper: Dump bitwise binary data through printk. */
58void bcm43xx_printk_bitdump(const unsigned char *data,
59 size_t bytes, int msb_to_lsb,
60 const char *description);
61#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
62 do { \
63 bcm43xx_printk_bitdump((const unsigned char *)(pointer), \
64 sizeof(*(pointer)), \
65 (msb_to_lsb), \
66 (description)); \
67 } while (0)
68
69#else /* CONFIG_BCM43XX_DEBUG*/
70
71static inline
72void bcm43xx_debugfs_init(void) { }
73static inline
74void bcm43xx_debugfs_exit(void) { }
75static inline
76void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
77static inline
78void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
79static inline
80void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
81 struct bcm43xx_xmitstatus *status) { }
82
83static inline
84void bcm43xx_printk_dump(const char *data,
85 size_t size,
86 const char *description)
87{
88}
89static inline
90void bcm43xx_printk_bitdump(const unsigned char *data,
91 size_t bytes, int msb_to_lsb,
92 const char *description)
93{
94}
95#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0)
96
97#endif /* CONFIG_BCM43XX_DEBUG*/
98
99/* Ugly helper macros to make incomplete code more verbose on runtime */
100#ifdef TODO
101# undef TODO
102#endif
103#define TODO() \
104 do { \
105 printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \
106 __FUNCTION__, __FILE__, __LINE__); \
107 } while (0)
108
109#ifdef FIXME
110# undef FIXME
111#endif
112#define FIXME() \
113 do { \
114 printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \
115 __FUNCTION__, __FILE__, __LINE__); \
116 } while (0)
117
118#endif /* BCM43xx_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
deleted file mode 100644
index 1f7731fcfbd5..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ /dev/null
@@ -1,1263 +0,0 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 DMA ringbuffer and descriptor allocation/management
6
7 Copyright (c) 2005, 2006 Michael Buesch <mbuesch@freenet.de>
8
9 Some code in this file is derived from the b44.c driver
10 Copyright (C) 2002 David S. Miller
11 Copyright (C) Pekka Pietikainen
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
27
28*/
29
30#include "bcm43xx.h"
31#include "bcm43xx_dma.h"
32#include "bcm43xx_main.h"
33#include "bcm43xx_debugfs.h"
34#include "bcm43xx_power.h"
35#include "bcm43xx_xmit.h"
36
37#include <linux/dma-mapping.h>
38#include <linux/pci.h>
39#include <linux/delay.h>
40#include <linux/skbuff.h>
41
42
43static inline int free_slots(struct bcm43xx_dmaring *ring)
44{
45 return (ring->nr_slots - ring->used_slots);
46}
47
48static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
49{
50 assert(slot >= -1 && slot <= ring->nr_slots - 1);
51 if (slot == ring->nr_slots - 1)
52 return 0;
53 return slot + 1;
54}
55
56static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
57{
58 assert(slot >= 0 && slot <= ring->nr_slots - 1);
59 if (slot == 0)
60 return ring->nr_slots - 1;
61 return slot - 1;
62}
63
64/* Request a slot for usage. */
65static inline
66int request_slot(struct bcm43xx_dmaring *ring)
67{
68 int slot;
69
70 assert(ring->tx);
71 assert(!ring->suspended);
72 assert(free_slots(ring) != 0);
73
74 slot = next_slot(ring, ring->current_slot);
75 ring->current_slot = slot;
76 ring->used_slots++;
77
78 /* Check the number of available slots and suspend TX,
79 * if we are running low on free slots.
80 */
81 if (unlikely(free_slots(ring) < ring->suspend_mark)) {
82 netif_stop_queue(ring->bcm->net_dev);
83 ring->suspended = 1;
84 }
85#ifdef CONFIG_BCM43XX_DEBUG
86 if (ring->used_slots > ring->max_used_slots)
87 ring->max_used_slots = ring->used_slots;
88#endif /* CONFIG_BCM43XX_DEBUG*/
89
90 return slot;
91}
92
93/* Return a slot to the free slots. */
94static inline
95void return_slot(struct bcm43xx_dmaring *ring, int slot)
96{
97 assert(ring->tx);
98
99 ring->used_slots--;
100
101 /* Check if TX is suspended and check if we have
102 * enough free slots to resume it again.
103 */
104 if (unlikely(ring->suspended)) {
105 if (free_slots(ring) >= ring->resume_mark) {
106 ring->suspended = 0;
107 netif_wake_queue(ring->bcm->net_dev);
108 }
109 }
110}
111
112u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx)
113{
114 static const u16 map64[] = {
115 BCM43xx_MMIO_DMA64_BASE0,
116 BCM43xx_MMIO_DMA64_BASE1,
117 BCM43xx_MMIO_DMA64_BASE2,
118 BCM43xx_MMIO_DMA64_BASE3,
119 BCM43xx_MMIO_DMA64_BASE4,
120 BCM43xx_MMIO_DMA64_BASE5,
121 };
122 static const u16 map32[] = {
123 BCM43xx_MMIO_DMA32_BASE0,
124 BCM43xx_MMIO_DMA32_BASE1,
125 BCM43xx_MMIO_DMA32_BASE2,
126 BCM43xx_MMIO_DMA32_BASE3,
127 BCM43xx_MMIO_DMA32_BASE4,
128 BCM43xx_MMIO_DMA32_BASE5,
129 };
130
131 if (dma64bit) {
132 assert(controller_idx >= 0 &&
133 controller_idx < ARRAY_SIZE(map64));
134 return map64[controller_idx];
135 }
136 assert(controller_idx >= 0 &&
137 controller_idx < ARRAY_SIZE(map32));
138 return map32[controller_idx];
139}
140
141static inline
142dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
143 unsigned char *buf,
144 size_t len,
145 int tx)
146{
147 dma_addr_t dmaaddr;
148 int direction = PCI_DMA_FROMDEVICE;
149
150 if (tx)
151 direction = PCI_DMA_TODEVICE;
152
153 dmaaddr = pci_map_single(ring->bcm->pci_dev,
154 buf, len,
155 direction);
156
157 return dmaaddr;
158}
159
160static inline
161void unmap_descbuffer(struct bcm43xx_dmaring *ring,
162 dma_addr_t addr,
163 size_t len,
164 int tx)
165{
166 if (tx) {
167 pci_unmap_single(ring->bcm->pci_dev,
168 addr, len,
169 PCI_DMA_TODEVICE);
170 } else {
171 pci_unmap_single(ring->bcm->pci_dev,
172 addr, len,
173 PCI_DMA_FROMDEVICE);
174 }
175}
176
177static inline
178void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
179 dma_addr_t addr,
180 size_t len)
181{
182 assert(!ring->tx);
183
184 pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
185 addr, len, PCI_DMA_FROMDEVICE);
186}
187
188static inline
189void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
190 dma_addr_t addr,
191 size_t len)
192{
193 assert(!ring->tx);
194
195 pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
196 addr, len, PCI_DMA_TODEVICE);
197}
198
199/* Unmap and free a descriptor buffer. */
200static inline
201void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
202 struct bcm43xx_dmadesc_meta *meta,
203 int irq_context)
204{
205 assert(meta->skb);
206 if (irq_context)
207 dev_kfree_skb_irq(meta->skb);
208 else
209 dev_kfree_skb(meta->skb);
210 meta->skb = NULL;
211}
212
213static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
214{
215 ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
216 &(ring->dmabase));
217 if (!ring->descbase) {
218 /* Allocation may have failed due to pci_alloc_consistent
219 insisting on use of GFP_DMA, which is more restrictive
220 than necessary... */
221 struct dma_desc *rx_ring;
222 dma_addr_t rx_ring_dma;
223
224 rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
225 if (!rx_ring)
226 goto out_err;
227
228 rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
229 BCM43xx_DMA_RINGMEMSIZE,
230 PCI_DMA_BIDIRECTIONAL);
231
232 if (pci_dma_mapping_error(rx_ring_dma) ||
233 rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
234 /* Sigh... */
235 if (!pci_dma_mapping_error(rx_ring_dma))
236 pci_unmap_single(ring->bcm->pci_dev,
237 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
238 PCI_DMA_BIDIRECTIONAL);
239 rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
240 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
241 PCI_DMA_BIDIRECTIONAL);
242 if (pci_dma_mapping_error(rx_ring_dma) ||
243 rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
244 assert(0);
245 if (!pci_dma_mapping_error(rx_ring_dma))
246 pci_unmap_single(ring->bcm->pci_dev,
247 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
248 PCI_DMA_BIDIRECTIONAL);
249 goto out_err;
250 }
251 }
252
253 ring->descbase = rx_ring;
254 ring->dmabase = rx_ring_dma;
255 }
256 memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
257
258 return 0;
259out_err:
260 printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
261 return -ENOMEM;
262}
263
264static void free_ringmemory(struct bcm43xx_dmaring *ring)
265{
266 struct device *dev = &(ring->bcm->pci_dev->dev);
267
268 dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
269 ring->descbase, ring->dmabase);
270}
271
272/* Reset the RX DMA channel */
273int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
274 u16 mmio_base, int dma64)
275{
276 int i;
277 u32 value;
278 u16 offset;
279
280 offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL;
281 bcm43xx_write32(bcm, mmio_base + offset, 0);
282 for (i = 0; i < 1000; i++) {
283 offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS;
284 value = bcm43xx_read32(bcm, mmio_base + offset);
285 if (dma64) {
286 value &= BCM43xx_DMA64_RXSTAT;
287 if (value == BCM43xx_DMA64_RXSTAT_DISABLED) {
288 i = -1;
289 break;
290 }
291 } else {
292 value &= BCM43xx_DMA32_RXSTATE;
293 if (value == BCM43xx_DMA32_RXSTAT_DISABLED) {
294 i = -1;
295 break;
296 }
297 }
298 udelay(10);
299 }
300 if (i != -1) {
301 printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
302 return -ENODEV;
303 }
304
305 return 0;
306}
307
308/* Reset the RX DMA channel */
309int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
310 u16 mmio_base, int dma64)
311{
312 int i;
313 u32 value;
314 u16 offset;
315
316 for (i = 0; i < 1000; i++) {
317 offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
318 value = bcm43xx_read32(bcm, mmio_base + offset);
319 if (dma64) {
320 value &= BCM43xx_DMA64_TXSTAT;
321 if (value == BCM43xx_DMA64_TXSTAT_DISABLED ||
322 value == BCM43xx_DMA64_TXSTAT_IDLEWAIT ||
323 value == BCM43xx_DMA64_TXSTAT_STOPPED)
324 break;
325 } else {
326 value &= BCM43xx_DMA32_TXSTATE;
327 if (value == BCM43xx_DMA32_TXSTAT_DISABLED ||
328 value == BCM43xx_DMA32_TXSTAT_IDLEWAIT ||
329 value == BCM43xx_DMA32_TXSTAT_STOPPED)
330 break;
331 }
332 udelay(10);
333 }
334 offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL;
335 bcm43xx_write32(bcm, mmio_base + offset, 0);
336 for (i = 0; i < 1000; i++) {
337 offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
338 value = bcm43xx_read32(bcm, mmio_base + offset);
339 if (dma64) {
340 value &= BCM43xx_DMA64_TXSTAT;
341 if (value == BCM43xx_DMA64_TXSTAT_DISABLED) {
342 i = -1;
343 break;
344 }
345 } else {
346 value &= BCM43xx_DMA32_TXSTATE;
347 if (value == BCM43xx_DMA32_TXSTAT_DISABLED) {
348 i = -1;
349 break;
350 }
351 }
352 udelay(10);
353 }
354 if (i != -1) {
355 printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
356 return -ENODEV;
357 }
358 /* ensure the reset is completed. */
359 udelay(300);
360
361 return 0;
362}
363
364static void fill_descriptor(struct bcm43xx_dmaring *ring,
365 struct bcm43xx_dmadesc_generic *desc,
366 dma_addr_t dmaaddr,
367 u16 bufsize,
368 int start, int end, int irq)
369{
370 int slot;
371
372 slot = bcm43xx_dma_desc2idx(ring, desc);
373 assert(slot >= 0 && slot < ring->nr_slots);
374
375 if (ring->dma64) {
376 u32 ctl0 = 0, ctl1 = 0;
377 u32 addrlo, addrhi;
378 u32 addrext;
379
380 addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
381 addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING);
382 addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
383 addrhi |= ring->routing;
384 if (slot == ring->nr_slots - 1)
385 ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND;
386 if (start)
387 ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART;
388 if (end)
389 ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND;
390 if (irq)
391 ctl0 |= BCM43xx_DMA64_DCTL0_IRQ;
392 ctl1 |= (bufsize - ring->frameoffset)
393 & BCM43xx_DMA64_DCTL1_BYTECNT;
394 ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT)
395 & BCM43xx_DMA64_DCTL1_ADDREXT_MASK;
396
397 desc->dma64.control0 = cpu_to_le32(ctl0);
398 desc->dma64.control1 = cpu_to_le32(ctl1);
399 desc->dma64.address_low = cpu_to_le32(addrlo);
400 desc->dma64.address_high = cpu_to_le32(addrhi);
401 } else {
402 u32 ctl;
403 u32 addr;
404 u32 addrext;
405
406 addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING);
407 addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING)
408 >> BCM43xx_DMA32_ROUTING_SHIFT;
409 addr |= ring->routing;
410 ctl = (bufsize - ring->frameoffset)
411 & BCM43xx_DMA32_DCTL_BYTECNT;
412 if (slot == ring->nr_slots - 1)
413 ctl |= BCM43xx_DMA32_DCTL_DTABLEEND;
414 if (start)
415 ctl |= BCM43xx_DMA32_DCTL_FRAMESTART;
416 if (end)
417 ctl |= BCM43xx_DMA32_DCTL_FRAMEEND;
418 if (irq)
419 ctl |= BCM43xx_DMA32_DCTL_IRQ;
420 ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT)
421 & BCM43xx_DMA32_DCTL_ADDREXT_MASK;
422
423 desc->dma32.control = cpu_to_le32(ctl);
424 desc->dma32.address = cpu_to_le32(addr);
425 }
426}
427
428static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
429 struct bcm43xx_dmadesc_generic *desc,
430 struct bcm43xx_dmadesc_meta *meta,
431 gfp_t gfp_flags)
432{
433 struct bcm43xx_rxhdr *rxhdr;
434 struct bcm43xx_hwxmitstatus *xmitstat;
435 dma_addr_t dmaaddr;
436 struct sk_buff *skb;
437
438 assert(!ring->tx);
439
440 skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
441 if (unlikely(!skb))
442 return -ENOMEM;
443 dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
444 /* This hardware bug work-around adapted from the b44 driver.
445 The chip may be unable to do PCI DMA to/from anything above 1GB */
446 if (pci_dma_mapping_error(dmaaddr) ||
447 dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
448 /* This one has 30-bit addressing... */
449 if (!pci_dma_mapping_error(dmaaddr))
450 pci_unmap_single(ring->bcm->pci_dev,
451 dmaaddr, ring->rx_buffersize,
452 PCI_DMA_FROMDEVICE);
453 dev_kfree_skb_any(skb);
454 skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
455 if (skb == NULL)
456 return -ENOMEM;
457 dmaaddr = pci_map_single(ring->bcm->pci_dev,
458 skb->data, ring->rx_buffersize,
459 PCI_DMA_FROMDEVICE);
460 if (pci_dma_mapping_error(dmaaddr) ||
461 dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
462 assert(0);
463 dev_kfree_skb_any(skb);
464 return -ENOMEM;
465 }
466 }
467 meta->skb = skb;
468 meta->dmaaddr = dmaaddr;
469 skb->dev = ring->bcm->net_dev;
470
471 fill_descriptor(ring, desc, dmaaddr,
472 ring->rx_buffersize, 0, 0, 0);
473
474 rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
475 rxhdr->frame_length = 0;
476 rxhdr->flags1 = 0;
477 xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data);
478 xmitstat->cookie = 0;
479
480 return 0;
481}
482
483/* Allocate the initial descbuffers.
484 * This is used for an RX ring only.
485 */
486static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
487{
488 int i, err = -ENOMEM;
489 struct bcm43xx_dmadesc_generic *desc;
490 struct bcm43xx_dmadesc_meta *meta;
491
492 for (i = 0; i < ring->nr_slots; i++) {
493 desc = bcm43xx_dma_idx2desc(ring, i, &meta);
494
495 err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
496 if (err)
497 goto err_unwind;
498 }
499 mb();
500 ring->used_slots = ring->nr_slots;
501 err = 0;
502out:
503 return err;
504
505err_unwind:
506 for (i--; i >= 0; i--) {
507 desc = bcm43xx_dma_idx2desc(ring, i, &meta);
508
509 unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
510 dev_kfree_skb(meta->skb);
511 }
512 goto out;
513}
514
515/* Do initial setup of the DMA controller.
516 * Reset the controller, write the ring busaddress
517 * and switch the "enable" bit on.
518 */
519static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
520{
521 int err = 0;
522 u32 value;
523 u32 addrext;
524
525 if (ring->tx) {
526 if (ring->dma64) {
527 u64 ringbase = (u64)(ring->dmabase);
528
529 addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
530 value = BCM43xx_DMA64_TXENABLE;
531 value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT)
532 & BCM43xx_DMA64_TXADDREXT_MASK;
533 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value);
534 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO,
535 (ringbase & 0xFFFFFFFF));
536 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI,
537 ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
538 | ring->routing);
539 } else {
540 u32 ringbase = (u32)(ring->dmabase);
541
542 addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
543 value = BCM43xx_DMA32_TXENABLE;
544 value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT)
545 & BCM43xx_DMA32_TXADDREXT_MASK;
546 bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value);
547 bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING,
548 (ringbase & ~BCM43xx_DMA32_ROUTING)
549 | ring->routing);
550 }
551 } else {
552 err = alloc_initial_descbuffers(ring);
553 if (err)
554 goto out;
555 if (ring->dma64) {
556 u64 ringbase = (u64)(ring->dmabase);
557
558 addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
559 value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT);
560 value |= BCM43xx_DMA64_RXENABLE;
561 value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT)
562 & BCM43xx_DMA64_RXADDREXT_MASK;
563 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value);
564 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO,
565 (ringbase & 0xFFFFFFFF));
566 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI,
567 ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
568 | ring->routing);
569 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200);
570 } else {
571 u32 ringbase = (u32)(ring->dmabase);
572
573 addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
574 value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT);
575 value |= BCM43xx_DMA32_RXENABLE;
576 value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT)
577 & BCM43xx_DMA32_RXADDREXT_MASK;
578 bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value);
579 bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING,
580 (ringbase & ~BCM43xx_DMA32_ROUTING)
581 | ring->routing);
582 bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200);
583 }
584 }
585
586out:
587 return err;
588}
589
590/* Shutdown the DMA controller. */
591static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
592{
593 if (ring->tx) {
594 bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64);
595 if (ring->dma64) {
596 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0);
597 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0);
598 } else
599 bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0);
600 } else {
601 bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64);
602 if (ring->dma64) {
603 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0);
604 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0);
605 } else
606 bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0);
607 }
608}
609
610static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
611{
612 struct bcm43xx_dmadesc_generic *desc;
613 struct bcm43xx_dmadesc_meta *meta;
614 int i;
615
616 if (!ring->used_slots)
617 return;
618 for (i = 0; i < ring->nr_slots; i++) {
619 desc = bcm43xx_dma_idx2desc(ring, i, &meta);
620
621 if (!meta->skb) {
622 assert(ring->tx);
623 continue;
624 }
625 if (ring->tx) {
626 unmap_descbuffer(ring, meta->dmaaddr,
627 meta->skb->len, 1);
628 } else {
629 unmap_descbuffer(ring, meta->dmaaddr,
630 ring->rx_buffersize, 0);
631 }
632 free_descriptor_buffer(ring, meta, 0);
633 }
634}
635
636/* Main initialization function. */
637static
638struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
639 int controller_index,
640 int for_tx,
641 int dma64)
642{
643 struct bcm43xx_dmaring *ring;
644 int err;
645 int nr_slots;
646
647 ring = kzalloc(sizeof(*ring), GFP_KERNEL);
648 if (!ring)
649 goto out;
650
651 nr_slots = BCM43xx_RXRING_SLOTS;
652 if (for_tx)
653 nr_slots = BCM43xx_TXRING_SLOTS;
654
655 ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta),
656 GFP_KERNEL);
657 if (!ring->meta)
658 goto err_kfree_ring;
659
660 ring->routing = BCM43xx_DMA32_CLIENTTRANS;
661 if (dma64)
662 ring->routing = BCM43xx_DMA64_CLIENTTRANS;
663
664 ring->bcm = bcm;
665 ring->nr_slots = nr_slots;
666 ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
667 ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
668 assert(ring->suspend_mark < ring->resume_mark);
669 ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index);
670 ring->index = controller_index;
671 ring->dma64 = !!dma64;
672 if (for_tx) {
673 ring->tx = 1;
674 ring->current_slot = -1;
675 } else {
676 if (ring->index == 0) {
677 ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE;
678 ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET;
679 } else if (ring->index == 3) {
680 ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE;
681 ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET;
682 } else
683 assert(0);
684 }
685
686 err = alloc_ringmemory(ring);
687 if (err)
688 goto err_kfree_meta;
689 err = dmacontroller_setup(ring);
690 if (err)
691 goto err_free_ringmemory;
692 return ring;
693
694out:
695 printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
696 return ring;
697
698err_free_ringmemory:
699 free_ringmemory(ring);
700err_kfree_meta:
701 kfree(ring->meta);
702err_kfree_ring:
703 kfree(ring);
704 ring = NULL;
705 goto out;
706}
707
708/* Main cleanup function. */
709static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
710{
711 if (!ring)
712 return;
713
714 dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
715 (ring->dma64) ? "64" : "32",
716 ring->mmio_base,
717 (ring->tx) ? "TX" : "RX",
718 ring->max_used_slots, ring->nr_slots);
719 /* Device IRQs are disabled prior entering this function,
720 * so no need to take care of concurrency with rx handler stuff.
721 */
722 dmacontroller_cleanup(ring);
723 free_all_descbuffers(ring);
724 free_ringmemory(ring);
725
726 kfree(ring->meta);
727 kfree(ring);
728}
729
730void bcm43xx_dma_free(struct bcm43xx_private *bcm)
731{
732 struct bcm43xx_dma *dma;
733
734 if (bcm43xx_using_pio(bcm))
735 return;
736 dma = bcm43xx_current_dma(bcm);
737
738 bcm43xx_destroy_dmaring(dma->rx_ring3);
739 dma->rx_ring3 = NULL;
740 bcm43xx_destroy_dmaring(dma->rx_ring0);
741 dma->rx_ring0 = NULL;
742
743 bcm43xx_destroy_dmaring(dma->tx_ring5);
744 dma->tx_ring5 = NULL;
745 bcm43xx_destroy_dmaring(dma->tx_ring4);
746 dma->tx_ring4 = NULL;
747 bcm43xx_destroy_dmaring(dma->tx_ring3);
748 dma->tx_ring3 = NULL;
749 bcm43xx_destroy_dmaring(dma->tx_ring2);
750 dma->tx_ring2 = NULL;
751 bcm43xx_destroy_dmaring(dma->tx_ring1);
752 dma->tx_ring1 = NULL;
753 bcm43xx_destroy_dmaring(dma->tx_ring0);
754 dma->tx_ring0 = NULL;
755}
756
757int bcm43xx_dma_init(struct bcm43xx_private *bcm)
758{
759 struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
760 struct bcm43xx_dmaring *ring;
761 int err = -ENOMEM;
762 int dma64 = 0;
763
764 bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
765 if (bcm->dma_mask == DMA_64BIT_MASK)
766 dma64 = 1;
767 err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
768 if (err)
769 goto no_dma;
770 err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
771 if (err)
772 goto no_dma;
773
774 /* setup TX DMA channels. */
775 ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
776 if (!ring)
777 goto out;
778 dma->tx_ring0 = ring;
779
780 ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64);
781 if (!ring)
782 goto err_destroy_tx0;
783 dma->tx_ring1 = ring;
784
785 ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64);
786 if (!ring)
787 goto err_destroy_tx1;
788 dma->tx_ring2 = ring;
789
790 ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64);
791 if (!ring)
792 goto err_destroy_tx2;
793 dma->tx_ring3 = ring;
794
795 ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64);
796 if (!ring)
797 goto err_destroy_tx3;
798 dma->tx_ring4 = ring;
799
800 ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64);
801 if (!ring)
802 goto err_destroy_tx4;
803 dma->tx_ring5 = ring;
804
805 /* setup RX DMA channels. */
806 ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64);
807 if (!ring)
808 goto err_destroy_tx5;
809 dma->rx_ring0 = ring;
810
811 if (bcm->current_core->rev < 5) {
812 ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64);
813 if (!ring)
814 goto err_destroy_rx0;
815 dma->rx_ring3 = ring;
816 }
817
818 dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
819 (bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
820 (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
821 err = 0;
822out:
823 return err;
824
825err_destroy_rx0:
826 bcm43xx_destroy_dmaring(dma->rx_ring0);
827 dma->rx_ring0 = NULL;
828err_destroy_tx5:
829 bcm43xx_destroy_dmaring(dma->tx_ring5);
830 dma->tx_ring5 = NULL;
831err_destroy_tx4:
832 bcm43xx_destroy_dmaring(dma->tx_ring4);
833 dma->tx_ring4 = NULL;
834err_destroy_tx3:
835 bcm43xx_destroy_dmaring(dma->tx_ring3);
836 dma->tx_ring3 = NULL;
837err_destroy_tx2:
838 bcm43xx_destroy_dmaring(dma->tx_ring2);
839 dma->tx_ring2 = NULL;
840err_destroy_tx1:
841 bcm43xx_destroy_dmaring(dma->tx_ring1);
842 dma->tx_ring1 = NULL;
843err_destroy_tx0:
844 bcm43xx_destroy_dmaring(dma->tx_ring0);
845 dma->tx_ring0 = NULL;
846no_dma:
847#ifdef CONFIG_BCM43XX_PIO
848 printk(KERN_WARNING PFX "DMA not supported on this device."
849 " Falling back to PIO.\n");
850 bcm->__using_pio = 1;
851 return -ENOSYS;
852#else
853 printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
854 "Please recompile the driver with PIO support.\n");
855 return -ENODEV;
856#endif /* CONFIG_BCM43XX_PIO */
857}
858
859/* Generate a cookie for the TX header. */
860static u16 generate_cookie(struct bcm43xx_dmaring *ring,
861 int slot)
862{
863 u16 cookie = 0x1000;
864
865 /* Use the upper 4 bits of the cookie as
866 * DMA controller ID and store the slot number
867 * in the lower 12 bits.
868 * Note that the cookie must never be 0, as this
869 * is a special value used in RX path.
870 */
871 switch (ring->index) {
872 case 0:
873 cookie = 0xA000;
874 break;
875 case 1:
876 cookie = 0xB000;
877 break;
878 case 2:
879 cookie = 0xC000;
880 break;
881 case 3:
882 cookie = 0xD000;
883 break;
884 case 4:
885 cookie = 0xE000;
886 break;
887 case 5:
888 cookie = 0xF000;
889 break;
890 }
891 assert(((u16)slot & 0xF000) == 0x0000);
892 cookie |= (u16)slot;
893
894 return cookie;
895}
896
897/* Inspect a cookie and find out to which controller/slot it belongs. */
898static
899struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
900 u16 cookie, int *slot)
901{
902 struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
903 struct bcm43xx_dmaring *ring = NULL;
904
905 switch (cookie & 0xF000) {
906 case 0xA000:
907 ring = dma->tx_ring0;
908 break;
909 case 0xB000:
910 ring = dma->tx_ring1;
911 break;
912 case 0xC000:
913 ring = dma->tx_ring2;
914 break;
915 case 0xD000:
916 ring = dma->tx_ring3;
917 break;
918 case 0xE000:
919 ring = dma->tx_ring4;
920 break;
921 case 0xF000:
922 ring = dma->tx_ring5;
923 break;
924 default:
925 assert(0);
926 }
927 *slot = (cookie & 0x0FFF);
928 assert(*slot >= 0 && *slot < ring->nr_slots);
929
930 return ring;
931}
932
933static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
934 int slot)
935{
936 u16 offset;
937 int descsize;
938
939 /* Everything is ready to start. Buffers are DMA mapped and
940 * associated with slots.
941 * "slot" is the last slot of the new frame we want to transmit.
942 * Close your seat belts now, please.
943 */
944 wmb();
945 slot = next_slot(ring, slot);
946 offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX;
947 descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64)
948 : sizeof(struct bcm43xx_dmadesc32);
949 bcm43xx_dma_write(ring, offset,
950 (u32)(slot * descsize));
951}
952
953static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
954 struct sk_buff *skb,
955 u8 cur_frag)
956{
957 int slot;
958 struct bcm43xx_dmadesc_generic *desc;
959 struct bcm43xx_dmadesc_meta *meta;
960 dma_addr_t dmaaddr;
961 struct sk_buff *bounce_skb;
962
963 assert(skb_shinfo(skb)->nr_frags == 0);
964
965 slot = request_slot(ring);
966 desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
967
968 /* Add a device specific TX header. */
969 assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
970 /* Reserve enough headroom for the device tx header. */
971 __skb_push(skb, sizeof(struct bcm43xx_txhdr));
972 /* Now calculate and add the tx header.
973 * The tx header includes the PLCP header.
974 */
975 bcm43xx_generate_txhdr(ring->bcm,
976 (struct bcm43xx_txhdr *)skb->data,
977 skb->data + sizeof(struct bcm43xx_txhdr),
978 skb->len - sizeof(struct bcm43xx_txhdr),
979 (cur_frag == 0),
980 generate_cookie(ring, slot));
981 dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
982 if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
983 /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
984 if (!dma_mapping_error(dmaaddr))
985 unmap_descbuffer(ring, dmaaddr, skb->len, 1);
986 bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
987 if (!bounce_skb)
988 return;
989 dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
990 if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
991 if (!dma_mapping_error(dmaaddr))
992 unmap_descbuffer(ring, dmaaddr, skb->len, 1);
993 dev_kfree_skb_any(bounce_skb);
994 assert(0);
995 return;
996 }
997 skb_copy_from_linear_data(skb, skb_put(bounce_skb, skb->len),
998 skb->len);
999 dev_kfree_skb_any(skb);
1000 skb = bounce_skb;
1001 }
1002
1003 meta->skb = skb;
1004 meta->dmaaddr = dmaaddr;
1005
1006 fill_descriptor(ring, desc, dmaaddr,
1007 skb->len, 1, 1, 1);
1008
1009 /* Now transfer the whole frame. */
1010 dmacontroller_poke_tx(ring, slot);
1011}
1012
1013int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
1014 struct ieee80211_txb *txb)
1015{
1016 /* We just received a packet from the kernel network subsystem.
1017 * Add headers and DMA map the memory. Poke
1018 * the device to send the stuff.
1019 * Note that this is called from atomic context.
1020 */
1021 struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
1022 u8 i;
1023 struct sk_buff *skb;
1024
1025 assert(ring->tx);
1026 if (unlikely(free_slots(ring) < txb->nr_frags)) {
1027 /* The queue should be stopped,
1028 * if we are low on free slots.
1029 * If this ever triggers, we have to lower the suspend_mark.
1030 */
1031 dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
1032 return -ENOMEM;
1033 }
1034
1035 for (i = 0; i < txb->nr_frags; i++) {
1036 skb = txb->fragments[i];
1037 /* Take skb from ieee80211_txb_free */
1038 txb->fragments[i] = NULL;
1039 dma_tx_fragment(ring, skb, i);
1040 }
1041 ieee80211_txb_free(txb);
1042
1043 return 0;
1044}
1045
1046void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
1047 struct bcm43xx_xmitstatus *status)
1048{
1049 struct bcm43xx_dmaring *ring;
1050 struct bcm43xx_dmadesc_generic *desc;
1051 struct bcm43xx_dmadesc_meta *meta;
1052 int is_last_fragment;
1053 int slot;
1054 u32 tmp;
1055
1056 ring = parse_cookie(bcm, status->cookie, &slot);
1057 assert(ring);
1058 assert(ring->tx);
1059 while (1) {
1060 assert(slot >= 0 && slot < ring->nr_slots);
1061 desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
1062
1063 if (ring->dma64) {
1064 tmp = le32_to_cpu(desc->dma64.control0);
1065 is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND);
1066 } else {
1067 tmp = le32_to_cpu(desc->dma32.control);
1068 is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND);
1069 }
1070 unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
1071 free_descriptor_buffer(ring, meta, 1);
1072 /* Everything belonging to the slot is unmapped
1073 * and freed, so we can return it.
1074 */
1075 return_slot(ring, slot);
1076
1077 if (is_last_fragment)
1078 break;
1079 slot = next_slot(ring, slot);
1080 }
1081 bcm->stats.last_tx = jiffies;
1082}
1083
1084static void dma_rx(struct bcm43xx_dmaring *ring,
1085 int *slot)
1086{
1087 struct bcm43xx_dmadesc_generic *desc;
1088 struct bcm43xx_dmadesc_meta *meta;
1089 struct bcm43xx_rxhdr *rxhdr;
1090 struct sk_buff *skb;
1091 u16 len;
1092 int err;
1093 dma_addr_t dmaaddr;
1094
1095 desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
1096
1097 sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
1098 skb = meta->skb;
1099
1100 if (ring->index == 3) {
1101 /* We received an xmit status. */
1102 struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
1103 struct bcm43xx_xmitstatus stat;
1104 int i = 0;
1105
1106 stat.cookie = le16_to_cpu(hw->cookie);
1107 while (stat.cookie == 0) {
1108 if (unlikely(++i >= 10000)) {
1109 assert(0);
1110 break;
1111 }
1112 udelay(2);
1113 barrier();
1114 stat.cookie = le16_to_cpu(hw->cookie);
1115 }
1116 stat.flags = hw->flags;
1117 stat.cnt1 = hw->cnt1;
1118 stat.cnt2 = hw->cnt2;
1119 stat.seq = le16_to_cpu(hw->seq);
1120 stat.unknown = le16_to_cpu(hw->unknown);
1121
1122 bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
1123 bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
1124 /* recycle the descriptor buffer. */
1125 sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
1126
1127 return;
1128 }
1129 rxhdr = (struct bcm43xx_rxhdr *)skb->data;
1130 len = le16_to_cpu(rxhdr->frame_length);
1131 if (len == 0) {
1132 int i = 0;
1133
1134 do {
1135 udelay(2);
1136 barrier();
1137 len = le16_to_cpu(rxhdr->frame_length);
1138 } while (len == 0 && i++ < 5);
1139 if (unlikely(len == 0)) {
1140 /* recycle the descriptor buffer. */
1141 sync_descbuffer_for_device(ring, meta->dmaaddr,
1142 ring->rx_buffersize);
1143 goto drop;
1144 }
1145 }
1146 if (unlikely(len > ring->rx_buffersize)) {
1147 /* The data did not fit into one descriptor buffer
1148 * and is split over multiple buffers.
1149 * This should never happen, as we try to allocate buffers
1150 * big enough. So simply ignore this packet.
1151 */
1152 int cnt = 0;
1153 s32 tmp = len;
1154
1155 while (1) {
1156 desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
1157 /* recycle the descriptor buffer. */
1158 sync_descbuffer_for_device(ring, meta->dmaaddr,
1159 ring->rx_buffersize);
1160 *slot = next_slot(ring, *slot);
1161 cnt++;
1162 tmp -= ring->rx_buffersize;
1163 if (tmp <= 0)
1164 break;
1165 }
1166 printkl(KERN_ERR PFX "DMA RX buffer too small "
1167 "(len: %u, buffer: %u, nr-dropped: %d)\n",
1168 len, ring->rx_buffersize, cnt);
1169 goto drop;
1170 }
1171 len -= IEEE80211_FCS_LEN;
1172
1173 dmaaddr = meta->dmaaddr;
1174 err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
1175 if (unlikely(err)) {
1176 dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
1177 sync_descbuffer_for_device(ring, dmaaddr,
1178 ring->rx_buffersize);
1179 goto drop;
1180 }
1181
1182 unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
1183 skb_put(skb, len + ring->frameoffset);
1184 skb_pull(skb, ring->frameoffset);
1185
1186 err = bcm43xx_rx(ring->bcm, skb, rxhdr);
1187 if (err) {
1188 dev_kfree_skb_irq(skb);
1189 goto drop;
1190 }
1191
1192drop:
1193 return;
1194}
1195
1196void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
1197{
1198 u32 status;
1199 u16 descptr;
1200 int slot, current_slot;
1201#ifdef CONFIG_BCM43XX_DEBUG
1202 int used_slots = 0;
1203#endif
1204
1205 assert(!ring->tx);
1206 if (ring->dma64) {
1207 status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS);
1208 descptr = (status & BCM43xx_DMA64_RXSTATDPTR);
1209 current_slot = descptr / sizeof(struct bcm43xx_dmadesc64);
1210 } else {
1211 status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS);
1212 descptr = (status & BCM43xx_DMA32_RXDPTR);
1213 current_slot = descptr / sizeof(struct bcm43xx_dmadesc32);
1214 }
1215 assert(current_slot >= 0 && current_slot < ring->nr_slots);
1216
1217 slot = ring->current_slot;
1218 for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
1219 dma_rx(ring, &slot);
1220#ifdef CONFIG_BCM43XX_DEBUG
1221 if (++used_slots > ring->max_used_slots)
1222 ring->max_used_slots = used_slots;
1223#endif
1224 }
1225 if (ring->dma64) {
1226 bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX,
1227 (u32)(slot * sizeof(struct bcm43xx_dmadesc64)));
1228 } else {
1229 bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX,
1230 (u32)(slot * sizeof(struct bcm43xx_dmadesc32)));
1231 }
1232 ring->current_slot = slot;
1233}
1234
1235void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
1236{
1237 assert(ring->tx);
1238 bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
1239 if (ring->dma64) {
1240 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
1241 bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
1242 | BCM43xx_DMA64_TXSUSPEND);
1243 } else {
1244 bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
1245 bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
1246 | BCM43xx_DMA32_TXSUSPEND);
1247 }
1248}
1249
1250void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
1251{
1252 assert(ring->tx);
1253 if (ring->dma64) {
1254 bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
1255 bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
1256 & ~BCM43xx_DMA64_TXSUSPEND);
1257 } else {
1258 bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
1259 bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
1260 & ~BCM43xx_DMA32_TXSUSPEND);
1261 }
1262 bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
1263}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
deleted file mode 100644
index d1105e569a41..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ /dev/null
@@ -1,386 +0,0 @@
1#ifndef BCM43xx_DMA_H_
2#define BCM43xx_DMA_H_
3
4#include <linux/list.h>
5#include <linux/spinlock.h>
6#include <linux/workqueue.h>
7#include <linux/dma-mapping.h>
8#include <linux/linkage.h>
9#include <asm/atomic.h>
10
11
12/* DMA-Interrupt reasons. */
13#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
14 | (1 << 14) | (1 << 15))
15#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13)
16#define BCM43xx_DMAIRQ_RX_DONE (1 << 16)
17
18
19/*** 32-bit DMA Engine. ***/
20
21/* 32-bit DMA controller registers. */
22#define BCM43xx_DMA32_TXCTL 0x00
23#define BCM43xx_DMA32_TXENABLE 0x00000001
24#define BCM43xx_DMA32_TXSUSPEND 0x00000002
25#define BCM43xx_DMA32_TXLOOPBACK 0x00000004
26#define BCM43xx_DMA32_TXFLUSH 0x00000010
27#define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000
28#define BCM43xx_DMA32_TXADDREXT_SHIFT 16
29#define BCM43xx_DMA32_TXRING 0x04
30#define BCM43xx_DMA32_TXINDEX 0x08
31#define BCM43xx_DMA32_TXSTATUS 0x0C
32#define BCM43xx_DMA32_TXDPTR 0x00000FFF
33#define BCM43xx_DMA32_TXSTATE 0x0000F000
34#define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000
35#define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000
36#define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000
37#define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000
38#define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000
39#define BCM43xx_DMA32_TXERROR 0x000F0000
40#define BCM43xx_DMA32_TXERR_NOERR 0x00000000
41#define BCM43xx_DMA32_TXERR_PROT 0x00010000
42#define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000
43#define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000
44#define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000
45#define BCM43xx_DMA32_TXACTIVE 0xFFF00000
46#define BCM43xx_DMA32_RXCTL 0x10
47#define BCM43xx_DMA32_RXENABLE 0x00000001
48#define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE
49#define BCM43xx_DMA32_RXFROFF_SHIFT 1
50#define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100
51#define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000
52#define BCM43xx_DMA32_RXADDREXT_SHIFT 16
53#define BCM43xx_DMA32_RXRING 0x14
54#define BCM43xx_DMA32_RXINDEX 0x18
55#define BCM43xx_DMA32_RXSTATUS 0x1C
56#define BCM43xx_DMA32_RXDPTR 0x00000FFF
57#define BCM43xx_DMA32_RXSTATE 0x0000F000
58#define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000
59#define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000
60#define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000
61#define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000
62#define BCM43xx_DMA32_RXERROR 0x000F0000
63#define BCM43xx_DMA32_RXERR_NOERR 0x00000000
64#define BCM43xx_DMA32_RXERR_PROT 0x00010000
65#define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000
66#define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000
67#define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000
68#define BCM43xx_DMA32_RXACTIVE 0xFFF00000
69
70/* 32-bit DMA descriptor. */
71struct bcm43xx_dmadesc32 {
72 __le32 control;
73 __le32 address;
74} __attribute__((__packed__));
75#define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF
76#define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000
77#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16
78#define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000
79#define BCM43xx_DMA32_DCTL_IRQ 0x20000000
80#define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000
81#define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000
82
83/* Address field Routing value. */
84#define BCM43xx_DMA32_ROUTING 0xC0000000
85#define BCM43xx_DMA32_ROUTING_SHIFT 30
86#define BCM43xx_DMA32_NOTRANS 0x00000000
87#define BCM43xx_DMA32_CLIENTTRANS 0x40000000
88
89
90
91/*** 64-bit DMA Engine. ***/
92
93/* 64-bit DMA controller registers. */
94#define BCM43xx_DMA64_TXCTL 0x00
95#define BCM43xx_DMA64_TXENABLE 0x00000001
96#define BCM43xx_DMA64_TXSUSPEND 0x00000002
97#define BCM43xx_DMA64_TXLOOPBACK 0x00000004
98#define BCM43xx_DMA64_TXFLUSH 0x00000010
99#define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000
100#define BCM43xx_DMA64_TXADDREXT_SHIFT 16
101#define BCM43xx_DMA64_TXINDEX 0x04
102#define BCM43xx_DMA64_TXRINGLO 0x08
103#define BCM43xx_DMA64_TXRINGHI 0x0C
104#define BCM43xx_DMA64_TXSTATUS 0x10
105#define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF
106#define BCM43xx_DMA64_TXSTAT 0xF0000000
107#define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000
108#define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000
109#define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000
110#define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000
111#define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000
112#define BCM43xx_DMA64_TXERROR 0x14
113#define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF
114#define BCM43xx_DMA64_TXERR 0xF0000000
115#define BCM43xx_DMA64_TXERR_NOERR 0x00000000
116#define BCM43xx_DMA64_TXERR_PROT 0x10000000
117#define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000
118#define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000
119#define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000
120#define BCM43xx_DMA64_TXERR_CORE 0x50000000
121#define BCM43xx_DMA64_RXCTL 0x20
122#define BCM43xx_DMA64_RXENABLE 0x00000001
123#define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE
124#define BCM43xx_DMA64_RXFROFF_SHIFT 1
125#define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100
126#define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000
127#define BCM43xx_DMA64_RXADDREXT_SHIFT 16
128#define BCM43xx_DMA64_RXINDEX 0x24
129#define BCM43xx_DMA64_RXRINGLO 0x28
130#define BCM43xx_DMA64_RXRINGHI 0x2C
131#define BCM43xx_DMA64_RXSTATUS 0x30
132#define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF
133#define BCM43xx_DMA64_RXSTAT 0xF0000000
134#define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000
135#define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000
136#define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000
137#define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000
138#define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000
139#define BCM43xx_DMA64_RXERROR 0x34
140#define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF
141#define BCM43xx_DMA64_RXERR 0xF0000000
142#define BCM43xx_DMA64_RXERR_NOERR 0x00000000
143#define BCM43xx_DMA64_RXERR_PROT 0x10000000
144#define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000
145#define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000
146#define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000
147#define BCM43xx_DMA64_RXERR_CORE 0x50000000
148
149/* 64-bit DMA descriptor. */
150struct bcm43xx_dmadesc64 {
151 __le32 control0;
152 __le32 control1;
153 __le32 address_low;
154 __le32 address_high;
155} __attribute__((__packed__));
156#define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000
157#define BCM43xx_DMA64_DCTL0_IRQ 0x20000000
158#define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000
159#define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000
160#define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF
161#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000
162#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16
163
164/* Address field Routing value. */
165#define BCM43xx_DMA64_ROUTING 0xC0000000
166#define BCM43xx_DMA64_ROUTING_SHIFT 30
167#define BCM43xx_DMA64_NOTRANS 0x00000000
168#define BCM43xx_DMA64_CLIENTTRANS 0x80000000
169
170
171
172struct bcm43xx_dmadesc_generic {
173 union {
174 struct bcm43xx_dmadesc32 dma32;
175 struct bcm43xx_dmadesc64 dma64;
176 } __attribute__((__packed__));
177} __attribute__((__packed__));
178
179
180/* Misc DMA constants */
181#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE
182#define BCM43xx_DMA0_RX_FRAMEOFFSET 30
183#define BCM43xx_DMA3_RX_FRAMEOFFSET 0
184
185
186/* DMA engine tuning knobs */
187#define BCM43xx_TXRING_SLOTS 512
188#define BCM43xx_RXRING_SLOTS 64
189#define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100)
190#define BCM43xx_DMA3_RX_BUFFERSIZE 16
191/* Suspend the tx queue, if less than this percent slots are free. */
192#define BCM43xx_TXSUSPEND_PERCENT 20
193/* Resume the tx queue, if more than this percent slots are free. */
194#define BCM43xx_TXRESUME_PERCENT 50
195
196
197
198#ifdef CONFIG_BCM43XX_DMA
199
200
201struct sk_buff;
202struct bcm43xx_private;
203struct bcm43xx_xmitstatus;
204
205
206struct bcm43xx_dmadesc_meta {
207 /* The kernel DMA-able buffer. */
208 struct sk_buff *skb;
209 /* DMA base bus-address of the descriptor buffer. */
210 dma_addr_t dmaaddr;
211};
212
213struct bcm43xx_dmaring {
214 /* Kernel virtual base address of the ring memory. */
215 void *descbase;
216 /* Meta data about all descriptors. */
217 struct bcm43xx_dmadesc_meta *meta;
218 /* DMA Routing value. */
219 u32 routing;
220 /* (Unadjusted) DMA base bus-address of the ring memory. */
221 dma_addr_t dmabase;
222 /* Number of descriptor slots in the ring. */
223 int nr_slots;
224 /* Number of used descriptor slots. */
225 int used_slots;
226 /* Currently used slot in the ring. */
227 int current_slot;
228 /* Marks to suspend/resume the queue. */
229 int suspend_mark;
230 int resume_mark;
231 /* Frameoffset in octets. */
232 u32 frameoffset;
233 /* Descriptor buffer size. */
234 u16 rx_buffersize;
235 /* The MMIO base register of the DMA controller. */
236 u16 mmio_base;
237 /* DMA controller index number (0-5). */
238 int index;
239 /* Boolean. Is this a TX ring? */
240 u8 tx;
241 /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
242 u8 dma64;
243 /* Boolean. Are transfers suspended on this ring? */
244 u8 suspended;
245 struct bcm43xx_private *bcm;
246#ifdef CONFIG_BCM43XX_DEBUG
247 /* Maximum number of used slots. */
248 int max_used_slots;
249#endif /* CONFIG_BCM43XX_DEBUG*/
250};
251
252
253static inline
254int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring,
255 struct bcm43xx_dmadesc_generic *desc)
256{
257 if (ring->dma64) {
258 struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
259 return (int)(&(desc->dma64) - dd64);
260 } else {
261 struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
262 return (int)(&(desc->dma32) - dd32);
263 }
264}
265
266static inline
267struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring,
268 int slot,
269 struct bcm43xx_dmadesc_meta **meta)
270{
271 *meta = &(ring->meta[slot]);
272 if (ring->dma64) {
273 struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
274 return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot]));
275 } else {
276 struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
277 return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot]));
278 }
279}
280
281static inline
282u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
283 u16 offset)
284{
285 return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
286}
287
288static inline
289void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
290 u16 offset, u32 value)
291{
292 bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
293}
294
295
296int bcm43xx_dma_init(struct bcm43xx_private *bcm);
297void bcm43xx_dma_free(struct bcm43xx_private *bcm);
298
299int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
300 u16 dmacontroller_mmio_base,
301 int dma64);
302int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
303 u16 dmacontroller_mmio_base,
304 int dma64);
305
306u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx);
307
308void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
309void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
310
311void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
312 struct bcm43xx_xmitstatus *status);
313
314int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
315 struct ieee80211_txb *txb);
316void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
317
318/* Helper function that returns the dma mask for this device. */
319static inline
320u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
321{
322 int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
323 BCM43xx_SBTMSTATEHIGH_DMA64BIT;
324 u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
325 u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
326
327 if (dma64)
328 return DMA_64BIT_MASK;
329 bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
330 if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
331 return DMA_32BIT_MASK;
332 return DMA_30BIT_MASK;
333}
334
335#else /* CONFIG_BCM43XX_DMA */
336
337
338static inline
339int bcm43xx_dma_init(struct bcm43xx_private *bcm)
340{
341 return 0;
342}
343static inline
344void bcm43xx_dma_free(struct bcm43xx_private *bcm)
345{
346}
347static inline
348int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
349 u16 dmacontroller_mmio_base,
350 int dma64)
351{
352 return 0;
353}
354static inline
355int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
356 u16 dmacontroller_mmio_base,
357 int dma64)
358{
359 return 0;
360}
361static inline
362int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
363 struct ieee80211_txb *txb)
364{
365 return 0;
366}
367static inline
368void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
369 struct bcm43xx_xmitstatus *status)
370{
371}
372static inline
373void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
374{
375}
376static inline
377void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
378{
379}
380static inline
381void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
382{
383}
384
385#endif /* CONFIG_BCM43XX_DMA */
386#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
deleted file mode 100644
index d2df6a0100a1..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 ethtool support
6
7 Copyright (c) 2006 Jason Lunz <lunz@falooley.org>
8
9 Some code in this file is derived from the 8139too.c driver
10 Copyright (C) 2002 Jeff Garzik
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; see the file COPYING. If not, write to
24 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
25 Boston, MA 02110-1301, USA.
26
27*/
28
29#include "bcm43xx.h"
30#include "bcm43xx_ethtool.h"
31
32#include <linux/netdevice.h>
33#include <linux/pci.h>
34#include <linux/string.h>
35#include <linux/utsname.h>
36
37
38static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
39{
40 struct bcm43xx_private *bcm = bcm43xx_priv(dev);
41
42 strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
43 strncpy(info->version, utsname()->release, sizeof(info->version));
44 strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
45}
46
47const struct ethtool_ops bcm43xx_ethtool_ops = {
48 .get_drvinfo = bcm43xx_get_drvinfo,
49 .get_link = ethtool_op_get_link,
50};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
deleted file mode 100644
index 6f8d42d3cdf5..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
+++ /dev/null
@@ -1,8 +0,0 @@
1#ifndef BCM43xx_ETHTOOL_H_
2#define BCM43xx_ETHTOOL_H_
3
4#include <linux/ethtool.h>
5
6extern const struct ethtool_ops bcm43xx_ethtool_ops;
7
8#endif /* BCM43xx_ETHTOOL_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
deleted file mode 100644
index f2b8dbac55a4..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
+++ /dev/null
@@ -1,352 +0,0 @@
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 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
24 Boston, MA 02110-1301, USA.
25
26*/
27
28#include "bcm43xx.h"
29#include "bcm43xx_ilt.h"
30#include "bcm43xx_phy.h"
31
32
33/**** Initial Internal Lookup Tables ****/
34
35const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
36 0xFEB93FFD, 0xFEC63FFD, /* 0 */
37 0xFED23FFD, 0xFEDF3FFD,
38 0xFEEC3FFE, 0xFEF83FFE,
39 0xFF053FFE, 0xFF113FFE,
40 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
41 0xFF373FFF, 0xFF443FFF,
42 0xFF503FFF, 0xFF5D3FFF,
43 0xFF693FFF, 0xFF763FFF,
44 0xFF824000, 0xFF8F4000, /* 16 */
45 0xFF9B4000, 0xFFA84000,
46 0xFFB54000, 0xFFC14000,
47 0xFFCE4000, 0xFFDA4000,
48 0xFFE74000, 0xFFF34000, /* 24 */
49 0x00004000, 0x000D4000,
50 0x00194000, 0x00264000,
51 0x00324000, 0x003F4000,
52 0x004B4000, 0x00584000, /* 32 */
53 0x00654000, 0x00714000,
54 0x007E4000, 0x008A3FFF,
55 0x00973FFF, 0x00A33FFF,
56 0x00B03FFF, 0x00BC3FFF, /* 40 */
57 0x00C93FFF, 0x00D63FFF,
58 0x00E23FFE, 0x00EF3FFE,
59 0x00FB3FFE, 0x01083FFE,
60 0x01143FFE, 0x01213FFD, /* 48 */
61 0x012E3FFD, 0x013A3FFD,
62 0x01473FFD,
63};
64
65const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
66 0xDB93CB87, 0xD666CF64, /* 0 */
67 0xD1FDD358, 0xCDA6D826,
68 0xCA38DD9F, 0xC729E2B4,
69 0xC469E88E, 0xC26AEE2B,
70 0xC0DEF46C, 0xC073FA62, /* 8 */
71 0xC01D00D5, 0xC0760743,
72 0xC1560D1E, 0xC2E51369,
73 0xC4ED18FF, 0xC7AC1ED7,
74 0xCB2823B2, 0xCEFA28D9, /* 16 */
75 0xD2F62D3F, 0xD7BB3197,
76 0xDCE53568, 0xE1FE3875,
77 0xE7D13B35, 0xED663D35,
78 0xF39B3EC4, 0xF98E3FA7, /* 24 */
79 0x00004000, 0x06723FA7,
80 0x0C653EC4, 0x129A3D35,
81 0x182F3B35, 0x1E023875,
82 0x231B3568, 0x28453197, /* 32 */
83 0x2D0A2D3F, 0x310628D9,
84 0x34D823B2, 0x38541ED7,
85 0x3B1318FF, 0x3D1B1369,
86 0x3EAA0D1E, 0x3F8A0743, /* 40 */
87 0x3FE300D5, 0x3F8DFA62,
88 0x3F22F46C, 0x3D96EE2B,
89 0x3B97E88E, 0x38D7E2B4,
90 0x35C8DD9F, 0x325AD826, /* 48 */
91 0x2E03D358, 0x299ACF64,
92 0x246DCB87,
93};
94
95const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
96 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
97 0x0202, 0x0282, 0x0302, 0x0382,
98 0x0402, 0x0482, 0x0502, 0x0582,
99 0x05E2, 0x0662, 0x06E2, 0x0762,
100 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
101 0x09C2, 0x0A22, 0x0AA2, 0x0B02,
102 0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
103 0x0D42, 0x0DA2, 0x0E02, 0x0E62,
104 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
105 0x1062, 0x10C2, 0x1122, 0x1182,
106 0x11E2, 0x1242, 0x12A2, 0x12E2,
107 0x1342, 0x13A2, 0x1402, 0x1442,
108 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
109 0x15E2, 0x1622, 0x1662, 0x16C1,
110 0x1701, 0x1741, 0x1781, 0x17E1,
111 0x1821, 0x1861, 0x18A1, 0x18E1,
112 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
113 0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
114 0x1B01, 0x1B41, 0x1B81, 0x1BA1,
115 0x1BE1, 0x1C21, 0x1C41, 0x1C81,
116 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
117 0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
118 0x1E21, 0x1E61, 0x1E81, 0x1EA1,
119 0x1EE1, 0x1F01, 0x1F21, 0x1F41,
120 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
121 0x2001, 0x2041, 0x2061, 0x2081,
122 0x20A1, 0x20C1, 0x20E1, 0x2101,
123 0x2121, 0x2141, 0x2161, 0x2181,
124 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
125 0x2221, 0x2241, 0x2261, 0x2281,
126 0x22A1, 0x22C1, 0x22C1, 0x22E1,
127 0x2301, 0x2321, 0x2341, 0x2361,
128 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
129 0x23E1, 0x23E1, 0x2401, 0x2421,
130 0x2441, 0x2441, 0x2461, 0x2481,
131 0x2481, 0x24A1, 0x24C1, 0x24C1,
132 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
133 0x2541, 0x2541, 0x2561, 0x2561,
134 0x2581, 0x25A1, 0x25A1, 0x25C1,
135 0x25C1, 0x25E1, 0x2601, 0x2601,
136 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
137 0x2661, 0x2661, 0x2681, 0x2681,
138 0x26A1, 0x26A1, 0x26C1, 0x26C1,
139 0x26E1, 0x26E1, 0x2701, 0x2701,
140 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
141 0x2760, 0x2760, 0x2780, 0x2780,
142 0x2780, 0x27A0, 0x27A0, 0x27C0,
143 0x27C0, 0x27E0, 0x27E0, 0x27E0,
144 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
145 0x2820, 0x2840, 0x2840, 0x2840,
146 0x2860, 0x2860, 0x2880, 0x2880,
147 0x2880, 0x28A0, 0x28A0, 0x28A0,
148 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
149 0x28E0, 0x28E0, 0x2900, 0x2900,
150 0x2900, 0x2920, 0x2920, 0x2920,
151 0x2940, 0x2940, 0x2940, 0x2960,
152 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
153 0x2980, 0x2980, 0x29A0, 0x29A0,
154 0x29A0, 0x29A0, 0x29C0, 0x29C0,
155 0x29C0, 0x29E0, 0x29E0, 0x29E0,
156 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
157 0x2A00, 0x2A20, 0x2A20, 0x2A20,
158 0x2A20, 0x2A40, 0x2A40, 0x2A40,
159 0x2A40, 0x2A60, 0x2A60, 0x2A60,
160};
161
162const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
163 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
164 0x05A9, 0x0669, 0x0709, 0x0789,
165 0x0829, 0x08A9, 0x0929, 0x0989,
166 0x0A09, 0x0A69, 0x0AC9, 0x0B29,
167 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
168 0x0D09, 0x0D69, 0x0DA9, 0x0E09,
169 0x0E69, 0x0EA9, 0x0F09, 0x0F49,
170 0x0FA9, 0x0FE9, 0x1029, 0x1089,
171 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
172 0x11E9, 0x1229, 0x1289, 0x12C9,
173 0x1309, 0x1349, 0x1389, 0x13C9,
174 0x1409, 0x1449, 0x14A9, 0x14E9,
175 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
176 0x1629, 0x1669, 0x16A9, 0x16E8,
177 0x1728, 0x1768, 0x17A8, 0x17E8,
178 0x1828, 0x1868, 0x18A8, 0x18E8,
179 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
180 0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
181 0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
182 0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
183 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
184 0x1E48, 0x1E88, 0x1EC8, 0x1F08,
185 0x1F48, 0x1F88, 0x1FE8, 0x2028,
186 0x2068, 0x20A8, 0x2108, 0x2148,
187 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
188 0x22C8, 0x2308, 0x2348, 0x23A8,
189 0x23E8, 0x2448, 0x24A8, 0x24E8,
190 0x2548, 0x25A8, 0x2608, 0x2668,
191 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
192 0x2847, 0x28C7, 0x2947, 0x29A7,
193 0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
194 0x2CA7, 0x2D67, 0x2E47, 0x2F67,
195 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
196 0x3806, 0x38A6, 0x3946, 0x39E6,
197 0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
198 0x3C45, 0x3CA5, 0x3D05, 0x3D85,
199 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
200 0x3F45, 0x3FA5, 0x4005, 0x4045,
201 0x40A5, 0x40E5, 0x4145, 0x4185,
202 0x41E5, 0x4225, 0x4265, 0x42C5,
203 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
204 0x4424, 0x4464, 0x44C4, 0x4504,
205 0x4544, 0x4584, 0x45C4, 0x4604,
206 0x4644, 0x46A4, 0x46E4, 0x4724,
207 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
208 0x4864, 0x48A4, 0x48E4, 0x4924,
209 0x4964, 0x49A4, 0x49E4, 0x4A24,
210 0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
211 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
212 0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
213 0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
214 0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
215 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
216 0x5083, 0x50C3, 0x5103, 0x5143,
217 0x5183, 0x51E2, 0x5222, 0x5262,
218 0x52A2, 0x52E2, 0x5342, 0x5382,
219 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
220 0x5502, 0x5542, 0x55A2, 0x55E2,
221 0x5642, 0x5682, 0x56E2, 0x5722,
222 0x5782, 0x57E1, 0x5841, 0x58A1,
223 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
224 0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
225 0x5C61, 0x5D01, 0x5D80, 0x5E20,
226 0x5EE0, 0x5FA0, 0x6080, 0x61C0,
227};
228
229const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
230 0x0001, 0x0001, 0x0001, 0xFFFE,
231 0xFFFE, 0x3FFF, 0x1000, 0x0393,
232};
233
234const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
235 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
236 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
237};
238
239const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
240 0x013C, 0x01F5, 0x031A, 0x0631,
241 0x0001, 0x0001, 0x0001, 0x0001,
242};
243
244const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
245 0x5484, 0x3C40, 0x0000, 0x0000,
246 0x0000, 0x0000, 0x0000, 0x0000,
247};
248
249const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
250 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
251 0x2F2D, 0x2A2A, 0x2527, 0x1F21,
252 0x1A1D, 0x1719, 0x1616, 0x1414,
253 0x1414, 0x1400, 0x1414, 0x1614,
254 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
255 0x2A27, 0x2F2A, 0x332D, 0x3B35,
256 0x5140, 0x6C62, 0x0077,
257};
258
259const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
260 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
261 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
262 0x969B, 0x9195, 0x8F8F, 0x8A8A,
263 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
264 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
265 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
266 0xCBC0, 0xD8D4, 0x00DD,
267};
268
269const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
270 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
271 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
272 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
273 0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
274 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
275 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
276 0xA4A4, 0xA4A4, 0x00A4,
277};
278
279const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
280 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
281 0x0067, 0x0063, 0x005E, 0x0059,
282 0x0054, 0x0050, 0x004B, 0x0046,
283 0x0042, 0x003D, 0x003D, 0x003D,
284 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
285 0x003D, 0x003D, 0x003D, 0x003D,
286 0x003D, 0x003D, 0x0000, 0x003D,
287 0x003D, 0x003D, 0x003D, 0x003D,
288 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
289 0x003D, 0x003D, 0x003D, 0x003D,
290 0x0042, 0x0046, 0x004B, 0x0050,
291 0x0054, 0x0059, 0x005E, 0x0063,
292 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
293 0x007A,
294};
295
296const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
297 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
298 0x00D6, 0x00D4, 0x00D2, 0x00CF,
299 0x00CD, 0x00CA, 0x00C7, 0x00C4,
300 0x00C1, 0x00BE, 0x00BE, 0x00BE,
301 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
302 0x00BE, 0x00BE, 0x00BE, 0x00BE,
303 0x00BE, 0x00BE, 0x0000, 0x00BE,
304 0x00BE, 0x00BE, 0x00BE, 0x00BE,
305 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
306 0x00BE, 0x00BE, 0x00BE, 0x00BE,
307 0x00C1, 0x00C4, 0x00C7, 0x00CA,
308 0x00CD, 0x00CF, 0x00D2, 0x00D4,
309 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
310 0x00DE,
311};
312
313/**** Helper functions to access the device Internal Lookup Tables ****/
314
315void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
316{
317 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
318 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
319 mmiowb();
320 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
321 } else {
322 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
323 mmiowb();
324 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
325 }
326}
327
328void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
329{
330 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
331 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
332 mmiowb();
333 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
334 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
335 } else {
336 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
337 mmiowb();
338 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
339 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
340 }
341}
342
343u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
344{
345 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
346 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
347 return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
348 } else {
349 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
350 return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
351 }
352}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
deleted file mode 100644
index d7eaf5f25b7f..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
+++ /dev/null
@@ -1,33 +0,0 @@
1#ifndef BCM43xx_ILT_H_
2#define BCM43xx_ILT_H_
3
4#define BCM43xx_ILT_ROTOR_SIZE 53
5extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
6#define BCM43xx_ILT_RETARD_SIZE 53
7extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
8#define BCM43xx_ILT_FINEFREQA_SIZE 256
9extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
10#define BCM43xx_ILT_FINEFREQG_SIZE 256
11extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
12#define BCM43xx_ILT_NOISEA2_SIZE 8
13extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
14#define BCM43xx_ILT_NOISEA3_SIZE 8
15extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
16#define BCM43xx_ILT_NOISEG1_SIZE 8
17extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
18#define BCM43xx_ILT_NOISEG2_SIZE 8
19extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
20#define BCM43xx_ILT_NOISESCALEG_SIZE 27
21extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
22extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
23extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
24#define BCM43xx_ILT_SIGMASQR_SIZE 53
25extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
26extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
27
28
29void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
30void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
31u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
32
33#endif /* BCM43xx_ILT_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
deleted file mode 100644
index cb51dc51cce6..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+++ /dev/null
@@ -1,307 +0,0 @@
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 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
24 Boston, MA 02110-1301, USA.
25
26*/
27
28#include "bcm43xx_leds.h"
29#include "bcm43xx_radio.h"
30#include "bcm43xx.h"
31
32#include <linux/bitops.h>
33
34
35static void bcm43xx_led_changestate(struct bcm43xx_led *led)
36{
37 struct bcm43xx_private *bcm = led->bcm;
38 const int index = bcm43xx_led_index(led);
39 const u16 mask = (1 << index);
40 u16 ledctl;
41
42 assert(index >= 0 && index < BCM43xx_NR_LEDS);
43 assert(led->blink_interval);
44 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
45 ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
46 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
47}
48
49static void bcm43xx_led_blink(unsigned long d)
50{
51 struct bcm43xx_led *led = (struct bcm43xx_led *)d;
52 struct bcm43xx_private *bcm = led->bcm;
53 unsigned long flags;
54
55 spin_lock_irqsave(&bcm->leds_lock, flags);
56 if (led->blink_interval) {
57 bcm43xx_led_changestate(led);
58 mod_timer(&led->blink_timer, jiffies + led->blink_interval);
59 }
60 spin_unlock_irqrestore(&bcm->leds_lock, flags);
61}
62
63static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
64 unsigned long interval)
65{
66 if (led->blink_interval)
67 return;
68 led->blink_interval = interval;
69 bcm43xx_led_changestate(led);
70 led->blink_timer.expires = jiffies + interval;
71 add_timer(&led->blink_timer);
72}
73
74static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
75{
76 struct bcm43xx_private *bcm = led->bcm;
77 const int index = bcm43xx_led_index(led);
78 u16 ledctl;
79
80 if (!led->blink_interval)
81 return;
82 if (unlikely(sync))
83 del_timer_sync(&led->blink_timer);
84 else
85 del_timer(&led->blink_timer);
86 led->blink_interval = 0;
87
88 /* Make sure the LED is turned off. */
89 assert(index >= 0 && index < BCM43xx_NR_LEDS);
90 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
91 if (led->activelow)
92 ledctl |= (1 << index);
93 else
94 ledctl &= ~(1 << index);
95 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
96}
97
98static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
99 struct bcm43xx_led *led,
100 int led_index)
101{
102 /* This function is called, if the behaviour (and activelow)
103 * information for a LED is missing in the SPROM.
104 * We hardcode the behaviour values for various devices here.
105 * Note that the BCM43xx_LED_TEST_XXX behaviour values can
106 * be used to figure out which led is mapped to which index.
107 */
108
109 switch (led_index) {
110 case 0:
111 led->behaviour = BCM43xx_LED_ACTIVITY;
112 led->activelow = 1;
113 if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
114 led->behaviour = BCM43xx_LED_RADIO_ALL;
115 break;
116 case 1:
117 led->behaviour = BCM43xx_LED_RADIO_B;
118 if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
119 led->behaviour = BCM43xx_LED_ASSOC;
120 break;
121 case 2:
122 led->behaviour = BCM43xx_LED_RADIO_A;
123 break;
124 case 3:
125 led->behaviour = BCM43xx_LED_OFF;
126 break;
127 default:
128 assert(0);
129 }
130}
131
132int bcm43xx_leds_init(struct bcm43xx_private *bcm)
133{
134 struct bcm43xx_led *led;
135 u8 sprom[4];
136 int i;
137
138 sprom[0] = bcm->sprom.wl0gpio0;
139 sprom[1] = bcm->sprom.wl0gpio1;
140 sprom[2] = bcm->sprom.wl0gpio2;
141 sprom[3] = bcm->sprom.wl0gpio3;
142
143 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
144 led = &(bcm->leds[i]);
145 led->bcm = bcm;
146 setup_timer(&led->blink_timer,
147 bcm43xx_led_blink,
148 (unsigned long)led);
149
150 if (sprom[i] == 0xFF) {
151 bcm43xx_led_init_hardcoded(bcm, led, i);
152 } else {
153 led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
154 led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
155 }
156 }
157
158 return 0;
159}
160
161void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
162{
163 struct bcm43xx_led *led;
164 int i;
165
166 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
167 led = &(bcm->leds[i]);
168 bcm43xx_led_blink_stop(led, 1);
169 }
170 bcm43xx_leds_switch_all(bcm, 0);
171}
172
173void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
174{
175 struct bcm43xx_led *led;
176 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
177 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
178 const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
179 int i, turn_on;
180 unsigned long interval = 0;
181 u16 ledctl;
182 unsigned long flags;
183
184 spin_lock_irqsave(&bcm->leds_lock, flags);
185 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
186 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
187 led = &(bcm->leds[i]);
188
189 turn_on = 0;
190 switch (led->behaviour) {
191 case BCM43xx_LED_INACTIVE:
192 continue;
193 case BCM43xx_LED_OFF:
194 case BCM43xx_LED_BCM4303_3:
195 break;
196 case BCM43xx_LED_ON:
197 turn_on = 1;
198 break;
199 case BCM43xx_LED_ACTIVITY:
200 case BCM43xx_LED_BCM4303_0:
201 turn_on = activity;
202 break;
203 case BCM43xx_LED_RADIO_ALL:
204 turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm);
205 break;
206 case BCM43xx_LED_RADIO_A:
207 case BCM43xx_LED_BCM4303_2:
208 turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
209 phy->type == BCM43xx_PHYTYPE_A);
210 break;
211 case BCM43xx_LED_RADIO_B:
212 case BCM43xx_LED_BCM4303_1:
213 turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
214 (phy->type == BCM43xx_PHYTYPE_B ||
215 phy->type == BCM43xx_PHYTYPE_G));
216 break;
217 case BCM43xx_LED_MODE_BG:
218 if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) &&
219 1/*FIXME: using G rates.*/)
220 turn_on = 1;
221 break;
222 case BCM43xx_LED_TRANSFER:
223 if (transferring)
224 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
225 else
226 bcm43xx_led_blink_stop(led, 0);
227 continue;
228 case BCM43xx_LED_APTRANSFER:
229 if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
230 if (transferring) {
231 interval = BCM43xx_LEDBLINK_FAST;
232 turn_on = 1;
233 }
234 } else {
235 turn_on = 1;
236 if (0/*TODO: not assoc*/)
237 interval = BCM43xx_LEDBLINK_SLOW;
238 else if (transferring)
239 interval = BCM43xx_LEDBLINK_FAST;
240 else
241 turn_on = 0;
242 }
243 if (turn_on)
244 bcm43xx_led_blink_start(led, interval);
245 else
246 bcm43xx_led_blink_stop(led, 0);
247 continue;
248 case BCM43xx_LED_WEIRD:
249 //TODO
250 break;
251 case BCM43xx_LED_ASSOC:
252 if (bcm->softmac->associnfo.associated)
253 turn_on = 1;
254 break;
255#ifdef CONFIG_BCM43XX_DEBUG
256 case BCM43xx_LED_TEST_BLINKSLOW:
257 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
258 continue;
259 case BCM43xx_LED_TEST_BLINKMEDIUM:
260 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
261 continue;
262 case BCM43xx_LED_TEST_BLINKFAST:
263 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
264 continue;
265#endif /* CONFIG_BCM43XX_DEBUG */
266 default:
267 dprintkl(KERN_INFO PFX "Bad value in leds_update,"
268 " led->behaviour: 0x%x\n", led->behaviour);
269 };
270
271 if (led->activelow)
272 turn_on = !turn_on;
273 if (turn_on)
274 ledctl |= (1 << i);
275 else
276 ledctl &= ~(1 << i);
277 }
278 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
279 spin_unlock_irqrestore(&bcm->leds_lock, flags);
280}
281
282void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
283{
284 struct bcm43xx_led *led;
285 u16 ledctl;
286 int i;
287 int bit_on;
288 unsigned long flags;
289
290 spin_lock_irqsave(&bcm->leds_lock, flags);
291 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
292 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
293 led = &(bcm->leds[i]);
294 if (led->behaviour == BCM43xx_LED_INACTIVE)
295 continue;
296 if (on)
297 bit_on = led->activelow ? 0 : 1;
298 else
299 bit_on = led->activelow ? 1 : 0;
300 if (bit_on)
301 ledctl |= (1 << i);
302 else
303 ledctl &= ~(1 << i);
304 }
305 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
306 spin_unlock_irqrestore(&bcm->leds_lock, flags);
307}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
deleted file mode 100644
index 811e14a81198..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
+++ /dev/null
@@ -1,62 +0,0 @@
1#ifndef BCM43xx_LEDS_H_
2#define BCM43xx_LEDS_H_
3
4#include <linux/types.h>
5#include <linux/timer.h>
6
7
8struct bcm43xx_led {
9 u8 behaviour:7;
10 u8 activelow:1;
11
12 struct bcm43xx_private *bcm;
13 struct timer_list blink_timer;
14 unsigned long blink_interval;
15};
16#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds))
17
18/* Delay between state changes when blinking in jiffies */
19#define BCM43xx_LEDBLINK_SLOW (HZ / 1)
20#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4)
21#define BCM43xx_LEDBLINK_FAST (HZ / 8)
22
23#define BCM43xx_LED_XFER_THRES (HZ / 100)
24
25#define BCM43xx_LED_BEHAVIOUR 0x7F
26#define BCM43xx_LED_ACTIVELOW 0x80
27enum { /* LED behaviour values */
28 BCM43xx_LED_OFF,
29 BCM43xx_LED_ON,
30 BCM43xx_LED_ACTIVITY,
31 BCM43xx_LED_RADIO_ALL,
32 BCM43xx_LED_RADIO_A,
33 BCM43xx_LED_RADIO_B,
34 BCM43xx_LED_MODE_BG,
35 BCM43xx_LED_TRANSFER,
36 BCM43xx_LED_APTRANSFER,
37 BCM43xx_LED_WEIRD,//FIXME
38 BCM43xx_LED_ASSOC,
39 BCM43xx_LED_INACTIVE,
40
41 /* Behaviour values for testing.
42 * With these values it is easier to figure out
43 * the real behaviour of leds, in case the SPROM
44 * is missing information.
45 */
46 BCM43xx_LED_TEST_BLINKSLOW,
47 BCM43xx_LED_TEST_BLINKMEDIUM,
48 BCM43xx_LED_TEST_BLINKFAST,
49
50 /* Misc values for BCM4303 */
51 BCM43xx_LED_BCM4303_0 = 0x2B,
52 BCM43xx_LED_BCM4303_1 = 0x78,
53 BCM43xx_LED_BCM4303_2 = 0x2E,
54 BCM43xx_LED_BCM4303_3 = 0x19,
55};
56
57int bcm43xx_leds_init(struct bcm43xx_private *bcm);
58void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
59void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
60void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
61
62#endif /* BCM43xx_LEDS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
deleted file mode 100644
index b96a325b6ec8..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ /dev/null
@@ -1,4281 +0,0 @@
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>
41#include <linux/dma-mapping.h>
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"
53#include "bcm43xx_ethtool.h"
54#include "bcm43xx_xmit.h"
55#include "bcm43xx_sysfs.h"
56
57
58MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
59MODULE_AUTHOR("Martin Langer");
60MODULE_AUTHOR("Stefano Brivio");
61MODULE_AUTHOR("Michael Buesch");
62MODULE_LICENSE("GPL");
63
64#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
65static int modparam_pio;
66module_param_named(pio, modparam_pio, int, 0444);
67MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
68#elif defined(CONFIG_BCM43XX_DMA)
69# define modparam_pio 0
70#elif defined(CONFIG_BCM43XX_PIO)
71# define modparam_pio 1
72#endif
73
74static int modparam_bad_frames_preempt;
75module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
76MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
77
78static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
79module_param_named(short_retry, modparam_short_retry, int, 0444);
80MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
81
82static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
83module_param_named(long_retry, modparam_long_retry, int, 0444);
84MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
85
86static int modparam_locale = -1;
87module_param_named(locale, modparam_locale, int, 0444);
88MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
89
90static int modparam_noleds;
91module_param_named(noleds, modparam_noleds, int, 0444);
92MODULE_PARM_DESC(noleds, "Turn off all LED activity");
93
94static char modparam_fwpostfix[64];
95module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
96MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
97
98
99/* If you want to debug with just a single device, enable this,
100 * where the string is the pci device ID (as given by the kernel's
101 * pci_name function) of the device to be used.
102 */
103//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0"
104
105/* If you want to enable printing of each MMIO access, enable this. */
106//#define DEBUG_ENABLE_MMIO_PRINT
107
108/* If you want to enable printing of MMIO access within
109 * ucode/pcm upload, initvals write, enable this.
110 */
111//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
112
113/* If you want to enable printing of PCI Config Space access, enable this */
114//#define DEBUG_ENABLE_PCILOG
115
116
117/* Detailed list maintained at:
118 * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
119 */
120 static struct pci_device_id bcm43xx_pci_tbl[] = {
121 /* Broadcom 4303 802.11b */
122 { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
123 /* Broadcom 4307 802.11b */
124 { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
125 /* Broadcom 4311 802.11(a)/b/g */
126 { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
127 /* Broadcom 4312 802.11a/b/g */
128 { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
129 /* Broadcom 4318 802.11b/g */
130 { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
131 /* Broadcom 4319 802.11a/b/g */
132 { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
133 /* Broadcom 4306 802.11b/g */
134 { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
135 /* Broadcom 4306 802.11a */
136// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
137 /* Broadcom 4309 802.11a/b/g */
138 { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
139 /* Broadcom 43XG 802.11b/g */
140 { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
141 { 0 },
142};
143MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
144
145static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
146{
147 u32 status;
148
149 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
150 if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
151 val = swab32(val);
152
153 bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
154 mmiowb();
155 bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
156}
157
158static inline
159void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
160 u16 routing, u16 offset)
161{
162 u32 control;
163
164 /* "offset" is the WORD offset. */
165
166 control = routing;
167 control <<= 16;
168 control |= offset;
169 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
170}
171
172u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
173 u16 routing, u16 offset)
174{
175 u32 ret;
176
177 if (routing == BCM43xx_SHM_SHARED) {
178 if (offset & 0x0003) {
179 /* Unaligned access */
180 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
181 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
182 ret <<= 16;
183 bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
184 ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
185
186 return ret;
187 }
188 offset >>= 2;
189 }
190 bcm43xx_shm_control_word(bcm, routing, offset);
191 ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
192
193 return ret;
194}
195
196u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
197 u16 routing, u16 offset)
198{
199 u16 ret;
200
201 if (routing == BCM43xx_SHM_SHARED) {
202 if (offset & 0x0003) {
203 /* Unaligned access */
204 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
205 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
206
207 return ret;
208 }
209 offset >>= 2;
210 }
211 bcm43xx_shm_control_word(bcm, routing, offset);
212 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
213
214 return ret;
215}
216
217void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
218 u16 routing, u16 offset,
219 u32 value)
220{
221 if (routing == BCM43xx_SHM_SHARED) {
222 if (offset & 0x0003) {
223 /* Unaligned access */
224 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
225 mmiowb();
226 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
227 (value >> 16) & 0xffff);
228 mmiowb();
229 bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
230 mmiowb();
231 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
232 value & 0xffff);
233 return;
234 }
235 offset >>= 2;
236 }
237 bcm43xx_shm_control_word(bcm, routing, offset);
238 mmiowb();
239 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
240}
241
242void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
243 u16 routing, u16 offset,
244 u16 value)
245{
246 if (routing == BCM43xx_SHM_SHARED) {
247 if (offset & 0x0003) {
248 /* Unaligned access */
249 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
250 mmiowb();
251 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
252 value);
253 return;
254 }
255 offset >>= 2;
256 }
257 bcm43xx_shm_control_word(bcm, routing, offset);
258 mmiowb();
259 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
260}
261
262void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
263{
264 /* We need to be careful. As we read the TSF from multiple
265 * registers, we should take care of register overflows.
266 * In theory, the whole tsf read process should be atomic.
267 * We try to be atomic here, by restaring the read process,
268 * if any of the high registers changed (overflew).
269 */
270 if (bcm->current_core->rev >= 3) {
271 u32 low, high, high2;
272
273 do {
274 high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
275 low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
276 high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
277 } while (unlikely(high != high2));
278
279 *tsf = high;
280 *tsf <<= 32;
281 *tsf |= low;
282 } else {
283 u64 tmp;
284 u16 v0, v1, v2, v3;
285 u16 test1, test2, test3;
286
287 do {
288 v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
289 v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
290 v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
291 v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
292
293 test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
294 test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
295 test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
296 } while (v3 != test3 || v2 != test2 || v1 != test1);
297
298 *tsf = v3;
299 *tsf <<= 48;
300 tmp = v2;
301 tmp <<= 32;
302 *tsf |= tmp;
303 tmp = v1;
304 tmp <<= 16;
305 *tsf |= tmp;
306 *tsf |= v0;
307 }
308}
309
310void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
311{
312 u32 status;
313
314 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
315 status |= BCM43xx_SBF_TIME_UPDATE;
316 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
317 mmiowb();
318
319 /* Be careful with the in-progress timer.
320 * First zero out the low register, so we have a full
321 * register-overflow duration to complete the operation.
322 */
323 if (bcm->current_core->rev >= 3) {
324 u32 lo = (tsf & 0x00000000FFFFFFFFULL);
325 u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
326
327 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
328 mmiowb();
329 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
330 mmiowb();
331 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
332 } else {
333 u16 v0 = (tsf & 0x000000000000FFFFULL);
334 u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
335 u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
336 u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
337
338 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
339 mmiowb();
340 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
341 mmiowb();
342 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
343 mmiowb();
344 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
345 mmiowb();
346 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
347 }
348
349 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
350 status &= ~BCM43xx_SBF_TIME_UPDATE;
351 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
352}
353
354static
355void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
356 u16 offset,
357 const u8 *mac)
358{
359 u16 data;
360
361 offset |= 0x0020;
362 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
363
364 data = mac[0];
365 data |= mac[1] << 8;
366 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
367 data = mac[2];
368 data |= mac[3] << 8;
369 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
370 data = mac[4];
371 data |= mac[5] << 8;
372 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
373}
374
375static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
376 u16 offset)
377{
378 const u8 zero_addr[ETH_ALEN] = { 0 };
379
380 bcm43xx_macfilter_set(bcm, offset, zero_addr);
381}
382
383static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
384{
385 const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
386 const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
387 u8 mac_bssid[ETH_ALEN * 2];
388 int i;
389
390 memcpy(mac_bssid, mac, ETH_ALEN);
391 memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
392
393 /* Write our MAC address and BSSID to template ram */
394 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
395 bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
396 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
397 bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
398 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
399 bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
400}
401
402//FIXME: Well, we should probably call them from somewhere.
403#if 0
404static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
405{
406 /* slot_time is in usec. */
407 if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
408 return;
409 bcm43xx_write16(bcm, 0x684, 510 + slot_time);
410 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
411}
412
413static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
414{
415 bcm43xx_set_slot_time(bcm, 9);
416}
417
418static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
419{
420 bcm43xx_set_slot_time(bcm, 20);
421}
422#endif
423
424/* FIXME: To get the MAC-filter working, we need to implement the
425 * following functions (and rename them :)
426 */
427#if 0
428static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
429{
430 bcm43xx_mac_suspend(bcm);
431 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
432
433 bcm43xx_ram_write(bcm, 0x0026, 0x0000);
434 bcm43xx_ram_write(bcm, 0x0028, 0x0000);
435 bcm43xx_ram_write(bcm, 0x007E, 0x0000);
436 bcm43xx_ram_write(bcm, 0x0080, 0x0000);
437 bcm43xx_ram_write(bcm, 0x047E, 0x0000);
438 bcm43xx_ram_write(bcm, 0x0480, 0x0000);
439
440 if (bcm->current_core->rev < 3) {
441 bcm43xx_write16(bcm, 0x0610, 0x8000);
442 bcm43xx_write16(bcm, 0x060E, 0x0000);
443 } else
444 bcm43xx_write32(bcm, 0x0188, 0x80000000);
445
446 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
447
448 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
449 ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
450 bcm43xx_short_slot_timing_enable(bcm);
451
452 bcm43xx_mac_enable(bcm);
453}
454
455static void bcm43xx_associate(struct bcm43xx_private *bcm,
456 const u8 *mac)
457{
458 memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
459
460 bcm43xx_mac_suspend(bcm);
461 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
462 bcm43xx_write_mac_bssid_templates(bcm);
463 bcm43xx_mac_enable(bcm);
464}
465#endif
466
467/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
468 * Returns the _previously_ enabled IRQ mask.
469 */
470static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
471{
472 u32 old_mask;
473
474 old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
475 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
476
477 return old_mask;
478}
479
480/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
481 * Returns the _previously_ enabled IRQ mask.
482 */
483static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
484{
485 u32 old_mask;
486
487 old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
488 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
489
490 return old_mask;
491}
492
493/* Synchronize IRQ top- and bottom-half.
494 * IRQs must be masked before calling this.
495 * This must not be called with the irq_lock held.
496 */
497static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
498{
499 synchronize_irq(bcm->irq);
500 tasklet_disable(&bcm->isr_tasklet);
501}
502
503/* Make sure we don't receive more data from the device. */
504static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
505{
506 unsigned long flags;
507
508 spin_lock_irqsave(&bcm->irq_lock, flags);
509 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
510 spin_unlock_irqrestore(&bcm->irq_lock, flags);
511 return -EBUSY;
512 }
513 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
514 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */
515 spin_unlock_irqrestore(&bcm->irq_lock, flags);
516 bcm43xx_synchronize_irq(bcm);
517
518 return 0;
519}
520
521static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
522{
523 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
524 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
525 u32 radio_id;
526 u16 manufact;
527 u16 version;
528 u8 revision;
529
530 if (bcm->chip_id == 0x4317) {
531 if (bcm->chip_rev == 0x00)
532 radio_id = 0x3205017F;
533 else if (bcm->chip_rev == 0x01)
534 radio_id = 0x4205017F;
535 else
536 radio_id = 0x5205017F;
537 } else {
538 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
539 radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
540 radio_id <<= 16;
541 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
542 radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
543 }
544
545 manufact = (radio_id & 0x00000FFF);
546 version = (radio_id & 0x0FFFF000) >> 12;
547 revision = (radio_id & 0xF0000000) >> 28;
548
549 dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
550 radio_id, manufact, version, revision);
551
552 switch (phy->type) {
553 case BCM43xx_PHYTYPE_A:
554 if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
555 goto err_unsupported_radio;
556 break;
557 case BCM43xx_PHYTYPE_B:
558 if ((version & 0xFFF0) != 0x2050)
559 goto err_unsupported_radio;
560 break;
561 case BCM43xx_PHYTYPE_G:
562 if (version != 0x2050)
563 goto err_unsupported_radio;
564 break;
565 }
566
567 radio->manufact = manufact;
568 radio->version = version;
569 radio->revision = revision;
570
571 if (phy->type == BCM43xx_PHYTYPE_A)
572 radio->txpower_desired = bcm->sprom.maxpower_aphy;
573 else
574 radio->txpower_desired = bcm->sprom.maxpower_bgphy;
575
576 return 0;
577
578err_unsupported_radio:
579 printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
580 return -ENODEV;
581}
582
583static const char * bcm43xx_locale_iso(u8 locale)
584{
585 /* ISO 3166-1 country codes.
586 * Note that there aren't ISO 3166-1 codes for
587 * all or locales. (Not all locales are countries)
588 */
589 switch (locale) {
590 case BCM43xx_LOCALE_WORLD:
591 case BCM43xx_LOCALE_ALL:
592 return "XX";
593 case BCM43xx_LOCALE_THAILAND:
594 return "TH";
595 case BCM43xx_LOCALE_ISRAEL:
596 return "IL";
597 case BCM43xx_LOCALE_JORDAN:
598 return "JO";
599 case BCM43xx_LOCALE_CHINA:
600 return "CN";
601 case BCM43xx_LOCALE_JAPAN:
602 case BCM43xx_LOCALE_JAPAN_HIGH:
603 return "JP";
604 case BCM43xx_LOCALE_USA_CANADA_ANZ:
605 case BCM43xx_LOCALE_USA_LOW:
606 return "US";
607 case BCM43xx_LOCALE_EUROPE:
608 return "EU";
609 case BCM43xx_LOCALE_NONE:
610 return " ";
611 }
612 assert(0);
613 return " ";
614}
615
616static const char * bcm43xx_locale_string(u8 locale)
617{
618 switch (locale) {
619 case BCM43xx_LOCALE_WORLD:
620 return "World";
621 case BCM43xx_LOCALE_THAILAND:
622 return "Thailand";
623 case BCM43xx_LOCALE_ISRAEL:
624 return "Israel";
625 case BCM43xx_LOCALE_JORDAN:
626 return "Jordan";
627 case BCM43xx_LOCALE_CHINA:
628 return "China";
629 case BCM43xx_LOCALE_JAPAN:
630 return "Japan";
631 case BCM43xx_LOCALE_USA_CANADA_ANZ:
632 return "USA/Canada/ANZ";
633 case BCM43xx_LOCALE_EUROPE:
634 return "Europe";
635 case BCM43xx_LOCALE_USA_LOW:
636 return "USAlow";
637 case BCM43xx_LOCALE_JAPAN_HIGH:
638 return "JapanHigh";
639 case BCM43xx_LOCALE_ALL:
640 return "All";
641 case BCM43xx_LOCALE_NONE:
642 return "None";
643 }
644 assert(0);
645 return "";
646}
647
648static inline u8 bcm43xx_crc8(u8 crc, u8 data)
649{
650 static const u8 t[] = {
651 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
652 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
653 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
654 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
655 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
656 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
657 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
658 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
659 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
660 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
661 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
662 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
663 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
664 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
665 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
666 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
667 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
668 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
669 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
670 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
671 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
672 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
673 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
674 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
675 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
676 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
677 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
678 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
679 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
680 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
681 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
682 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
683 };
684 return t[crc ^ data];
685}
686
687static u8 bcm43xx_sprom_crc(const u16 *sprom)
688{
689 int word;
690 u8 crc = 0xFF;
691
692 for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
693 crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
694 crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
695 }
696 crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
697 crc ^= 0xFF;
698
699 return crc;
700}
701
702int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
703{
704 int i;
705 u8 crc, expected_crc;
706
707 for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
708 sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
709 /* CRC-8 check. */
710 crc = bcm43xx_sprom_crc(sprom);
711 expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
712 if (crc != expected_crc) {
713 printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
714 "(0x%02X, expected: 0x%02X)\n",
715 crc, expected_crc);
716 return -EINVAL;
717 }
718
719 return 0;
720}
721
722int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
723{
724 int i, err;
725 u8 crc, expected_crc;
726 u32 spromctl;
727
728 /* CRC-8 validation of the input data. */
729 crc = bcm43xx_sprom_crc(sprom);
730 expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
731 if (crc != expected_crc) {
732 printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
733 return -EINVAL;
734 }
735
736 printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
737 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
738 if (err)
739 goto err_ctlreg;
740 spromctl |= 0x10; /* SPROM WRITE enable. */
741 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
742 if (err)
743 goto err_ctlreg;
744 /* We must burn lots of CPU cycles here, but that does not
745 * really matter as one does not write the SPROM every other minute...
746 */
747 printk(KERN_INFO PFX "[ 0%%");
748 mdelay(500);
749 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
750 if (i == 16)
751 printk("25%%");
752 else if (i == 32)
753 printk("50%%");
754 else if (i == 48)
755 printk("75%%");
756 else if (i % 2)
757 printk(".");
758 bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
759 mmiowb();
760 mdelay(20);
761 }
762 spromctl &= ~0x10; /* SPROM WRITE enable. */
763 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
764 if (err)
765 goto err_ctlreg;
766 mdelay(500);
767 printk("100%% ]\n");
768 printk(KERN_INFO PFX "SPROM written.\n");
769 bcm43xx_controller_restart(bcm, "SPROM update");
770
771 return 0;
772err_ctlreg:
773 printk(KERN_ERR PFX "Could not access SPROM control register.\n");
774 return -ENODEV;
775}
776
777static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
778{
779 u16 value;
780 u16 *sprom;
781
782 sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
783 GFP_KERNEL);
784 if (!sprom) {
785 printk(KERN_ERR PFX "sprom_extract OOM\n");
786 return -ENOMEM;
787 }
788 bcm43xx_sprom_read(bcm, sprom);
789
790 /* boardflags2 */
791 value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
792 bcm->sprom.boardflags2 = value;
793
794 /* il0macaddr */
795 value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
796 *(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
797 value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
798 *(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
799 value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
800 *(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
801
802 /* et0macaddr */
803 value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
804 *(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
805 value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
806 *(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
807 value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
808 *(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
809
810 /* et1macaddr */
811 value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
812 *(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
813 value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
814 *(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
815 value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
816 *(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
817
818 /* ethernet phy settings */
819 value = sprom[BCM43xx_SPROM_ETHPHY];
820 bcm->sprom.et0phyaddr = (value & 0x001F);
821 bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
822
823 /* boardrev, antennas, locale */
824 value = sprom[BCM43xx_SPROM_BOARDREV];
825 bcm->sprom.boardrev = (value & 0x00FF);
826 bcm->sprom.locale = (value & 0x0F00) >> 8;
827 bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
828 bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
829 if (modparam_locale != -1) {
830 if (modparam_locale >= 0 && modparam_locale <= 11) {
831 bcm->sprom.locale = modparam_locale;
832 printk(KERN_WARNING PFX "Operating with modified "
833 "LocaleCode %u (%s)\n",
834 bcm->sprom.locale,
835 bcm43xx_locale_string(bcm->sprom.locale));
836 } else {
837 printk(KERN_WARNING PFX "Module parameter \"locale\" "
838 "invalid value. (0 - 11)\n");
839 }
840 }
841
842 /* pa0b* */
843 value = sprom[BCM43xx_SPROM_PA0B0];
844 bcm->sprom.pa0b0 = value;
845 value = sprom[BCM43xx_SPROM_PA0B1];
846 bcm->sprom.pa0b1 = value;
847 value = sprom[BCM43xx_SPROM_PA0B2];
848 bcm->sprom.pa0b2 = value;
849
850 /* wl0gpio* */
851 value = sprom[BCM43xx_SPROM_WL0GPIO0];
852 if (value == 0x0000)
853 value = 0xFFFF;
854 bcm->sprom.wl0gpio0 = value & 0x00FF;
855 bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
856 value = sprom[BCM43xx_SPROM_WL0GPIO2];
857 if (value == 0x0000)
858 value = 0xFFFF;
859 bcm->sprom.wl0gpio2 = value & 0x00FF;
860 bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
861
862 /* maxpower */
863 value = sprom[BCM43xx_SPROM_MAXPWR];
864 bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
865 bcm->sprom.maxpower_bgphy = value & 0x00FF;
866
867 /* pa1b* */
868 value = sprom[BCM43xx_SPROM_PA1B0];
869 bcm->sprom.pa1b0 = value;
870 value = sprom[BCM43xx_SPROM_PA1B1];
871 bcm->sprom.pa1b1 = value;
872 value = sprom[BCM43xx_SPROM_PA1B2];
873 bcm->sprom.pa1b2 = value;
874
875 /* idle tssi target */
876 value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
877 bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
878 bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
879
880 /* boardflags */
881 value = sprom[BCM43xx_SPROM_BOARDFLAGS];
882 if (value == 0xFFFF)
883 value = 0x0000;
884 bcm->sprom.boardflags = value;
885 /* boardflags workarounds */
886 if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
887 bcm->chip_id == 0x4301 &&
888 bcm->board_revision == 0x74)
889 bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
890 if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
891 bcm->board_type == 0x4E &&
892 bcm->board_revision > 0x40)
893 bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
894
895 /* antenna gain */
896 value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
897 if (value == 0x0000 || value == 0xFFFF)
898 value = 0x0202;
899 /* convert values to Q5.2 */
900 bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
901 bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
902
903 kfree(sprom);
904
905 return 0;
906}
907
908static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
909{
910 struct ieee80211_geo *geo;
911 struct ieee80211_channel *chan;
912 int have_a = 0, have_bg = 0;
913 int i;
914 u8 channel;
915 struct bcm43xx_phyinfo *phy;
916 const char *iso_country;
917 u8 max_bg_channel;
918
919 geo = kzalloc(sizeof(*geo), GFP_KERNEL);
920 if (!geo)
921 return -ENOMEM;
922
923 for (i = 0; i < bcm->nr_80211_available; i++) {
924 phy = &(bcm->core_80211_ext[i].phy);
925 switch (phy->type) {
926 case BCM43xx_PHYTYPE_B:
927 case BCM43xx_PHYTYPE_G:
928 have_bg = 1;
929 break;
930 case BCM43xx_PHYTYPE_A:
931 have_a = 1;
932 break;
933 default:
934 assert(0);
935 }
936 }
937 iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
938
939/* set the maximum channel based on locale set in sprom or witle locale option */
940 switch (bcm->sprom.locale) {
941 case BCM43xx_LOCALE_THAILAND:
942 case BCM43xx_LOCALE_ISRAEL:
943 case BCM43xx_LOCALE_JORDAN:
944 case BCM43xx_LOCALE_USA_CANADA_ANZ:
945 case BCM43xx_LOCALE_USA_LOW:
946 max_bg_channel = 11;
947 break;
948 case BCM43xx_LOCALE_JAPAN:
949 case BCM43xx_LOCALE_JAPAN_HIGH:
950 max_bg_channel = 14;
951 break;
952 default:
953 max_bg_channel = 13;
954 }
955
956 if (have_a) {
957 for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
958 channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
959 chan = &geo->a[i++];
960 chan->freq = bcm43xx_channel_to_freq_a(channel);
961 chan->channel = channel;
962 }
963 geo->a_channels = i;
964 }
965 if (have_bg) {
966 for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
967 channel <= max_bg_channel; channel++) {
968 chan = &geo->bg[i++];
969 chan->freq = bcm43xx_channel_to_freq_bg(channel);
970 chan->channel = channel;
971 }
972 geo->bg_channels = i;
973 }
974 memcpy(geo->name, iso_country, 2);
975 if (0 /*TODO: Outdoor use only */)
976 geo->name[2] = 'O';
977 else if (0 /*TODO: Indoor use only */)
978 geo->name[2] = 'I';
979 else
980 geo->name[2] = ' ';
981 geo->name[3] = '\0';
982
983 ieee80211_set_geo(bcm->ieee, geo);
984 kfree(geo);
985
986 return 0;
987}
988
989/* DummyTransmission function, as documented on
990 * http://bcm-specs.sipsolutions.net/DummyTransmission
991 */
992void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
993{
994 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
995 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
996 unsigned int i, max_loop;
997 u16 value = 0;
998 u32 buffer[5] = {
999 0x00000000,
1000 0x0000D400,
1001 0x00000000,
1002 0x00000001,
1003 0x00000000,
1004 };
1005
1006 switch (phy->type) {
1007 case BCM43xx_PHYTYPE_A:
1008 max_loop = 0x1E;
1009 buffer[0] = 0xCC010200;
1010 break;
1011 case BCM43xx_PHYTYPE_B:
1012 case BCM43xx_PHYTYPE_G:
1013 max_loop = 0xFA;
1014 buffer[0] = 0x6E840B00;
1015 break;
1016 default:
1017 assert(0);
1018 return;
1019 }
1020
1021 for (i = 0; i < 5; i++)
1022 bcm43xx_ram_write(bcm, i * 4, buffer[i]);
1023
1024 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
1025
1026 bcm43xx_write16(bcm, 0x0568, 0x0000);
1027 bcm43xx_write16(bcm, 0x07C0, 0x0000);
1028 bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
1029 bcm43xx_write16(bcm, 0x0508, 0x0000);
1030 bcm43xx_write16(bcm, 0x050A, 0x0000);
1031 bcm43xx_write16(bcm, 0x054C, 0x0000);
1032 bcm43xx_write16(bcm, 0x056A, 0x0014);
1033 bcm43xx_write16(bcm, 0x0568, 0x0826);
1034 bcm43xx_write16(bcm, 0x0500, 0x0000);
1035 bcm43xx_write16(bcm, 0x0502, 0x0030);
1036
1037 if (radio->version == 0x2050 && radio->revision <= 0x5)
1038 bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
1039 for (i = 0x00; i < max_loop; i++) {
1040 value = bcm43xx_read16(bcm, 0x050E);
1041 if (value & 0x0080)
1042 break;
1043 udelay(10);
1044 }
1045 for (i = 0x00; i < 0x0A; i++) {
1046 value = bcm43xx_read16(bcm, 0x050E);
1047 if (value & 0x0400)
1048 break;
1049 udelay(10);
1050 }
1051 for (i = 0x00; i < 0x0A; i++) {
1052 value = bcm43xx_read16(bcm, 0x0690);
1053 if (!(value & 0x0100))
1054 break;
1055 udelay(10);
1056 }
1057 if (radio->version == 0x2050 && radio->revision <= 0x5)
1058 bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
1059}
1060
1061static void key_write(struct bcm43xx_private *bcm,
1062 u8 index, u8 algorithm, const __le16 *key)
1063{
1064 unsigned int i, basic_wep = 0;
1065 u32 offset;
1066 u16 value;
1067
1068 /* Write associated key information */
1069 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
1070 ((index << 4) | (algorithm & 0x0F)));
1071
1072 /* The first 4 WEP keys need extra love */
1073 if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
1074 (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
1075 basic_wep = 1;
1076
1077 /* Write key payload, 8 little endian words */
1078 offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
1079 for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
1080 value = le16_to_cpu(key[i]);
1081 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1082 offset + (i * 2), value);
1083
1084 if (!basic_wep)
1085 continue;
1086
1087 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1088 offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
1089 value);
1090 }
1091}
1092
1093static void keymac_write(struct bcm43xx_private *bcm,
1094 u8 index, const __be32 *addr)
1095{
1096 /* for keys 0-3 there is no associated mac address */
1097 if (index < 4)
1098 return;
1099
1100 index -= 4;
1101 if (bcm->current_core->rev >= 5) {
1102 bcm43xx_shm_write32(bcm,
1103 BCM43xx_SHM_HWMAC,
1104 index * 2,
1105 be32_to_cpu(*addr));
1106 bcm43xx_shm_write16(bcm,
1107 BCM43xx_SHM_HWMAC,
1108 (index * 2) + 1,
1109 be16_to_cpu(*((__be16 *)(addr + 1))));
1110 } else {
1111 if (index < 8) {
1112 TODO(); /* Put them in the macaddress filter */
1113 } else {
1114 TODO();
1115 /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
1116 Keep in mind to update the count of keymacs in 0x003E as well! */
1117 }
1118 }
1119}
1120
1121static int bcm43xx_key_write(struct bcm43xx_private *bcm,
1122 u8 index, u8 algorithm,
1123 const u8 *_key, int key_len,
1124 const u8 *mac_addr)
1125{
1126 u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
1127
1128 if (index >= ARRAY_SIZE(bcm->key))
1129 return -EINVAL;
1130 if (key_len > ARRAY_SIZE(key))
1131 return -EINVAL;
1132 if (algorithm < 1 || algorithm > 5)
1133 return -EINVAL;
1134
1135 memcpy(key, _key, key_len);
1136 key_write(bcm, index, algorithm, (const __le16 *)key);
1137 keymac_write(bcm, index, (const __be32 *)mac_addr);
1138
1139 bcm->key[index].algorithm = algorithm;
1140
1141 return 0;
1142}
1143
1144static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
1145{
1146 static const __be32 zero_mac[2] = { 0 };
1147 unsigned int i,j, nr_keys = 54;
1148 u16 offset;
1149
1150 if (bcm->current_core->rev < 5)
1151 nr_keys = 16;
1152 assert(nr_keys <= ARRAY_SIZE(bcm->key));
1153
1154 for (i = 0; i < nr_keys; i++) {
1155 bcm->key[i].enabled = 0;
1156 /* returns for i < 4 immediately */
1157 keymac_write(bcm, i, zero_mac);
1158 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1159 0x100 + (i * 2), 0x0000);
1160 for (j = 0; j < 8; j++) {
1161 offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
1162 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1163 offset, 0x0000);
1164 }
1165 }
1166 dprintk(KERN_INFO PFX "Keys cleared\n");
1167}
1168
1169/* Lowlevel core-switch function. This is only to be used in
1170 * bcm43xx_switch_core() and bcm43xx_probe_cores()
1171 */
1172static int _switch_core(struct bcm43xx_private *bcm, int core)
1173{
1174 int err;
1175 int attempts = 0;
1176 u32 current_core;
1177
1178 assert(core >= 0);
1179 while (1) {
1180 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
1181 (core * 0x1000) + 0x18000000);
1182 if (unlikely(err))
1183 goto error;
1184 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
1185 &current_core);
1186 if (unlikely(err))
1187 goto error;
1188 current_core = (current_core - 0x18000000) / 0x1000;
1189 if (current_core == core)
1190 break;
1191
1192 if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
1193 goto error;
1194 udelay(10);
1195 }
1196
1197 return 0;
1198error:
1199 printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
1200 return -ENODEV;
1201}
1202
1203int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
1204{
1205 int err;
1206
1207 if (unlikely(!new_core))
1208 return 0;
1209 if (!new_core->available)
1210 return -ENODEV;
1211 if (bcm->current_core == new_core)
1212 return 0;
1213 err = _switch_core(bcm, new_core->index);
1214 if (unlikely(err))
1215 goto out;
1216
1217 bcm->current_core = new_core;
1218out:
1219 return err;
1220}
1221
1222static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
1223{
1224 u32 value;
1225
1226 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1227 value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
1228 | BCM43xx_SBTMSTATELOW_REJECT;
1229
1230 return (value == BCM43xx_SBTMSTATELOW_CLOCK);
1231}
1232
1233/* disable current core */
1234static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
1235{
1236 u32 sbtmstatelow;
1237 u32 sbtmstatehigh;
1238 int i;
1239
1240 /* fetch sbtmstatelow from core information registers */
1241 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1242
1243 /* core is already in reset */
1244 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
1245 goto out;
1246
1247 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
1248 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1249 BCM43xx_SBTMSTATELOW_REJECT;
1250 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1251
1252 for (i = 0; i < 1000; i++) {
1253 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1254 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
1255 i = -1;
1256 break;
1257 }
1258 udelay(10);
1259 }
1260 if (i != -1) {
1261 printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
1262 return -EBUSY;
1263 }
1264
1265 for (i = 0; i < 1000; i++) {
1266 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1267 if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
1268 i = -1;
1269 break;
1270 }
1271 udelay(10);
1272 }
1273 if (i != -1) {
1274 printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
1275 return -EBUSY;
1276 }
1277
1278 sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1279 BCM43xx_SBTMSTATELOW_REJECT |
1280 BCM43xx_SBTMSTATELOW_RESET |
1281 BCM43xx_SBTMSTATELOW_CLOCK |
1282 core_flags;
1283 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1284 udelay(10);
1285 }
1286
1287 sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
1288 BCM43xx_SBTMSTATELOW_REJECT |
1289 core_flags;
1290 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1291
1292out:
1293 bcm->current_core->enabled = 0;
1294
1295 return 0;
1296}
1297
1298/* enable (reset) current core */
1299static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
1300{
1301 u32 sbtmstatelow;
1302 u32 sbtmstatehigh;
1303 u32 sbimstate;
1304 int err;
1305
1306 err = bcm43xx_core_disable(bcm, core_flags);
1307 if (err)
1308 goto out;
1309
1310 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1311 BCM43xx_SBTMSTATELOW_RESET |
1312 BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1313 core_flags;
1314 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1315 udelay(1);
1316
1317 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1318 if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
1319 sbtmstatehigh = 0x00000000;
1320 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
1321 }
1322
1323 sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
1324 if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
1325 sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
1326 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
1327 }
1328
1329 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1330 BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1331 core_flags;
1332 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1333 udelay(1);
1334
1335 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
1336 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1337 udelay(1);
1338
1339 bcm->current_core->enabled = 1;
1340 assert(err == 0);
1341out:
1342 return err;
1343}
1344
1345/* http://bcm-specs.sipsolutions.net/80211CoreReset */
1346void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
1347{
1348 u32 flags = 0x00040000;
1349
1350 if ((bcm43xx_core_enabled(bcm)) &&
1351 !bcm43xx_using_pio(bcm)) {
1352 }
1353 if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
1354 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1355 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1356 & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
1357 } else {
1358 if (connect_phy)
1359 flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
1360 bcm43xx_phy_connect(bcm, connect_phy);
1361 bcm43xx_core_enable(bcm, flags);
1362 bcm43xx_write16(bcm, 0x03E6, 0x0000);
1363 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1364 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1365 | BCM43xx_SBF_400);
1366 }
1367}
1368
1369static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
1370{
1371 bcm43xx_radio_turn_off(bcm);
1372 bcm43xx_write16(bcm, 0x03E6, 0x00F4);
1373 bcm43xx_core_disable(bcm, 0);
1374}
1375
1376/* Mark the current 80211 core inactive. */
1377static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
1378{
1379 u32 sbtmstatelow;
1380
1381 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1382 bcm43xx_radio_turn_off(bcm);
1383 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1384 sbtmstatelow &= 0xDFF5FFFF;
1385 sbtmstatelow |= 0x000A0000;
1386 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1387 udelay(1);
1388 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1389 sbtmstatelow &= 0xFFF5FFFF;
1390 sbtmstatelow |= 0x00080000;
1391 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1392 udelay(1);
1393}
1394
1395static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
1396{
1397 u32 v0, v1;
1398 u16 tmp;
1399 struct bcm43xx_xmitstatus stat;
1400
1401 while (1) {
1402 v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
1403 if (!v0)
1404 break;
1405 v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
1406
1407 stat.cookie = (v0 >> 16) & 0x0000FFFF;
1408 tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
1409 stat.flags = tmp & 0xFF;
1410 stat.cnt1 = (tmp & 0x0F00) >> 8;
1411 stat.cnt2 = (tmp & 0xF000) >> 12;
1412 stat.seq = (u16)(v1 & 0xFFFF);
1413 stat.unknown = (u16)((v1 >> 16) & 0xFF);
1414
1415 bcm43xx_debugfs_log_txstat(bcm, &stat);
1416
1417 if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
1418 continue;
1419 if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
1420 continue;
1421
1422 if (bcm43xx_using_pio(bcm))
1423 bcm43xx_pio_handle_xmitstatus(bcm, &stat);
1424 else
1425 bcm43xx_dma_handle_xmitstatus(bcm, &stat);
1426 }
1427}
1428
1429static void drain_txstatus_queue(struct bcm43xx_private *bcm)
1430{
1431 u32 dummy;
1432
1433 if (bcm->current_core->rev < 5)
1434 return;
1435 /* Read all entries from the microcode TXstatus FIFO
1436 * and throw them away.
1437 */
1438 while (1) {
1439 dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
1440 if (!dummy)
1441 break;
1442 dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
1443 }
1444}
1445
1446static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
1447{
1448 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
1449 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
1450 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
1451 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
1452 assert(bcm->noisecalc.core_at_start == bcm->current_core);
1453 assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
1454}
1455
1456static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
1457{
1458 /* Top half of Link Quality calculation. */
1459
1460 if (bcm->noisecalc.calculation_running)
1461 return;
1462 bcm->noisecalc.core_at_start = bcm->current_core;
1463 bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
1464 bcm->noisecalc.calculation_running = 1;
1465 bcm->noisecalc.nr_samples = 0;
1466
1467 bcm43xx_generate_noise_sample(bcm);
1468}
1469
1470static void handle_irq_noise(struct bcm43xx_private *bcm)
1471{
1472 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1473 u16 tmp;
1474 u8 noise[4];
1475 u8 i, j;
1476 s32 average;
1477
1478 /* Bottom half of Link Quality calculation. */
1479
1480 assert(bcm->noisecalc.calculation_running);
1481 if (bcm->noisecalc.core_at_start != bcm->current_core ||
1482 bcm->noisecalc.channel_at_start != radio->channel)
1483 goto drop_calculation;
1484 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
1485 noise[0] = (tmp & 0x00FF);
1486 noise[1] = (tmp & 0xFF00) >> 8;
1487 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
1488 noise[2] = (tmp & 0x00FF);
1489 noise[3] = (tmp & 0xFF00) >> 8;
1490 if (noise[0] == 0x7F || noise[1] == 0x7F ||
1491 noise[2] == 0x7F || noise[3] == 0x7F)
1492 goto generate_new;
1493
1494 /* Get the noise samples. */
1495 assert(bcm->noisecalc.nr_samples < 8);
1496 i = bcm->noisecalc.nr_samples;
1497 noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1498 noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1499 noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1500 noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1501 bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
1502 bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
1503 bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
1504 bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
1505 bcm->noisecalc.nr_samples++;
1506 if (bcm->noisecalc.nr_samples == 8) {
1507 /* Calculate the Link Quality by the noise samples. */
1508 average = 0;
1509 for (i = 0; i < 8; i++) {
1510 for (j = 0; j < 4; j++)
1511 average += bcm->noisecalc.samples[i][j];
1512 }
1513 average /= (8 * 4);
1514 average *= 125;
1515 average += 64;
1516 average /= 128;
1517
1518 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
1519 tmp = (tmp / 128) & 0x1F;
1520 if (tmp >= 8)
1521 average += 2;
1522 else
1523 average -= 25;
1524 if (tmp == 8)
1525 average -= 72;
1526 else
1527 average -= 48;
1528
1529 bcm->stats.noise = average;
1530drop_calculation:
1531 bcm->noisecalc.calculation_running = 0;
1532 return;
1533 }
1534generate_new:
1535 bcm43xx_generate_noise_sample(bcm);
1536}
1537
1538static void handle_irq_ps(struct bcm43xx_private *bcm)
1539{
1540 if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
1541 ///TODO: PS TBTT
1542 } else {
1543 if (1/*FIXME: the last PSpoll frame was sent successfully */)
1544 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
1545 }
1546 if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
1547 bcm->reg124_set_0x4 = 1;
1548 //FIXME else set to false?
1549}
1550
1551static void handle_irq_reg124(struct bcm43xx_private *bcm)
1552{
1553 if (!bcm->reg124_set_0x4)
1554 return;
1555 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
1556 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
1557 | 0x4);
1558 //FIXME: reset reg124_set_0x4 to false?
1559}
1560
1561static void handle_irq_pmq(struct bcm43xx_private *bcm)
1562{
1563 u32 tmp;
1564
1565 //TODO: AP mode.
1566
1567 while (1) {
1568 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
1569 if (!(tmp & 0x00000008))
1570 break;
1571 }
1572 /* 16bit write is odd, but correct. */
1573 bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
1574}
1575
1576static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
1577 u16 ram_offset, u16 shm_size_offset)
1578{
1579 u32 value;
1580 u16 size = 0;
1581
1582 /* Timestamp. */
1583 //FIXME: assumption: The chip sets the timestamp
1584 value = 0;
1585 bcm43xx_ram_write(bcm, ram_offset++, value);
1586 bcm43xx_ram_write(bcm, ram_offset++, value);
1587 size += 8;
1588
1589 /* Beacon Interval / Capability Information */
1590 value = 0x0000;//FIXME: Which interval?
1591 value |= (1 << 0) << 16; /* ESS */
1592 value |= (1 << 2) << 16; /* CF Pollable */ //FIXME?
1593 value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME?
1594 if (!bcm->ieee->open_wep)
1595 value |= (1 << 4) << 16; /* Privacy */
1596 bcm43xx_ram_write(bcm, ram_offset++, value);
1597 size += 4;
1598
1599 /* SSID */
1600 //TODO
1601
1602 /* FH Parameter Set */
1603 //TODO
1604
1605 /* DS Parameter Set */
1606 //TODO
1607
1608 /* CF Parameter Set */
1609 //TODO
1610
1611 /* TIM */
1612 //TODO
1613
1614 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
1615}
1616
1617static void handle_irq_beacon(struct bcm43xx_private *bcm)
1618{
1619 u32 status;
1620
1621 bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
1622 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
1623
1624 if ((status & 0x1) && (status & 0x2)) {
1625 /* ACK beacon IRQ. */
1626 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
1627 BCM43xx_IRQ_BEACON);
1628 bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
1629 return;
1630 }
1631 if (!(status & 0x1)) {
1632 bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
1633 status |= 0x1;
1634 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
1635 }
1636 if (!(status & 0x2)) {
1637 bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
1638 status |= 0x2;
1639 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
1640 }
1641}
1642
1643/* Interrupt handler bottom-half */
1644static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1645{
1646 u32 reason;
1647 u32 dma_reason[6];
1648 u32 merged_dma_reason = 0;
1649 int i, activity = 0;
1650 unsigned long flags;
1651
1652#ifdef CONFIG_BCM43XX_DEBUG
1653 u32 _handled = 0x00000000;
1654# define bcmirq_handled(irq) do { _handled |= (irq); } while (0)
1655#else
1656# define bcmirq_handled(irq) do { /* nothing */ } while (0)
1657#endif /* CONFIG_BCM43XX_DEBUG*/
1658
1659 spin_lock_irqsave(&bcm->irq_lock, flags);
1660 reason = bcm->irq_reason;
1661 for (i = 5; i >= 0; i--) {
1662 dma_reason[i] = bcm->dma_reason[i];
1663 merged_dma_reason |= dma_reason[i];
1664 }
1665
1666 if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
1667 /* TX error. We get this when Template Ram is written in wrong endianess
1668 * in dummy_tx(). We also get this if something is wrong with the TX header
1669 * on DMA or PIO queues.
1670 * Maybe we get this in other error conditions, too.
1671 */
1672 printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
1673 bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
1674 }
1675 if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) {
1676 printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
1677 "0x%08X, 0x%08X, 0x%08X, "
1678 "0x%08X, 0x%08X, 0x%08X\n",
1679 dma_reason[0], dma_reason[1],
1680 dma_reason[2], dma_reason[3],
1681 dma_reason[4], dma_reason[5]);
1682 bcm43xx_controller_restart(bcm, "DMA error");
1683 mmiowb();
1684 spin_unlock_irqrestore(&bcm->irq_lock, flags);
1685 return;
1686 }
1687 if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) {
1688 printkl(KERN_ERR PFX "DMA error: "
1689 "0x%08X, 0x%08X, 0x%08X, "
1690 "0x%08X, 0x%08X, 0x%08X\n",
1691 dma_reason[0], dma_reason[1],
1692 dma_reason[2], dma_reason[3],
1693 dma_reason[4], dma_reason[5]);
1694 }
1695
1696 if (reason & BCM43xx_IRQ_PS) {
1697 handle_irq_ps(bcm);
1698 bcmirq_handled(BCM43xx_IRQ_PS);
1699 }
1700
1701 if (reason & BCM43xx_IRQ_REG124) {
1702 handle_irq_reg124(bcm);
1703 bcmirq_handled(BCM43xx_IRQ_REG124);
1704 }
1705
1706 if (reason & BCM43xx_IRQ_BEACON) {
1707 if (bcm->ieee->iw_mode == IW_MODE_MASTER)
1708 handle_irq_beacon(bcm);
1709 bcmirq_handled(BCM43xx_IRQ_BEACON);
1710 }
1711
1712 if (reason & BCM43xx_IRQ_PMQ) {
1713 handle_irq_pmq(bcm);
1714 bcmirq_handled(BCM43xx_IRQ_PMQ);
1715 }
1716
1717 if (reason & BCM43xx_IRQ_SCAN) {
1718 /*TODO*/
1719 //bcmirq_handled(BCM43xx_IRQ_SCAN);
1720 }
1721
1722 if (reason & BCM43xx_IRQ_NOISE) {
1723 handle_irq_noise(bcm);
1724 bcmirq_handled(BCM43xx_IRQ_NOISE);
1725 }
1726
1727 /* Check the DMA reason registers for received data. */
1728 if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
1729 if (bcm43xx_using_pio(bcm))
1730 bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
1731 else
1732 bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
1733 /* We intentionally don't set "activity" to 1, here. */
1734 }
1735 assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
1736 assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
1737 if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
1738 if (bcm43xx_using_pio(bcm))
1739 bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
1740 else
1741 bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3);
1742 activity = 1;
1743 }
1744 assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE));
1745 assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE));
1746 bcmirq_handled(BCM43xx_IRQ_RX);
1747
1748 if (reason & BCM43xx_IRQ_XMIT_STATUS) {
1749 handle_irq_transmit_status(bcm);
1750 activity = 1;
1751 //TODO: In AP mode, this also causes sending of powersave responses.
1752 bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
1753 }
1754
1755 /* IRQ_PIO_WORKAROUND is handled in the top-half. */
1756 bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
1757#ifdef CONFIG_BCM43XX_DEBUG
1758 if (unlikely(reason & ~_handled)) {
1759 printkl(KERN_WARNING PFX
1760 "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, "
1761 "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1762 reason, (reason & ~_handled),
1763 dma_reason[0], dma_reason[1],
1764 dma_reason[2], dma_reason[3]);
1765 }
1766#endif
1767#undef bcmirq_handled
1768
1769 if (!modparam_noleds)
1770 bcm43xx_leds_update(bcm, activity);
1771 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
1772 mmiowb();
1773 spin_unlock_irqrestore(&bcm->irq_lock, flags);
1774}
1775
1776static void pio_irq_workaround(struct bcm43xx_private *bcm,
1777 u16 base, int queueidx)
1778{
1779 u16 rxctl;
1780
1781 rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
1782 if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
1783 bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
1784 else
1785 bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
1786}
1787
1788static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
1789{
1790 if (bcm43xx_using_pio(bcm) &&
1791 (bcm->current_core->rev < 3) &&
1792 (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
1793 /* Apply a PIO specific workaround to the dma_reasons */
1794 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
1795 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
1796 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
1797 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
1798 }
1799
1800 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
1801
1802 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON,
1803 bcm->dma_reason[0]);
1804 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
1805 bcm->dma_reason[1]);
1806 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
1807 bcm->dma_reason[2]);
1808 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
1809 bcm->dma_reason[3]);
1810 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
1811 bcm->dma_reason[4]);
1812 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON,
1813 bcm->dma_reason[5]);
1814}
1815
1816/* Interrupt handler top-half */
1817static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
1818{
1819 irqreturn_t ret = IRQ_HANDLED;
1820 struct bcm43xx_private *bcm = dev_id;
1821 u32 reason;
1822
1823 if (!bcm)
1824 return IRQ_NONE;
1825
1826 spin_lock(&bcm->irq_lock);
1827
1828 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
1829 if (reason == 0xffffffff) {
1830 /* irq not for us (shared irq) */
1831 ret = IRQ_NONE;
1832 goto out;
1833 }
1834 reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
1835 if (!reason)
1836 goto out;
1837
1838 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
1839 assert(bcm->current_core->id == BCM43xx_COREID_80211);
1840
1841 bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
1842 & 0x0001DC00;
1843 bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
1844 & 0x0000DC00;
1845 bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
1846 & 0x0000DC00;
1847 bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
1848 & 0x0001DC00;
1849 bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
1850 & 0x0000DC00;
1851 bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON)
1852 & 0x0000DC00;
1853
1854 bcm43xx_interrupt_ack(bcm, reason);
1855
1856 /* disable all IRQs. They are enabled again in the bottom half. */
1857 bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1858 /* save the reason code and call our bottom half. */
1859 bcm->irq_reason = reason;
1860 tasklet_schedule(&bcm->isr_tasklet);
1861
1862out:
1863 mmiowb();
1864 spin_unlock(&bcm->irq_lock);
1865
1866 return ret;
1867}
1868
1869static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
1870{
1871 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1872
1873 if (bcm->firmware_norelease && !force)
1874 return; /* Suspending or controller reset. */
1875 release_firmware(phy->ucode);
1876 phy->ucode = NULL;
1877 release_firmware(phy->pcm);
1878 phy->pcm = NULL;
1879 release_firmware(phy->initvals0);
1880 phy->initvals0 = NULL;
1881 release_firmware(phy->initvals1);
1882 phy->initvals1 = NULL;
1883}
1884
1885static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1886{
1887 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1888 u8 rev = bcm->current_core->rev;
1889 int err = 0;
1890 int nr;
1891 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
1892
1893 if (!phy->ucode) {
1894 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
1895 (rev >= 5 ? 5 : rev),
1896 modparam_fwpostfix);
1897 err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
1898 if (err) {
1899 printk(KERN_ERR PFX
1900 "Error: Microcode \"%s\" not available or load failed.\n",
1901 buf);
1902 goto error;
1903 }
1904 }
1905
1906 if (!phy->pcm) {
1907 snprintf(buf, ARRAY_SIZE(buf),
1908 "bcm43xx_pcm%d%s.fw",
1909 (rev < 5 ? 4 : 5),
1910 modparam_fwpostfix);
1911 err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
1912 if (err) {
1913 printk(KERN_ERR PFX
1914 "Error: PCM \"%s\" not available or load failed.\n",
1915 buf);
1916 goto error;
1917 }
1918 }
1919
1920 if (!phy->initvals0) {
1921 if (rev == 2 || rev == 4) {
1922 switch (phy->type) {
1923 case BCM43xx_PHYTYPE_A:
1924 nr = 3;
1925 break;
1926 case BCM43xx_PHYTYPE_B:
1927 case BCM43xx_PHYTYPE_G:
1928 nr = 1;
1929 break;
1930 default:
1931 goto err_noinitval;
1932 }
1933
1934 } else if (rev >= 5) {
1935 switch (phy->type) {
1936 case BCM43xx_PHYTYPE_A:
1937 nr = 7;
1938 break;
1939 case BCM43xx_PHYTYPE_B:
1940 case BCM43xx_PHYTYPE_G:
1941 nr = 5;
1942 break;
1943 default:
1944 goto err_noinitval;
1945 }
1946 } else
1947 goto err_noinitval;
1948 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
1949 nr, modparam_fwpostfix);
1950
1951 err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
1952 if (err) {
1953 printk(KERN_ERR PFX
1954 "Error: InitVals \"%s\" not available or load failed.\n",
1955 buf);
1956 goto error;
1957 }
1958 if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
1959 printk(KERN_ERR PFX "InitVals fileformat error.\n");
1960 goto error;
1961 }
1962 }
1963
1964 if (!phy->initvals1) {
1965 if (rev >= 5) {
1966 u32 sbtmstatehigh;
1967
1968 switch (phy->type) {
1969 case BCM43xx_PHYTYPE_A:
1970 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1971 if (sbtmstatehigh & 0x00010000)
1972 nr = 9;
1973 else
1974 nr = 10;
1975 break;
1976 case BCM43xx_PHYTYPE_B:
1977 case BCM43xx_PHYTYPE_G:
1978 nr = 6;
1979 break;
1980 default:
1981 goto err_noinitval;
1982 }
1983 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
1984 nr, modparam_fwpostfix);
1985
1986 err = request_firmware(&phy->initvals1, 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 (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
1994 printk(KERN_ERR PFX "InitVals fileformat error.\n");
1995 goto error;
1996 }
1997 }
1998 }
1999
2000out:
2001 return err;
2002error:
2003 bcm43xx_release_firmware(bcm, 1);
2004 goto out;
2005err_noinitval:
2006 printk(KERN_ERR PFX "Error: No InitVals available!\n");
2007 err = -ENOENT;
2008 goto error;
2009}
2010
2011static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2012{
2013 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2014 const __be32 *data;
2015 unsigned int i, len;
2016
2017 /* Upload Microcode. */
2018 data = (__be32 *)(phy->ucode->data);
2019 len = phy->ucode->size / sizeof(u32);
2020 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
2021 for (i = 0; i < len; i++) {
2022 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
2023 be32_to_cpu(data[i]));
2024 udelay(10);
2025 }
2026
2027 /* Upload PCM data. */
2028 data = (__be32 *)(phy->pcm->data);
2029 len = phy->pcm->size / sizeof(u32);
2030 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
2031 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
2032 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
2033 for (i = 0; i < len; i++) {
2034 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
2035 be32_to_cpu(data[i]));
2036 udelay(10);
2037 }
2038}
2039
2040static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
2041 const struct bcm43xx_initval *data,
2042 const unsigned int len)
2043{
2044 u16 offset, size;
2045 u32 value;
2046 unsigned int i;
2047
2048 for (i = 0; i < len; i++) {
2049 offset = be16_to_cpu(data[i].offset);
2050 size = be16_to_cpu(data[i].size);
2051 value = be32_to_cpu(data[i].value);
2052
2053 if (unlikely(offset >= 0x1000))
2054 goto err_format;
2055 if (size == 2) {
2056 if (unlikely(value & 0xFFFF0000))
2057 goto err_format;
2058 bcm43xx_write16(bcm, offset, (u16)value);
2059 } else if (size == 4) {
2060 bcm43xx_write32(bcm, offset, value);
2061 } else
2062 goto err_format;
2063 }
2064
2065 return 0;
2066
2067err_format:
2068 printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
2069 "Please fix your bcm43xx firmware files.\n");
2070 return -EPROTO;
2071}
2072
2073static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
2074{
2075 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2076 int err;
2077
2078 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
2079 phy->initvals0->size / sizeof(struct bcm43xx_initval));
2080 if (err)
2081 goto out;
2082 if (phy->initvals1) {
2083 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
2084 phy->initvals1->size / sizeof(struct bcm43xx_initval));
2085 if (err)
2086 goto out;
2087 }
2088out:
2089 return err;
2090}
2091
2092static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2093{
2094 int err;
2095
2096 bcm->irq = bcm->pci_dev->irq;
2097 err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
2098 IRQF_SHARED, KBUILD_MODNAME, bcm);
2099 if (err)
2100 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
2101
2102 return err;
2103}
2104
2105/* Switch to the core used to write the GPIO register.
2106 * This is either the ChipCommon, or the PCI core.
2107 */
2108static int switch_to_gpio_core(struct bcm43xx_private *bcm)
2109{
2110 int err;
2111
2112 /* Where to find the GPIO register depends on the chipset.
2113 * If it has a ChipCommon, its register at offset 0x6c is the GPIO
2114 * control register. Otherwise the register at offset 0x6c in the
2115 * PCI core is the GPIO control register.
2116 */
2117 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
2118 if (err == -ENODEV) {
2119 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
2120 if (unlikely(err == -ENODEV)) {
2121 printk(KERN_ERR PFX "gpio error: "
2122 "Neither ChipCommon nor PCI core available!\n");
2123 }
2124 }
2125
2126 return err;
2127}
2128
2129/* Initialize the GPIOs
2130 * http://bcm-specs.sipsolutions.net/GPIO
2131 */
2132static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
2133{
2134 struct bcm43xx_coreinfo *old_core;
2135 int err;
2136 u32 mask, set;
2137
2138 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2139 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2140 & 0xFFFF3FFF);
2141
2142 bcm43xx_leds_switch_all(bcm, 0);
2143 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2144 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
2145
2146 mask = 0x0000001F;
2147 set = 0x0000000F;
2148 if (bcm->chip_id == 0x4301) {
2149 mask |= 0x0060;
2150 set |= 0x0060;
2151 }
2152 if (0 /* FIXME: conditional unknown */) {
2153 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2154 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
2155 | 0x0100);
2156 mask |= 0x0180;
2157 set |= 0x0180;
2158 }
2159 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
2160 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2161 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
2162 | 0x0200);
2163 mask |= 0x0200;
2164 set |= 0x0200;
2165 }
2166 if (bcm->current_core->rev >= 2)
2167 mask |= 0x0010; /* FIXME: This is redundant. */
2168
2169 old_core = bcm->current_core;
2170 err = switch_to_gpio_core(bcm);
2171 if (err)
2172 goto out;
2173 bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
2174 (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
2175 err = bcm43xx_switch_core(bcm, old_core);
2176out:
2177 return err;
2178}
2179
2180/* Turn off all GPIO stuff. Call this on module unload, for example. */
2181static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
2182{
2183 struct bcm43xx_coreinfo *old_core;
2184 int err;
2185
2186 old_core = bcm->current_core;
2187 err = switch_to_gpio_core(bcm);
2188 if (err)
2189 return err;
2190 bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
2191 err = bcm43xx_switch_core(bcm, old_core);
2192 assert(err == 0);
2193
2194 return 0;
2195}
2196
2197/* http://bcm-specs.sipsolutions.net/EnableMac */
2198void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
2199{
2200 bcm->mac_suspended--;
2201 assert(bcm->mac_suspended >= 0);
2202 if (bcm->mac_suspended == 0) {
2203 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2204 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2205 | BCM43xx_SBF_MAC_ENABLED);
2206 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
2207 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
2208 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2209 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
2210 }
2211}
2212
2213/* http://bcm-specs.sipsolutions.net/SuspendMAC */
2214void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
2215{
2216 int i;
2217 u32 tmp;
2218
2219 assert(bcm->mac_suspended >= 0);
2220 if (bcm->mac_suspended == 0) {
2221 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
2222 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2223 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2224 & ~BCM43xx_SBF_MAC_ENABLED);
2225 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2226 for (i = 10000; i; i--) {
2227 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2228 if (tmp & BCM43xx_IRQ_READY)
2229 goto out;
2230 udelay(1);
2231 }
2232 printkl(KERN_ERR PFX "MAC suspend failed\n");
2233 }
2234out:
2235 bcm->mac_suspended++;
2236}
2237
2238void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
2239 int iw_mode)
2240{
2241 unsigned long flags;
2242 struct net_device *net_dev = bcm->net_dev;
2243 u32 status;
2244 u16 value;
2245
2246 spin_lock_irqsave(&bcm->ieee->lock, flags);
2247 bcm->ieee->iw_mode = iw_mode;
2248 spin_unlock_irqrestore(&bcm->ieee->lock, flags);
2249 if (iw_mode == IW_MODE_MONITOR)
2250 net_dev->type = ARPHRD_IEEE80211;
2251 else
2252 net_dev->type = ARPHRD_ETHER;
2253
2254 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2255 /* Reset status to infrastructured mode */
2256 status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
2257 status &= ~BCM43xx_SBF_MODE_PROMISC;
2258 status |= BCM43xx_SBF_MODE_NOTADHOC;
2259
2260/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
2261status |= BCM43xx_SBF_MODE_PROMISC;
2262
2263 switch (iw_mode) {
2264 case IW_MODE_MONITOR:
2265 status |= BCM43xx_SBF_MODE_MONITOR;
2266 status |= BCM43xx_SBF_MODE_PROMISC;
2267 break;
2268 case IW_MODE_ADHOC:
2269 status &= ~BCM43xx_SBF_MODE_NOTADHOC;
2270 break;
2271 case IW_MODE_MASTER:
2272 status |= BCM43xx_SBF_MODE_AP;
2273 break;
2274 case IW_MODE_SECOND:
2275 case IW_MODE_REPEAT:
2276 TODO(); /* TODO */
2277 break;
2278 case IW_MODE_INFRA:
2279 /* nothing to be done here... */
2280 break;
2281 default:
2282 dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
2283 }
2284 if (net_dev->flags & IFF_PROMISC)
2285 status |= BCM43xx_SBF_MODE_PROMISC;
2286 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
2287
2288 value = 0x0002;
2289 if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
2290 if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
2291 value = 0x0064;
2292 else
2293 value = 0x0032;
2294 }
2295 bcm43xx_write16(bcm, 0x0612, value);
2296}
2297
2298/* This is the opposite of bcm43xx_chip_init() */
2299static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
2300{
2301 bcm43xx_radio_turn_off(bcm);
2302 if (!modparam_noleds)
2303 bcm43xx_leds_exit(bcm);
2304 bcm43xx_gpio_cleanup(bcm);
2305 bcm43xx_release_firmware(bcm, 0);
2306}
2307
2308/* Initialize the chip
2309 * http://bcm-specs.sipsolutions.net/ChipInit
2310 */
2311static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2312{
2313 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2314 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2315 int err;
2316 int i, tmp;
2317 u32 value32;
2318 u16 value16;
2319
2320 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2321 BCM43xx_SBF_CORE_READY
2322 | BCM43xx_SBF_400);
2323
2324 err = bcm43xx_request_firmware(bcm);
2325 if (err)
2326 goto out;
2327 bcm43xx_upload_microcode(bcm);
2328
2329 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
2330 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2331 i = 0;
2332 while (1) {
2333 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2334 if (value32 == BCM43xx_IRQ_READY)
2335 break;
2336 i++;
2337 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2338 printk(KERN_ERR PFX "IRQ_READY timeout\n");
2339 err = -ENODEV;
2340 goto err_release_fw;
2341 }
2342 udelay(10);
2343 }
2344 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2345
2346 value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2347 BCM43xx_UCODE_REVISION);
2348
2349 dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x "
2350 "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16,
2351 bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2352 BCM43xx_UCODE_PATCHLEVEL),
2353 (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2354 BCM43xx_UCODE_DATE) >> 12) & 0xf,
2355 (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2356 BCM43xx_UCODE_DATE) >> 8) & 0xf,
2357 bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2358 BCM43xx_UCODE_DATE) & 0xff,
2359 (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2360 BCM43xx_UCODE_TIME) >> 11) & 0x1f,
2361 (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2362 BCM43xx_UCODE_TIME) >> 5) & 0x3f,
2363 bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
2364 BCM43xx_UCODE_TIME) & 0x1f);
2365
2366 if ( value16 > 0x128 ) {
2367 printk(KERN_ERR PFX
2368 "Firmware: no support for microcode extracted "
2369 "from version 4.x binary drivers.\n");
2370 err = -EOPNOTSUPP;
2371 goto err_release_fw;
2372 }
2373
2374 err = bcm43xx_gpio_init(bcm);
2375 if (err)
2376 goto err_release_fw;
2377
2378 err = bcm43xx_upload_initvals(bcm);
2379 if (err)
2380 goto err_gpio_cleanup;
2381 bcm43xx_radio_turn_on(bcm);
2382 bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
2383 printk(KERN_INFO PFX "Radio %s by hardware\n",
2384 (bcm->radio_hw_enable == 0) ? "disabled" : "enabled");
2385
2386 bcm43xx_write16(bcm, 0x03E6, 0x0000);
2387 err = bcm43xx_phy_init(bcm);
2388 if (err)
2389 goto err_radio_off;
2390
2391 /* Select initial Interference Mitigation. */
2392 tmp = radio->interfmode;
2393 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2394 bcm43xx_radio_set_interference_mitigation(bcm, tmp);
2395
2396 bcm43xx_phy_set_antenna_diversity(bcm);
2397 bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
2398 if (phy->type == BCM43xx_PHYTYPE_B) {
2399 value16 = bcm43xx_read16(bcm, 0x005E);
2400 value16 |= 0x0004;
2401 bcm43xx_write16(bcm, 0x005E, value16);
2402 }
2403 bcm43xx_write32(bcm, 0x0100, 0x01000000);
2404 if (bcm->current_core->rev < 5)
2405 bcm43xx_write32(bcm, 0x010C, 0x01000000);
2406
2407 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2408 value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
2409 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2410 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2411 value32 |= BCM43xx_SBF_MODE_NOTADHOC;
2412 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2413
2414 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2415 value32 |= 0x100000;
2416 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2417
2418 if (bcm43xx_using_pio(bcm)) {
2419 bcm43xx_write32(bcm, 0x0210, 0x00000100);
2420 bcm43xx_write32(bcm, 0x0230, 0x00000100);
2421 bcm43xx_write32(bcm, 0x0250, 0x00000100);
2422 bcm43xx_write32(bcm, 0x0270, 0x00000100);
2423 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
2424 }
2425
2426 /* Probe Response Timeout value */
2427 /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
2428 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
2429
2430 /* Initially set the wireless operation mode. */
2431 bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
2432
2433 if (bcm->current_core->rev < 3) {
2434 bcm43xx_write16(bcm, 0x060E, 0x0000);
2435 bcm43xx_write16(bcm, 0x0610, 0x8000);
2436 bcm43xx_write16(bcm, 0x0604, 0x0000);
2437 bcm43xx_write16(bcm, 0x0606, 0x0200);
2438 } else {
2439 bcm43xx_write32(bcm, 0x0188, 0x80000000);
2440 bcm43xx_write32(bcm, 0x018C, 0x02000000);
2441 }
2442 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
2443 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
2444 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
2445 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
2446 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
2447 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
2448 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
2449
2450 value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
2451 value32 |= 0x00100000;
2452 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
2453
2454 bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
2455
2456 assert(err == 0);
2457 dprintk(KERN_INFO PFX "Chip initialized\n");
2458out:
2459 return err;
2460
2461err_radio_off:
2462 bcm43xx_radio_turn_off(bcm);
2463err_gpio_cleanup:
2464 bcm43xx_gpio_cleanup(bcm);
2465err_release_fw:
2466 bcm43xx_release_firmware(bcm, 1);
2467 goto out;
2468}
2469
2470/* Validate chip access
2471 * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
2472static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
2473{
2474 u32 value;
2475 u32 shm_backup;
2476
2477 shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
2478 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
2479 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
2480 goto error;
2481 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
2482 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
2483 goto error;
2484 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
2485
2486 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2487 if ((value | 0x80000000) != 0x80000400)
2488 goto error;
2489
2490 value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2491 if (value != 0x00000000)
2492 goto error;
2493
2494 return 0;
2495error:
2496 printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
2497 return -ENODEV;
2498}
2499
2500static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
2501{
2502 /* Initialize a "phyinfo" structure. The structure is already
2503 * zeroed out.
2504 * This is called on insmod time to initialize members.
2505 */
2506 phy->savedpctlreg = 0xFFFF;
2507 spin_lock_init(&phy->lock);
2508}
2509
2510static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
2511{
2512 /* Initialize a "radioinfo" structure. The structure is already
2513 * zeroed out.
2514 * This is called on insmod time to initialize members.
2515 */
2516 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2517 radio->channel = 0xFF;
2518 radio->initial_channel = 0xFF;
2519}
2520
2521static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2522{
2523 int err, i;
2524 int current_core;
2525 u32 core_vendor, core_id, core_rev;
2526 u32 sb_id_hi, chip_id_32 = 0;
2527 u16 pci_device, chip_id_16;
2528 u8 core_count;
2529
2530 memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
2531 memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
2532 memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
2533 * BCM43xx_MAX_80211_CORES);
2534 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
2535 * BCM43xx_MAX_80211_CORES);
2536 bcm->nr_80211_available = 0;
2537 bcm->current_core = NULL;
2538 bcm->active_80211_core = NULL;
2539
2540 /* map core 0 */
2541 err = _switch_core(bcm, 0);
2542 if (err)
2543 goto out;
2544
2545 /* fetch sb_id_hi from core information registers */
2546 sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
2547
2548 core_id = (sb_id_hi & 0x8FF0) >> 4;
2549 core_rev = (sb_id_hi & 0x7000) >> 8;
2550 core_rev |= (sb_id_hi & 0xF);
2551 core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
2552
2553 /* if present, chipcommon is always core 0; read the chipid from it */
2554 if (core_id == BCM43xx_COREID_CHIPCOMMON) {
2555 chip_id_32 = bcm43xx_read32(bcm, 0);
2556 chip_id_16 = chip_id_32 & 0xFFFF;
2557 bcm->core_chipcommon.available = 1;
2558 bcm->core_chipcommon.id = core_id;
2559 bcm->core_chipcommon.rev = core_rev;
2560 bcm->core_chipcommon.index = 0;
2561 /* While we are at it, also read the capabilities. */
2562 bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
2563 } else {
2564 /* without a chipCommon, use a hard coded table. */
2565 pci_device = bcm->pci_dev->device;
2566 if (pci_device == 0x4301)
2567 chip_id_16 = 0x4301;
2568 else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
2569 chip_id_16 = 0x4307;
2570 else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
2571 chip_id_16 = 0x4402;
2572 else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
2573 chip_id_16 = 0x4610;
2574 else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
2575 chip_id_16 = 0x4710;
2576 else {
2577 printk(KERN_ERR PFX "Could not determine Chip ID\n");
2578 return -ENODEV;
2579 }
2580 }
2581
2582 /* ChipCommon with Core Rev >=4 encodes number of cores,
2583 * otherwise consult hardcoded table */
2584 if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
2585 core_count = (chip_id_32 & 0x0F000000) >> 24;
2586 } else {
2587 switch (chip_id_16) {
2588 case 0x4610:
2589 case 0x4704:
2590 case 0x4710:
2591 core_count = 9;
2592 break;
2593 case 0x4310:
2594 core_count = 8;
2595 break;
2596 case 0x5365:
2597 core_count = 7;
2598 break;
2599 case 0x4306:
2600 core_count = 6;
2601 break;
2602 case 0x4301:
2603 case 0x4307:
2604 core_count = 5;
2605 break;
2606 case 0x4402:
2607 core_count = 3;
2608 break;
2609 default:
2610 /* SOL if we get here */
2611 assert(0);
2612 core_count = 1;
2613 }
2614 }
2615
2616 bcm->chip_id = chip_id_16;
2617 bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
2618 bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
2619
2620 dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
2621 bcm->chip_id, bcm->chip_rev);
2622 dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
2623 if (bcm->core_chipcommon.available) {
2624 dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n",
2625 core_id, core_rev, core_vendor);
2626 current_core = 1;
2627 } else
2628 current_core = 0;
2629 for ( ; current_core < core_count; current_core++) {
2630 struct bcm43xx_coreinfo *core;
2631 struct bcm43xx_coreinfo_80211 *ext_80211;
2632
2633 err = _switch_core(bcm, current_core);
2634 if (err)
2635 goto out;
2636 /* Gather information */
2637 /* fetch sb_id_hi from core information registers */
2638 sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
2639
2640 /* extract core_id, core_rev, core_vendor */
2641 core_id = (sb_id_hi & 0x8FF0) >> 4;
2642 core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
2643 core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
2644
2645 dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
2646 current_core, core_id, core_rev, core_vendor);
2647
2648 core = NULL;
2649 switch (core_id) {
2650 case BCM43xx_COREID_PCI:
2651 case BCM43xx_COREID_PCIE:
2652 core = &bcm->core_pci;
2653 if (core->available) {
2654 printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
2655 continue;
2656 }
2657 break;
2658 case BCM43xx_COREID_80211:
2659 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
2660 core = &(bcm->core_80211[i]);
2661 ext_80211 = &(bcm->core_80211_ext[i]);
2662 if (!core->available)
2663 break;
2664 core = NULL;
2665 }
2666 if (!core) {
2667 printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
2668 BCM43xx_MAX_80211_CORES);
2669 continue;
2670 }
2671 if (i != 0) {
2672 /* More than one 80211 core is only supported
2673 * by special chips.
2674 * There are chips with two 80211 cores, but with
2675 * dangling pins on the second core. Be careful
2676 * and ignore these cores here.
2677 */
2678 if (1 /*bcm->pci_dev->device != 0x4324*/ ) {
2679 /* TODO: A PHY */
2680 dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n");
2681 continue;
2682 }
2683 }
2684 switch (core_rev) {
2685 case 2:
2686 case 4:
2687 case 5:
2688 case 6:
2689 case 7:
2690 case 9:
2691 case 10:
2692 break;
2693 default:
2694 printk(KERN_WARNING PFX
2695 "Unsupported 80211 core revision %u\n",
2696 core_rev);
2697 }
2698 bcm->nr_80211_available++;
2699 core->priv = ext_80211;
2700 bcm43xx_init_struct_phyinfo(&ext_80211->phy);
2701 bcm43xx_init_struct_radioinfo(&ext_80211->radio);
2702 break;
2703 case BCM43xx_COREID_CHIPCOMMON:
2704 printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
2705 break;
2706 }
2707 if (core) {
2708 core->available = 1;
2709 core->id = core_id;
2710 core->rev = core_rev;
2711 core->index = current_core;
2712 }
2713 }
2714
2715 if (!bcm->core_80211[0].available) {
2716 printk(KERN_ERR PFX "Error: No 80211 core found!\n");
2717 err = -ENODEV;
2718 goto out;
2719 }
2720
2721 err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
2722
2723 assert(err == 0);
2724out:
2725 return err;
2726}
2727
2728static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
2729{
2730 const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
2731 u8 *bssid = bcm->ieee->bssid;
2732
2733 switch (bcm->ieee->iw_mode) {
2734 case IW_MODE_ADHOC:
2735 random_ether_addr(bssid);
2736 break;
2737 case IW_MODE_MASTER:
2738 case IW_MODE_INFRA:
2739 case IW_MODE_REPEAT:
2740 case IW_MODE_SECOND:
2741 case IW_MODE_MONITOR:
2742 memcpy(bssid, mac, ETH_ALEN);
2743 break;
2744 default:
2745 assert(0);
2746 }
2747}
2748
2749static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
2750 u16 rate,
2751 int is_ofdm)
2752{
2753 u16 offset;
2754
2755 if (is_ofdm) {
2756 offset = 0x480;
2757 offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
2758 }
2759 else {
2760 offset = 0x4C0;
2761 offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
2762 }
2763 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
2764 bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
2765}
2766
2767static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
2768{
2769 switch (bcm43xx_current_phy(bcm)->type) {
2770 case BCM43xx_PHYTYPE_A:
2771 case BCM43xx_PHYTYPE_G:
2772 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
2773 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
2774 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
2775 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
2776 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
2777 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
2778 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
2779 case BCM43xx_PHYTYPE_B:
2780 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
2781 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
2782 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
2783 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
2784 break;
2785 default:
2786 assert(0);
2787 }
2788}
2789
2790static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
2791{
2792 bcm43xx_chip_cleanup(bcm);
2793 bcm43xx_pio_free(bcm);
2794 bcm43xx_dma_free(bcm);
2795
2796 bcm->current_core->initialized = 0;
2797}
2798
2799/* http://bcm-specs.sipsolutions.net/80211Init */
2800static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
2801 int active_wlcore)
2802{
2803 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2804 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2805 u32 ucodeflags;
2806 int err;
2807 u32 sbimconfiglow;
2808 u8 limit;
2809
2810 if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
2811 sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
2812 sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
2813 sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
2814 if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
2815 sbimconfiglow |= 0x32;
2816 else
2817 sbimconfiglow |= 0x53;
2818 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
2819 }
2820
2821 bcm43xx_phy_calibrate(bcm);
2822 err = bcm43xx_chip_init(bcm);
2823 if (err)
2824 goto out;
2825
2826 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
2827 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
2828
2829 if (0 /*FIXME: which condition has to be used here? */)
2830 ucodeflags |= 0x00000010;
2831
2832 /* HW decryption needs to be set now */
2833 ucodeflags |= 0x40000000;
2834
2835 if (phy->type == BCM43xx_PHYTYPE_G) {
2836 ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
2837 if (phy->rev == 1)
2838 ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
2839 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
2840 ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
2841 } else if (phy->type == BCM43xx_PHYTYPE_B) {
2842 ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
2843 if (phy->rev >= 2 && radio->version == 0x2050)
2844 ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
2845 }
2846
2847 if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
2848 BCM43xx_UCODEFLAGS_OFFSET)) {
2849 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
2850 BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
2851 }
2852
2853 /* Short/Long Retry Limit.
2854 * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
2855 * the chip-internal counter.
2856 */
2857 limit = limit_value(modparam_short_retry, 0, 0xF);
2858 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
2859 limit = limit_value(modparam_long_retry, 0, 0xF);
2860 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
2861
2862 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
2863 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
2864
2865 bcm43xx_rate_memory_init(bcm);
2866
2867 /* Minimum Contention Window */
2868 if (phy->type == BCM43xx_PHYTYPE_B)
2869 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
2870 else
2871 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
2872 /* Maximum Contention Window */
2873 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
2874
2875 bcm43xx_gen_bssid(bcm);
2876 bcm43xx_write_mac_bssid_templates(bcm);
2877
2878 if (bcm->current_core->rev >= 5)
2879 bcm43xx_write16(bcm, 0x043C, 0x000C);
2880
2881 if (active_wlcore) {
2882 if (bcm43xx_using_pio(bcm)) {
2883 err = bcm43xx_pio_init(bcm);
2884 } else {
2885 err = bcm43xx_dma_init(bcm);
2886 if (err == -ENOSYS)
2887 err = bcm43xx_pio_init(bcm);
2888 }
2889 if (err)
2890 goto err_chip_cleanup;
2891 }
2892 bcm43xx_write16(bcm, 0x0612, 0x0050);
2893 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
2894 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
2895
2896 if (active_wlcore) {
2897 if (radio->initial_channel != 0xFF)
2898 bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
2899 }
2900
2901 /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
2902 * We enable it later.
2903 */
2904 bcm->current_core->initialized = 1;
2905out:
2906 return err;
2907
2908err_chip_cleanup:
2909 bcm43xx_chip_cleanup(bcm);
2910 goto out;
2911}
2912
2913static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
2914{
2915 int err;
2916 u16 pci_status;
2917
2918 err = bcm43xx_pctl_set_crystal(bcm, 1);
2919 if (err)
2920 goto out;
2921 err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
2922 if (err)
2923 goto out;
2924 err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
2925
2926out:
2927 return err;
2928}
2929
2930static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
2931{
2932 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
2933 bcm43xx_pctl_set_crystal(bcm, 0);
2934}
2935
2936static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
2937 u32 address,
2938 u32 data)
2939{
2940 bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
2941 bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
2942}
2943
2944static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
2945{
2946 int err = 0;
2947
2948 bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
2949
2950 if (bcm->core_chipcommon.available) {
2951 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
2952 if (err)
2953 goto out;
2954
2955 bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
2956
2957 /* this function is always called when a PCI core is mapped */
2958 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
2959 if (err)
2960 goto out;
2961 } else
2962 bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
2963
2964 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
2965
2966out:
2967 return err;
2968}
2969
2970static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
2971{
2972 bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
2973 return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
2974}
2975
2976static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
2977 u32 data)
2978{
2979 bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
2980 bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
2981}
2982
2983static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
2984 u16 data)
2985{
2986 int i;
2987
2988 bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
2989 bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
2990 BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
2991 (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
2992 data);
2993 udelay(10);
2994
2995 for (i = 0; i < 10; i++) {
2996 if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
2997 BCM43xx_PCIE_MDIO_TC)
2998 break;
2999 msleep(1);
3000 }
3001 bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
3002}
3003
3004/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
3005 * To enable core 0, pass a core_mask of 1<<0
3006 */
3007static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
3008 u32 core_mask)
3009{
3010 u32 backplane_flag_nr;
3011 u32 value;
3012 struct bcm43xx_coreinfo *old_core;
3013 int err = 0;
3014
3015 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
3016 backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
3017
3018 old_core = bcm->current_core;
3019 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
3020 if (err)
3021 goto out;
3022
3023 if (bcm->current_core->rev < 6 &&
3024 bcm->current_core->id == BCM43xx_COREID_PCI) {
3025 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
3026 value |= (1 << backplane_flag_nr);
3027 bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
3028 } else {
3029 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
3030 if (err) {
3031 printk(KERN_ERR PFX "Error: ICR setup failure!\n");
3032 goto out_switch_back;
3033 }
3034 value |= core_mask << 8;
3035 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
3036 if (err) {
3037 printk(KERN_ERR PFX "Error: ICR setup failure!\n");
3038 goto out_switch_back;
3039 }
3040 }
3041
3042 if (bcm->current_core->id == BCM43xx_COREID_PCI) {
3043 value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
3044 value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
3045 bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
3046
3047 if (bcm->current_core->rev < 5) {
3048 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
3049 value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
3050 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
3051 value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
3052 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
3053 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
3054 err = bcm43xx_pcicore_commit_settings(bcm);
3055 assert(err == 0);
3056 } else if (bcm->current_core->rev >= 11) {
3057 value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
3058 value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
3059 bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
3060 }
3061 } else {
3062 if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
3063 value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
3064 value |= 0x8;
3065 bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
3066 value);
3067 }
3068 if (bcm->current_core->rev == 0) {
3069 bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
3070 BCM43xx_SERDES_RXTIMER, 0x8128);
3071 bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
3072 BCM43xx_SERDES_CDR, 0x0100);
3073 bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
3074 BCM43xx_SERDES_CDR_BW, 0x1466);
3075 } else if (bcm->current_core->rev == 1) {
3076 value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
3077 value |= 0x40;
3078 bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
3079 value);
3080 }
3081 }
3082out_switch_back:
3083 err = bcm43xx_switch_core(bcm, old_core);
3084out:
3085 return err;
3086}
3087
3088static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
3089{
3090 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
3091
3092 if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
3093 return;
3094
3095 bcm43xx_mac_suspend(bcm);
3096 bcm43xx_phy_lo_g_measure(bcm);
3097 bcm43xx_mac_enable(bcm);
3098}
3099
3100static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
3101{
3102 bcm43xx_phy_lo_mark_all_unused(bcm);
3103 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
3104 bcm43xx_mac_suspend(bcm);
3105 bcm43xx_calc_nrssi_slope(bcm);
3106 bcm43xx_mac_enable(bcm);
3107 }
3108}
3109
3110static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
3111{
3112 /* Update device statistics. */
3113 bcm43xx_calculate_link_quality(bcm);
3114}
3115
3116static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
3117{
3118 bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
3119 //TODO for APHY (temperature?)
3120}
3121
3122static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm)
3123{
3124 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
3125 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
3126 int radio_hw_enable;
3127
3128 /* check if radio hardware enabled status changed */
3129 radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
3130 if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) {
3131 bcm->radio_hw_enable = radio_hw_enable;
3132 printk(KERN_INFO PFX "Radio hardware status changed to %s\n",
3133 (radio_hw_enable == 0) ? "disabled" : "enabled");
3134 bcm43xx_leds_update(bcm, 0);
3135 }
3136 if (phy->type == BCM43xx_PHYTYPE_G) {
3137 //TODO: update_aci_moving_average
3138 if (radio->aci_enable && radio->aci_wlan_automatic) {
3139 bcm43xx_mac_suspend(bcm);
3140 if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
3141 if (0 /*TODO: bunch of conditions*/) {
3142 bcm43xx_radio_set_interference_mitigation(bcm,
3143 BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3144 }
3145 } else if (1/*TODO*/) {
3146 /*
3147 if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
3148 bcm43xx_radio_set_interference_mitigation(bcm,
3149 BCM43xx_RADIO_INTERFMODE_NONE);
3150 }
3151 */
3152 }
3153 bcm43xx_mac_enable(bcm);
3154 } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
3155 phy->rev == 1) {
3156 //TODO: implement rev1 workaround
3157 }
3158 }
3159}
3160
3161static void do_periodic_work(struct bcm43xx_private *bcm)
3162{
3163 if (bcm->periodic_state % 120 == 0)
3164 bcm43xx_periodic_every120sec(bcm);
3165 if (bcm->periodic_state % 60 == 0)
3166 bcm43xx_periodic_every60sec(bcm);
3167 if (bcm->periodic_state % 30 == 0)
3168 bcm43xx_periodic_every30sec(bcm);
3169 if (bcm->periodic_state % 15 == 0)
3170 bcm43xx_periodic_every15sec(bcm);
3171 bcm43xx_periodic_every1sec(bcm);
3172
3173 schedule_delayed_work(&bcm->periodic_work, HZ);
3174}
3175
3176static void bcm43xx_periodic_work_handler(struct work_struct *work)
3177{
3178 struct bcm43xx_private *bcm =
3179 container_of(work, struct bcm43xx_private, periodic_work.work);
3180 struct net_device *net_dev = bcm->net_dev;
3181 unsigned long flags;
3182 u32 savedirqs = 0;
3183 unsigned long orig_trans_start = 0;
3184
3185 mutex_lock(&bcm->mutex);
3186 /* keep from doing and rearming periodic work if shutting down */
3187 if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
3188 goto unlock_mutex;
3189 if (unlikely(bcm->periodic_state % 60 == 0)) {
3190 /* Periodic work will take a long time, so we want it to
3191 * be preemtible.
3192 */
3193
3194 netif_tx_lock_bh(net_dev);
3195 /* We must fake a started transmission here, as we are going to
3196 * disable TX. If we wouldn't fake a TX, it would be possible to
3197 * trigger the netdev watchdog, if the last real TX is already
3198 * some time on the past (slightly less than 5secs)
3199 */
3200 orig_trans_start = net_dev->trans_start;
3201 net_dev->trans_start = jiffies;
3202 netif_stop_queue(net_dev);
3203 netif_tx_unlock_bh(net_dev);
3204
3205 spin_lock_irqsave(&bcm->irq_lock, flags);
3206 bcm43xx_mac_suspend(bcm);
3207 if (bcm43xx_using_pio(bcm))
3208 bcm43xx_pio_freeze_txqueues(bcm);
3209 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3210 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3211 bcm43xx_synchronize_irq(bcm);
3212 } else {
3213 /* Periodic work should take short time, so we want low
3214 * locking overhead.
3215 */
3216 spin_lock_irqsave(&bcm->irq_lock, flags);
3217 }
3218
3219 do_periodic_work(bcm);
3220
3221 if (unlikely(bcm->periodic_state % 60 == 0)) {
3222 spin_lock_irqsave(&bcm->irq_lock, flags);
3223 tasklet_enable(&bcm->isr_tasklet);
3224 bcm43xx_interrupt_enable(bcm, savedirqs);
3225 if (bcm43xx_using_pio(bcm))
3226 bcm43xx_pio_thaw_txqueues(bcm);
3227 bcm43xx_mac_enable(bcm);
3228 netif_wake_queue(bcm->net_dev);
3229 net_dev->trans_start = orig_trans_start;
3230 }
3231 mmiowb();
3232 bcm->periodic_state++;
3233 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3234unlock_mutex:
3235 mutex_unlock(&bcm->mutex);
3236}
3237
3238void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
3239{
3240 struct delayed_work *work = &bcm->periodic_work;
3241
3242 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3243 INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
3244 schedule_delayed_work(work, 0);
3245}
3246
3247static void bcm43xx_security_init(struct bcm43xx_private *bcm)
3248{
3249 bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
3250 0x0056) * 2;
3251 bcm43xx_clear_keys(bcm);
3252}
3253
3254static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
3255{
3256 struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
3257 unsigned long flags;
3258
3259 spin_lock_irqsave(&(bcm)->irq_lock, flags);
3260 *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
3261 spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
3262
3263 return (sizeof(u16));
3264}
3265
3266static void bcm43xx_rng_exit(struct bcm43xx_private *bcm)
3267{
3268 hwrng_unregister(&bcm->rng);
3269}
3270
3271static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
3272{
3273 int err;
3274
3275 snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name),
3276 "%s_%s", KBUILD_MODNAME, bcm->net_dev->name);
3277 bcm->rng.name = bcm->rng_name;
3278 bcm->rng.data_read = bcm43xx_rng_read;
3279 bcm->rng.priv = (unsigned long)bcm;
3280 err = hwrng_register(&bcm->rng);
3281 if (err)
3282 printk(KERN_ERR PFX "RNG init failed (%d)\n", err);
3283
3284 return err;
3285}
3286
3287void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
3288{
3289 /* The system must be unlocked when this routine is entered.
3290 * If not, the next 2 steps may deadlock */
3291 cancel_work_sync(&bcm->restart_work);
3292 cancel_delayed_work_sync(&bcm->periodic_work);
3293}
3294
3295static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
3296{
3297 int ret = 0;
3298 int i, err;
3299 struct bcm43xx_coreinfo *core;
3300
3301 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
3302 for (i = 0; i < bcm->nr_80211_available; i++) {
3303 core = &(bcm->core_80211[i]);
3304 assert(core->available);
3305 if (!core->initialized)
3306 continue;
3307 err = bcm43xx_switch_core(bcm, core);
3308 if (err) {
3309 dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
3310 "switch_core failed (%d)\n", err);
3311 ret = err;
3312 continue;
3313 }
3314 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3315 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
3316 bcm43xx_wireless_core_cleanup(bcm);
3317 if (core == bcm->active_80211_core)
3318 bcm->active_80211_core = NULL;
3319 }
3320 free_irq(bcm->irq, bcm);
3321 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3322
3323 return ret;
3324}
3325
3326/* This is the opposite of bcm43xx_init_board() */
3327static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3328{
3329 bcm43xx_rng_exit(bcm);
3330 bcm43xx_sysfs_unregister(bcm);
3331
3332 mutex_lock(&(bcm)->mutex);
3333 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3334 mutex_unlock(&(bcm)->mutex);
3335
3336 bcm43xx_cancel_work(bcm);
3337
3338 mutex_lock(&(bcm)->mutex);
3339 bcm43xx_shutdown_all_wireless_cores(bcm);
3340 bcm43xx_pctl_set_crystal(bcm, 0);
3341 mutex_unlock(&(bcm)->mutex);
3342}
3343
3344static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
3345{
3346 phy->antenna_diversity = 0xFFFF;
3347 memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
3348 memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
3349
3350 /* Flags */
3351 phy->calibrated = 0;
3352 phy->is_locked = 0;
3353
3354 if (phy->_lo_pairs) {
3355 memset(phy->_lo_pairs, 0,
3356 sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
3357 }
3358 memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
3359}
3360
3361static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
3362 struct bcm43xx_radioinfo *radio)
3363{
3364 int i;
3365
3366 /* Set default attenuation values. */
3367 radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
3368 radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
3369 radio->txctl1 = bcm43xx_default_txctl1(bcm);
3370 radio->txctl2 = 0xFFFF;
3371 radio->txpwr_offset = 0;
3372
3373 /* NRSSI */
3374 radio->nrssislope = 0;
3375 for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
3376 radio->nrssi[i] = -1000;
3377 for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
3378 radio->nrssi_lt[i] = i;
3379
3380 radio->lofcal = 0xFFFF;
3381 radio->initval = 0xFFFF;
3382
3383 radio->aci_enable = 0;
3384 radio->aci_wlan_automatic = 0;
3385 radio->aci_hw_rssi = 0;
3386}
3387
3388static void prepare_priv_for_init(struct bcm43xx_private *bcm)
3389{
3390 int i;
3391 struct bcm43xx_coreinfo *core;
3392 struct bcm43xx_coreinfo_80211 *wlext;
3393
3394 assert(!bcm->active_80211_core);
3395
3396 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3397
3398 /* Flags */
3399 bcm->was_initialized = 0;
3400 bcm->reg124_set_0x4 = 0;
3401
3402 /* Stats */
3403 memset(&bcm->stats, 0, sizeof(bcm->stats));
3404
3405 /* Wireless core data */
3406 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3407 core = &(bcm->core_80211[i]);
3408 wlext = core->priv;
3409
3410 if (!core->available)
3411 continue;
3412 assert(wlext == &(bcm->core_80211_ext[i]));
3413
3414 prepare_phydata_for_init(&wlext->phy);
3415 prepare_radiodata_for_init(bcm, &wlext->radio);
3416 }
3417
3418 /* IRQ related flags */
3419 bcm->irq_reason = 0;
3420 memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
3421 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3422
3423 bcm->mac_suspended = 1;
3424
3425 /* Noise calculation context */
3426 memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
3427
3428 /* Periodic work context */
3429 bcm->periodic_state = 0;
3430}
3431
3432static int wireless_core_up(struct bcm43xx_private *bcm,
3433 int active_wlcore)
3434{
3435 int err;
3436
3437 if (!bcm43xx_core_enabled(bcm))
3438 bcm43xx_wireless_core_reset(bcm, 1);
3439 if (!active_wlcore)
3440 bcm43xx_wireless_core_mark_inactive(bcm);
3441 err = bcm43xx_wireless_core_init(bcm, active_wlcore);
3442 if (err)
3443 goto out;
3444 if (!active_wlcore)
3445 bcm43xx_radio_turn_off(bcm);
3446out:
3447 return err;
3448}
3449
3450/* Select and enable the "to be used" wireless core.
3451 * Locking: bcm->mutex must be aquired before calling this.
3452 * bcm->irq_lock must not be aquired.
3453 */
3454int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
3455 int phytype)
3456{
3457 int i, err;
3458 struct bcm43xx_coreinfo *active_core = NULL;
3459 struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
3460 struct bcm43xx_coreinfo *core;
3461 struct bcm43xx_coreinfo_80211 *wlext;
3462 int adjust_active_sbtmstatelow = 0;
3463
3464 might_sleep();
3465
3466 if (phytype < 0) {
3467 /* If no phytype is requested, select the first core. */
3468 assert(bcm->core_80211[0].available);
3469 wlext = bcm->core_80211[0].priv;
3470 phytype = wlext->phy.type;
3471 }
3472 /* Find the requested core. */
3473 for (i = 0; i < bcm->nr_80211_available; i++) {
3474 core = &(bcm->core_80211[i]);
3475 wlext = core->priv;
3476 if (wlext->phy.type == phytype) {
3477 active_core = core;
3478 active_wlext = wlext;
3479 break;
3480 }
3481 }
3482 if (!active_core)
3483 return -ESRCH; /* No such PHYTYPE on this board. */
3484
3485 if (bcm->active_80211_core) {
3486 /* We already selected a wl core in the past.
3487 * So first clean up everything.
3488 */
3489 dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
3490 ieee80211softmac_stop(bcm->net_dev);
3491 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3492 err = bcm43xx_disable_interrupts_sync(bcm);
3493 assert(!err);
3494 tasklet_enable(&bcm->isr_tasklet);
3495 err = bcm43xx_shutdown_all_wireless_cores(bcm);
3496 if (err)
3497 goto error;
3498 /* Ok, everything down, continue to re-initialize. */
3499 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3500 }
3501
3502 /* Reset all data structures. */
3503 prepare_priv_for_init(bcm);
3504
3505 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
3506 if (err)
3507 goto error;
3508
3509 /* Mark all unused cores "inactive". */
3510 for (i = 0; i < bcm->nr_80211_available; i++) {
3511 core = &(bcm->core_80211[i]);
3512 wlext = core->priv;
3513
3514 if (core == active_core)
3515 continue;
3516 err = bcm43xx_switch_core(bcm, core);
3517 if (err) {
3518 dprintk(KERN_ERR PFX "Could not switch to inactive "
3519 "802.11 core (%d)\n", err);
3520 goto error;
3521 }
3522 err = wireless_core_up(bcm, 0);
3523 if (err) {
3524 dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
3525 "failed (%d)\n", err);
3526 goto error;
3527 }
3528 adjust_active_sbtmstatelow = 1;
3529 }
3530
3531 /* Now initialize the active 802.11 core. */
3532 err = bcm43xx_switch_core(bcm, active_core);
3533 if (err) {
3534 dprintk(KERN_ERR PFX "Could not switch to active "
3535 "802.11 core (%d)\n", err);
3536 goto error;
3537 }
3538 if (adjust_active_sbtmstatelow &&
3539 active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
3540 u32 sbtmstatelow;
3541
3542 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
3543 sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
3544 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
3545 }
3546 err = wireless_core_up(bcm, 1);
3547 if (err) {
3548 dprintk(KERN_ERR PFX "core_up for active 802.11 core "
3549 "failed (%d)\n", err);
3550 goto error;
3551 }
3552 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
3553 if (err)
3554 goto error;
3555 bcm->active_80211_core = active_core;
3556
3557 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3558 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
3559 bcm43xx_security_init(bcm);
3560 drain_txstatus_queue(bcm);
3561 ieee80211softmac_start(bcm->net_dev);
3562
3563 /* Let's go! Be careful after enabling the IRQs.
3564 * Don't switch cores, for example.
3565 */
3566 bcm43xx_mac_enable(bcm);
3567 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3568 err = bcm43xx_initialize_irq(bcm);
3569 if (err)
3570 goto error;
3571 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
3572
3573 dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
3574 active_wlext->phy.type);
3575
3576 return 0;
3577
3578error:
3579 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3580 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
3581 return err;
3582}
3583
3584static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3585{
3586 int err;
3587
3588 mutex_lock(&(bcm)->mutex);
3589
3590 tasklet_enable(&bcm->isr_tasklet);
3591 err = bcm43xx_pctl_set_crystal(bcm, 1);
3592 if (err)
3593 goto err_tasklet;
3594 err = bcm43xx_pctl_init(bcm);
3595 if (err)
3596 goto err_crystal_off;
3597 err = bcm43xx_select_wireless_core(bcm, -1);
3598 if (err)
3599 goto err_crystal_off;
3600 err = bcm43xx_sysfs_register(bcm);
3601 if (err)
3602 goto err_wlshutdown;
3603 err = bcm43xx_rng_init(bcm);
3604 if (err)
3605 goto err_sysfs_unreg;
3606 bcm43xx_periodic_tasks_setup(bcm);
3607
3608 /*FIXME: This should be handled by softmac instead. */
3609 schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
3610
3611out:
3612 mutex_unlock(&(bcm)->mutex);
3613
3614 return err;
3615
3616err_sysfs_unreg:
3617 bcm43xx_sysfs_unregister(bcm);
3618err_wlshutdown:
3619 bcm43xx_shutdown_all_wireless_cores(bcm);
3620err_crystal_off:
3621 bcm43xx_pctl_set_crystal(bcm, 0);
3622err_tasklet:
3623 tasklet_disable(&bcm->isr_tasklet);
3624 goto out;
3625}
3626
3627static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
3628{
3629 struct pci_dev *pci_dev = bcm->pci_dev;
3630 int i;
3631
3632 bcm43xx_chipset_detach(bcm);
3633 /* Do _not_ access the chip, after it is detached. */
3634 pci_iounmap(pci_dev, bcm->mmio_addr);
3635 pci_release_regions(pci_dev);
3636 pci_disable_device(pci_dev);
3637
3638 /* Free allocated structures/fields */
3639 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3640 kfree(bcm->core_80211_ext[i].phy._lo_pairs);
3641 if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
3642 kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
3643 }
3644}
3645
3646static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
3647{
3648 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
3649 u16 value;
3650 u8 phy_analog;
3651 u8 phy_type;
3652 u8 phy_rev;
3653 int phy_rev_ok = 1;
3654 void *p;
3655
3656 value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
3657
3658 phy_analog = (value & 0xF000) >> 12;
3659 phy_type = (value & 0x0F00) >> 8;
3660 phy_rev = (value & 0x000F);
3661
3662 dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
3663 phy_analog, phy_type, phy_rev);
3664
3665 switch (phy_type) {
3666 case BCM43xx_PHYTYPE_A:
3667 if (phy_rev >= 4)
3668 phy_rev_ok = 0;
3669 /*FIXME: We need to switch the ieee->modulation, etc.. flags,
3670 * if we switch 80211 cores after init is done.
3671 * As we do not implement on the fly switching between
3672 * wireless cores, I will leave this as a future task.
3673 */
3674 bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
3675 bcm->ieee->mode = IEEE_A;
3676 bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
3677 IEEE80211_24GHZ_BAND;
3678 break;
3679 case BCM43xx_PHYTYPE_B:
3680 if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
3681 phy_rev_ok = 0;
3682 bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
3683 bcm->ieee->mode = IEEE_B;
3684 bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
3685 break;
3686 case BCM43xx_PHYTYPE_G:
3687 if (phy_rev > 8)
3688 phy_rev_ok = 0;
3689 bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
3690 IEEE80211_CCK_MODULATION;
3691 bcm->ieee->mode = IEEE_G;
3692 bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
3693 break;
3694 default:
3695 printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
3696 phy_type);
3697 return -ENODEV;
3698 };
3699 bcm->ieee->perfect_rssi = RX_RSSI_MAX;
3700 bcm->ieee->worst_rssi = 0;
3701 if (!phy_rev_ok) {
3702 printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
3703 phy_rev);
3704 }
3705
3706 phy->analog = phy_analog;
3707 phy->type = phy_type;
3708 phy->rev = phy_rev;
3709 if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
3710 p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
3711 GFP_KERNEL);
3712 if (!p)
3713 return -ENOMEM;
3714 phy->_lo_pairs = p;
3715 }
3716
3717 return 0;
3718}
3719
3720static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
3721{
3722 struct pci_dev *pci_dev = bcm->pci_dev;
3723 struct net_device *net_dev = bcm->net_dev;
3724 int err;
3725 int i;
3726 u32 coremask;
3727
3728 err = pci_enable_device(pci_dev);
3729 if (err) {
3730 printk(KERN_ERR PFX "pci_enable_device() failed\n");
3731 goto out;
3732 }
3733 err = pci_request_regions(pci_dev, KBUILD_MODNAME);
3734 if (err) {
3735 printk(KERN_ERR PFX "pci_request_regions() failed\n");
3736 goto err_pci_disable;
3737 }
3738 /* enable PCI bus-mastering */
3739 pci_set_master(pci_dev);
3740 bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
3741 if (!bcm->mmio_addr) {
3742 printk(KERN_ERR PFX "pci_iomap() failed\n");
3743 err = -EIO;
3744 goto err_pci_release;
3745 }
3746 net_dev->base_addr = (unsigned long)bcm->mmio_addr;
3747
3748 err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
3749 &bcm->board_vendor);
3750 if (err)
3751 goto err_iounmap;
3752 err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
3753 &bcm->board_type);
3754 if (err)
3755 goto err_iounmap;
3756
3757 bcm->board_revision = bcm->pci_dev->revision;
3758
3759 err = bcm43xx_chipset_attach(bcm);
3760 if (err)
3761 goto err_iounmap;
3762 err = bcm43xx_pctl_init(bcm);
3763 if (err)
3764 goto err_chipset_detach;
3765 err = bcm43xx_probe_cores(bcm);
3766 if (err)
3767 goto err_chipset_detach;
3768
3769 /* Attach all IO cores to the backplane. */
3770 coremask = 0;
3771 for (i = 0; i < bcm->nr_80211_available; i++)
3772 coremask |= (1 << bcm->core_80211[i].index);
3773 //FIXME: Also attach some non80211 cores?
3774 err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
3775 if (err) {
3776 printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
3777 goto err_chipset_detach;
3778 }
3779
3780 err = bcm43xx_sprom_extract(bcm);
3781 if (err)
3782 goto err_chipset_detach;
3783 err = bcm43xx_leds_init(bcm);
3784 if (err)
3785 goto err_chipset_detach;
3786
3787 for (i = 0; i < bcm->nr_80211_available; i++) {
3788 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3789 assert(err != -ENODEV);
3790 if (err)
3791 goto err_80211_unwind;
3792
3793 /* Enable the selected wireless core.
3794 * Connect PHY only on the first core.
3795 */
3796 bcm43xx_wireless_core_reset(bcm, (i == 0));
3797
3798 err = bcm43xx_read_phyinfo(bcm);
3799 if (err && (i == 0))
3800 goto err_80211_unwind;
3801
3802 err = bcm43xx_read_radioinfo(bcm);
3803 if (err && (i == 0))
3804 goto err_80211_unwind;
3805
3806 err = bcm43xx_validate_chip(bcm);
3807 if (err && (i == 0))
3808 goto err_80211_unwind;
3809
3810 bcm43xx_radio_turn_off(bcm);
3811 err = bcm43xx_phy_init_tssi2dbm_table(bcm);
3812 if (err)
3813 goto err_80211_unwind;
3814 bcm43xx_wireless_core_disable(bcm);
3815 }
3816 err = bcm43xx_geo_init(bcm);
3817 if (err)
3818 goto err_80211_unwind;
3819 bcm43xx_pctl_set_crystal(bcm, 0);
3820
3821 /* Set the MAC address in the networking subsystem */
3822 if (is_valid_ether_addr(bcm->sprom.et1macaddr))
3823 memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
3824 else
3825 memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
3826
3827 snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
3828 "Broadcom %04X", bcm->chip_id);
3829
3830 assert(err == 0);
3831out:
3832 return err;
3833
3834err_80211_unwind:
3835 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3836 kfree(bcm->core_80211_ext[i].phy._lo_pairs);
3837 if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
3838 kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
3839 }
3840err_chipset_detach:
3841 bcm43xx_chipset_detach(bcm);
3842err_iounmap:
3843 pci_iounmap(pci_dev, bcm->mmio_addr);
3844err_pci_release:
3845 pci_release_regions(pci_dev);
3846err_pci_disable:
3847 pci_disable_device(pci_dev);
3848 printk(KERN_ERR PFX "Unable to attach board\n");
3849 goto out;
3850}
3851
3852/* Do the Hardware IO operations to send the txb */
3853static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
3854 struct ieee80211_txb *txb)
3855{
3856 int err = -ENODEV;
3857
3858 if (bcm43xx_using_pio(bcm))
3859 err = bcm43xx_pio_tx(bcm, txb);
3860 else
3861 err = bcm43xx_dma_tx(bcm, txb);
3862 bcm->net_dev->trans_start = jiffies;
3863
3864 return err;
3865}
3866
3867static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
3868 u8 channel)
3869{
3870 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3871 struct bcm43xx_radioinfo *radio;
3872 unsigned long flags;
3873
3874 mutex_lock(&bcm->mutex);
3875 spin_lock_irqsave(&bcm->irq_lock, flags);
3876 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
3877 bcm43xx_mac_suspend(bcm);
3878 bcm43xx_radio_selectchannel(bcm, channel, 0);
3879 bcm43xx_mac_enable(bcm);
3880 } else {
3881 radio = bcm43xx_current_radio(bcm);
3882 radio->initial_channel = channel;
3883 }
3884 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3885 mutex_unlock(&bcm->mutex);
3886}
3887
3888/* set_security() callback in struct ieee80211_device */
3889static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3890 struct ieee80211_security *sec)
3891{
3892 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3893 struct ieee80211_security *secinfo = &bcm->ieee->sec;
3894 unsigned long flags;
3895 int keyidx;
3896
3897 dprintk(KERN_INFO PFX "set security called");
3898
3899 mutex_lock(&bcm->mutex);
3900 spin_lock_irqsave(&bcm->irq_lock, flags);
3901
3902 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
3903 if (sec->flags & (1<<keyidx)) {
3904 secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
3905 secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
3906 memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
3907 }
3908
3909 if (sec->flags & SEC_ACTIVE_KEY) {
3910 secinfo->active_key = sec->active_key;
3911 dprintk(", .active_key = %d", sec->active_key);
3912 }
3913 if (sec->flags & SEC_UNICAST_GROUP) {
3914 secinfo->unicast_uses_group = sec->unicast_uses_group;
3915 dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
3916 }
3917 if (sec->flags & SEC_LEVEL) {
3918 secinfo->level = sec->level;
3919 dprintk(", .level = %d", sec->level);
3920 }
3921 if (sec->flags & SEC_ENABLED) {
3922 secinfo->enabled = sec->enabled;
3923 dprintk(", .enabled = %d", sec->enabled);
3924 }
3925 if (sec->flags & SEC_ENCRYPT) {
3926 secinfo->encrypt = sec->encrypt;
3927 dprintk(", .encrypt = %d", sec->encrypt);
3928 }
3929 if (sec->flags & SEC_AUTH_MODE) {
3930 secinfo->auth_mode = sec->auth_mode;
3931 dprintk(", .auth_mode = %d", sec->auth_mode);
3932 }
3933 dprintk("\n");
3934 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
3935 !bcm->ieee->host_encrypt) {
3936 if (secinfo->enabled) {
3937 /* upload WEP keys to hardware */
3938 char null_address[6] = { 0 };
3939 u8 algorithm = 0;
3940 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
3941 if (!(sec->flags & (1<<keyidx)))
3942 continue;
3943 switch (sec->encode_alg[keyidx]) {
3944 case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
3945 case SEC_ALG_WEP:
3946 algorithm = BCM43xx_SEC_ALGO_WEP;
3947 if (secinfo->key_sizes[keyidx] == 13)
3948 algorithm = BCM43xx_SEC_ALGO_WEP104;
3949 break;
3950 case SEC_ALG_TKIP:
3951 FIXME();
3952 algorithm = BCM43xx_SEC_ALGO_TKIP;
3953 break;
3954 case SEC_ALG_CCMP:
3955 FIXME();
3956 algorithm = BCM43xx_SEC_ALGO_AES;
3957 break;
3958 default:
3959 assert(0);
3960 break;
3961 }
3962 bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
3963 bcm->key[keyidx].enabled = 1;
3964 bcm->key[keyidx].algorithm = algorithm;
3965 }
3966 } else
3967 bcm43xx_clear_keys(bcm);
3968 }
3969 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3970 mutex_unlock(&bcm->mutex);
3971}
3972
3973/* hard_start_xmit() callback in struct ieee80211_device */
3974static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
3975 struct net_device *net_dev,
3976 int pri)
3977{
3978 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3979 int err = -ENODEV;
3980 unsigned long flags;
3981
3982 spin_lock_irqsave(&bcm->irq_lock, flags);
3983 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
3984 err = bcm43xx_tx(bcm, txb);
3985 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3986
3987 if (unlikely(err))
3988 return NETDEV_TX_BUSY;
3989 return NETDEV_TX_OK;
3990}
3991
3992static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
3993{
3994 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3995 unsigned long flags;
3996
3997 spin_lock_irqsave(&bcm->irq_lock, flags);
3998 bcm43xx_controller_restart(bcm, "TX timeout");
3999 spin_unlock_irqrestore(&bcm->irq_lock, flags);
4000}
4001
4002#ifdef CONFIG_NET_POLL_CONTROLLER
4003static void bcm43xx_net_poll_controller(struct net_device *net_dev)
4004{
4005 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4006 unsigned long flags;
4007
4008 local_irq_save(flags);
4009 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
4010 bcm43xx_interrupt_handler(bcm->irq, bcm);
4011 local_irq_restore(flags);
4012}
4013#endif /* CONFIG_NET_POLL_CONTROLLER */
4014
4015static int bcm43xx_net_open(struct net_device *net_dev)
4016{
4017 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4018
4019 return bcm43xx_init_board(bcm);
4020}
4021
4022static int bcm43xx_net_stop(struct net_device *net_dev)
4023{
4024 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4025 int err;
4026
4027 ieee80211softmac_stop(net_dev);
4028 err = bcm43xx_disable_interrupts_sync(bcm);
4029 assert(!err);
4030 bcm43xx_free_board(bcm);
4031 bcm43xx_cancel_work(bcm);
4032
4033 return 0;
4034}
4035
4036static int bcm43xx_init_private(struct bcm43xx_private *bcm,
4037 struct net_device *net_dev,
4038 struct pci_dev *pci_dev)
4039{
4040 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
4041 bcm->ieee = netdev_priv(net_dev);
4042 bcm->softmac = ieee80211_priv(net_dev);
4043 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
4044
4045 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
4046 bcm->mac_suspended = 1;
4047 bcm->pci_dev = pci_dev;
4048 bcm->net_dev = net_dev;
4049 bcm->bad_frames_preempt = modparam_bad_frames_preempt;
4050 spin_lock_init(&bcm->irq_lock);
4051 spin_lock_init(&bcm->leds_lock);
4052 mutex_init(&bcm->mutex);
4053 tasklet_init(&bcm->isr_tasklet,
4054 (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
4055 (unsigned long)bcm);
4056 tasklet_disable_nosync(&bcm->isr_tasklet);
4057 if (modparam_pio)
4058 bcm->__using_pio = 1;
4059 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
4060
4061 /* default to sw encryption for now */
4062 bcm->ieee->host_build_iv = 0;
4063 bcm->ieee->host_encrypt = 1;
4064 bcm->ieee->host_decrypt = 1;
4065
4066 bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
4067 bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
4068 bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
4069 bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
4070
4071 return 0;
4072}
4073
4074static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
4075 const struct pci_device_id *ent)
4076{
4077 struct net_device *net_dev;
4078 struct bcm43xx_private *bcm;
4079 int err;
4080
4081#ifdef DEBUG_SINGLE_DEVICE_ONLY
4082 if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
4083 return -ENODEV;
4084#endif
4085
4086 net_dev = alloc_ieee80211softmac(sizeof(*bcm));
4087 if (!net_dev) {
4088 printk(KERN_ERR PFX
4089 "could not allocate ieee80211 device %s\n",
4090 pci_name(pdev));
4091 err = -ENOMEM;
4092 goto out;
4093 }
4094 /* initialize the net_device struct */
4095 SET_NETDEV_DEV(net_dev, &pdev->dev);
4096
4097 net_dev->open = bcm43xx_net_open;
4098 net_dev->stop = bcm43xx_net_stop;
4099 net_dev->tx_timeout = bcm43xx_net_tx_timeout;
4100#ifdef CONFIG_NET_POLL_CONTROLLER
4101 net_dev->poll_controller = bcm43xx_net_poll_controller;
4102#endif
4103 net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
4104 net_dev->irq = pdev->irq;
4105 SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
4106
4107 /* initialize the bcm43xx_private struct */
4108 bcm = bcm43xx_priv(net_dev);
4109 memset(bcm, 0, sizeof(*bcm));
4110 err = bcm43xx_init_private(bcm, net_dev, pdev);
4111 if (err)
4112 goto err_free_netdev;
4113
4114 pci_set_drvdata(pdev, net_dev);
4115
4116 err = bcm43xx_attach_board(bcm);
4117 if (err)
4118 goto err_free_netdev;
4119
4120 err = register_netdev(net_dev);
4121 if (err) {
4122 printk(KERN_ERR PFX "Cannot register net device, "
4123 "aborting.\n");
4124 err = -ENOMEM;
4125 goto err_detach_board;
4126 }
4127
4128 bcm43xx_debugfs_add_device(bcm);
4129
4130 assert(err == 0);
4131out:
4132 return err;
4133
4134err_detach_board:
4135 bcm43xx_detach_board(bcm);
4136err_free_netdev:
4137 free_ieee80211softmac(net_dev);
4138 goto out;
4139}
4140
4141static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
4142{
4143 struct net_device *net_dev = pci_get_drvdata(pdev);
4144 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4145
4146 bcm43xx_debugfs_remove_device(bcm);
4147 unregister_netdev(net_dev);
4148 bcm43xx_detach_board(bcm);
4149 free_ieee80211softmac(net_dev);
4150}
4151
4152/* Hard-reset the chip. Do not call this directly.
4153 * Use bcm43xx_controller_restart()
4154 */
4155static void bcm43xx_chip_reset(struct work_struct *work)
4156{
4157 struct bcm43xx_private *bcm =
4158 container_of(work, struct bcm43xx_private, restart_work);
4159 struct bcm43xx_phyinfo *phy;
4160 int err = -ENODEV;
4161
4162 bcm43xx_cancel_work(bcm);
4163 mutex_lock(&(bcm)->mutex);
4164 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
4165 phy = bcm43xx_current_phy(bcm);
4166 err = bcm43xx_select_wireless_core(bcm, phy->type);
4167 if (!err)
4168 bcm43xx_periodic_tasks_setup(bcm);
4169 }
4170 mutex_unlock(&(bcm)->mutex);
4171
4172 printk(KERN_ERR PFX "Controller restart%s\n",
4173 (err == 0) ? "ed" : " failed");
4174}
4175
4176/* Hard-reset the chip.
4177 * This can be called from interrupt or process context.
4178 * bcm->irq_lock must be locked.
4179 */
4180void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
4181{
4182 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
4183 return;
4184 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
4185 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
4186 schedule_work(&bcm->restart_work);
4187}
4188
4189#ifdef CONFIG_PM
4190
4191static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
4192{
4193 struct net_device *net_dev = pci_get_drvdata(pdev);
4194 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4195 int err;
4196
4197 dprintk(KERN_INFO PFX "Suspending...\n");
4198
4199 netif_device_detach(net_dev);
4200 bcm->was_initialized = 0;
4201 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
4202 bcm->was_initialized = 1;
4203 ieee80211softmac_stop(net_dev);
4204 err = bcm43xx_disable_interrupts_sync(bcm);
4205 if (unlikely(err)) {
4206 dprintk(KERN_ERR PFX "Suspend failed.\n");
4207 return -EAGAIN;
4208 }
4209 bcm->firmware_norelease = 1;
4210 bcm43xx_free_board(bcm);
4211 bcm->firmware_norelease = 0;
4212 }
4213 bcm43xx_chipset_detach(bcm);
4214
4215 pci_save_state(pdev);
4216 pci_disable_device(pdev);
4217 pci_set_power_state(pdev, pci_choose_state(pdev, state));
4218
4219 dprintk(KERN_INFO PFX "Device suspended.\n");
4220
4221 return 0;
4222}
4223
4224static int bcm43xx_resume(struct pci_dev *pdev)
4225{
4226 struct net_device *net_dev = pci_get_drvdata(pdev);
4227 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
4228 int err = 0;
4229
4230 dprintk(KERN_INFO PFX "Resuming...\n");
4231
4232 pci_set_power_state(pdev, 0);
4233 err = pci_enable_device(pdev);
4234 if (err) {
4235 printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
4236 return err;
4237 }
4238 pci_restore_state(pdev);
4239
4240 bcm43xx_chipset_attach(bcm);
4241 if (bcm->was_initialized)
4242 err = bcm43xx_init_board(bcm);
4243 if (err) {
4244 printk(KERN_ERR PFX "Resume failed!\n");
4245 return err;
4246 }
4247 netif_device_attach(net_dev);
4248
4249 dprintk(KERN_INFO PFX "Device resumed.\n");
4250
4251 return 0;
4252}
4253
4254#endif /* CONFIG_PM */
4255
4256static struct pci_driver bcm43xx_pci_driver = {
4257 .name = KBUILD_MODNAME,
4258 .id_table = bcm43xx_pci_tbl,
4259 .probe = bcm43xx_init_one,
4260 .remove = __devexit_p(bcm43xx_remove_one),
4261#ifdef CONFIG_PM
4262 .suspend = bcm43xx_suspend,
4263 .resume = bcm43xx_resume,
4264#endif /* CONFIG_PM */
4265};
4266
4267static int __init bcm43xx_init(void)
4268{
4269 printk(KERN_INFO KBUILD_MODNAME " driver\n");
4270 bcm43xx_debugfs_init();
4271 return pci_register_driver(&bcm43xx_pci_driver);
4272}
4273
4274static void __exit bcm43xx_exit(void)
4275{
4276 pci_unregister_driver(&bcm43xx_pci_driver);
4277 bcm43xx_debugfs_exit();
4278}
4279
4280module_init(bcm43xx_init)
4281module_exit(bcm43xx_exit)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
deleted file mode 100644
index 14cfbeb582ef..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ /dev/null
@@ -1,133 +0,0 @@
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#ifndef BCM43xx_MAIN_H_
32#define BCM43xx_MAIN_H_
33
34#include "bcm43xx.h"
35
36#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
37#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
38/* Magic helper macro to pad structures. Ignore those above. It's magic. */
39#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
40
41
42/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
43static inline
44u8 bcm43xx_freq_to_channel_a(int freq)
45{
46 return ((freq - 5000) / 5);
47}
48static inline
49u8 bcm43xx_freq_to_channel_bg(int freq)
50{
51 u8 channel;
52
53 if (freq == 2484)
54 channel = 14;
55 else
56 channel = (freq - 2407) / 5;
57
58 return channel;
59}
60static inline
61u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
62 int freq)
63{
64 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
65 return bcm43xx_freq_to_channel_a(freq);
66 return bcm43xx_freq_to_channel_bg(freq);
67}
68
69/* Lightweight function to convert a channel number to a frequency (in Mhz). */
70static inline
71int bcm43xx_channel_to_freq_a(u8 channel)
72{
73 return (5000 + (5 * channel));
74}
75static inline
76int bcm43xx_channel_to_freq_bg(u8 channel)
77{
78 int freq;
79
80 if (channel == 14)
81 freq = 2484;
82 else
83 freq = 2407 + (5 * channel);
84
85 return freq;
86}
87static inline
88int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
89 u8 channel)
90{
91 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
92 return bcm43xx_channel_to_freq_a(channel);
93 return bcm43xx_channel_to_freq_bg(channel);
94}
95
96void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
97void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
98
99void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
100 int iw_mode);
101
102u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
103 u16 routing, u16 offset);
104u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
105 u16 routing, u16 offset);
106void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
107 u16 routing, u16 offset,
108 u32 value);
109void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
110 u16 routing, u16 offset,
111 u16 value);
112
113void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
114
115int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
116
117int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
118 int phytype);
119
120void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
121
122void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
123void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
124
125void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
126void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
127
128void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
129
130int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
131int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
132
133#endif /* BCM43xx_MAIN_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
deleted file mode 100644
index af3de3343650..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ /dev/null
@@ -1,2346 +0,0 @@
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/pci.h>
33#include <linux/types.h>
34
35#include "bcm43xx.h"
36#include "bcm43xx_phy.h"
37#include "bcm43xx_main.h"
38#include "bcm43xx_radio.h"
39#include "bcm43xx_ilt.h"
40#include "bcm43xx_power.h"
41
42
43static const s8 bcm43xx_tssi2dbm_b_table[] = {
44 0x4D, 0x4C, 0x4B, 0x4A,
45 0x4A, 0x49, 0x48, 0x47,
46 0x47, 0x46, 0x45, 0x45,
47 0x44, 0x43, 0x42, 0x42,
48 0x41, 0x40, 0x3F, 0x3E,
49 0x3D, 0x3C, 0x3B, 0x3A,
50 0x39, 0x38, 0x37, 0x36,
51 0x35, 0x34, 0x32, 0x31,
52 0x30, 0x2F, 0x2D, 0x2C,
53 0x2B, 0x29, 0x28, 0x26,
54 0x25, 0x23, 0x21, 0x1F,
55 0x1D, 0x1A, 0x17, 0x14,
56 0x10, 0x0C, 0x06, 0x00,
57 -7, -7, -7, -7,
58 -7, -7, -7, -7,
59 -7, -7, -7, -7,
60};
61
62static const s8 bcm43xx_tssi2dbm_g_table[] = {
63 77, 77, 77, 76,
64 76, 76, 75, 75,
65 74, 74, 73, 73,
66 73, 72, 72, 71,
67 71, 70, 70, 69,
68 68, 68, 67, 67,
69 66, 65, 65, 64,
70 63, 63, 62, 61,
71 60, 59, 58, 57,
72 56, 55, 54, 53,
73 52, 50, 49, 47,
74 45, 43, 40, 37,
75 33, 28, 22, 14,
76 5, -7, -20, -20,
77 -20, -20, -20, -20,
78 -20, -20, -20, -20,
79};
80
81static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
82
83
84static inline
85void bcm43xx_voluntary_preempt(void)
86{
87 assert(!in_atomic() && !in_irq() &&
88 !in_interrupt() && !irqs_disabled());
89#ifndef CONFIG_PREEMPT
90 cond_resched();
91#endif /* CONFIG_PREEMPT */
92}
93
94void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
95{
96 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
97
98 assert(irqs_disabled());
99 if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
100 phy->is_locked = 0;
101 return;
102 }
103 if (bcm->current_core->rev < 3) {
104 bcm43xx_mac_suspend(bcm);
105 spin_lock(&phy->lock);
106 } else {
107 if (bcm->ieee->iw_mode != IW_MODE_MASTER)
108 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
109 }
110 phy->is_locked = 1;
111}
112
113void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
114{
115 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
116
117 assert(irqs_disabled());
118 if (bcm->current_core->rev < 3) {
119 if (phy->is_locked) {
120 spin_unlock(&phy->lock);
121 bcm43xx_mac_enable(bcm);
122 }
123 } else {
124 if (bcm->ieee->iw_mode != IW_MODE_MASTER)
125 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
126 }
127 phy->is_locked = 0;
128}
129
130u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
131{
132 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
133 return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
134}
135
136void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
137{
138 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
139 mmiowb();
140 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
141}
142
143void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
144{
145 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
146
147 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
148 if (phy->calibrated)
149 return;
150 if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
151 bcm43xx_wireless_core_reset(bcm, 0);
152 bcm43xx_phy_initg(bcm);
153 bcm43xx_wireless_core_reset(bcm, 1);
154 }
155 phy->calibrated = 1;
156}
157
158/* Connect the PHY
159 * http://bcm-specs.sipsolutions.net/SetPHY
160 */
161int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
162{
163 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
164 u32 flags;
165
166 if (bcm->current_core->rev < 5)
167 goto out;
168
169 flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
170 if (connect) {
171 if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL))
172 return -ENODEV;
173 flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
174 flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
175 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
176 } else {
177 if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL))
178 return -ENODEV;
179 flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
180 flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
181 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
182 }
183out:
184 phy->connected = connect;
185 if (connect)
186 dprintk(KERN_INFO PFX "PHY connected\n");
187 else
188 dprintk(KERN_INFO PFX "PHY disconnected\n");
189
190 return 0;
191}
192
193/* intialize B PHY power control
194 * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
195 */
196static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
197{
198 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
199 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
200 u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
201 int must_reset_txpower = 0;
202
203 assert(phy->type != BCM43xx_PHYTYPE_A);
204 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
205 (bcm->board_type == 0x0416))
206 return;
207
208 bcm43xx_phy_write(bcm, 0x0028, 0x8018);
209 bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
210
211 if (phy->type == BCM43xx_PHYTYPE_G) {
212 if (!phy->connected)
213 return;
214 bcm43xx_phy_write(bcm, 0x047A, 0xC111);
215 }
216 if (phy->savedpctlreg != 0xFFFF)
217 return;
218
219 if (phy->type == BCM43xx_PHYTYPE_B &&
220 phy->rev >= 2 &&
221 radio->version == 0x2050) {
222 bcm43xx_radio_write16(bcm, 0x0076,
223 bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
224 } else {
225 saved_batt = radio->baseband_atten;
226 saved_ratt = radio->radio_atten;
227 saved_txctl1 = radio->txctl1;
228 if ((radio->revision >= 6) && (radio->revision <= 8)
229 && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
230 bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
231 else
232 bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
233 must_reset_txpower = 1;
234 }
235 bcm43xx_dummy_transmission(bcm);
236
237 phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
238
239 if (must_reset_txpower)
240 bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
241 else
242 bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
243 bcm43xx_radio_clear_tssi(bcm);
244}
245
246static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
247{
248 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
249 u16 offset = 0x0000;
250
251 if (phy->rev == 1)
252 offset = 0x4C00;
253
254 bcm43xx_ilt_write(bcm, offset, 0x00FE);
255 bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
256 bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
257 bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
258
259 if (phy->rev == 1) {
260 bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
261 bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
262 bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
263 bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
264 bcm43xx_phy_write(bcm, 0x0455, 0x0004);
265 }
266
267 bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
268 bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
269 bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
270 bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
271
272 bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
273
274 bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
275 bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
276 bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
277 bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
278
279 if (phy->rev == 1)
280 bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
281
282 bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
283 bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
284 bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
285 bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
286 bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
287 bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
288 bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
289 bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
290 bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
291
292 if (phy->rev == 1) {
293 bcm43xx_phy_write(bcm, 0x0430, 0x092B);
294 bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
295 } else {
296 bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
297 bcm43xx_phy_write(bcm, 0x041F, 0x287A);
298 bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
299 }
300
301 if (phy->rev > 2) {
302 bcm43xx_phy_write(bcm, 0x0422, 0x287A);
303 bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420)
304 & 0x0FFF) | 0x3000);
305 }
306
307 bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080)
308 | 0x7874);
309 bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
310
311 if (phy->rev == 1) {
312 bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB)
313 & 0xF0FF) | 0x0600);
314 bcm43xx_phy_write(bcm, 0x048B, 0x005E);
315 bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C)
316 & 0xFF00) | 0x001E);
317 bcm43xx_phy_write(bcm, 0x048D, 0x0002);
318 }
319
320 bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
321 bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
322 bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
323 bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
324
325 if (phy->rev >= 6) {
326 bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
327 & 0xFFFC));
328 bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
329 & 0xEFFF));
330 }
331}
332
333static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
334{
335 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
336 u16 i;
337
338 assert(phy->type == BCM43xx_PHYTYPE_G);
339 if (phy->rev == 1) {
340 bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
341 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
342 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
343 & 0xFC3F) | 0x0340);
344 bcm43xx_phy_write(bcm, 0x042C, 0x005A);
345 bcm43xx_phy_write(bcm, 0x0427, 0x001A);
346
347 for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
348 bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
349 for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
350 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
351 for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
352 bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
353 } else {
354 /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
355 bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
356
357 if (phy->rev == 2) {
358 bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
359 bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
360 } else if (phy->rev > 2) {
361 bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
362 bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
363 bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
364 }
365 bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
366
367 for (i = 0; i < 64; i++)
368 bcm43xx_ilt_write(bcm, 0x4000 + i, i);
369 for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
370 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
371 }
372
373 if (phy->rev <= 2)
374 for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
375 bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
376 else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
377 for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
378 bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
379 else
380 for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
381 bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
382
383 if (phy->rev == 2)
384 for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
385 bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
386 else if ((phy->rev > 2) && (phy->rev <= 8))
387 for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
388 bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
389
390 if (phy->rev == 1) {
391 for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
392 bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
393 for (i = 0; i < 4; i++) {
394 bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
395 bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
396 bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
397 bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
398 }
399 bcm43xx_phy_agcsetup(bcm);
400
401 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
402 (bcm->board_type == 0x0416) &&
403 (bcm->board_revision == 0x0017))
404 return;
405
406 bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
407 bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
408 } else {
409 for (i = 0; i <= 0x2F; i++)
410 bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
411 bcm43xx_phy_agcsetup(bcm);
412 bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
413 bcm43xx_phy_write(bcm, 0x0403, 0x1000);
414 bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
415 bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
416
417 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
418 (bcm->board_type == 0x0416) &&
419 (bcm->board_revision == 0x0017))
420 return;
421
422 bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
423 bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
424 }
425}
426
427/* Initialize the noisescaletable for APHY */
428static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
429{
430 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
431 int i;
432
433 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
434 for (i = 0; i < 12; i++) {
435 if (phy->rev == 2)
436 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
437 else
438 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
439 }
440 if (phy->rev == 2)
441 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
442 else
443 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
444 for (i = 0; i < 11; i++) {
445 if (phy->rev == 2)
446 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
447 else
448 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
449 }
450 if (phy->rev == 2)
451 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
452 else
453 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
454}
455
456static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
457{
458 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
459 u16 i;
460
461 assert(phy->type == BCM43xx_PHYTYPE_A);
462 switch (phy->rev) {
463 case 2:
464 bcm43xx_phy_write(bcm, 0x008E, 0x3800);
465 bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
466 bcm43xx_phy_write(bcm, 0x0036, 0x0400);
467
468 bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
469
470 bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
471 bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
472 bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
473 bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
474
475 bcm43xx_phy_write(bcm, 0x0024, 0x4680);
476 bcm43xx_phy_write(bcm, 0x0020, 0x0003);
477 bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
478 bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
479
480 bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
481 bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
482 bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
483
484 bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
485 bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
486 bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
487 bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
488 bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
489
490 bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
491 bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
492 bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
493 bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
494 bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
495 bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
496 bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
497
498 bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
499 bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
500 bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
501
502 for (i = 0; i < 16; i++)
503 bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
504
505 bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
506 bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
507 bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
508 bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
509
510 for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
511 bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
512 for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
513 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
514 for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
515 bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
516 bcm43xx_phy_init_noisescaletbl(bcm);
517 for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
518 bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
519 break;
520 case 3:
521 for (i = 0; i < 64; i++)
522 bcm43xx_ilt_write(bcm, 0x4000 + i, i);
523
524 bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
525
526 bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
527 bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
528 bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
529
530 bcm43xx_phy_write(bcm, 0x0024, 0x4680);
531 bcm43xx_phy_write(bcm, 0x0020, 0x0003);
532 bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
533 bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
534 bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
535
536 bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
537 for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
538 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
539 bcm43xx_phy_init_noisescaletbl(bcm);
540 for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
541 bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
542
543 bcm43xx_phy_write(bcm, 0x0003, 0x1808);
544
545 bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
546 bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
547 bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
548 bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
549 bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
550
551 bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
552 bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
553 bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
554 bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
555 bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
556 bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
557 bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
558
559 bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
560 bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
561 bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
562
563 bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
564 bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
565 break;
566 default:
567 assert(0);
568 }
569}
570
571/* Initialize APHY. This is also called for the GPHY in some cases. */
572static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
573{
574 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
575 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
576 u16 tval;
577
578 if (phy->type == BCM43xx_PHYTYPE_A) {
579 bcm43xx_phy_setupa(bcm);
580 } else {
581 bcm43xx_phy_setupg(bcm);
582 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
583 bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
584 return;
585 }
586
587 bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
588 (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
589 bcm43xx_phy_write(bcm, 0x0034, 0x0001);
590
591 TODO();//TODO: RSSI AGC
592 bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
593 bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
594 bcm43xx_radio_init2060(bcm);
595
596 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
597 && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
598 if (radio->lofcal == 0xFFFF) {
599 TODO();//TODO: LOF Cal
600 bcm43xx_radio_set_tx_iq(bcm);
601 } else
602 bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
603 }
604
605 bcm43xx_phy_write(bcm, 0x007A, 0xF111);
606
607 if (phy->savedpctlreg == 0xFFFF) {
608 bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
609 bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
610
611 tval = bcm43xx_ilt_read(bcm, 0x3001);
612 if (phy->rev == 1) {
613 bcm43xx_ilt_write(bcm, 0x3001,
614 (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
615 | 0x0058);
616 } else {
617 bcm43xx_ilt_write(bcm, 0x3001,
618 (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
619 | 0x002C);
620 }
621 bcm43xx_dummy_transmission(bcm);
622 phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
623 bcm43xx_ilt_write(bcm, 0x3001, tval);
624
625 bcm43xx_radio_set_txpower_a(bcm, 0x0018);
626 }
627 bcm43xx_radio_clear_tssi(bcm);
628}
629
630static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
631{
632 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
633 u16 offset, val;
634
635 bcm43xx_write16(bcm, 0x03EC, 0x3F22);
636 bcm43xx_phy_write(bcm, 0x0020, 0x301C);
637 bcm43xx_phy_write(bcm, 0x0026, 0x0000);
638 bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
639 bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
640 val = 0x3C3D;
641 for (offset = 0x0089; offset < 0x00A7; offset++) {
642 bcm43xx_phy_write(bcm, offset, val);
643 val -= 0x0202;
644 }
645 bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
646 if (radio->channel == 0xFF)
647 bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
648 else
649 bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
650 if (radio->version != 0x2050) {
651 bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
652 bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
653 }
654 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
655 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
656 if (radio->version == 0x2050) {
657 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
658 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
659 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
660 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
661 bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
662 bcm43xx_phy_write(bcm, 0x0038, 0x0677);
663 bcm43xx_radio_init2050(bcm);
664 }
665 bcm43xx_phy_write(bcm, 0x0014, 0x0080);
666 bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
667 bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
668 bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
669 bcm43xx_phy_lo_b_measure(bcm);
670 bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
671 if (radio->version != 0x2050)
672 bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
673 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
674 bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
675 if (radio->version != 0x2050)
676 bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
677 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
678 bcm43xx_phy_init_pctl(bcm);
679}
680
681static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
682{
683 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
684 u16 offset, val;
685
686 bcm43xx_write16(bcm, 0x03EC, 0x3F22);
687 bcm43xx_phy_write(bcm, 0x0020, 0x301C);
688 bcm43xx_phy_write(bcm, 0x0026, 0x0000);
689 bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
690 bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
691 val = 0x3C3D;
692 for (offset = 0x0089; offset < 0x00A7; offset++) {
693 bcm43xx_phy_write(bcm, offset, val);
694 val -= 0x0202;
695 }
696 bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
697 if (radio->channel == 0xFF)
698 bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
699 else
700 bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
701 if (radio->version != 0x2050) {
702 bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
703 bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
704 }
705 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
706 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
707 if (radio->version == 0x2050) {
708 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
709 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
710 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
711 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
712 bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
713 bcm43xx_phy_write(bcm, 0x0038, 0x0677);
714 bcm43xx_radio_init2050(bcm);
715 }
716 bcm43xx_phy_write(bcm, 0x0014, 0x0080);
717 bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
718 if (radio->version == 0x2050)
719 bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
720 bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
721
722 bcm43xx_phy_lo_b_measure(bcm);
723
724 bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
725 if (radio->version == 0x2050)
726 bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
727 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
728 bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
729 if (radio->version == 0x2050)
730 bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
731 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
732 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
733 bcm43xx_calc_nrssi_slope(bcm);
734 bcm43xx_calc_nrssi_threshold(bcm);
735 }
736 bcm43xx_phy_init_pctl(bcm);
737}
738
739static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
740{
741 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
742 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
743 u16 offset;
744 u16 value;
745 u8 old_channel;
746
747 if (phy->analog == 1)
748 bcm43xx_radio_write16(bcm, 0x007A,
749 bcm43xx_radio_read16(bcm, 0x007A)
750 | 0x0050);
751 if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
752 (bcm->board_type != 0x0416)) {
753 value = 0x2120;
754 for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
755 bcm43xx_phy_write(bcm, offset, value);
756 value += 0x0202;
757 }
758 }
759 bcm43xx_phy_write(bcm, 0x0035,
760 (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
761 | 0x0700);
762 if (radio->version == 0x2050)
763 bcm43xx_phy_write(bcm, 0x0038, 0x0667);
764
765 if (phy->connected) {
766 if (radio->version == 0x2050) {
767 bcm43xx_radio_write16(bcm, 0x007A,
768 bcm43xx_radio_read16(bcm, 0x007A)
769 | 0x0020);
770 bcm43xx_radio_write16(bcm, 0x0051,
771 bcm43xx_radio_read16(bcm, 0x0051)
772 | 0x0004);
773 }
774 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
775
776 bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
777 bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
778
779 bcm43xx_phy_write(bcm, 0x001C, 0x186A);
780
781 bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
782 bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
783 bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
784 }
785
786 if (bcm->bad_frames_preempt) {
787 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
788 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
789 }
790
791 if (phy->analog == 1) {
792 bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
793 bcm43xx_phy_write(bcm, 0x0021, 0x3763);
794 bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
795 bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
796 bcm43xx_phy_write(bcm, 0x0024, 0x037E);
797 } else
798 bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
799 bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
800 bcm43xx_write16(bcm, 0x03EC, 0x3F22);
801
802 if (phy->analog == 1)
803 bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
804 else
805 bcm43xx_phy_write(bcm, 0x0020, 0x301C);
806
807 if (phy->analog == 0)
808 bcm43xx_write16(bcm, 0x03E4, 0x3000);
809
810 old_channel = radio->channel;
811 /* Force to channel 7, even if not supported. */
812 bcm43xx_radio_selectchannel(bcm, 7, 0);
813
814 if (radio->version != 0x2050) {
815 bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
816 bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
817 }
818
819 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
820 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
821
822 if (radio->version == 0x2050) {
823 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
824 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
825 }
826
827 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
828 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
829
830 bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
831
832 bcm43xx_radio_selectchannel(bcm, old_channel, 0);
833
834 bcm43xx_phy_write(bcm, 0x0014, 0x0080);
835 bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
836 bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
837
838 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
839
840 if (radio->version == 0x2050)
841 bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
842
843 bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
844}
845
846static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
847{
848 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
849 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
850 u16 offset, val;
851 u8 old_channel;
852
853 bcm43xx_phy_write(bcm, 0x003E, 0x817A);
854 bcm43xx_radio_write16(bcm, 0x007A,
855 (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
856 if (radio->revision == 4 ||
857 radio->revision == 5) {
858 bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
859 bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
860 bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
861 bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
862 bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
863 bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
864 bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
865 bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
866 bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
867 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
868 BCM43xx_UCODEFLAGS_OFFSET,
869 (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
870 BCM43xx_UCODEFLAGS_OFFSET)
871 | 0x00000200));
872 }
873 if (radio->revision == 8) {
874 bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
875 bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
876 bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
877 bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
878 bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
879 bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
880 bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
881 if (bcm->sprom.boardflags & 0x8000) {
882 bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
883 bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
884 } else {
885 bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
886 bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
887 }
888 bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
889 bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
890 bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
891 bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
892 }
893 val = 0x1E1F;
894 for (offset = 0x0088; offset < 0x0098; offset++) {
895 bcm43xx_phy_write(bcm, offset, val);
896 val -= 0x0202;
897 }
898 val = 0x3E3F;
899 for (offset = 0x0098; offset < 0x00A8; offset++) {
900 bcm43xx_phy_write(bcm, offset, val);
901 val -= 0x0202;
902 }
903 val = 0x2120;
904 for (offset = 0x00A8; offset < 0x00C8; offset++) {
905 bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
906 val += 0x0202;
907 }
908 if (phy->type == BCM43xx_PHYTYPE_G) {
909 bcm43xx_radio_write16(bcm, 0x007A,
910 bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
911 bcm43xx_radio_write16(bcm, 0x0051,
912 bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
913 bcm43xx_phy_write(bcm, 0x0802,
914 bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
915 bcm43xx_phy_write(bcm, 0x042B,
916 bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
917 bcm43xx_phy_write(bcm, 0x5B, 0x0000);
918 bcm43xx_phy_write(bcm, 0x5C, 0x0000);
919 }
920
921 old_channel = radio->channel;
922 if (old_channel >= 8)
923 bcm43xx_radio_selectchannel(bcm, 1, 0);
924 else
925 bcm43xx_radio_selectchannel(bcm, 13, 0);
926
927 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
928 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
929 udelay(40);
930 if (radio->revision < 6 || radio-> revision == 8) {
931 bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
932 | 0x0002));
933 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
934 }
935 if (radio->revision <= 2) {
936 bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
937 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
938 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
939 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
940 }
941 bcm43xx_radio_write16(bcm, 0x007A,
942 (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
943
944 bcm43xx_radio_selectchannel(bcm, old_channel, 0);
945
946 bcm43xx_phy_write(bcm, 0x0014, 0x0200);
947 if (radio->revision >= 6)
948 bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
949 else
950 bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
951 bcm43xx_phy_write(bcm, 0x0038, 0x0668);
952 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
953 if (radio->revision <= 5)
954 bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D)
955 & 0xFF80) | 0x0003);
956 if (radio->revision <= 2)
957 bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
958
959 if (phy->analog == 4){
960 bcm43xx_write16(bcm, 0x03E4, 0x0009);
961 bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
962 } else {
963 bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
964 }
965 if (phy->type == BCM43xx_PHYTYPE_G)
966 bcm43xx_write16(bcm, 0x03E6, 0x0);
967 if (phy->type == BCM43xx_PHYTYPE_B) {
968 bcm43xx_write16(bcm, 0x03E6, 0x8140);
969 bcm43xx_phy_write(bcm, 0x0016, 0x0410);
970 bcm43xx_phy_write(bcm, 0x0017, 0x0820);
971 bcm43xx_phy_write(bcm, 0x0062, 0x0007);
972 bcm43xx_radio_init2050(bcm);
973 bcm43xx_phy_lo_g_measure(bcm);
974 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
975 bcm43xx_calc_nrssi_slope(bcm);
976 bcm43xx_calc_nrssi_threshold(bcm);
977 }
978 bcm43xx_phy_init_pctl(bcm);
979 }
980}
981
982static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
983{
984 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
985 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
986 u16 backup_phy[15] = {0};
987 u16 backup_radio[3];
988 u16 backup_bband;
989 u16 i;
990 u16 loop1_cnt, loop1_done, loop1_omitted;
991 u16 loop2_done;
992
993 backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
994 backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
995 backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
996 backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
997 if (phy->rev != 1) {
998 backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
999 backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
1000 }
1001 backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
1002 backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
1003 backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
1004 backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
1005 backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
1006 backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
1007 backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
1008 backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
1009 backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
1010 bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
1011 backup_bband = radio->baseband_atten;
1012 backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
1013 backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
1014 backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
1015
1016 bcm43xx_phy_write(bcm, 0x0429,
1017 bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
1018 bcm43xx_phy_write(bcm, 0x0001,
1019 bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
1020 bcm43xx_phy_write(bcm, 0x0811,
1021 bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
1022 bcm43xx_phy_write(bcm, 0x0812,
1023 bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
1024 bcm43xx_phy_write(bcm, 0x0811,
1025 bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
1026 bcm43xx_phy_write(bcm, 0x0812,
1027 bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
1028 if (phy->rev != 1) {
1029 bcm43xx_phy_write(bcm, 0x0814,
1030 bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
1031 bcm43xx_phy_write(bcm, 0x0815,
1032 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
1033 bcm43xx_phy_write(bcm, 0x0814,
1034 bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
1035 bcm43xx_phy_write(bcm, 0x0815,
1036 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
1037 }
1038 bcm43xx_phy_write(bcm, 0x0811,
1039 bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
1040 bcm43xx_phy_write(bcm, 0x0812,
1041 bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
1042
1043 bcm43xx_phy_write(bcm, 0x0811,
1044 (bcm43xx_phy_read(bcm, 0x0811)
1045 & 0xFFCF) | 0x0030);
1046 bcm43xx_phy_write(bcm, 0x0812,
1047 (bcm43xx_phy_read(bcm, 0x0812)
1048 & 0xFFCF) | 0x0010);
1049
1050 bcm43xx_phy_write(bcm, 0x005A, 0x0780);
1051 bcm43xx_phy_write(bcm, 0x0059, 0xC810);
1052 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
1053 if (phy->analog == 0) {
1054 bcm43xx_phy_write(bcm, 0x0003, 0x0122);
1055 } else {
1056 bcm43xx_phy_write(bcm, 0x000A,
1057 bcm43xx_phy_read(bcm, 0x000A)
1058 | 0x2000);
1059 }
1060 if (phy->rev != 1) {
1061 bcm43xx_phy_write(bcm, 0x0814,
1062 bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
1063 bcm43xx_phy_write(bcm, 0x0815,
1064 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
1065 }
1066 bcm43xx_phy_write(bcm, 0x0003,
1067 (bcm43xx_phy_read(bcm, 0x0003)
1068 & 0xFF9F) | 0x0040);
1069 if (radio->version == 0x2050 && radio->revision == 2) {
1070 bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
1071 bcm43xx_radio_write16(bcm, 0x0043,
1072 (bcm43xx_radio_read16(bcm, 0x0043)
1073 & 0xFFF0) | 0x0009);
1074 loop1_cnt = 9;
1075 } else if (radio->revision == 8) {
1076 bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
1077 loop1_cnt = 15;
1078 } else
1079 loop1_cnt = 0;
1080
1081 bcm43xx_phy_set_baseband_attenuation(bcm, 11);
1082
1083 if (phy->rev >= 3)
1084 bcm43xx_phy_write(bcm, 0x080F, 0xC020);
1085 else
1086 bcm43xx_phy_write(bcm, 0x080F, 0x8020);
1087 bcm43xx_phy_write(bcm, 0x0810, 0x0000);
1088
1089 bcm43xx_phy_write(bcm, 0x002B,
1090 (bcm43xx_phy_read(bcm, 0x002B)
1091 & 0xFFC0) | 0x0001);
1092 bcm43xx_phy_write(bcm, 0x002B,
1093 (bcm43xx_phy_read(bcm, 0x002B)
1094 & 0xC0FF) | 0x0800);
1095 bcm43xx_phy_write(bcm, 0x0811,
1096 bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
1097 bcm43xx_phy_write(bcm, 0x0812,
1098 bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
1099 if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
1100 if (phy->rev >= 7) {
1101 bcm43xx_phy_write(bcm, 0x0811,
1102 bcm43xx_phy_read(bcm, 0x0811)
1103 | 0x0800);
1104 bcm43xx_phy_write(bcm, 0x0812,
1105 bcm43xx_phy_read(bcm, 0x0812)
1106 | 0x8000);
1107 }
1108 }
1109 bcm43xx_radio_write16(bcm, 0x007A,
1110 bcm43xx_radio_read16(bcm, 0x007A)
1111 & 0x00F7);
1112
1113 for (i = 0; i < loop1_cnt; i++) {
1114 bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
1115 bcm43xx_phy_write(bcm, 0x0812,
1116 (bcm43xx_phy_read(bcm, 0x0812)
1117 & 0xF0FF) | (i << 8));
1118 bcm43xx_phy_write(bcm, 0x0015,
1119 (bcm43xx_phy_read(bcm, 0x0015)
1120 & 0x0FFF) | 0xA000);
1121 bcm43xx_phy_write(bcm, 0x0015,
1122 (bcm43xx_phy_read(bcm, 0x0015)
1123 & 0x0FFF) | 0xF000);
1124 udelay(20);
1125 if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
1126 break;
1127 }
1128 loop1_done = i;
1129 loop1_omitted = loop1_cnt - loop1_done;
1130
1131 loop2_done = 0;
1132 if (loop1_done >= 8) {
1133 bcm43xx_phy_write(bcm, 0x0812,
1134 bcm43xx_phy_read(bcm, 0x0812)
1135 | 0x0030);
1136 for (i = loop1_done - 8; i < 16; i++) {
1137 bcm43xx_phy_write(bcm, 0x0812,
1138 (bcm43xx_phy_read(bcm, 0x0812)
1139 & 0xF0FF) | (i << 8));
1140 bcm43xx_phy_write(bcm, 0x0015,
1141 (bcm43xx_phy_read(bcm, 0x0015)
1142 & 0x0FFF) | 0xA000);
1143 bcm43xx_phy_write(bcm, 0x0015,
1144 (bcm43xx_phy_read(bcm, 0x0015)
1145 & 0x0FFF) | 0xF000);
1146 udelay(20);
1147 if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
1148 break;
1149 }
1150 }
1151
1152 if (phy->rev != 1) {
1153 bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
1154 bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
1155 }
1156 bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
1157 bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
1158 bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
1159 bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
1160 bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
1161 bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
1162 bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
1163 bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
1164 bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
1165
1166 bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
1167
1168 bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
1169 bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
1170 bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
1171
1172 bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
1173 udelay(10);
1174 bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
1175 bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
1176 bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
1177 bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
1178
1179 phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
1180 phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
1181}
1182
1183static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
1184{
1185 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1186 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1187 u16 tmp;
1188
1189 if (phy->rev == 1)
1190 bcm43xx_phy_initb5(bcm);
1191 else
1192 bcm43xx_phy_initb6(bcm);
1193 if (phy->rev >= 2 || phy->connected)
1194 bcm43xx_phy_inita(bcm);
1195
1196 if (phy->rev >= 2) {
1197 bcm43xx_phy_write(bcm, 0x0814, 0x0000);
1198 bcm43xx_phy_write(bcm, 0x0815, 0x0000);
1199 }
1200 if (phy->rev == 2) {
1201 bcm43xx_phy_write(bcm, 0x0811, 0x0000);
1202 bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
1203 }
1204 if (phy->rev > 5) {
1205 bcm43xx_phy_write(bcm, 0x0811, 0x0400);
1206 bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
1207 }
1208 if (phy->rev >= 2 && phy->connected) {
1209 tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
1210 if (tmp ==3 || tmp == 5) {
1211 bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
1212 bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
1213 if (tmp == 5) {
1214 bcm43xx_phy_write(bcm, 0x04CC,
1215 (bcm43xx_phy_read(bcm, 0x04CC)
1216 & 0x00FF) | 0x1F00);
1217 }
1218 }
1219 bcm43xx_phy_write(bcm, 0x047E, 0x0078);
1220 }
1221 if (radio->revision == 8) {
1222 bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
1223 bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
1224 }
1225 if (phy->rev >= 2 && phy->connected)
1226 bcm43xx_calc_loopback_gain(bcm);
1227 if (radio->revision != 8) {
1228 if (radio->initval == 0xFFFF)
1229 radio->initval = bcm43xx_radio_init2050(bcm);
1230 else
1231 bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
1232 }
1233 if (radio->txctl2 == 0xFFFF) {
1234 bcm43xx_phy_lo_g_measure(bcm);
1235 } else {
1236 if (radio->version == 0x2050 && radio->revision == 8) {
1237 bcm43xx_radio_write16(bcm, 0x0052,
1238 (radio->txctl1 << 4) | radio->txctl2);
1239 } else {
1240 bcm43xx_radio_write16(bcm, 0x0052,
1241 (bcm43xx_radio_read16(bcm, 0x0052)
1242 & 0xFFF0) | radio->txctl1);
1243 }
1244 if (phy->rev >= 6) {
1245 bcm43xx_phy_write(bcm, 0x0036,
1246 (bcm43xx_phy_read(bcm, 0x0036)
1247 & 0x0FFF) | (radio->txctl2 << 12));
1248 }
1249 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
1250 bcm43xx_phy_write(bcm, 0x002E, 0x8075);
1251 else
1252 bcm43xx_phy_write(bcm, 0x002E, 0x807F);
1253 if (phy->rev < 2)
1254 bcm43xx_phy_write(bcm, 0x002F, 0x0101);
1255 else
1256 bcm43xx_phy_write(bcm, 0x002F, 0x0202);
1257 }
1258 if (phy->connected || phy->rev >= 2) {
1259 bcm43xx_phy_lo_adjust(bcm, 0);
1260 bcm43xx_phy_write(bcm, 0x080F, 0x8078);
1261 }
1262
1263 if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
1264 /* The specs state to update the NRSSI LT with
1265 * the value 0x7FFFFFFF here. I think that is some weird
1266 * compiler optimization in the original driver.
1267 * Essentially, what we do here is resetting all NRSSI LT
1268 * entries to -32 (see the limit_value() in nrssi_hw_update())
1269 */
1270 bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
1271 bcm43xx_calc_nrssi_threshold(bcm);
1272 } else if (phy->connected || phy->rev >= 2) {
1273 if (radio->nrssi[0] == -1000) {
1274 assert(radio->nrssi[1] == -1000);
1275 bcm43xx_calc_nrssi_slope(bcm);
1276 } else {
1277 assert(radio->nrssi[1] != -1000);
1278 bcm43xx_calc_nrssi_threshold(bcm);
1279 }
1280 }
1281 if (radio->revision == 8)
1282 bcm43xx_phy_write(bcm, 0x0805, 0x3230);
1283 bcm43xx_phy_init_pctl(bcm);
1284 if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
1285 bcm43xx_phy_write(bcm, 0x0429,
1286 bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
1287 bcm43xx_phy_write(bcm, 0x04C3,
1288 bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
1289 }
1290}
1291
1292static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
1293{
1294 int i;
1295 u16 ret = 0;
1296 unsigned long flags;
1297
1298 local_irq_save(flags);
1299 for (i = 0; i < 10; i++){
1300 bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
1301 udelay(1);
1302 bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
1303 udelay(10);
1304 bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
1305 udelay(40);
1306 ret += bcm43xx_phy_read(bcm, 0x002C);
1307 }
1308 local_irq_restore(flags);
1309 bcm43xx_voluntary_preempt();
1310
1311 return ret;
1312}
1313
1314void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
1315{
1316 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1317 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1318 u16 regstack[12] = { 0 };
1319 u16 mls;
1320 u16 fval;
1321 int i, j;
1322
1323 regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
1324 regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
1325
1326 if (radio->version == 0x2053) {
1327 regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
1328 regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
1329 regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
1330 regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
1331 regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
1332 regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
1333
1334 regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
1335 regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
1336 regstack[10] = bcm43xx_read16(bcm, 0x03EC);
1337 regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
1338
1339 bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
1340 bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
1341 bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
1342 bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
1343 }
1344 bcm43xx_phy_write(bcm, 0x0015, 0xB000);
1345 bcm43xx_phy_write(bcm, 0x002B, 0x0004);
1346
1347 if (radio->version == 0x2053) {
1348 bcm43xx_phy_write(bcm, 0x002B, 0x0203);
1349 bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
1350 }
1351
1352 phy->minlowsig[0] = 0xFFFF;
1353
1354 for (i = 0; i < 4; i++) {
1355 bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
1356 bcm43xx_phy_lo_b_r15_loop(bcm);
1357 }
1358 for (i = 0; i < 10; i++) {
1359 bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
1360 mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
1361 if (mls < phy->minlowsig[0]) {
1362 phy->minlowsig[0] = mls;
1363 phy->minlowsigpos[0] = i;
1364 }
1365 }
1366 bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
1367
1368 phy->minlowsig[1] = 0xFFFF;
1369
1370 for (i = -4; i < 5; i += 2) {
1371 for (j = -4; j < 5; j += 2) {
1372 if (j < 0)
1373 fval = (0x0100 * i) + j + 0x0100;
1374 else
1375 fval = (0x0100 * i) + j;
1376 bcm43xx_phy_write(bcm, 0x002F, fval);
1377 mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
1378 if (mls < phy->minlowsig[1]) {
1379 phy->minlowsig[1] = mls;
1380 phy->minlowsigpos[1] = fval;
1381 }
1382 }
1383 }
1384 phy->minlowsigpos[1] += 0x0101;
1385
1386 bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
1387 if (radio->version == 0x2053) {
1388 bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
1389 bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
1390 bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
1391 bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
1392 bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
1393 bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
1394
1395 bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
1396 bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
1397
1398 bcm43xx_radio_write16(bcm, 0x0052,
1399 (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
1400 | regstack[11]);
1401
1402 bcm43xx_write16(bcm, 0x03EC, regstack[10]);
1403 }
1404 bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
1405}
1406
1407static inline
1408u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
1409{
1410 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1411 u16 ret;
1412 unsigned long flags;
1413
1414 local_irq_save(flags);
1415 if (phy->connected) {
1416 bcm43xx_phy_write(bcm, 0x15, 0xE300);
1417 control <<= 8;
1418 bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
1419 udelay(5);
1420 bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
1421 udelay(2);
1422 bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
1423 udelay(4);
1424 bcm43xx_phy_write(bcm, 0x0015, 0xF300);
1425 udelay(8);
1426 } else {
1427 bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
1428 udelay(2);
1429 bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
1430 udelay(4);
1431 bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
1432 udelay(8);
1433 }
1434 ret = bcm43xx_phy_read(bcm, 0x002D);
1435 local_irq_restore(flags);
1436 bcm43xx_voluntary_preempt();
1437
1438 return ret;
1439}
1440
1441static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
1442{
1443 int i;
1444 u32 ret = 0;
1445
1446 for (i = 0; i < 8; i++)
1447 ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
1448
1449 return ret;
1450}
1451
1452/* Write the LocalOscillator CONTROL */
1453static inline
1454void bcm43xx_lo_write(struct bcm43xx_private *bcm,
1455 struct bcm43xx_lopair *pair)
1456{
1457 u16 value;
1458
1459 value = (u8)(pair->low);
1460 value |= ((u8)(pair->high)) << 8;
1461
1462#ifdef CONFIG_BCM43XX_DEBUG
1463 /* Sanity check. */
1464 if (pair->low < -8 || pair->low > 8 ||
1465 pair->high < -8 || pair->high > 8) {
1466 printk(KERN_WARNING PFX
1467 "WARNING: Writing invalid LOpair "
1468 "(low: %d, high: %d, index: %lu)\n",
1469 pair->low, pair->high,
1470 (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
1471 dump_stack();
1472 }
1473#endif
1474
1475 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
1476}
1477
1478static inline
1479struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
1480 u16 baseband_attenuation,
1481 u16 radio_attenuation,
1482 u16 tx)
1483{
1484 static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
1485 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1486
1487 if (baseband_attenuation > 6)
1488 baseband_attenuation = 6;
1489 assert(radio_attenuation < 10);
1490
1491 if (tx == 3) {
1492 return bcm43xx_get_lopair(phy,
1493 radio_attenuation,
1494 baseband_attenuation);
1495 }
1496 return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
1497}
1498
1499static inline
1500struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
1501{
1502 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1503
1504 return bcm43xx_find_lopair(bcm,
1505 radio->baseband_atten,
1506 radio->radio_atten,
1507 radio->txctl1);
1508}
1509
1510/* Adjust B/G LO */
1511void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
1512{
1513 struct bcm43xx_lopair *pair;
1514
1515 if (fixed) {
1516 /* Use fixed values. Only for initialization. */
1517 pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
1518 } else
1519 pair = bcm43xx_current_lopair(bcm);
1520 bcm43xx_lo_write(bcm, pair);
1521}
1522
1523static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
1524{
1525 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1526 u16 txctl2 = 0, i;
1527 u32 smallest, tmp;
1528
1529 bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
1530 udelay(10);
1531 smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
1532 for (i = 0; i < 16; i++) {
1533 bcm43xx_radio_write16(bcm, 0x0052, i);
1534 udelay(10);
1535 tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
1536 if (tmp < smallest) {
1537 smallest = tmp;
1538 txctl2 = i;
1539 }
1540 }
1541 radio->txctl2 = txctl2;
1542}
1543
1544static
1545void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
1546 const struct bcm43xx_lopair *in_pair,
1547 struct bcm43xx_lopair *out_pair,
1548 u16 r27)
1549{
1550 static const struct bcm43xx_lopair transitions[8] = {
1551 { .high = 1, .low = 1, },
1552 { .high = 1, .low = 0, },
1553 { .high = 1, .low = -1, },
1554 { .high = 0, .low = -1, },
1555 { .high = -1, .low = -1, },
1556 { .high = -1, .low = 0, },
1557 { .high = -1, .low = 1, },
1558 { .high = 0, .low = 1, },
1559 };
1560 struct bcm43xx_lopair lowest_transition = {
1561 .high = in_pair->high,
1562 .low = in_pair->low,
1563 };
1564 struct bcm43xx_lopair tmp_pair;
1565 struct bcm43xx_lopair transition;
1566 int i = 12;
1567 int state = 0;
1568 int found_lower;
1569 int j, begin, end;
1570 u32 lowest_deviation;
1571 u32 tmp;
1572
1573 /* Note that in_pair and out_pair can point to the same pair. Be careful. */
1574
1575 bcm43xx_lo_write(bcm, &lowest_transition);
1576 lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
1577 do {
1578 found_lower = 0;
1579 assert(state >= 0 && state <= 8);
1580 if (state == 0) {
1581 begin = 1;
1582 end = 8;
1583 } else if (state % 2 == 0) {
1584 begin = state - 1;
1585 end = state + 1;
1586 } else {
1587 begin = state - 2;
1588 end = state + 2;
1589 }
1590 if (begin < 1)
1591 begin += 8;
1592 if (end > 8)
1593 end -= 8;
1594
1595 j = begin;
1596 tmp_pair.high = lowest_transition.high;
1597 tmp_pair.low = lowest_transition.low;
1598 while (1) {
1599 assert(j >= 1 && j <= 8);
1600 transition.high = tmp_pair.high + transitions[j - 1].high;
1601 transition.low = tmp_pair.low + transitions[j - 1].low;
1602 if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
1603 bcm43xx_lo_write(bcm, &transition);
1604 tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
1605 if (tmp < lowest_deviation) {
1606 lowest_deviation = tmp;
1607 state = j;
1608 found_lower = 1;
1609
1610 lowest_transition.high = transition.high;
1611 lowest_transition.low = transition.low;
1612 }
1613 }
1614 if (j == end)
1615 break;
1616 if (j == 8)
1617 j = 1;
1618 else
1619 j++;
1620 }
1621 } while (i-- && found_lower);
1622
1623 out_pair->high = lowest_transition.high;
1624 out_pair->low = lowest_transition.low;
1625}
1626
1627/* Set the baseband attenuation value on chip. */
1628void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
1629 u16 baseband_attenuation)
1630{
1631 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1632 u16 value;
1633
1634 if (phy->analog == 0) {
1635 value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
1636 value |= (baseband_attenuation & 0x000F);
1637 bcm43xx_write16(bcm, 0x03E6, value);
1638 return;
1639 }
1640
1641 if (phy->analog > 1) {
1642 value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
1643 value |= (baseband_attenuation << 2) & 0x003C;
1644 } else {
1645 value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
1646 value |= (baseband_attenuation << 3) & 0x0078;
1647 }
1648 bcm43xx_phy_write(bcm, 0x0060, value);
1649}
1650
1651/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
1652void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
1653{
1654 static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
1655 const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
1656 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1657 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1658 u16 h, i, oldi = 0, j;
1659 struct bcm43xx_lopair control;
1660 struct bcm43xx_lopair *tmp_control;
1661 u16 tmp;
1662 u16 regstack[16] = { 0 };
1663 u8 oldchannel;
1664
1665 //XXX: What are these?
1666 u8 r27 = 0, r31;
1667
1668 oldchannel = radio->channel;
1669 /* Setup */
1670 if (phy->connected) {
1671 regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
1672 regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
1673 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
1674 bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
1675 }
1676 regstack[3] = bcm43xx_read16(bcm, 0x03E2);
1677 bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
1678 regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
1679 regstack[5] = bcm43xx_phy_read(bcm, 0x15);
1680 regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
1681 regstack[7] = bcm43xx_phy_read(bcm, 0x35);
1682 regstack[8] = bcm43xx_phy_read(bcm, 0x60);
1683 regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
1684 regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
1685 regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
1686 if (phy->connected) {
1687 regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
1688 regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
1689 regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
1690 regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
1691 }
1692 bcm43xx_radio_selectchannel(bcm, 6, 0);
1693 if (phy->connected) {
1694 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
1695 bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
1696 bcm43xx_dummy_transmission(bcm);
1697 }
1698 bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
1699
1700 bcm43xx_phy_set_baseband_attenuation(bcm, 2);
1701
1702 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
1703 bcm43xx_phy_write(bcm, 0x002E, 0x007F);
1704 bcm43xx_phy_write(bcm, 0x080F, 0x0078);
1705 bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
1706 bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
1707 bcm43xx_phy_write(bcm, 0x002B, 0x0203);
1708 bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
1709 if (phy->connected) {
1710 bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
1711 bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
1712 bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
1713 bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
1714 }
1715 if (is_initializing)
1716 bcm43xx_phy_lo_g_measure_txctl2(bcm);
1717 bcm43xx_phy_write(bcm, 0x080F, 0x8078);
1718
1719 /* Measure */
1720 control.low = 0;
1721 control.high = 0;
1722 for (h = 0; h < 10; h++) {
1723 /* Loop over each possible RadioAttenuation (0-9) */
1724 i = pairorder[h];
1725 if (is_initializing) {
1726 if (i == 3) {
1727 control.low = 0;
1728 control.high = 0;
1729 } else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
1730 ((i % 2 == 0) && (oldi % 2 == 0))) {
1731 tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
1732 memcpy(&control, tmp_control, sizeof(control));
1733 } else {
1734 tmp_control = bcm43xx_get_lopair(phy, 3, 0);
1735 memcpy(&control, tmp_control, sizeof(control));
1736 }
1737 }
1738 /* Loop over each possible BasebandAttenuation/2 */
1739 for (j = 0; j < 4; j++) {
1740 if (is_initializing) {
1741 tmp = i * 2 + j;
1742 r27 = 0;
1743 r31 = 0;
1744 if (tmp > 14) {
1745 r31 = 1;
1746 if (tmp > 17)
1747 r27 = 1;
1748 if (tmp > 19)
1749 r27 = 2;
1750 }
1751 } else {
1752 tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
1753 if (!tmp_control->used)
1754 continue;
1755 memcpy(&control, tmp_control, sizeof(control));
1756 r27 = 3;
1757 r31 = 0;
1758 }
1759 bcm43xx_radio_write16(bcm, 0x43, i);
1760 bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
1761 udelay(10);
1762 bcm43xx_voluntary_preempt();
1763
1764 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
1765
1766 tmp = (regstack[10] & 0xFFF0);
1767 if (r31)
1768 tmp |= 0x0008;
1769 bcm43xx_radio_write16(bcm, 0x007A, tmp);
1770
1771 tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
1772 bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
1773 }
1774 oldi = i;
1775 }
1776 /* Loop over each possible RadioAttenuation (10-13) */
1777 for (i = 10; i < 14; i++) {
1778 /* Loop over each possible BasebandAttenuation/2 */
1779 for (j = 0; j < 4; j++) {
1780 if (is_initializing) {
1781 tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
1782 memcpy(&control, tmp_control, sizeof(control));
1783 tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
1784 r27 = 0;
1785 r31 = 0;
1786 if (tmp > 14) {
1787 r31 = 1;
1788 if (tmp > 17)
1789 r27 = 1;
1790 if (tmp > 19)
1791 r27 = 2;
1792 }
1793 } else {
1794 tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
1795 if (!tmp_control->used)
1796 continue;
1797 memcpy(&control, tmp_control, sizeof(control));
1798 r27 = 3;
1799 r31 = 0;
1800 }
1801 bcm43xx_radio_write16(bcm, 0x43, i - 9);
1802 bcm43xx_radio_write16(bcm, 0x52,
1803 radio->txctl2
1804 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
1805 udelay(10);
1806 bcm43xx_voluntary_preempt();
1807
1808 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
1809
1810 tmp = (regstack[10] & 0xFFF0);
1811 if (r31)
1812 tmp |= 0x0008;
1813 bcm43xx_radio_write16(bcm, 0x7A, tmp);
1814
1815 tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
1816 bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
1817 }
1818 }
1819
1820 /* Restoration */
1821 if (phy->connected) {
1822 bcm43xx_phy_write(bcm, 0x0015, 0xE300);
1823 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
1824 udelay(5);
1825 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
1826 udelay(2);
1827 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
1828 bcm43xx_voluntary_preempt();
1829 } else
1830 bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
1831 bcm43xx_phy_lo_adjust(bcm, is_initializing);
1832 bcm43xx_phy_write(bcm, 0x002E, 0x807F);
1833 if (phy->connected)
1834 bcm43xx_phy_write(bcm, 0x002F, 0x0202);
1835 else
1836 bcm43xx_phy_write(bcm, 0x002F, 0x0101);
1837 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
1838 bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
1839 bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
1840 bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
1841 bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
1842 bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
1843 bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
1844 regstack[11] &= 0x00F0;
1845 regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
1846 bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
1847 bcm43xx_write16(bcm, 0x03E2, regstack[3]);
1848 if (phy->connected) {
1849 bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
1850 bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
1851 bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
1852 bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
1853 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
1854 bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
1855 }
1856 bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
1857
1858#ifdef CONFIG_BCM43XX_DEBUG
1859 {
1860 /* Sanity check for all lopairs. */
1861 for (i = 0; i < BCM43xx_LO_COUNT; i++) {
1862 tmp_control = phy->_lo_pairs + i;
1863 if (tmp_control->low < -8 || tmp_control->low > 8 ||
1864 tmp_control->high < -8 || tmp_control->high > 8) {
1865 printk(KERN_WARNING PFX
1866 "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
1867 tmp_control->low, tmp_control->high, i);
1868 }
1869 }
1870 }
1871#endif /* CONFIG_BCM43XX_DEBUG */
1872}
1873
1874static
1875void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
1876{
1877 struct bcm43xx_lopair *pair;
1878
1879 pair = bcm43xx_current_lopair(bcm);
1880 pair->used = 1;
1881}
1882
1883void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
1884{
1885 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1886 struct bcm43xx_lopair *pair;
1887 int i;
1888
1889 for (i = 0; i < BCM43xx_LO_COUNT; i++) {
1890 pair = phy->_lo_pairs + i;
1891 pair->used = 0;
1892 }
1893}
1894
1895/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
1896 * This function converts a TSSI value to dBm in Q5.2
1897 */
1898static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
1899{
1900 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1901 s8 dbm = 0;
1902 s32 tmp;
1903
1904 tmp = phy->idle_tssi;
1905 tmp += tssi;
1906 tmp -= phy->savedpctlreg;
1907
1908 switch (phy->type) {
1909 case BCM43xx_PHYTYPE_A:
1910 tmp += 0x80;
1911 tmp = limit_value(tmp, 0x00, 0xFF);
1912 dbm = phy->tssi2dbm[tmp];
1913 TODO(); //TODO: There's a FIXME on the specs
1914 break;
1915 case BCM43xx_PHYTYPE_B:
1916 case BCM43xx_PHYTYPE_G:
1917 tmp = limit_value(tmp, 0x00, 0x3F);
1918 dbm = phy->tssi2dbm[tmp];
1919 break;
1920 default:
1921 assert(0);
1922 }
1923
1924 return dbm;
1925}
1926
1927/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
1928void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
1929{
1930 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1931 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1932
1933 if (phy->savedpctlreg == 0xFFFF)
1934 return;
1935 if ((bcm->board_type == 0x0416) &&
1936 (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
1937 return;
1938
1939 switch (phy->type) {
1940 case BCM43xx_PHYTYPE_A: {
1941
1942 TODO(); //TODO: Nothing for A PHYs yet :-/
1943
1944 break;
1945 }
1946 case BCM43xx_PHYTYPE_B:
1947 case BCM43xx_PHYTYPE_G: {
1948 u16 tmp;
1949 u16 txpower;
1950 s8 v0, v1, v2, v3;
1951 s8 average;
1952 u8 max_pwr;
1953 s16 desired_pwr, estimated_pwr, pwr_adjust;
1954 s16 radio_att_delta, baseband_att_delta;
1955 s16 radio_attenuation, baseband_attenuation;
1956 unsigned long phylock_flags;
1957
1958 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
1959 v0 = (s8)(tmp & 0x00FF);
1960 v1 = (s8)((tmp & 0xFF00) >> 8);
1961 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
1962 v2 = (s8)(tmp & 0x00FF);
1963 v3 = (s8)((tmp & 0xFF00) >> 8);
1964 tmp = 0;
1965
1966 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
1967 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
1968 v0 = (s8)(tmp & 0x00FF);
1969 v1 = (s8)((tmp & 0xFF00) >> 8);
1970 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
1971 v2 = (s8)(tmp & 0x00FF);
1972 v3 = (s8)((tmp & 0xFF00) >> 8);
1973 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
1974 return;
1975 v0 = (v0 + 0x20) & 0x3F;
1976 v1 = (v1 + 0x20) & 0x3F;
1977 v2 = (v2 + 0x20) & 0x3F;
1978 v3 = (v3 + 0x20) & 0x3F;
1979 tmp = 1;
1980 }
1981 bcm43xx_radio_clear_tssi(bcm);
1982
1983 average = (v0 + v1 + v2 + v3 + 2) / 4;
1984
1985 if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
1986 average -= 13;
1987
1988 estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
1989
1990 max_pwr = bcm->sprom.maxpower_bgphy;
1991
1992 if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
1993 (phy->type == BCM43xx_PHYTYPE_G))
1994 max_pwr -= 0x3;
1995
1996 /*TODO:
1997 max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
1998 where REG is the max power as per the regulatory domain
1999 */
2000
2001 desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
2002 /* Check if we need to adjust the current power. */
2003 pwr_adjust = desired_pwr - estimated_pwr;
2004 radio_att_delta = -(pwr_adjust + 7) >> 3;
2005 baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
2006 if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
2007 bcm43xx_phy_lo_mark_current_used(bcm);
2008 return;
2009 }
2010
2011 /* Calculate the new attenuation values. */
2012 baseband_attenuation = radio->baseband_atten;
2013 baseband_attenuation += baseband_att_delta;
2014 radio_attenuation = radio->radio_atten;
2015 radio_attenuation += radio_att_delta;
2016
2017 /* Get baseband and radio attenuation values into their permitted ranges.
2018 * baseband 0-11, radio 0-9.
2019 * Radio attenuation affects power level 4 times as much as baseband.
2020 */
2021 if (radio_attenuation < 0) {
2022 baseband_attenuation -= (4 * -radio_attenuation);
2023 radio_attenuation = 0;
2024 } else if (radio_attenuation > 9) {
2025 baseband_attenuation += (4 * (radio_attenuation - 9));
2026 radio_attenuation = 9;
2027 } else {
2028 while (baseband_attenuation < 0 && radio_attenuation > 0) {
2029 baseband_attenuation += 4;
2030 radio_attenuation--;
2031 }
2032 while (baseband_attenuation > 11 && radio_attenuation < 9) {
2033 baseband_attenuation -= 4;
2034 radio_attenuation++;
2035 }
2036 }
2037 baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
2038
2039 txpower = radio->txctl1;
2040 if ((radio->version == 0x2050) && (radio->revision == 2)) {
2041 if (radio_attenuation <= 1) {
2042 if (txpower == 0) {
2043 txpower = 3;
2044 radio_attenuation += 2;
2045 baseband_attenuation += 2;
2046 } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
2047 baseband_attenuation += 4 * (radio_attenuation - 2);
2048 radio_attenuation = 2;
2049 }
2050 } else if (radio_attenuation > 4 && txpower != 0) {
2051 txpower = 0;
2052 if (baseband_attenuation < 3) {
2053 radio_attenuation -= 3;
2054 baseband_attenuation += 2;
2055 } else {
2056 radio_attenuation -= 2;
2057 baseband_attenuation -= 2;
2058 }
2059 }
2060 }
2061 radio->txctl1 = txpower;
2062 baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
2063 radio_attenuation = limit_value(radio_attenuation, 0, 9);
2064
2065 bcm43xx_phy_lock(bcm, phylock_flags);
2066 bcm43xx_radio_lock(bcm);
2067 bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
2068 radio_attenuation, txpower);
2069 bcm43xx_phy_lo_mark_current_used(bcm);
2070 bcm43xx_radio_unlock(bcm);
2071 bcm43xx_phy_unlock(bcm, phylock_flags);
2072 break;
2073 }
2074 default:
2075 assert(0);
2076 }
2077}
2078
2079static inline
2080s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
2081{
2082 if (num < 0)
2083 return num/den;
2084 else
2085 return (num+den/2)/den;
2086}
2087
2088static inline
2089s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
2090{
2091 s32 m1, m2, f = 256, q, delta;
2092 s8 i = 0;
2093
2094 m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
2095 m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
2096 do {
2097 if (i > 15)
2098 return -EINVAL;
2099 q = bcm43xx_tssi2dbm_ad(f * 4096 -
2100 bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
2101 delta = abs(q - f);
2102 f = q;
2103 i++;
2104 } while (delta >= 2);
2105 entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
2106 return 0;
2107}
2108
2109/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
2110int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
2111{
2112 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2113 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2114 s16 pab0, pab1, pab2;
2115 u8 idx;
2116 s8 *dyn_tssi2dbm;
2117
2118 if (phy->type == BCM43xx_PHYTYPE_A) {
2119 pab0 = (s16)(bcm->sprom.pa1b0);
2120 pab1 = (s16)(bcm->sprom.pa1b1);
2121 pab2 = (s16)(bcm->sprom.pa1b2);
2122 } else {
2123 pab0 = (s16)(bcm->sprom.pa0b0);
2124 pab1 = (s16)(bcm->sprom.pa0b1);
2125 pab2 = (s16)(bcm->sprom.pa0b2);
2126 }
2127
2128 if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
2129 phy->idle_tssi = 0x34;
2130 phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
2131 return 0;
2132 }
2133
2134 if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
2135 pab0 != -1 && pab1 != -1 && pab2 != -1) {
2136 /* The pabX values are set in SPROM. Use them. */
2137 if (phy->type == BCM43xx_PHYTYPE_A) {
2138 if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
2139 (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
2140 phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
2141 else
2142 phy->idle_tssi = 62;
2143 } else {
2144 if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
2145 (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
2146 phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
2147 else
2148 phy->idle_tssi = 62;
2149 }
2150 dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
2151 if (dyn_tssi2dbm == NULL) {
2152 printk(KERN_ERR PFX "Could not allocate memory "
2153 "for tssi2dbm table\n");
2154 return -ENOMEM;
2155 }
2156 for (idx = 0; idx < 64; idx++)
2157 if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
2158 phy->tssi2dbm = NULL;
2159 printk(KERN_ERR PFX "Could not generate "
2160 "tssi2dBm table\n");
2161 kfree(dyn_tssi2dbm);
2162 return -ENODEV;
2163 }
2164 phy->tssi2dbm = dyn_tssi2dbm;
2165 phy->dyn_tssi_tbl = 1;
2166 } else {
2167 /* pabX values not set in SPROM. */
2168 switch (phy->type) {
2169 case BCM43xx_PHYTYPE_A:
2170 /* APHY needs a generated table. */
2171 phy->tssi2dbm = NULL;
2172 printk(KERN_ERR PFX "Could not generate tssi2dBm "
2173 "table (wrong SPROM info)!\n");
2174 return -ENODEV;
2175 case BCM43xx_PHYTYPE_B:
2176 phy->idle_tssi = 0x34;
2177 phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
2178 break;
2179 case BCM43xx_PHYTYPE_G:
2180 phy->idle_tssi = 0x34;
2181 phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
2182 break;
2183 }
2184 }
2185
2186 return 0;
2187}
2188
2189int bcm43xx_phy_init(struct bcm43xx_private *bcm)
2190{
2191 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2192 int err = -ENODEV;
2193
2194 switch (phy->type) {
2195 case BCM43xx_PHYTYPE_A:
2196 if (phy->rev == 2 || phy->rev == 3) {
2197 bcm43xx_phy_inita(bcm);
2198 err = 0;
2199 }
2200 break;
2201 case BCM43xx_PHYTYPE_B:
2202 switch (phy->rev) {
2203 case 2:
2204 bcm43xx_phy_initb2(bcm);
2205 err = 0;
2206 break;
2207 case 4:
2208 bcm43xx_phy_initb4(bcm);
2209 err = 0;
2210 break;
2211 case 5:
2212 bcm43xx_phy_initb5(bcm);
2213 err = 0;
2214 break;
2215 case 6:
2216 bcm43xx_phy_initb6(bcm);
2217 err = 0;
2218 break;
2219 }
2220 break;
2221 case BCM43xx_PHYTYPE_G:
2222 bcm43xx_phy_initg(bcm);
2223 err = 0;
2224 break;
2225 }
2226 if (err)
2227 printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
2228
2229 return err;
2230}
2231
2232void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
2233{
2234 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2235 u16 antennadiv;
2236 u16 offset;
2237 u16 value;
2238 u32 ucodeflags;
2239
2240 antennadiv = phy->antenna_diversity;
2241
2242 if (antennadiv == 0xFFFF)
2243 antennadiv = 3;
2244 assert(antennadiv <= 3);
2245
2246 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
2247 BCM43xx_UCODEFLAGS_OFFSET);
2248 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
2249 BCM43xx_UCODEFLAGS_OFFSET,
2250 ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
2251
2252 switch (phy->type) {
2253 case BCM43xx_PHYTYPE_A:
2254 case BCM43xx_PHYTYPE_G:
2255 if (phy->type == BCM43xx_PHYTYPE_A)
2256 offset = 0x0000;
2257 else
2258 offset = 0x0400;
2259
2260 if (antennadiv == 2)
2261 value = (3/*automatic*/ << 7);
2262 else
2263 value = (antennadiv << 7);
2264 bcm43xx_phy_write(bcm, offset + 1,
2265 (bcm43xx_phy_read(bcm, offset + 1)
2266 & 0x7E7F) | value);
2267
2268 if (antennadiv >= 2) {
2269 if (antennadiv == 2)
2270 value = (antennadiv << 7);
2271 else
2272 value = (0/*force0*/ << 7);
2273 bcm43xx_phy_write(bcm, offset + 0x2B,
2274 (bcm43xx_phy_read(bcm, offset + 0x2B)
2275 & 0xFEFF) | value);
2276 }
2277
2278 if (phy->type == BCM43xx_PHYTYPE_G) {
2279 if (antennadiv >= 2)
2280 bcm43xx_phy_write(bcm, 0x048C,
2281 bcm43xx_phy_read(bcm, 0x048C)
2282 | 0x2000);
2283 else
2284 bcm43xx_phy_write(bcm, 0x048C,
2285 bcm43xx_phy_read(bcm, 0x048C)
2286 & ~0x2000);
2287 if (phy->rev >= 2) {
2288 bcm43xx_phy_write(bcm, 0x0461,
2289 bcm43xx_phy_read(bcm, 0x0461)
2290 | 0x0010);
2291 bcm43xx_phy_write(bcm, 0x04AD,
2292 (bcm43xx_phy_read(bcm, 0x04AD)
2293 & 0x00FF) | 0x0015);
2294 if (phy->rev == 2)
2295 bcm43xx_phy_write(bcm, 0x0427, 0x0008);
2296 else
2297 bcm43xx_phy_write(bcm, 0x0427,
2298 (bcm43xx_phy_read(bcm, 0x0427)
2299 & 0x00FF) | 0x0008);
2300 }
2301 else if (phy->rev >= 6)
2302 bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
2303 } else {
2304 if (phy->rev < 3)
2305 bcm43xx_phy_write(bcm, 0x002B,
2306 (bcm43xx_phy_read(bcm, 0x002B)
2307 & 0x00FF) | 0x0024);
2308 else {
2309 bcm43xx_phy_write(bcm, 0x0061,
2310 bcm43xx_phy_read(bcm, 0x0061)
2311 | 0x0010);
2312 if (phy->rev == 3) {
2313 bcm43xx_phy_write(bcm, 0x0093, 0x001D);
2314 bcm43xx_phy_write(bcm, 0x0027, 0x0008);
2315 } else {
2316 bcm43xx_phy_write(bcm, 0x0093, 0x003A);
2317 bcm43xx_phy_write(bcm, 0x0027,
2318 (bcm43xx_phy_read(bcm, 0x0027)
2319 & 0x00FF) | 0x0008);
2320 }
2321 }
2322 }
2323 break;
2324 case BCM43xx_PHYTYPE_B:
2325 if (bcm->current_core->rev == 2)
2326 value = (3/*automatic*/ << 7);
2327 else
2328 value = (antennadiv << 7);
2329 bcm43xx_phy_write(bcm, 0x03E2,
2330 (bcm43xx_phy_read(bcm, 0x03E2)
2331 & 0xFE7F) | value);
2332 break;
2333 default:
2334 assert(0);
2335 }
2336
2337 if (antennadiv >= 2) {
2338 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
2339 BCM43xx_UCODEFLAGS_OFFSET);
2340 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
2341 BCM43xx_UCODEFLAGS_OFFSET,
2342 ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
2343 }
2344
2345 phy->antenna_diversity = antennadiv;
2346}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
deleted file mode 100644
index 73118364b552..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
+++ /dev/null
@@ -1,78 +0,0 @@
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#ifndef BCM43xx_PHY_H_
32#define BCM43xx_PHY_H_
33
34#include <linux/types.h>
35
36struct bcm43xx_private;
37
38void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
39#define bcm43xx_phy_lock(bcm, flags) \
40 do { \
41 local_irq_save(flags); \
42 bcm43xx_raw_phy_lock(bcm); \
43 } while (0)
44void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
45#define bcm43xx_phy_unlock(bcm, flags) \
46 do { \
47 bcm43xx_raw_phy_unlock(bcm); \
48 local_irq_restore(flags); \
49 } while (0)
50
51/* Card uses the loopback gain stuff */
52#define has_loopback_gain(phy) \
53 (((phy)->rev > 1) || ((phy)->connected))
54
55u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
56void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
57
58int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
59int bcm43xx_phy_init(struct bcm43xx_private *bcm);
60
61void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
62void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
63int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
64
65void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
66void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
67void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
68
69/* Adjust the LocalOscillator to the saved values.
70 * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
71 */
72void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
73void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
74
75void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
76 u16 baseband_attenuation);
77
78#endif /* BCM43xx_PHY_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
deleted file mode 100644
index 76ab109cd2db..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ /dev/null
@@ -1,674 +0,0 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 PIO Transmission
6
7 Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26#include "bcm43xx.h"
27#include "bcm43xx_pio.h"
28#include "bcm43xx_main.h"
29#include "bcm43xx_xmit.h"
30#include "bcm43xx_power.h"
31
32#include <linux/delay.h>
33
34
35static void tx_start(struct bcm43xx_pioqueue *queue)
36{
37 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
38 BCM43xx_PIO_TXCTL_INIT);
39}
40
41static void tx_octet(struct bcm43xx_pioqueue *queue,
42 u8 octet)
43{
44 if (queue->need_workarounds) {
45 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
46 octet);
47 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
48 BCM43xx_PIO_TXCTL_WRITELO);
49 } else {
50 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
51 BCM43xx_PIO_TXCTL_WRITELO);
52 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
53 octet);
54 }
55}
56
57static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
58 const u8 *packet,
59 unsigned int *pos)
60{
61 const u8 *source;
62 unsigned int i = *pos;
63 u16 ret;
64
65 if (i < sizeof(*txhdr)) {
66 source = (const u8 *)txhdr;
67 } else {
68 source = packet;
69 i -= sizeof(*txhdr);
70 }
71 ret = le16_to_cpu( *((__le16 *)(source + i)) );
72 *pos += 2;
73
74 return ret;
75}
76
77static void tx_data(struct bcm43xx_pioqueue *queue,
78 struct bcm43xx_txhdr *txhdr,
79 const u8 *packet,
80 unsigned int octets)
81{
82 u16 data;
83 unsigned int i = 0;
84
85 if (queue->need_workarounds) {
86 data = tx_get_next_word(txhdr, packet, &i);
87 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
88 }
89 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
90 BCM43xx_PIO_TXCTL_WRITELO |
91 BCM43xx_PIO_TXCTL_WRITEHI);
92 while (i < octets - 1) {
93 data = tx_get_next_word(txhdr, packet, &i);
94 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
95 }
96 if (octets % 2)
97 tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
98}
99
100static void tx_complete(struct bcm43xx_pioqueue *queue,
101 struct sk_buff *skb)
102{
103 if (queue->need_workarounds) {
104 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
105 skb->data[skb->len - 1]);
106 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
107 BCM43xx_PIO_TXCTL_WRITELO |
108 BCM43xx_PIO_TXCTL_COMPLETE);
109 } else {
110 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
111 BCM43xx_PIO_TXCTL_COMPLETE);
112 }
113}
114
115static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
116 struct bcm43xx_pio_txpacket *packet)
117{
118 u16 cookie = 0x0000;
119 int packetindex;
120
121 /* We use the upper 4 bits for the PIO
122 * controller ID and the lower 12 bits
123 * for the packet index (in the cache).
124 */
125 switch (queue->mmio_base) {
126 case BCM43xx_MMIO_PIO1_BASE:
127 break;
128 case BCM43xx_MMIO_PIO2_BASE:
129 cookie = 0x1000;
130 break;
131 case BCM43xx_MMIO_PIO3_BASE:
132 cookie = 0x2000;
133 break;
134 case BCM43xx_MMIO_PIO4_BASE:
135 cookie = 0x3000;
136 break;
137 default:
138 assert(0);
139 }
140 packetindex = pio_txpacket_getindex(packet);
141 assert(((u16)packetindex & 0xF000) == 0x0000);
142 cookie |= (u16)packetindex;
143
144 return cookie;
145}
146
147static
148struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
149 u16 cookie,
150 struct bcm43xx_pio_txpacket **packet)
151{
152 struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
153 struct bcm43xx_pioqueue *queue = NULL;
154 int packetindex;
155
156 switch (cookie & 0xF000) {
157 case 0x0000:
158 queue = pio->queue0;
159 break;
160 case 0x1000:
161 queue = pio->queue1;
162 break;
163 case 0x2000:
164 queue = pio->queue2;
165 break;
166 case 0x3000:
167 queue = pio->queue3;
168 break;
169 default:
170 assert(0);
171 }
172 packetindex = (cookie & 0x0FFF);
173 assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
174 *packet = &(queue->tx_packets_cache[packetindex]);
175
176 return queue;
177}
178
179static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
180 struct sk_buff *skb,
181 struct bcm43xx_pio_txpacket *packet)
182{
183 struct bcm43xx_txhdr txhdr;
184 unsigned int octets;
185
186 assert(skb_shinfo(skb)->nr_frags == 0);
187 bcm43xx_generate_txhdr(queue->bcm,
188 &txhdr, skb->data, skb->len,
189 (packet->xmitted_frags == 0),
190 generate_cookie(queue, packet));
191
192 tx_start(queue);
193 octets = skb->len + sizeof(txhdr);
194 if (queue->need_workarounds)
195 octets--;
196 tx_data(queue, &txhdr, (u8 *)skb->data, octets);
197 tx_complete(queue, skb);
198}
199
200static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
201 int irq_context)
202{
203 struct bcm43xx_pioqueue *queue = packet->queue;
204
205 ieee80211_txb_free(packet->txb);
206 list_move(&packet->list, &queue->txfree);
207 queue->nr_txfree++;
208
209 assert(queue->tx_devq_used >= packet->xmitted_octets);
210 assert(queue->tx_devq_packets >= packet->xmitted_frags);
211 queue->tx_devq_used -= packet->xmitted_octets;
212 queue->tx_devq_packets -= packet->xmitted_frags;
213}
214
215static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
216{
217 struct bcm43xx_pioqueue *queue = packet->queue;
218 struct ieee80211_txb *txb = packet->txb;
219 struct sk_buff *skb;
220 u16 octets;
221 int i;
222
223 for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
224 skb = txb->fragments[i];
225
226 octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
227 assert(queue->tx_devq_size >= octets);
228 assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
229 assert(queue->tx_devq_used <= queue->tx_devq_size);
230 /* Check if there is sufficient free space on the device
231 * TX queue. If not, return and let the TX tasklet
232 * retry later.
233 */
234 if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
235 return -EBUSY;
236 if (queue->tx_devq_used + octets > queue->tx_devq_size)
237 return -EBUSY;
238 /* Now poke the device. */
239 pio_tx_write_fragment(queue, skb, packet);
240
241 /* Account for the packet size.
242 * (We must not overflow the device TX queue)
243 */
244 queue->tx_devq_packets++;
245 queue->tx_devq_used += octets;
246
247 assert(packet->xmitted_frags < packet->txb->nr_frags);
248 packet->xmitted_frags++;
249 packet->xmitted_octets += octets;
250 }
251 list_move_tail(&packet->list, &queue->txrunning);
252
253 return 0;
254}
255
256static void tx_tasklet(unsigned long d)
257{
258 struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
259 struct bcm43xx_private *bcm = queue->bcm;
260 unsigned long flags;
261 struct bcm43xx_pio_txpacket *packet, *tmp_packet;
262 int err;
263 u16 txctl;
264
265 spin_lock_irqsave(&bcm->irq_lock, flags);
266
267 if (queue->tx_frozen)
268 goto out_unlock;
269 txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
270 if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
271 goto out_unlock;
272
273 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
274 assert(packet->xmitted_frags < packet->txb->nr_frags);
275 if (packet->xmitted_frags == 0) {
276 int i;
277 struct sk_buff *skb;
278
279 /* Check if the device queue is big
280 * enough for every fragment. If not, drop the
281 * whole packet.
282 */
283 for (i = 0; i < packet->txb->nr_frags; i++) {
284 skb = packet->txb->fragments[i];
285 if (unlikely(skb->len > queue->tx_devq_size)) {
286 dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
287 "Dropping packet.\n");
288 free_txpacket(packet, 1);
289 goto next_packet;
290 }
291 }
292 }
293 /* Try to transmit the packet.
294 * This may not completely succeed.
295 */
296 err = pio_tx_packet(packet);
297 if (err)
298 break;
299 next_packet:
300 continue;
301 }
302out_unlock:
303 spin_unlock_irqrestore(&bcm->irq_lock, flags);
304}
305
306static void setup_txqueues(struct bcm43xx_pioqueue *queue)
307{
308 struct bcm43xx_pio_txpacket *packet;
309 int i;
310
311 queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
312 for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
313 packet = &(queue->tx_packets_cache[i]);
314
315 packet->queue = queue;
316 INIT_LIST_HEAD(&packet->list);
317
318 list_add(&packet->list, &queue->txfree);
319 }
320}
321
322static
323struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
324 u16 pio_mmio_base)
325{
326 struct bcm43xx_pioqueue *queue;
327 u32 value;
328 u16 qsize;
329
330 queue = kzalloc(sizeof(*queue), GFP_KERNEL);
331 if (!queue)
332 goto out;
333
334 queue->bcm = bcm;
335 queue->mmio_base = pio_mmio_base;
336 queue->need_workarounds = (bcm->current_core->rev < 3);
337
338 INIT_LIST_HEAD(&queue->txfree);
339 INIT_LIST_HEAD(&queue->txqueue);
340 INIT_LIST_HEAD(&queue->txrunning);
341 tasklet_init(&queue->txtask, tx_tasklet,
342 (unsigned long)queue);
343
344 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
345 value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
346 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
347
348 qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
349 if (qsize == 0) {
350 printk(KERN_ERR PFX "ERROR: This card does not support PIO "
351 "operation mode. Please use DMA mode "
352 "(module parameter pio=0).\n");
353 goto err_freequeue;
354 }
355 if (qsize <= BCM43xx_PIO_TXQADJUST) {
356 printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
357 qsize);
358 goto err_freequeue;
359 }
360 qsize -= BCM43xx_PIO_TXQADJUST;
361 queue->tx_devq_size = qsize;
362
363 setup_txqueues(queue);
364
365out:
366 return queue;
367
368err_freequeue:
369 kfree(queue);
370 queue = NULL;
371 goto out;
372}
373
374static void cancel_transfers(struct bcm43xx_pioqueue *queue)
375{
376 struct bcm43xx_pio_txpacket *packet, *tmp_packet;
377
378 netif_tx_disable(queue->bcm->net_dev);
379 tasklet_disable(&queue->txtask);
380
381 list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
382 free_txpacket(packet, 0);
383 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
384 free_txpacket(packet, 0);
385}
386
387static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
388{
389 if (!queue)
390 return;
391
392 cancel_transfers(queue);
393 kfree(queue);
394}
395
396void bcm43xx_pio_free(struct bcm43xx_private *bcm)
397{
398 struct bcm43xx_pio *pio;
399
400 if (!bcm43xx_using_pio(bcm))
401 return;
402 pio = bcm43xx_current_pio(bcm);
403
404 bcm43xx_destroy_pioqueue(pio->queue3);
405 pio->queue3 = NULL;
406 bcm43xx_destroy_pioqueue(pio->queue2);
407 pio->queue2 = NULL;
408 bcm43xx_destroy_pioqueue(pio->queue1);
409 pio->queue1 = NULL;
410 bcm43xx_destroy_pioqueue(pio->queue0);
411 pio->queue0 = NULL;
412}
413
414int bcm43xx_pio_init(struct bcm43xx_private *bcm)
415{
416 struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
417 struct bcm43xx_pioqueue *queue;
418 int err = -ENOMEM;
419
420 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
421 if (!queue)
422 goto out;
423 pio->queue0 = queue;
424
425 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
426 if (!queue)
427 goto err_destroy0;
428 pio->queue1 = queue;
429
430 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
431 if (!queue)
432 goto err_destroy1;
433 pio->queue2 = queue;
434
435 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
436 if (!queue)
437 goto err_destroy2;
438 pio->queue3 = queue;
439
440 if (bcm->current_core->rev < 3)
441 bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
442
443 dprintk(KERN_INFO PFX "PIO initialized\n");
444 err = 0;
445out:
446 return err;
447
448err_destroy2:
449 bcm43xx_destroy_pioqueue(pio->queue2);
450 pio->queue2 = NULL;
451err_destroy1:
452 bcm43xx_destroy_pioqueue(pio->queue1);
453 pio->queue1 = NULL;
454err_destroy0:
455 bcm43xx_destroy_pioqueue(pio->queue0);
456 pio->queue0 = NULL;
457 goto out;
458}
459
460int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
461 struct ieee80211_txb *txb)
462{
463 struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
464 struct bcm43xx_pio_txpacket *packet;
465
466 assert(!queue->tx_suspended);
467 assert(!list_empty(&queue->txfree));
468
469 packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
470 packet->txb = txb;
471 packet->xmitted_frags = 0;
472 packet->xmitted_octets = 0;
473 list_move_tail(&packet->list, &queue->txqueue);
474 queue->nr_txfree--;
475 assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
476
477 /* Suspend TX, if we are out of packets in the "free" queue. */
478 if (list_empty(&queue->txfree)) {
479 netif_stop_queue(queue->bcm->net_dev);
480 queue->tx_suspended = 1;
481 }
482
483 tasklet_schedule(&queue->txtask);
484
485 return 0;
486}
487
488void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
489 struct bcm43xx_xmitstatus *status)
490{
491 struct bcm43xx_pioqueue *queue;
492 struct bcm43xx_pio_txpacket *packet;
493
494 queue = parse_cookie(bcm, status->cookie, &packet);
495 assert(queue);
496
497 free_txpacket(packet, 1);
498 if (queue->tx_suspended) {
499 queue->tx_suspended = 0;
500 netif_wake_queue(queue->bcm->net_dev);
501 }
502 /* If there are packets on the txqueue, poke the tasklet
503 * to transmit them.
504 */
505 if (!list_empty(&queue->txqueue))
506 tasklet_schedule(&queue->txtask);
507}
508
509static void pio_rx_error(struct bcm43xx_pioqueue *queue,
510 int clear_buffers,
511 const char *error)
512{
513 int i;
514
515 printkl("PIO RX error: %s\n", error);
516 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
517 BCM43xx_PIO_RXCTL_READY);
518 if (clear_buffers) {
519 assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
520 for (i = 0; i < 15; i++) {
521 /* Dummy read. */
522 bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
523 }
524 }
525}
526
527void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
528{
529 __le16 preamble[21] = { 0 };
530 struct bcm43xx_rxhdr *rxhdr;
531 u16 tmp, len, rxflags2;
532 int i, preamble_readwords;
533 struct sk_buff *skb;
534
535 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
536 if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
537 return;
538 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
539 BCM43xx_PIO_RXCTL_DATAAVAILABLE);
540
541 for (i = 0; i < 10; i++) {
542 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
543 if (tmp & BCM43xx_PIO_RXCTL_READY)
544 goto data_ready;
545 udelay(10);
546 }
547 dprintkl(KERN_ERR PFX "PIO RX timed out\n");
548 return;
549data_ready:
550
551 len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
552 if (unlikely(len > 0x700)) {
553 pio_rx_error(queue, 0, "len > 0x700");
554 return;
555 }
556 if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
557 pio_rx_error(queue, 0, "len == 0");
558 return;
559 }
560 preamble[0] = cpu_to_le16(len);
561 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
562 preamble_readwords = 14 / sizeof(u16);
563 else
564 preamble_readwords = 18 / sizeof(u16);
565 for (i = 0; i < preamble_readwords; i++) {
566 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
567 preamble[i + 1] = cpu_to_le16(tmp);
568 }
569 rxhdr = (struct bcm43xx_rxhdr *)preamble;
570 rxflags2 = le16_to_cpu(rxhdr->flags2);
571 if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
572 pio_rx_error(queue,
573 (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
574 "invalid frame");
575 return;
576 }
577 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
578 /* We received an xmit status. */
579 struct bcm43xx_hwxmitstatus *hw;
580 struct bcm43xx_xmitstatus stat;
581
582 hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
583 stat.cookie = le16_to_cpu(hw->cookie);
584 stat.flags = hw->flags;
585 stat.cnt1 = hw->cnt1;
586 stat.cnt2 = hw->cnt2;
587 stat.seq = le16_to_cpu(hw->seq);
588 stat.unknown = le16_to_cpu(hw->unknown);
589
590 bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
591 bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
592
593 return;
594 }
595
596 skb = dev_alloc_skb(len);
597 if (unlikely(!skb)) {
598 pio_rx_error(queue, 1, "OOM");
599 return;
600 }
601 skb_put(skb, len);
602 for (i = 0; i < len - 1; i += 2) {
603 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
604 *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
605 }
606 if (len % 2) {
607 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
608 skb->data[len - 1] = (tmp & 0x00FF);
609/* The specs say the following is required, but
610 * it is wrong and corrupts the PLCP. If we don't do
611 * this, the PLCP seems to be correct. So ifdef it out for now.
612 */
613#if 0
614 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
615 skb->data[2] = (tmp & 0xFF00) >> 8;
616 else
617 skb->data[0] = (tmp & 0xFF00) >> 8;
618#endif
619 }
620 skb_trim(skb, len - IEEE80211_FCS_LEN);
621 bcm43xx_rx(queue->bcm, skb, rxhdr);
622}
623
624void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
625{
626 bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
627 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
628 bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
629 | BCM43xx_PIO_TXCTL_SUSPEND);
630}
631
632void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
633{
634 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
635 bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
636 & ~BCM43xx_PIO_TXCTL_SUSPEND);
637 bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
638 if (!list_empty(&queue->txqueue))
639 tasklet_schedule(&queue->txtask);
640}
641
642void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
643{
644 struct bcm43xx_pio *pio;
645
646 assert(bcm43xx_using_pio(bcm));
647 pio = bcm43xx_current_pio(bcm);
648 pio->queue0->tx_frozen = 1;
649 pio->queue1->tx_frozen = 1;
650 pio->queue2->tx_frozen = 1;
651 pio->queue3->tx_frozen = 1;
652}
653
654void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
655{
656 struct bcm43xx_pio *pio;
657
658 assert(bcm43xx_using_pio(bcm));
659 pio = bcm43xx_current_pio(bcm);
660 pio->queue0->tx_frozen = 0;
661 pio->queue1->tx_frozen = 0;
662 pio->queue2->tx_frozen = 0;
663 pio->queue3->tx_frozen = 0;
664 if (!list_empty(&pio->queue0->txqueue))
665 tasklet_schedule(&pio->queue0->txtask);
666 if (!list_empty(&pio->queue1->txqueue))
667 tasklet_schedule(&pio->queue1->txtask);
668 if (!list_empty(&pio->queue2->txqueue))
669 tasklet_schedule(&pio->queue2->txtask);
670 if (!list_empty(&pio->queue3->txqueue))
671 tasklet_schedule(&pio->queue3->txtask);
672}
673
674
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
deleted file mode 100644
index bc78a3c2cafb..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+++ /dev/null
@@ -1,163 +0,0 @@
1#ifndef BCM43xx_PIO_H_
2#define BCM43xx_PIO_H_
3
4#include "bcm43xx.h"
5
6#include <linux/interrupt.h>
7#include <linux/list.h>
8#include <linux/skbuff.h>
9
10
11#define BCM43xx_PIO_TXCTL 0x00
12#define BCM43xx_PIO_TXDATA 0x02
13#define BCM43xx_PIO_TXQBUFSIZE 0x04
14#define BCM43xx_PIO_RXCTL 0x08
15#define BCM43xx_PIO_RXDATA 0x0A
16
17#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0)
18#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1)
19#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
20#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
21#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
22
23#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0)
24#define BCM43xx_PIO_RXCTL_READY (1 << 1)
25
26/* PIO constants */
27#define BCM43xx_PIO_MAXTXDEVQPACKETS 31
28#define BCM43xx_PIO_TXQADJUST 80
29
30/* PIO tuning knobs */
31#define BCM43xx_PIO_MAXTXPACKETS 256
32
33
34
35#ifdef CONFIG_BCM43XX_PIO
36
37
38struct bcm43xx_pioqueue;
39struct bcm43xx_xmitstatus;
40
41struct bcm43xx_pio_txpacket {
42 struct bcm43xx_pioqueue *queue;
43 struct ieee80211_txb *txb;
44 struct list_head list;
45
46 u8 xmitted_frags;
47 u16 xmitted_octets;
48};
49
50#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
51
52struct bcm43xx_pioqueue {
53 struct bcm43xx_private *bcm;
54 u16 mmio_base;
55
56 u8 tx_suspended:1,
57 tx_frozen:1,
58 need_workarounds:1; /* Workarounds needed for core.rev < 3 */
59
60 /* Adjusted size of the device internal TX buffer. */
61 u16 tx_devq_size;
62 /* Used octets of the device internal TX buffer. */
63 u16 tx_devq_used;
64 /* Used packet slots in the device internal TX buffer. */
65 u8 tx_devq_packets;
66 /* Packets from the txfree list can
67 * be taken on incoming TX requests.
68 */
69 struct list_head txfree;
70 unsigned int nr_txfree;
71 /* Packets on the txqueue are queued,
72 * but not completely written to the chip, yet.
73 */
74 struct list_head txqueue;
75 /* Packets on the txrunning queue are completely
76 * posted to the device. We are waiting for the txstatus.
77 */
78 struct list_head txrunning;
79 /* Total number or packets sent.
80 * (This counter can obviously wrap).
81 */
82 unsigned int nr_tx_packets;
83 struct tasklet_struct txtask;
84 struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
85};
86
87static inline
88u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
89 u16 offset)
90{
91 return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
92}
93
94static inline
95void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
96 u16 offset, u16 value)
97{
98 bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
99 mmiowb();
100}
101
102
103int bcm43xx_pio_init(struct bcm43xx_private *bcm);
104void bcm43xx_pio_free(struct bcm43xx_private *bcm);
105
106int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
107 struct ieee80211_txb *txb);
108void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
109 struct bcm43xx_xmitstatus *status);
110void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
111
112/* Suspend a TX queue on hardware level. */
113void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
114void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
115/* Suspend (freeze) the TX tasklet (software level). */
116void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
117void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
118
119#else /* CONFIG_BCM43XX_PIO */
120
121static inline
122int bcm43xx_pio_init(struct bcm43xx_private *bcm)
123{
124 return 0;
125}
126static inline
127void bcm43xx_pio_free(struct bcm43xx_private *bcm)
128{
129}
130static inline
131int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
132 struct ieee80211_txb *txb)
133{
134 return 0;
135}
136static inline
137void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
138 struct bcm43xx_xmitstatus *status)
139{
140}
141static inline
142void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
143{
144}
145static inline
146void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
147{
148}
149static inline
150void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
151{
152}
153static inline
154void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
155{
156}
157static inline
158void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
159{
160}
161
162#endif /* CONFIG_BCM43XX_PIO */
163#endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
deleted file mode 100644
index 7e774f410953..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+++ /dev/null
@@ -1,393 +0,0 @@
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
33#include "bcm43xx.h"
34#include "bcm43xx_power.h"
35#include "bcm43xx_main.h"
36
37
38/* Get the Slow Clock Source */
39static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
40{
41 u32 tmp;
42 int err;
43
44 assert(bcm->current_core == &bcm->core_chipcommon);
45 if (bcm->current_core->rev < 6) {
46 if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
47 bcm->bustype == BCM43xx_BUSTYPE_SB)
48 return BCM43xx_PCTL_CLKSRC_XTALOS;
49 if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
50 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
51 assert(!err);
52 if (tmp & 0x10)
53 return BCM43xx_PCTL_CLKSRC_PCI;
54 return BCM43xx_PCTL_CLKSRC_XTALOS;
55 }
56 }
57 if (bcm->current_core->rev < 10) {
58 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
59 tmp &= 0x7;
60 if (tmp == 0)
61 return BCM43xx_PCTL_CLKSRC_LOPWROS;
62 if (tmp == 1)
63 return BCM43xx_PCTL_CLKSRC_XTALOS;
64 if (tmp == 2)
65 return BCM43xx_PCTL_CLKSRC_PCI;
66 }
67
68 return BCM43xx_PCTL_CLKSRC_XTALOS;
69}
70
71/* Get max/min slowclock frequency
72 * as described in http://bcm-specs.sipsolutions.net/PowerControl
73 */
74static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
75 int get_max)
76{
77 int limit;
78 int clocksrc;
79 int divisor;
80 u32 tmp;
81
82 assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
83 assert(bcm->current_core == &bcm->core_chipcommon);
84
85 clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
86 if (bcm->current_core->rev < 6) {
87 switch (clocksrc) {
88 case BCM43xx_PCTL_CLKSRC_PCI:
89 divisor = 64;
90 break;
91 case BCM43xx_PCTL_CLKSRC_XTALOS:
92 divisor = 32;
93 break;
94 default:
95 assert(0);
96 divisor = 1;
97 }
98 } else if (bcm->current_core->rev < 10) {
99 switch (clocksrc) {
100 case BCM43xx_PCTL_CLKSRC_LOPWROS:
101 divisor = 1;
102 break;
103 case BCM43xx_PCTL_CLKSRC_XTALOS:
104 case BCM43xx_PCTL_CLKSRC_PCI:
105 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
106 divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
107 divisor *= 4;
108 break;
109 default:
110 assert(0);
111 divisor = 1;
112 }
113 } else {
114 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
115 divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
116 divisor *= 4;
117 }
118
119 switch (clocksrc) {
120 case BCM43xx_PCTL_CLKSRC_LOPWROS:
121 if (get_max)
122 limit = 43000;
123 else
124 limit = 25000;
125 break;
126 case BCM43xx_PCTL_CLKSRC_XTALOS:
127 if (get_max)
128 limit = 20200000;
129 else
130 limit = 19800000;
131 break;
132 case BCM43xx_PCTL_CLKSRC_PCI:
133 if (get_max)
134 limit = 34000000;
135 else
136 limit = 25000000;
137 break;
138 default:
139 assert(0);
140 limit = 0;
141 }
142 limit /= divisor;
143
144 return limit;
145}
146
147
148/* init power control
149 * as described in http://bcm-specs.sipsolutions.net/PowerControl
150 */
151int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
152{
153 int err, maxfreq;
154 struct bcm43xx_coreinfo *old_core;
155
156 old_core = bcm->current_core;
157 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
158 if (err == -ENODEV)
159 return 0;
160 if (err)
161 goto out;
162
163 if (bcm->chip_id == 0x4321) {
164 if (bcm->chip_rev == 0)
165 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
166 if (bcm->chip_rev == 1)
167 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
168 }
169
170 if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
171 if (bcm->current_core->rev >= 10) {
172 /* Set Idle Power clock rate to 1Mhz */
173 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
174 (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
175 & 0x0000FFFF) | 0x40000);
176 } else {
177 maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
178 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
179 (maxfreq * 150 + 999999) / 1000000);
180 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
181 (maxfreq * 15 + 999999) / 1000000);
182 }
183 }
184
185 err = bcm43xx_switch_core(bcm, old_core);
186 assert(err == 0);
187
188out:
189 return err;
190}
191
192u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
193{
194 u16 delay = 0;
195 int err;
196 u32 pll_on_delay;
197 struct bcm43xx_coreinfo *old_core;
198 int minfreq;
199
200 if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
201 goto out;
202 if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
203 goto out;
204 old_core = bcm->current_core;
205 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
206 if (err == -ENODEV)
207 goto out;
208
209 minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
210 pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
211 delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
212
213 err = bcm43xx_switch_core(bcm, old_core);
214 assert(err == 0);
215
216out:
217 return delay;
218}
219
220/* set the powercontrol clock
221 * as described in http://bcm-specs.sipsolutions.net/PowerControl
222 */
223int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
224{
225 int err;
226 struct bcm43xx_coreinfo *old_core;
227 u32 tmp;
228
229 old_core = bcm->current_core;
230 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
231 if (err == -ENODEV)
232 return 0;
233 if (err)
234 goto out;
235
236 if (bcm->core_chipcommon.rev < 6) {
237 if (mode == BCM43xx_PCTL_CLK_FAST) {
238 err = bcm43xx_pctl_set_crystal(bcm, 1);
239 if (err)
240 goto out;
241 }
242 } else {
243 if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
244 (bcm->core_chipcommon.rev < 10)) {
245 switch (mode) {
246 case BCM43xx_PCTL_CLK_FAST:
247 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
248 tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
249 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
250 break;
251 case BCM43xx_PCTL_CLK_SLOW:
252 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
253 tmp |= BCM43xx_PCTL_FORCE_SLOW;
254 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
255 break;
256 case BCM43xx_PCTL_CLK_DYNAMIC:
257 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
258 tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
259 tmp |= BCM43xx_PCTL_FORCE_PLL;
260 tmp &= ~BCM43xx_PCTL_DYN_XTAL;
261 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
262 }
263 }
264 }
265
266 err = bcm43xx_switch_core(bcm, old_core);
267 assert(err == 0);
268
269out:
270 return err;
271}
272
273int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
274{
275 int err;
276 u32 in, out, outenable;
277
278 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
279 if (err)
280 goto err_pci;
281 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
282 if (err)
283 goto err_pci;
284 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
285 if (err)
286 goto err_pci;
287
288 outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
289
290 if (on) {
291 if (in & 0x40)
292 return 0;
293
294 out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
295
296 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
297 if (err)
298 goto err_pci;
299 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
300 if (err)
301 goto err_pci;
302 udelay(1000);
303
304 out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
305 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
306 if (err)
307 goto err_pci;
308 udelay(5000);
309 } else {
310 if (bcm->current_core->rev < 5)
311 return 0;
312 if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
313 return 0;
314
315/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
316 * err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
317 * if (err)
318 * return err;
319 * if (((bcm->current_core->rev >= 3) &&
320 * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
321 * ((bcm->current_core->rev < 3) &&
322 * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
323 * return 0;
324 * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
325 * if (err)
326 * return err;
327 */
328
329 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
330 if (err)
331 goto out;
332 out &= ~BCM43xx_PCTL_XTAL_POWERUP;
333 out |= BCM43xx_PCTL_PLL_POWERDOWN;
334 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
335 if (err)
336 goto err_pci;
337 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
338 if (err)
339 goto err_pci;
340 }
341
342out:
343 return err;
344
345err_pci:
346 printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
347 err = -EBUSY;
348 goto out;
349}
350
351/* Set the PowerSavingControlBits.
352 * Bitvalues:
353 * 0 => unset the bit
354 * 1 => set the bit
355 * -1 => calculate the bit
356 */
357void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
358 int bit25, int bit26)
359{
360 int i;
361 u32 status;
362
363//FIXME: Force 25 to off and 26 to on for now:
364bit25 = 0;
365bit26 = 1;
366
367 if (bit25 == -1) {
368 //TODO: If powersave is not off and FIXME is not set and we are not in adhoc
369 // and thus is not an AP and we are associated, set bit 25
370 }
371 if (bit26 == -1) {
372 //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
373 // or we are associated, or FIXME, or the latest PS-Poll packet sent was
374 // successful, set bit26
375 }
376 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
377 if (bit25)
378 status |= BCM43xx_SBF_PS1;
379 else
380 status &= ~BCM43xx_SBF_PS1;
381 if (bit26)
382 status |= BCM43xx_SBF_PS2;
383 else
384 status &= ~BCM43xx_SBF_PS2;
385 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
386 if (bit26 && bcm->current_core->rev >= 5) {
387 for (i = 0; i < 100; i++) {
388 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
389 break;
390 udelay(10);
391 }
392 }
393}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
deleted file mode 100644
index c966ab3a5a8c..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h
+++ /dev/null
@@ -1,56 +0,0 @@
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#ifndef BCM43xx_POWER_H_
32#define BCM43xx_POWER_H_
33
34#include <linux/types.h>
35
36/* Clock sources */
37enum {
38 /* PCI clock */
39 BCM43xx_PCTL_CLKSRC_PCI,
40 /* Crystal slow clock oscillator */
41 BCM43xx_PCTL_CLKSRC_XTALOS,
42 /* Low power oscillator */
43 BCM43xx_PCTL_CLKSRC_LOPWROS,
44};
45
46struct bcm43xx_private;
47
48int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
49int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
50int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
51u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
52
53void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
54 int bit25, int bit26);
55
56#endif /* BCM43xx_POWER_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
deleted file mode 100644
index c605099c9baf..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ /dev/null
@@ -1,2170 +0,0 @@
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
33#include "bcm43xx.h"
34#include "bcm43xx_main.h"
35#include "bcm43xx_phy.h"
36#include "bcm43xx_radio.h"
37#include "bcm43xx_ilt.h"
38
39
40/* Table for bcm43xx_radio_calibrationvalue() */
41static const u16 rcc_table[16] = {
42 0x0002, 0x0003, 0x0001, 0x000F,
43 0x0006, 0x0007, 0x0005, 0x000F,
44 0x000A, 0x000B, 0x0009, 0x000F,
45 0x000E, 0x000F, 0x000D, 0x000F,
46};
47
48/* Reverse the bits of a 4bit value.
49 * Example: 1101 is flipped 1011
50 */
51static u16 flip_4bit(u16 value)
52{
53 u16 flipped = 0x0000;
54
55 assert((value & ~0x000F) == 0x0000);
56
57 flipped |= (value & 0x0001) << 3;
58 flipped |= (value & 0x0002) << 1;
59 flipped |= (value & 0x0004) >> 1;
60 flipped |= (value & 0x0008) >> 3;
61
62 return flipped;
63}
64
65/* Get the freq, as it has to be written to the device. */
66static inline
67u16 channel2freq_bg(u8 channel)
68{
69 /* Frequencies are given as frequencies_bg[index] + 2.4GHz
70 * Starting with channel 1
71 */
72 static const u16 frequencies_bg[14] = {
73 12, 17, 22, 27,
74 32, 37, 42, 47,
75 52, 57, 62, 67,
76 72, 84,
77 };
78
79 assert(channel >= 1 && channel <= 14);
80
81 return frequencies_bg[channel - 1];
82}
83
84/* Get the freq, as it has to be written to the device. */
85static inline
86u16 channel2freq_a(u8 channel)
87{
88 assert(channel <= 200);
89
90 return (5000 + 5 * channel);
91}
92
93void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
94{
95 u32 status;
96
97 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
98 status |= BCM43xx_SBF_RADIOREG_LOCK;
99 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
100 mmiowb();
101 udelay(10);
102}
103
104void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
105{
106 u32 status;
107
108 bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
109 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
110 status &= ~BCM43xx_SBF_RADIOREG_LOCK;
111 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
112 mmiowb();
113}
114
115u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
116{
117 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
118 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
119
120 switch (phy->type) {
121 case BCM43xx_PHYTYPE_A:
122 offset |= 0x0040;
123 break;
124 case BCM43xx_PHYTYPE_B:
125 if (radio->version == 0x2053) {
126 if (offset < 0x70)
127 offset += 0x80;
128 else if (offset < 0x80)
129 offset += 0x70;
130 } else if (radio->version == 0x2050) {
131 offset |= 0x80;
132 } else
133 assert(0);
134 break;
135 case BCM43xx_PHYTYPE_G:
136 offset |= 0x80;
137 break;
138 }
139
140 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
141 return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
142}
143
144void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
145{
146 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
147 mmiowb();
148 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
149}
150
151static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
152 s16 first, s16 second, s16 third)
153{
154 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
155 u16 i;
156 u16 start = 0x08, end = 0x18;
157 u16 offset = 0x0400;
158 u16 tmp;
159
160 if (phy->rev <= 1) {
161 offset = 0x5000;
162 start = 0x10;
163 end = 0x20;
164 }
165
166 for (i = 0; i < 4; i++)
167 bcm43xx_ilt_write(bcm, offset + i, first);
168
169 for (i = start; i < end; i++)
170 bcm43xx_ilt_write(bcm, offset + i, second);
171
172 if (third != -1) {
173 tmp = ((u16)third << 14) | ((u16)third << 6);
174 bcm43xx_phy_write(bcm, 0x04A0,
175 (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
176 bcm43xx_phy_write(bcm, 0x04A1,
177 (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
178 bcm43xx_phy_write(bcm, 0x04A2,
179 (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
180 }
181 bcm43xx_dummy_transmission(bcm);
182}
183
184static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
185{
186 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
187 u16 i, tmp;
188 u16 offset = 0x0400;
189 u16 start = 0x0008, end = 0x0018;
190
191 if (phy->rev <= 1) {
192 offset = 0x5000;
193 start = 0x0010;
194 end = 0x0020;
195 }
196
197 for (i = 0; i < 4; i++) {
198 tmp = (i & 0xFFFC);
199 tmp |= (i & 0x0001) << 1;
200 tmp |= (i & 0x0002) >> 1;
201
202 bcm43xx_ilt_write(bcm, offset + i, tmp);
203 }
204
205 for (i = start; i < end; i++)
206 bcm43xx_ilt_write(bcm, offset + i, i - start);
207
208 bcm43xx_phy_write(bcm, 0x04A0,
209 (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
210 bcm43xx_phy_write(bcm, 0x04A1,
211 (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
212 bcm43xx_phy_write(bcm, 0x04A2,
213 (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
214 bcm43xx_dummy_transmission(bcm);
215}
216
217/* Synthetic PU workaround */
218static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
219{
220 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
221
222 if (radio->version != 0x2050 || radio->revision >= 6) {
223 /* We do not need the workaround. */
224 return;
225 }
226
227 if (channel <= 10) {
228 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
229 channel2freq_bg(channel + 4));
230 } else {
231 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
232 channel2freq_bg(1));
233 }
234 udelay(100);
235 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
236 channel2freq_bg(channel));
237}
238
239u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
240{
241 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
242 u8 ret = 0;
243 u16 saved, rssi, temp;
244 int i, j = 0;
245
246 saved = bcm43xx_phy_read(bcm, 0x0403);
247 bcm43xx_radio_selectchannel(bcm, channel, 0);
248 bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
249 if (radio->aci_hw_rssi)
250 rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
251 else
252 rssi = saved & 0x3F;
253 /* clamp temp to signed 5bit */
254 if (rssi > 32)
255 rssi -= 64;
256 for (i = 0;i < 100; i++) {
257 temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
258 if (temp > 32)
259 temp -= 64;
260 if (temp < rssi)
261 j++;
262 if (j >= 20)
263 ret = 1;
264 }
265 bcm43xx_phy_write(bcm, 0x0403, saved);
266
267 return ret;
268}
269
270u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
271{
272 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
273 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
274 u8 ret[13];
275 unsigned int channel = radio->channel;
276 unsigned int i, j, start, end;
277 unsigned long phylock_flags;
278
279 if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
280 return 0;
281
282 bcm43xx_phy_lock(bcm, phylock_flags);
283 bcm43xx_radio_lock(bcm);
284 bcm43xx_phy_write(bcm, 0x0802,
285 bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
286 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
287 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
288 bcm43xx_set_all_gains(bcm, 3, 8, 1);
289
290 start = (channel - 5 > 0) ? channel - 5 : 1;
291 end = (channel + 5 < 14) ? channel + 5 : 13;
292
293 for (i = start; i <= end; i++) {
294 if (abs(channel - i) > 2)
295 ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
296 }
297 bcm43xx_radio_selectchannel(bcm, channel, 0);
298 bcm43xx_phy_write(bcm, 0x0802,
299 (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
300 bcm43xx_phy_write(bcm, 0x0403,
301 bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
302 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
303 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
304 bcm43xx_set_original_gains(bcm);
305 for (i = 0; i < 13; i++) {
306 if (!ret[i])
307 continue;
308 end = (i + 5 < 13) ? i + 5 : 13;
309 for (j = i; j < end; j++)
310 ret[j] = 1;
311 }
312 bcm43xx_radio_unlock(bcm);
313 bcm43xx_phy_unlock(bcm, phylock_flags);
314
315 return ret[channel - 1];
316}
317
318/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
319void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
320{
321 bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
322 mmiowb();
323 bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
324}
325
326/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
327s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
328{
329 u16 val;
330
331 bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
332 val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
333
334 return (s16)val;
335}
336
337/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
338void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
339{
340 u16 i;
341 s16 tmp;
342
343 for (i = 0; i < 64; i++) {
344 tmp = bcm43xx_nrssi_hw_read(bcm, i);
345 tmp -= val;
346 tmp = limit_value(tmp, -32, 31);
347 bcm43xx_nrssi_hw_write(bcm, i, tmp);
348 }
349}
350
351/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
352void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
353{
354 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
355 s16 i, delta;
356 s32 tmp;
357
358 delta = 0x1F - radio->nrssi[0];
359 for (i = 0; i < 64; i++) {
360 tmp = (i - delta) * radio->nrssislope;
361 tmp /= 0x10000;
362 tmp += 0x3A;
363 tmp = limit_value(tmp, 0, 0x3F);
364 radio->nrssi_lt[i] = tmp;
365 }
366}
367
368static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
369{
370 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
371 u16 backup[20] = { 0 };
372 s16 v47F;
373 u16 i;
374 u16 saved = 0xFFFF;
375
376 backup[0] = bcm43xx_phy_read(bcm, 0x0001);
377 backup[1] = bcm43xx_phy_read(bcm, 0x0811);
378 backup[2] = bcm43xx_phy_read(bcm, 0x0812);
379 backup[3] = bcm43xx_phy_read(bcm, 0x0814);
380 backup[4] = bcm43xx_phy_read(bcm, 0x0815);
381 backup[5] = bcm43xx_phy_read(bcm, 0x005A);
382 backup[6] = bcm43xx_phy_read(bcm, 0x0059);
383 backup[7] = bcm43xx_phy_read(bcm, 0x0058);
384 backup[8] = bcm43xx_phy_read(bcm, 0x000A);
385 backup[9] = bcm43xx_phy_read(bcm, 0x0003);
386 backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
387 backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
388
389 bcm43xx_phy_write(bcm, 0x0429,
390 bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
391 bcm43xx_phy_write(bcm, 0x0001,
392 (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
393 bcm43xx_phy_write(bcm, 0x0811,
394 bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
395 bcm43xx_phy_write(bcm, 0x0812,
396 (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
397 bcm43xx_phy_write(bcm, 0x0802,
398 bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
399 if (phy->rev >= 6) {
400 backup[12] = bcm43xx_phy_read(bcm, 0x002E);
401 backup[13] = bcm43xx_phy_read(bcm, 0x002F);
402 backup[14] = bcm43xx_phy_read(bcm, 0x080F);
403 backup[15] = bcm43xx_phy_read(bcm, 0x0810);
404 backup[16] = bcm43xx_phy_read(bcm, 0x0801);
405 backup[17] = bcm43xx_phy_read(bcm, 0x0060);
406 backup[18] = bcm43xx_phy_read(bcm, 0x0014);
407 backup[19] = bcm43xx_phy_read(bcm, 0x0478);
408
409 bcm43xx_phy_write(bcm, 0x002E, 0);
410 bcm43xx_phy_write(bcm, 0x002F, 0);
411 bcm43xx_phy_write(bcm, 0x080F, 0);
412 bcm43xx_phy_write(bcm, 0x0810, 0);
413 bcm43xx_phy_write(bcm, 0x0478,
414 bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
415 bcm43xx_phy_write(bcm, 0x0801,
416 bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
417 bcm43xx_phy_write(bcm, 0x0060,
418 bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
419 bcm43xx_phy_write(bcm, 0x0014,
420 bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
421 }
422 bcm43xx_radio_write16(bcm, 0x007A,
423 bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
424 bcm43xx_radio_write16(bcm, 0x007A,
425 bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
426 udelay(30);
427
428 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
429 if (v47F >= 0x20)
430 v47F -= 0x40;
431 if (v47F == 31) {
432 for (i = 7; i >= 4; i--) {
433 bcm43xx_radio_write16(bcm, 0x007B, i);
434 udelay(20);
435 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
436 if (v47F >= 0x20)
437 v47F -= 0x40;
438 if (v47F < 31 && saved == 0xFFFF)
439 saved = i;
440 }
441 if (saved == 0xFFFF)
442 saved = 4;
443 } else {
444 bcm43xx_radio_write16(bcm, 0x007A,
445 bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
446 bcm43xx_phy_write(bcm, 0x0814,
447 bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
448 bcm43xx_phy_write(bcm, 0x0815,
449 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
450 bcm43xx_phy_write(bcm, 0x0811,
451 bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
452 bcm43xx_phy_write(bcm, 0x0812,
453 bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
454 bcm43xx_phy_write(bcm, 0x0811,
455 bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
456 bcm43xx_phy_write(bcm, 0x0812,
457 bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
458 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
459 bcm43xx_phy_write(bcm, 0x0059, 0x0810);
460 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
461 if (phy->analog == 0) {
462 bcm43xx_phy_write(bcm, 0x0003, 0x0122);
463 } else {
464 bcm43xx_phy_write(bcm, 0x000A,
465 bcm43xx_phy_read(bcm, 0x000A)
466 | 0x2000);
467 }
468 bcm43xx_phy_write(bcm, 0x0814,
469 bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
470 bcm43xx_phy_write(bcm, 0x0815,
471 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
472 bcm43xx_phy_write(bcm, 0x0003,
473 (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
474 | 0x0040);
475 bcm43xx_radio_write16(bcm, 0x007A,
476 bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
477 bcm43xx_set_all_gains(bcm, 3, 0, 1);
478 bcm43xx_radio_write16(bcm, 0x0043,
479 (bcm43xx_radio_read16(bcm, 0x0043)
480 & 0x00F0) | 0x000F);
481 udelay(30);
482 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
483 if (v47F >= 0x20)
484 v47F -= 0x40;
485 if (v47F == -32) {
486 for (i = 0; i < 4; i++) {
487 bcm43xx_radio_write16(bcm, 0x007B, i);
488 udelay(20);
489 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
490 if (v47F >= 0x20)
491 v47F -= 0x40;
492 if (v47F > -31 && saved == 0xFFFF)
493 saved = i;
494 }
495 if (saved == 0xFFFF)
496 saved = 3;
497 } else
498 saved = 0;
499 }
500 bcm43xx_radio_write16(bcm, 0x007B, saved);
501
502 if (phy->rev >= 6) {
503 bcm43xx_phy_write(bcm, 0x002E, backup[12]);
504 bcm43xx_phy_write(bcm, 0x002F, backup[13]);
505 bcm43xx_phy_write(bcm, 0x080F, backup[14]);
506 bcm43xx_phy_write(bcm, 0x0810, backup[15]);
507 }
508 bcm43xx_phy_write(bcm, 0x0814, backup[3]);
509 bcm43xx_phy_write(bcm, 0x0815, backup[4]);
510 bcm43xx_phy_write(bcm, 0x005A, backup[5]);
511 bcm43xx_phy_write(bcm, 0x0059, backup[6]);
512 bcm43xx_phy_write(bcm, 0x0058, backup[7]);
513 bcm43xx_phy_write(bcm, 0x000A, backup[8]);
514 bcm43xx_phy_write(bcm, 0x0003, backup[9]);
515 bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
516 bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
517 bcm43xx_phy_write(bcm, 0x0802,
518 bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
519 bcm43xx_phy_write(bcm, 0x0429,
520 bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
521 bcm43xx_set_original_gains(bcm);
522 if (phy->rev >= 6) {
523 bcm43xx_phy_write(bcm, 0x0801, backup[16]);
524 bcm43xx_phy_write(bcm, 0x0060, backup[17]);
525 bcm43xx_phy_write(bcm, 0x0014, backup[18]);
526 bcm43xx_phy_write(bcm, 0x0478, backup[19]);
527 }
528 bcm43xx_phy_write(bcm, 0x0001, backup[0]);
529 bcm43xx_phy_write(bcm, 0x0812, backup[2]);
530 bcm43xx_phy_write(bcm, 0x0811, backup[1]);
531}
532
533void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
534{
535 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
536 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
537 u16 backup[18] = { 0 };
538 u16 tmp;
539 s16 nrssi0, nrssi1;
540
541 switch (phy->type) {
542 case BCM43xx_PHYTYPE_B:
543 backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
544 backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
545 backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
546 backup[3] = bcm43xx_phy_read(bcm, 0x0030);
547 backup[4] = bcm43xx_phy_read(bcm, 0x0026);
548 backup[5] = bcm43xx_phy_read(bcm, 0x0015);
549 backup[6] = bcm43xx_phy_read(bcm, 0x002A);
550 backup[7] = bcm43xx_phy_read(bcm, 0x0020);
551 backup[8] = bcm43xx_phy_read(bcm, 0x005A);
552 backup[9] = bcm43xx_phy_read(bcm, 0x0059);
553 backup[10] = bcm43xx_phy_read(bcm, 0x0058);
554 backup[11] = bcm43xx_read16(bcm, 0x03E2);
555 backup[12] = bcm43xx_read16(bcm, 0x03E6);
556 backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
557
558 tmp = bcm43xx_radio_read16(bcm, 0x007A);
559 tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
560 bcm43xx_radio_write16(bcm, 0x007A, tmp);
561 bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
562 bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
563 bcm43xx_phy_write(bcm, 0x0026, 0x0000);
564 bcm43xx_phy_write(bcm, 0x0015,
565 bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
566 bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
567 bcm43xx_radio_write16(bcm, 0x007A,
568 bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
569
570 nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
571 bcm43xx_radio_write16(bcm, 0x007A,
572 bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
573 if (phy->analog >= 2) {
574 bcm43xx_write16(bcm, 0x03E6, 0x0040);
575 } else if (phy->analog == 0) {
576 bcm43xx_write16(bcm, 0x03E6, 0x0122);
577 } else {
578 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
579 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
580 }
581 bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
582 bcm43xx_phy_write(bcm, 0x0015, 0xF330);
583 bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
584 bcm43xx_radio_write16(bcm, 0x0043,
585 bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
586 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
587 bcm43xx_phy_write(bcm, 0x0059, 0x0810);
588 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
589 udelay(20);
590
591 nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
592 bcm43xx_phy_write(bcm, 0x0030, backup[3]);
593 bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
594 bcm43xx_write16(bcm, 0x03E2, backup[11]);
595 bcm43xx_phy_write(bcm, 0x0026, backup[4]);
596 bcm43xx_phy_write(bcm, 0x0015, backup[5]);
597 bcm43xx_phy_write(bcm, 0x002A, backup[6]);
598 bcm43xx_synth_pu_workaround(bcm, radio->channel);
599 if (phy->analog != 0)
600 bcm43xx_write16(bcm, 0x03F4, backup[13]);
601
602 bcm43xx_phy_write(bcm, 0x0020, backup[7]);
603 bcm43xx_phy_write(bcm, 0x005A, backup[8]);
604 bcm43xx_phy_write(bcm, 0x0059, backup[9]);
605 bcm43xx_phy_write(bcm, 0x0058, backup[10]);
606 bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
607 bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
608
609 if (nrssi0 == nrssi1)
610 radio->nrssislope = 0x00010000;
611 else
612 radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
613
614 if (nrssi0 <= -4) {
615 radio->nrssi[0] = nrssi0;
616 radio->nrssi[1] = nrssi1;
617 }
618 break;
619 case BCM43xx_PHYTYPE_G:
620 if (radio->revision >= 9)
621 return;
622 if (radio->revision == 8)
623 bcm43xx_calc_nrssi_offset(bcm);
624
625 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
626 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
627 bcm43xx_phy_write(bcm, 0x0802,
628 bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
629 backup[7] = bcm43xx_read16(bcm, 0x03E2);
630 bcm43xx_write16(bcm, 0x03E2,
631 bcm43xx_read16(bcm, 0x03E2) | 0x8000);
632 backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
633 backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
634 backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
635 backup[3] = bcm43xx_phy_read(bcm, 0x0015);
636 backup[4] = bcm43xx_phy_read(bcm, 0x005A);
637 backup[5] = bcm43xx_phy_read(bcm, 0x0059);
638 backup[6] = bcm43xx_phy_read(bcm, 0x0058);
639 backup[8] = bcm43xx_read16(bcm, 0x03E6);
640 backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
641 if (phy->rev >= 3) {
642 backup[10] = bcm43xx_phy_read(bcm, 0x002E);
643 backup[11] = bcm43xx_phy_read(bcm, 0x002F);
644 backup[12] = bcm43xx_phy_read(bcm, 0x080F);
645 backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
646 backup[14] = bcm43xx_phy_read(bcm, 0x0801);
647 backup[15] = bcm43xx_phy_read(bcm, 0x0060);
648 backup[16] = bcm43xx_phy_read(bcm, 0x0014);
649 backup[17] = bcm43xx_phy_read(bcm, 0x0478);
650 bcm43xx_phy_write(bcm, 0x002E, 0);
651 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
652 switch (phy->rev) {
653 case 4: case 6: case 7:
654 bcm43xx_phy_write(bcm, 0x0478,
655 bcm43xx_phy_read(bcm, 0x0478)
656 | 0x0100);
657 bcm43xx_phy_write(bcm, 0x0801,
658 bcm43xx_phy_read(bcm, 0x0801)
659 | 0x0040);
660 break;
661 case 3: case 5:
662 bcm43xx_phy_write(bcm, 0x0801,
663 bcm43xx_phy_read(bcm, 0x0801)
664 & 0xFFBF);
665 break;
666 }
667 bcm43xx_phy_write(bcm, 0x0060,
668 bcm43xx_phy_read(bcm, 0x0060)
669 | 0x0040);
670 bcm43xx_phy_write(bcm, 0x0014,
671 bcm43xx_phy_read(bcm, 0x0014)
672 | 0x0200);
673 }
674 bcm43xx_radio_write16(bcm, 0x007A,
675 bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
676 bcm43xx_set_all_gains(bcm, 0, 8, 0);
677 bcm43xx_radio_write16(bcm, 0x007A,
678 bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
679 if (phy->rev >= 2) {
680 bcm43xx_phy_write(bcm, 0x0811,
681 (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
682 bcm43xx_phy_write(bcm, 0x0812,
683 (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
684 }
685 bcm43xx_radio_write16(bcm, 0x007A,
686 bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
687 udelay(20);
688
689 nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
690 if (nrssi0 >= 0x0020)
691 nrssi0 -= 0x0040;
692
693 bcm43xx_radio_write16(bcm, 0x007A,
694 bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
695 if (phy->analog >= 2) {
696 bcm43xx_phy_write(bcm, 0x0003,
697 (bcm43xx_phy_read(bcm, 0x0003)
698 & 0xFF9F) | 0x0040);
699 }
700
701 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
702 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
703 | 0x2000);
704 bcm43xx_radio_write16(bcm, 0x007A,
705 bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
706 bcm43xx_phy_write(bcm, 0x0015, 0xF330);
707 if (phy->rev >= 2) {
708 bcm43xx_phy_write(bcm, 0x0812,
709 (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
710 bcm43xx_phy_write(bcm, 0x0811,
711 (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
712 }
713
714 bcm43xx_set_all_gains(bcm, 3, 0, 1);
715 if (radio->revision == 8) {
716 bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
717 } else {
718 tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
719 bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
720 tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
721 bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
722 }
723 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
724 bcm43xx_phy_write(bcm, 0x0059, 0x0810);
725 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
726 udelay(20);
727 nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
728 if (nrssi1 >= 0x0020)
729 nrssi1 -= 0x0040;
730 if (nrssi0 == nrssi1)
731 radio->nrssislope = 0x00010000;
732 else
733 radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
734 if (nrssi0 >= -4) {
735 radio->nrssi[0] = nrssi1;
736 radio->nrssi[1] = nrssi0;
737 }
738 if (phy->rev >= 3) {
739 bcm43xx_phy_write(bcm, 0x002E, backup[10]);
740 bcm43xx_phy_write(bcm, 0x002F, backup[11]);
741 bcm43xx_phy_write(bcm, 0x080F, backup[12]);
742 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
743 }
744 if (phy->rev >= 2) {
745 bcm43xx_phy_write(bcm, 0x0812,
746 bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
747 bcm43xx_phy_write(bcm, 0x0811,
748 bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
749 }
750
751 bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
752 bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
753 bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
754 bcm43xx_write16(bcm, 0x03E2, backup[7]);
755 bcm43xx_write16(bcm, 0x03E6, backup[8]);
756 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
757 bcm43xx_phy_write(bcm, 0x0015, backup[3]);
758 bcm43xx_phy_write(bcm, 0x005A, backup[4]);
759 bcm43xx_phy_write(bcm, 0x0059, backup[5]);
760 bcm43xx_phy_write(bcm, 0x0058, backup[6]);
761 bcm43xx_synth_pu_workaround(bcm, radio->channel);
762 bcm43xx_phy_write(bcm, 0x0802,
763 bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
764 bcm43xx_set_original_gains(bcm);
765 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
766 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
767 if (phy->rev >= 3) {
768 bcm43xx_phy_write(bcm, 0x0801, backup[14]);
769 bcm43xx_phy_write(bcm, 0x0060, backup[15]);
770 bcm43xx_phy_write(bcm, 0x0014, backup[16]);
771 bcm43xx_phy_write(bcm, 0x0478, backup[17]);
772 }
773 bcm43xx_nrssi_mem_update(bcm);
774 bcm43xx_calc_nrssi_threshold(bcm);
775 break;
776 default:
777 assert(0);
778 }
779}
780
781void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
782{
783 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
784 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
785 s32 threshold;
786 s32 a, b;
787 s16 tmp16;
788 u16 tmp_u16;
789
790 switch (phy->type) {
791 case BCM43xx_PHYTYPE_B: {
792 if (radio->version != 0x2050)
793 return;
794 if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
795 return;
796
797 if (radio->revision >= 6) {
798 threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
799 threshold += 20 * (radio->nrssi[0] + 1);
800 threshold /= 40;
801 } else
802 threshold = radio->nrssi[1] - 5;
803
804 threshold = limit_value(threshold, 0, 0x3E);
805 bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
806 bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
807
808 if (radio->revision >= 6) {
809 bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
810 bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
811 bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
812 bcm43xx_phy_write(bcm, 0x0084, 0x0808);
813 bcm43xx_phy_write(bcm, 0x0083, 0x0808);
814 bcm43xx_phy_write(bcm, 0x0082, 0x0604);
815 bcm43xx_phy_write(bcm, 0x0081, 0x0302);
816 bcm43xx_phy_write(bcm, 0x0080, 0x0100);
817 }
818 break;
819 }
820 case BCM43xx_PHYTYPE_G:
821 if (!phy->connected ||
822 !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
823 tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
824 if (tmp16 >= 0x20)
825 tmp16 -= 0x40;
826 if (tmp16 < 3) {
827 bcm43xx_phy_write(bcm, 0x048A,
828 (bcm43xx_phy_read(bcm, 0x048A)
829 & 0xF000) | 0x09EB);
830 } else {
831 bcm43xx_phy_write(bcm, 0x048A,
832 (bcm43xx_phy_read(bcm, 0x048A)
833 & 0xF000) | 0x0AED);
834 }
835 } else {
836 if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
837 a = 0xE;
838 b = 0xA;
839 } else if (!radio->aci_wlan_automatic && radio->aci_enable) {
840 a = 0x13;
841 b = 0x12;
842 } else {
843 a = 0xE;
844 b = 0x11;
845 }
846
847 a = a * (radio->nrssi[1] - radio->nrssi[0]);
848 a += (radio->nrssi[0] << 6);
849 if (a < 32)
850 a += 31;
851 else
852 a += 32;
853 a = a >> 6;
854 a = limit_value(a, -31, 31);
855
856 b = b * (radio->nrssi[1] - radio->nrssi[0]);
857 b += (radio->nrssi[0] << 6);
858 if (b < 32)
859 b += 31;
860 else
861 b += 32;
862 b = b >> 6;
863 b = limit_value(b, -31, 31);
864
865 tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
866 tmp_u16 |= ((u32)b & 0x0000003F);
867 tmp_u16 |= (((u32)a & 0x0000003F) << 6);
868 bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
869 }
870 break;
871 default:
872 assert(0);
873 }
874}
875
876/* Stack implementation to save/restore values from the
877 * interference mitigation code.
878 * It is save to restore values in random order.
879 */
880static void _stack_save(u32 *_stackptr, size_t *stackidx,
881 u8 id, u16 offset, u16 value)
882{
883 u32 *stackptr = &(_stackptr[*stackidx]);
884
885 assert((offset & 0xE000) == 0x0000);
886 assert((id & 0xF8) == 0x00);
887 *stackptr = offset;
888 *stackptr |= ((u32)id) << 13;
889 *stackptr |= ((u32)value) << 16;
890 (*stackidx)++;
891 assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
892}
893
894static u16 _stack_restore(u32 *stackptr,
895 u8 id, u16 offset)
896{
897 size_t i;
898
899 assert((offset & 0xE000) == 0x0000);
900 assert((id & 0xF8) == 0x00);
901 for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
902 if ((*stackptr & 0x00001FFF) != offset)
903 continue;
904 if (((*stackptr & 0x00007000) >> 13) != id)
905 continue;
906 return ((*stackptr & 0xFFFF0000) >> 16);
907 }
908 assert(0);
909
910 return 0;
911}
912
913#define phy_stacksave(offset) \
914 do { \
915 _stack_save(stack, &stackidx, 0x1, (offset), \
916 bcm43xx_phy_read(bcm, (offset))); \
917 } while (0)
918#define phy_stackrestore(offset) \
919 do { \
920 bcm43xx_phy_write(bcm, (offset), \
921 _stack_restore(stack, 0x1, \
922 (offset))); \
923 } while (0)
924#define radio_stacksave(offset) \
925 do { \
926 _stack_save(stack, &stackidx, 0x2, (offset), \
927 bcm43xx_radio_read16(bcm, (offset))); \
928 } while (0)
929#define radio_stackrestore(offset) \
930 do { \
931 bcm43xx_radio_write16(bcm, (offset), \
932 _stack_restore(stack, 0x2, \
933 (offset))); \
934 } while (0)
935#define ilt_stacksave(offset) \
936 do { \
937 _stack_save(stack, &stackidx, 0x3, (offset), \
938 bcm43xx_ilt_read(bcm, (offset))); \
939 } while (0)
940#define ilt_stackrestore(offset) \
941 do { \
942 bcm43xx_ilt_write(bcm, (offset), \
943 _stack_restore(stack, 0x3, \
944 (offset))); \
945 } while (0)
946
947static void
948bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
949 int mode)
950{
951 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
952 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
953 u16 tmp, flipped;
954 u32 tmp32;
955 size_t stackidx = 0;
956 u32 *stack = radio->interfstack;
957
958 switch (mode) {
959 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
960 if (phy->rev != 1) {
961 bcm43xx_phy_write(bcm, 0x042B,
962 bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
963 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
964 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
965 break;
966 }
967 radio_stacksave(0x0078);
968 tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
969 flipped = flip_4bit(tmp);
970 if (flipped < 10 && flipped >= 8)
971 flipped = 7;
972 else if (flipped >= 10)
973 flipped -= 3;
974 flipped = flip_4bit(flipped);
975 flipped = (flipped << 1) | 0x0020;
976 bcm43xx_radio_write16(bcm, 0x0078, flipped);
977
978 bcm43xx_calc_nrssi_threshold(bcm);
979
980 phy_stacksave(0x0406);
981 bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
982
983 bcm43xx_phy_write(bcm, 0x042B,
984 bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
985 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
986 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
987
988 phy_stacksave(0x04A0);
989 bcm43xx_phy_write(bcm, 0x04A0,
990 (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
991 phy_stacksave(0x04A1);
992 bcm43xx_phy_write(bcm, 0x04A1,
993 (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
994 phy_stacksave(0x04A2);
995 bcm43xx_phy_write(bcm, 0x04A2,
996 (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
997 phy_stacksave(0x04A8);
998 bcm43xx_phy_write(bcm, 0x04A8,
999 (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
1000 phy_stacksave(0x04AB);
1001 bcm43xx_phy_write(bcm, 0x04AB,
1002 (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
1003
1004 phy_stacksave(0x04A7);
1005 bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
1006 phy_stacksave(0x04A3);
1007 bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
1008 phy_stacksave(0x04A9);
1009 bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
1010 phy_stacksave(0x0493);
1011 bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
1012 phy_stacksave(0x04AA);
1013 bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
1014 phy_stacksave(0x04AC);
1015 bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
1016 break;
1017 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1018 if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
1019 break;
1020
1021 radio->aci_enable = 1;
1022
1023 phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
1024 phy_stacksave(BCM43xx_PHY_G_CRS);
1025 if (phy->rev < 2) {
1026 phy_stacksave(0x0406);
1027 } else {
1028 phy_stacksave(0x04C0);
1029 phy_stacksave(0x04C1);
1030 }
1031 phy_stacksave(0x0033);
1032 phy_stacksave(0x04A7);
1033 phy_stacksave(0x04A3);
1034 phy_stacksave(0x04A9);
1035 phy_stacksave(0x04AA);
1036 phy_stacksave(0x04AC);
1037 phy_stacksave(0x0493);
1038 phy_stacksave(0x04A1);
1039 phy_stacksave(0x04A0);
1040 phy_stacksave(0x04A2);
1041 phy_stacksave(0x048A);
1042 phy_stacksave(0x04A8);
1043 phy_stacksave(0x04AB);
1044 if (phy->rev == 2) {
1045 phy_stacksave(0x04AD);
1046 phy_stacksave(0x04AE);
1047 } else if (phy->rev >= 3) {
1048 phy_stacksave(0x04AD);
1049 phy_stacksave(0x0415);
1050 phy_stacksave(0x0416);
1051 phy_stacksave(0x0417);
1052 ilt_stacksave(0x1A00 + 0x2);
1053 ilt_stacksave(0x1A00 + 0x3);
1054 }
1055 phy_stacksave(0x042B);
1056 phy_stacksave(0x048C);
1057
1058 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
1059 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
1060 & ~0x1000);
1061 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1062 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
1063 & 0xFFFC) | 0x0002);
1064
1065 bcm43xx_phy_write(bcm, 0x0033, 0x0800);
1066 bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
1067 bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
1068 bcm43xx_phy_write(bcm, 0x0493, 0x287A);
1069 bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
1070 bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
1071
1072 bcm43xx_phy_write(bcm, 0x04A0,
1073 (bcm43xx_phy_read(bcm, 0x04A0)
1074 & 0xFFC0) | 0x001A);
1075 bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
1076
1077 if (phy->rev < 2) {
1078 bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
1079 } else if (phy->rev == 2) {
1080 bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
1081 bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
1082 } else {
1083 bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
1084 bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
1085 }
1086
1087 bcm43xx_phy_write(bcm, 0x04A1,
1088 (bcm43xx_phy_read(bcm, 0x04A1)
1089 & 0xC0FF) | 0x1800);
1090 bcm43xx_phy_write(bcm, 0x04A1,
1091 (bcm43xx_phy_read(bcm, 0x04A1)
1092 & 0xFFC0) | 0x0015);
1093 bcm43xx_phy_write(bcm, 0x04A8,
1094 (bcm43xx_phy_read(bcm, 0x04A8)
1095 & 0xCFFF) | 0x1000);
1096 bcm43xx_phy_write(bcm, 0x04A8,
1097 (bcm43xx_phy_read(bcm, 0x04A8)
1098 & 0xF0FF) | 0x0A00);
1099 bcm43xx_phy_write(bcm, 0x04AB,
1100 (bcm43xx_phy_read(bcm, 0x04AB)
1101 & 0xCFFF) | 0x1000);
1102 bcm43xx_phy_write(bcm, 0x04AB,
1103 (bcm43xx_phy_read(bcm, 0x04AB)
1104 & 0xF0FF) | 0x0800);
1105 bcm43xx_phy_write(bcm, 0x04AB,
1106 (bcm43xx_phy_read(bcm, 0x04AB)
1107 & 0xFFCF) | 0x0010);
1108 bcm43xx_phy_write(bcm, 0x04AB,
1109 (bcm43xx_phy_read(bcm, 0x04AB)
1110 & 0xFFF0) | 0x0005);
1111 bcm43xx_phy_write(bcm, 0x04A8,
1112 (bcm43xx_phy_read(bcm, 0x04A8)
1113 & 0xFFCF) | 0x0010);
1114 bcm43xx_phy_write(bcm, 0x04A8,
1115 (bcm43xx_phy_read(bcm, 0x04A8)
1116 & 0xFFF0) | 0x0006);
1117 bcm43xx_phy_write(bcm, 0x04A2,
1118 (bcm43xx_phy_read(bcm, 0x04A2)
1119 & 0xF0FF) | 0x0800);
1120 bcm43xx_phy_write(bcm, 0x04A0,
1121 (bcm43xx_phy_read(bcm, 0x04A0)
1122 & 0xF0FF) | 0x0500);
1123 bcm43xx_phy_write(bcm, 0x04A2,
1124 (bcm43xx_phy_read(bcm, 0x04A2)
1125 & 0xFFF0) | 0x000B);
1126
1127 if (phy->rev >= 3) {
1128 bcm43xx_phy_write(bcm, 0x048A,
1129 bcm43xx_phy_read(bcm, 0x048A)
1130 & ~0x8000);
1131 bcm43xx_phy_write(bcm, 0x0415,
1132 (bcm43xx_phy_read(bcm, 0x0415)
1133 & 0x8000) | 0x36D8);
1134 bcm43xx_phy_write(bcm, 0x0416,
1135 (bcm43xx_phy_read(bcm, 0x0416)
1136 & 0x8000) | 0x36D8);
1137 bcm43xx_phy_write(bcm, 0x0417,
1138 (bcm43xx_phy_read(bcm, 0x0417)
1139 & 0xFE00) | 0x016D);
1140 } else {
1141 bcm43xx_phy_write(bcm, 0x048A,
1142 bcm43xx_phy_read(bcm, 0x048A)
1143 | 0x1000);
1144 bcm43xx_phy_write(bcm, 0x048A,
1145 (bcm43xx_phy_read(bcm, 0x048A)
1146 & 0x9FFF) | 0x2000);
1147 tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1148 BCM43xx_UCODEFLAGS_OFFSET);
1149 if (!(tmp32 & 0x800)) {
1150 tmp32 |= 0x800;
1151 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1152 BCM43xx_UCODEFLAGS_OFFSET,
1153 tmp32);
1154 }
1155 }
1156 if (phy->rev >= 2) {
1157 bcm43xx_phy_write(bcm, 0x042B,
1158 bcm43xx_phy_read(bcm, 0x042B)
1159 | 0x0800);
1160 }
1161 bcm43xx_phy_write(bcm, 0x048C,
1162 (bcm43xx_phy_read(bcm, 0x048C)
1163 & 0xF0FF) | 0x0200);
1164 if (phy->rev == 2) {
1165 bcm43xx_phy_write(bcm, 0x04AE,
1166 (bcm43xx_phy_read(bcm, 0x04AE)
1167 & 0xFF00) | 0x007F);
1168 bcm43xx_phy_write(bcm, 0x04AD,
1169 (bcm43xx_phy_read(bcm, 0x04AD)
1170 & 0x00FF) | 0x1300);
1171 } else if (phy->rev >= 6) {
1172 bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
1173 bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
1174 bcm43xx_phy_write(bcm, 0x04AD,
1175 bcm43xx_phy_read(bcm, 0x04AD)
1176 & 0x00FF);
1177 }
1178 bcm43xx_calc_nrssi_slope(bcm);
1179 break;
1180 default:
1181 assert(0);
1182 }
1183}
1184
1185static void
1186bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
1187 int mode)
1188{
1189 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1190 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1191 u32 tmp32;
1192 u32 *stack = radio->interfstack;
1193
1194 switch (mode) {
1195 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
1196 if (phy->rev != 1) {
1197 bcm43xx_phy_write(bcm, 0x042B,
1198 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
1199 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1200 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
1201 break;
1202 }
1203 phy_stackrestore(0x0078);
1204 bcm43xx_calc_nrssi_threshold(bcm);
1205 phy_stackrestore(0x0406);
1206 bcm43xx_phy_write(bcm, 0x042B,
1207 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
1208 if (!bcm->bad_frames_preempt) {
1209 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
1210 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
1211 & ~(1 << 11));
1212 }
1213 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1214 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
1215 phy_stackrestore(0x04A0);
1216 phy_stackrestore(0x04A1);
1217 phy_stackrestore(0x04A2);
1218 phy_stackrestore(0x04A8);
1219 phy_stackrestore(0x04AB);
1220 phy_stackrestore(0x04A7);
1221 phy_stackrestore(0x04A3);
1222 phy_stackrestore(0x04A9);
1223 phy_stackrestore(0x0493);
1224 phy_stackrestore(0x04AA);
1225 phy_stackrestore(0x04AC);
1226 break;
1227 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1228 if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
1229 break;
1230
1231 radio->aci_enable = 0;
1232
1233 phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
1234 phy_stackrestore(BCM43xx_PHY_G_CRS);
1235 phy_stackrestore(0x0033);
1236 phy_stackrestore(0x04A3);
1237 phy_stackrestore(0x04A9);
1238 phy_stackrestore(0x0493);
1239 phy_stackrestore(0x04AA);
1240 phy_stackrestore(0x04AC);
1241 phy_stackrestore(0x04A0);
1242 phy_stackrestore(0x04A7);
1243 if (phy->rev >= 2) {
1244 phy_stackrestore(0x04C0);
1245 phy_stackrestore(0x04C1);
1246 } else
1247 phy_stackrestore(0x0406);
1248 phy_stackrestore(0x04A1);
1249 phy_stackrestore(0x04AB);
1250 phy_stackrestore(0x04A8);
1251 if (phy->rev == 2) {
1252 phy_stackrestore(0x04AD);
1253 phy_stackrestore(0x04AE);
1254 } else if (phy->rev >= 3) {
1255 phy_stackrestore(0x04AD);
1256 phy_stackrestore(0x0415);
1257 phy_stackrestore(0x0416);
1258 phy_stackrestore(0x0417);
1259 ilt_stackrestore(0x1A00 + 0x2);
1260 ilt_stackrestore(0x1A00 + 0x3);
1261 }
1262 phy_stackrestore(0x04A2);
1263 phy_stackrestore(0x04A8);
1264 phy_stackrestore(0x042B);
1265 phy_stackrestore(0x048C);
1266 tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1267 BCM43xx_UCODEFLAGS_OFFSET);
1268 if (tmp32 & 0x800) {
1269 tmp32 &= ~0x800;
1270 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1271 BCM43xx_UCODEFLAGS_OFFSET,
1272 tmp32);
1273 }
1274 bcm43xx_calc_nrssi_slope(bcm);
1275 break;
1276 default:
1277 assert(0);
1278 }
1279}
1280
1281#undef phy_stacksave
1282#undef phy_stackrestore
1283#undef radio_stacksave
1284#undef radio_stackrestore
1285#undef ilt_stacksave
1286#undef ilt_stackrestore
1287
1288int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
1289 int mode)
1290{
1291 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1292 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1293 int currentmode;
1294
1295 if ((phy->type != BCM43xx_PHYTYPE_G) ||
1296 (phy->rev == 0) ||
1297 (!phy->connected))
1298 return -ENODEV;
1299
1300 radio->aci_wlan_automatic = 0;
1301 switch (mode) {
1302 case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
1303 radio->aci_wlan_automatic = 1;
1304 if (radio->aci_enable)
1305 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
1306 else
1307 mode = BCM43xx_RADIO_INTERFMODE_NONE;
1308 break;
1309 case BCM43xx_RADIO_INTERFMODE_NONE:
1310 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
1311 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1312 break;
1313 default:
1314 return -EINVAL;
1315 }
1316
1317 currentmode = radio->interfmode;
1318 if (currentmode == mode)
1319 return 0;
1320 if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
1321 bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
1322
1323 if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
1324 radio->aci_enable = 0;
1325 radio->aci_hw_rssi = 0;
1326 } else
1327 bcm43xx_radio_interference_mitigation_enable(bcm, mode);
1328 radio->interfmode = mode;
1329
1330 return 0;
1331}
1332
1333u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
1334{
1335 u16 reg, index, ret;
1336
1337 reg = bcm43xx_radio_read16(bcm, 0x0060);
1338 index = (reg & 0x001E) >> 1;
1339 ret = rcc_table[index] << 1;
1340 ret |= (reg & 0x0001);
1341 ret |= 0x0020;
1342
1343 return ret;
1344}
1345
1346#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
1347static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd)
1348{
1349 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1350 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1351 u16 loop_or = 0;
1352 u16 adj_loopback_gain = phy->loopback_gain[0];
1353 u8 loop;
1354 u16 extern_lna_control;
1355
1356 if (!phy->connected)
1357 return 0;
1358 if (!has_loopback_gain(phy)) {
1359 if (phy->rev < 7 || !(bcm->sprom.boardflags
1360 & BCM43xx_BFL_EXTLNA)) {
1361 switch (lpd) {
1362 case LPD(0, 1, 1):
1363 return 0x0FB2;
1364 case LPD(0, 0, 1):
1365 return 0x00B2;
1366 case LPD(1, 0, 1):
1367 return 0x30B2;
1368 case LPD(1, 0, 0):
1369 return 0x30B3;
1370 default:
1371 assert(0);
1372 }
1373 } else {
1374 switch (lpd) {
1375 case LPD(0, 1, 1):
1376 return 0x8FB2;
1377 case LPD(0, 0, 1):
1378 return 0x80B2;
1379 case LPD(1, 0, 1):
1380 return 0x20B2;
1381 case LPD(1, 0, 0):
1382 return 0x20B3;
1383 default:
1384 assert(0);
1385 }
1386 }
1387 } else {
1388 if (radio->revision == 8)
1389 adj_loopback_gain += 0x003E;
1390 else
1391 adj_loopback_gain += 0x0026;
1392 if (adj_loopback_gain >= 0x46) {
1393 adj_loopback_gain -= 0x46;
1394 extern_lna_control = 0x3000;
1395 } else if (adj_loopback_gain >= 0x3A) {
1396 adj_loopback_gain -= 0x3A;
1397 extern_lna_control = 0x2000;
1398 } else if (adj_loopback_gain >= 0x2E) {
1399 adj_loopback_gain -= 0x2E;
1400 extern_lna_control = 0x1000;
1401 } else {
1402 adj_loopback_gain -= 0x10;
1403 extern_lna_control = 0x0000;
1404 }
1405 for (loop = 0; loop < 16; loop++) {
1406 u16 tmp = adj_loopback_gain - 6 * loop;
1407 if (tmp < 6)
1408 break;
1409 }
1410
1411 loop_or = (loop << 8) | extern_lna_control;
1412 if (phy->rev >= 7 && bcm->sprom.boardflags
1413 & BCM43xx_BFL_EXTLNA) {
1414 if (extern_lna_control)
1415 loop_or |= 0x8000;
1416 switch (lpd) {
1417 case LPD(0, 1, 1):
1418 return 0x8F92;
1419 case LPD(0, 0, 1):
1420 return (0x8092 | loop_or);
1421 case LPD(1, 0, 1):
1422 return (0x2092 | loop_or);
1423 case LPD(1, 0, 0):
1424 return (0x2093 | loop_or);
1425 default:
1426 assert(0);
1427 }
1428 } else {
1429 switch (lpd) {
1430 case LPD(0, 1, 1):
1431 return 0x0F92;
1432 case LPD(0, 0, 1):
1433 case LPD(1, 0, 1):
1434 return (0x0092 | loop_or);
1435 case LPD(1, 0, 0):
1436 return (0x0093 | loop_or);
1437 default:
1438 assert(0);
1439 }
1440 }
1441 }
1442 return 0;
1443}
1444
1445u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
1446{
1447 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1448 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1449 u16 backup[21] = { 0 };
1450 u16 ret;
1451 u16 i, j;
1452 u32 tmp1 = 0, tmp2 = 0;
1453
1454 backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
1455 backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
1456 backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
1457 backup[1] = bcm43xx_phy_read(bcm, 0x0015);
1458 backup[16] = bcm43xx_phy_read(bcm, 0x005A);
1459 backup[17] = bcm43xx_phy_read(bcm, 0x0059);
1460 backup[18] = bcm43xx_phy_read(bcm, 0x0058);
1461 if (phy->type == BCM43xx_PHYTYPE_B) {
1462 backup[2] = bcm43xx_phy_read(bcm, 0x0030);
1463 backup[3] = bcm43xx_read16(bcm, 0x03EC);
1464 bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
1465 bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
1466 } else {
1467 if (phy->connected) {
1468 backup[4] = bcm43xx_phy_read(bcm, 0x0811);
1469 backup[5] = bcm43xx_phy_read(bcm, 0x0812);
1470 backup[6] = bcm43xx_phy_read(bcm, 0x0814);
1471 backup[7] = bcm43xx_phy_read(bcm, 0x0815);
1472 backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
1473 backup[9] = bcm43xx_phy_read(bcm, 0x0802);
1474 bcm43xx_phy_write(bcm, 0x0814,
1475 (bcm43xx_phy_read(bcm, 0x0814)
1476 | 0x0003));
1477 bcm43xx_phy_write(bcm, 0x0815,
1478 (bcm43xx_phy_read(bcm, 0x0815)
1479 & 0xFFFC));
1480 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1481 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
1482 & 0x7FFF));
1483 bcm43xx_phy_write(bcm, 0x0802,
1484 (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
1485 if (phy->rev > 1) { /* loopback gain enabled */
1486 backup[19] = bcm43xx_phy_read(bcm, 0x080F);
1487 backup[20] = bcm43xx_phy_read(bcm, 0x0810);
1488 if (phy->rev >= 3)
1489 bcm43xx_phy_write(bcm, 0x080F, 0xC020);
1490 else
1491 bcm43xx_phy_write(bcm, 0x080F, 0x8020);
1492 bcm43xx_phy_write(bcm, 0x0810, 0x0000);
1493 }
1494 bcm43xx_phy_write(bcm, 0x0812,
1495 bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
1496 if (phy->rev < 7 || !(bcm->sprom.boardflags
1497 & BCM43xx_BFL_EXTLNA))
1498 bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
1499 else
1500 bcm43xx_phy_write(bcm, 0x0811, 0x09B3);
1501 }
1502 }
1503 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
1504 (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
1505 backup[10] = bcm43xx_phy_read(bcm, 0x0035);
1506 bcm43xx_phy_write(bcm, 0x0035,
1507 (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
1508 backup[11] = bcm43xx_read16(bcm, 0x03E6);
1509 backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
1510
1511 // Initialization
1512 if (phy->analog == 0) {
1513 bcm43xx_write16(bcm, 0x03E6, 0x0122);
1514 } else {
1515 if (phy->analog >= 2)
1516 bcm43xx_phy_write(bcm, 0x0003,
1517 (bcm43xx_phy_read(bcm, 0x0003)
1518 & 0xFFBF) | 0x0040);
1519 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
1520 (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
1521 | 0x2000));
1522 }
1523
1524 ret = bcm43xx_radio_calibrationvalue(bcm);
1525
1526 if (phy->type == BCM43xx_PHYTYPE_B)
1527 bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
1528
1529 if (phy->connected)
1530 bcm43xx_phy_write(bcm, 0x0812,
1531 bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
1532 bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
1533 bcm43xx_phy_write(bcm, 0x002B, 0x1403);
1534 if (phy->connected)
1535 bcm43xx_phy_write(bcm, 0x0812,
1536 bcm43xx_get_812_value(bcm, LPD(0, 0, 1)));
1537 bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
1538 bcm43xx_radio_write16(bcm, 0x0051,
1539 (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
1540 if (radio->revision == 8)
1541 bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
1542 else {
1543 bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
1544 bcm43xx_radio_write16(bcm, 0x0043,
1545 (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0)
1546 | 0x0009);
1547 }
1548 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1549
1550 for (i = 0; i < 16; i++) {
1551 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
1552 bcm43xx_phy_write(bcm, 0x0059, 0xC810);
1553 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
1554 if (phy->connected)
1555 bcm43xx_phy_write(bcm, 0x0812,
1556 bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
1557 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1558 udelay(10);
1559 if (phy->connected)
1560 bcm43xx_phy_write(bcm, 0x0812,
1561 bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
1562 bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
1563 udelay(10);
1564 if (phy->connected)
1565 bcm43xx_phy_write(bcm, 0x0812,
1566 bcm43xx_get_812_value(bcm, LPD(1, 0, 0)));
1567 bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
1568 udelay(20);
1569 tmp1 += bcm43xx_phy_read(bcm, 0x002D);
1570 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1571 if (phy->connected)
1572 bcm43xx_phy_write(bcm, 0x0812,
1573 bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
1574 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1575 }
1576
1577 tmp1++;
1578 tmp1 >>= 9;
1579 udelay(10);
1580 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1581
1582 for (i = 0; i < 16; i++) {
1583 bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
1584 backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
1585 udelay(10);
1586 for (j = 0; j < 16; j++) {
1587 bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
1588 bcm43xx_phy_write(bcm, 0x0059, 0xC810);
1589 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
1590 if (phy->connected)
1591 bcm43xx_phy_write(bcm, 0x0812,
1592 bcm43xx_get_812_value(bcm,
1593 LPD(1, 0, 1)));
1594 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1595 udelay(10);
1596 if (phy->connected)
1597 bcm43xx_phy_write(bcm, 0x0812,
1598 bcm43xx_get_812_value(bcm,
1599 LPD(1, 0, 1)));
1600 bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
1601 udelay(10);
1602 if (phy->connected)
1603 bcm43xx_phy_write(bcm, 0x0812,
1604 bcm43xx_get_812_value(bcm,
1605 LPD(1, 0, 0)));
1606 bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
1607 udelay(10);
1608 tmp2 += bcm43xx_phy_read(bcm, 0x002D);
1609 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1610 if (phy->connected)
1611 bcm43xx_phy_write(bcm, 0x0812,
1612 bcm43xx_get_812_value(bcm,
1613 LPD(1, 0, 1)));
1614 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1615 }
1616 tmp2++;
1617 tmp2 >>= 8;
1618 if (tmp1 < tmp2)
1619 break;
1620 }
1621
1622 /* Restore the registers */
1623 bcm43xx_phy_write(bcm, 0x0015, backup[1]);
1624 bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
1625 bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
1626 bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
1627 bcm43xx_phy_write(bcm, 0x005A, backup[16]);
1628 bcm43xx_phy_write(bcm, 0x0059, backup[17]);
1629 bcm43xx_phy_write(bcm, 0x0058, backup[18]);
1630 bcm43xx_write16(bcm, 0x03E6, backup[11]);
1631 if (phy->analog != 0)
1632 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
1633 bcm43xx_phy_write(bcm, 0x0035, backup[10]);
1634 bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
1635 if (phy->type == BCM43xx_PHYTYPE_B) {
1636 bcm43xx_phy_write(bcm, 0x0030, backup[2]);
1637 bcm43xx_write16(bcm, 0x03EC, backup[3]);
1638 } else {
1639 if (phy->connected) {
1640 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
1641 (bcm43xx_read16(bcm,
1642 BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
1643 bcm43xx_phy_write(bcm, 0x0811, backup[4]);
1644 bcm43xx_phy_write(bcm, 0x0812, backup[5]);
1645 bcm43xx_phy_write(bcm, 0x0814, backup[6]);
1646 bcm43xx_phy_write(bcm, 0x0815, backup[7]);
1647 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
1648 bcm43xx_phy_write(bcm, 0x0802, backup[9]);
1649 if (phy->rev > 1) {
1650 bcm43xx_phy_write(bcm, 0x080F, backup[19]);
1651 bcm43xx_phy_write(bcm, 0x0810, backup[20]);
1652 }
1653 }
1654 }
1655 if (i >= 15)
1656 ret = backup[13];
1657
1658 return ret;
1659}
1660
1661void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
1662{
1663 int err;
1664
1665 bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
1666 bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
1667 bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
1668 bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
1669 bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
1670 bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
1671 bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
1672 bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
1673 bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
1674 bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
1675 bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
1676 bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
1677 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
1678 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
1679 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
1680 udelay(400);
1681
1682 bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
1683 udelay(400);
1684
1685 bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
1686 bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
1687 bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
1688 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
1689 bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
1690 bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
1691 bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
1692 bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
1693 bcm43xx_phy_write(bcm, 0x006A, 0x0000);
1694
1695 err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
1696 assert(err == 0);
1697 udelay(1000);
1698}
1699
1700static inline
1701u16 freq_r3A_value(u16 frequency)
1702{
1703 u16 value;
1704
1705 if (frequency < 5091)
1706 value = 0x0040;
1707 else if (frequency < 5321)
1708 value = 0x0000;
1709 else if (frequency < 5806)
1710 value = 0x0080;
1711 else
1712 value = 0x0040;
1713
1714 return value;
1715}
1716
1717void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
1718{
1719 static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
1720 static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
1721 u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
1722 int i, j;
1723
1724 for (i = 0; i < 5; i++) {
1725 for (j = 0; j < 5; j++) {
1726 if (tmp == (data_high[i] | data_low[j])) {
1727 bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
1728 return;
1729 }
1730 }
1731 }
1732}
1733
1734int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
1735 u8 channel,
1736 int synthetic_pu_workaround)
1737{
1738 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1739 u16 r8, tmp;
1740 u16 freq;
1741
1742 if (!ieee80211_is_valid_channel(bcm->ieee, channel))
1743 return -EINVAL;
1744 if ((radio->manufact == 0x17F) &&
1745 (radio->version == 0x2060) &&
1746 (radio->revision == 1)) {
1747 freq = channel2freq_a(channel);
1748
1749 r8 = bcm43xx_radio_read16(bcm, 0x0008);
1750 bcm43xx_write16(bcm, 0x03F0, freq);
1751 bcm43xx_radio_write16(bcm, 0x0008, r8);
1752
1753 TODO();//TODO: write max channel TX power? to Radio 0x2D
1754 tmp = bcm43xx_radio_read16(bcm, 0x002E);
1755 tmp &= 0x0080;
1756 TODO();//TODO: OR tmp with the Power out estimation for this channel?
1757 bcm43xx_radio_write16(bcm, 0x002E, tmp);
1758
1759 if (freq >= 4920 && freq <= 5500) {
1760 /*
1761 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
1762 * = (freq * 0.025862069
1763 */
1764 r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
1765 }
1766 bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
1767 bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
1768 bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
1769 bcm43xx_radio_write16(bcm, 0x0022,
1770 (bcm43xx_radio_read16(bcm, 0x0022)
1771 & 0x000F) | (r8 << 4));
1772 bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
1773 bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
1774 bcm43xx_radio_write16(bcm, 0x0008,
1775 (bcm43xx_radio_read16(bcm, 0x0008)
1776 & 0x00F0) | (r8 << 4));
1777 bcm43xx_radio_write16(bcm, 0x0029,
1778 (bcm43xx_radio_read16(bcm, 0x0029)
1779 & 0xFF0F) | 0x00B0);
1780 bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
1781 bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
1782 bcm43xx_radio_write16(bcm, 0x003A,
1783 (bcm43xx_radio_read16(bcm, 0x003A)
1784 & 0xFF20) | freq_r3A_value(freq));
1785 bcm43xx_radio_write16(bcm, 0x003D,
1786 bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
1787 bcm43xx_radio_write16(bcm, 0x0081,
1788 (bcm43xx_radio_read16(bcm, 0x0081)
1789 & 0xFF7F) | 0x0080);
1790 bcm43xx_radio_write16(bcm, 0x0035,
1791 bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
1792 bcm43xx_radio_write16(bcm, 0x0035,
1793 (bcm43xx_radio_read16(bcm, 0x0035)
1794 & 0xFFEF) | 0x0010);
1795 bcm43xx_radio_set_tx_iq(bcm);
1796 TODO(); //TODO: TSSI2dbm workaround
1797 bcm43xx_phy_xmitpower(bcm);//FIXME correct?
1798 } else {
1799 if (synthetic_pu_workaround)
1800 bcm43xx_synth_pu_workaround(bcm, channel);
1801
1802 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
1803 channel2freq_bg(channel));
1804
1805 if (channel == 14) {
1806 if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
1807 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1808 BCM43xx_UCODEFLAGS_OFFSET,
1809 bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1810 BCM43xx_UCODEFLAGS_OFFSET)
1811 & ~(1 << 7));
1812 } else {
1813 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1814 BCM43xx_UCODEFLAGS_OFFSET,
1815 bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1816 BCM43xx_UCODEFLAGS_OFFSET)
1817 | (1 << 7));
1818 }
1819 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
1820 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
1821 | (1 << 11));
1822 } else {
1823 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
1824 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
1825 & 0xF7BF);
1826 }
1827 }
1828
1829 radio->channel = channel;
1830 //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
1831 // that 2000 usecs might suffice.
1832 udelay(8000);
1833
1834 return 0;
1835}
1836
1837void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
1838{
1839 u16 tmp;
1840
1841 val <<= 8;
1842 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
1843 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
1844 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
1845 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
1846 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
1847 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
1848}
1849
1850/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
1851static u16 bcm43xx_get_txgain_base_band(u16 txpower)
1852{
1853 u16 ret;
1854
1855 assert(txpower <= 63);
1856
1857 if (txpower >= 54)
1858 ret = 2;
1859 else if (txpower >= 49)
1860 ret = 4;
1861 else if (txpower >= 44)
1862 ret = 5;
1863 else
1864 ret = 6;
1865
1866 return ret;
1867}
1868
1869/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
1870static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
1871{
1872 u16 ret;
1873
1874 assert(txpower <= 63);
1875
1876 if (txpower >= 32)
1877 ret = 0;
1878 else if (txpower >= 25)
1879 ret = 1;
1880 else if (txpower >= 20)
1881 ret = 2;
1882 else if (txpower >= 12)
1883 ret = 3;
1884 else
1885 ret = 4;
1886
1887 return ret;
1888}
1889
1890/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
1891static u16 bcm43xx_get_txgain_dac(u16 txpower)
1892{
1893 u16 ret;
1894
1895 assert(txpower <= 63);
1896
1897 if (txpower >= 54)
1898 ret = txpower - 53;
1899 else if (txpower >= 49)
1900 ret = txpower - 42;
1901 else if (txpower >= 44)
1902 ret = txpower - 37;
1903 else if (txpower >= 32)
1904 ret = txpower - 32;
1905 else if (txpower >= 25)
1906 ret = txpower - 20;
1907 else if (txpower >= 20)
1908 ret = txpower - 13;
1909 else if (txpower >= 12)
1910 ret = txpower - 8;
1911 else
1912 ret = txpower;
1913
1914 return ret;
1915}
1916
1917void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
1918{
1919 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1920 u16 pamp, base, dac, ilt;
1921
1922 txpower = limit_value(txpower, 0, 63);
1923
1924 pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
1925 pamp <<= 5;
1926 pamp &= 0x00E0;
1927 bcm43xx_phy_write(bcm, 0x0019, pamp);
1928
1929 base = bcm43xx_get_txgain_base_band(txpower);
1930 base &= 0x000F;
1931 bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
1932
1933 ilt = bcm43xx_ilt_read(bcm, 0x3001);
1934 ilt &= 0x0007;
1935
1936 dac = bcm43xx_get_txgain_dac(txpower);
1937 dac <<= 3;
1938 dac |= ilt;
1939
1940 bcm43xx_ilt_write(bcm, 0x3001, dac);
1941
1942 radio->txpwr_offset = txpower;
1943
1944 TODO();
1945 //TODO: FuncPlaceholder (Adjust BB loft cancel)
1946}
1947
1948void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
1949 u16 baseband_attenuation, u16 radio_attenuation,
1950 u16 txpower)
1951{
1952 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1953 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1954
1955 if (baseband_attenuation == 0xFFFF)
1956 baseband_attenuation = radio->baseband_atten;
1957 if (radio_attenuation == 0xFFFF)
1958 radio_attenuation = radio->radio_atten;
1959 if (txpower == 0xFFFF)
1960 txpower = radio->txctl1;
1961 radio->baseband_atten = baseband_attenuation;
1962 radio->radio_atten = radio_attenuation;
1963 radio->txctl1 = txpower;
1964
1965 assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
1966 if (radio->revision < 6)
1967 assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
1968 else
1969 assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
1970 assert(/*txpower >= 0 &&*/ txpower <= 7);
1971
1972 bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
1973 bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
1974 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
1975 if (radio->version == 0x2050) {
1976 bcm43xx_radio_write16(bcm, 0x0052,
1977 (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
1978 | ((txpower << 4) & 0x0070));
1979 }
1980 //FIXME: The spec is very weird and unclear here.
1981 if (phy->type == BCM43xx_PHYTYPE_G)
1982 bcm43xx_phy_lo_adjust(bcm, 0);
1983}
1984
1985u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
1986{
1987 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1988
1989 if (radio->version == 0x2050 && radio->revision < 6)
1990 return 0;
1991 return 2;
1992}
1993
1994u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
1995{
1996 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1997 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1998 u16 att = 0xFFFF;
1999
2000 if (phy->type == BCM43xx_PHYTYPE_A)
2001 return 0x60;
2002
2003 switch (radio->version) {
2004 case 0x2053:
2005 switch (radio->revision) {
2006 case 1:
2007 att = 6;
2008 break;
2009 }
2010 break;
2011 case 0x2050:
2012 switch (radio->revision) {
2013 case 0:
2014 att = 5;
2015 break;
2016 case 1:
2017 if (phy->type == BCM43xx_PHYTYPE_G) {
2018 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
2019 bcm->board_type == 0x421 &&
2020 bcm->board_revision >= 30)
2021 att = 3;
2022 else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
2023 bcm->board_type == 0x416)
2024 att = 3;
2025 else
2026 att = 1;
2027 } else {
2028 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
2029 bcm->board_type == 0x421 &&
2030 bcm->board_revision >= 30)
2031 att = 7;
2032 else
2033 att = 6;
2034 }
2035 break;
2036 case 2:
2037 if (phy->type == BCM43xx_PHYTYPE_G) {
2038 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
2039 bcm->board_type == 0x421 &&
2040 bcm->board_revision >= 30)
2041 att = 3;
2042 else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
2043 bcm->board_type == 0x416)
2044 att = 5;
2045 else if (bcm->chip_id == 0x4320)
2046 att = 4;
2047 else
2048 att = 3;
2049 } else
2050 att = 6;
2051 break;
2052 case 3:
2053 att = 5;
2054 break;
2055 case 4:
2056 case 5:
2057 att = 1;
2058 break;
2059 case 6:
2060 case 7:
2061 att = 5;
2062 break;
2063 case 8:
2064 att = 0x1A;
2065 break;
2066 case 9:
2067 default:
2068 att = 5;
2069 }
2070 }
2071 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
2072 bcm->board_type == 0x421) {
2073 if (bcm->board_revision < 0x43)
2074 att = 2;
2075 else if (bcm->board_revision < 0x51)
2076 att = 3;
2077 }
2078 if (att == 0xFFFF)
2079 att = 5;
2080
2081 return att;
2082}
2083
2084u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
2085{
2086 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2087
2088 if (radio->version != 0x2050)
2089 return 0;
2090 if (radio->revision == 1)
2091 return 3;
2092 if (radio->revision < 6)
2093 return 2;
2094 if (radio->revision == 8)
2095 return 1;
2096 return 0;
2097}
2098
2099void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
2100{
2101 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2102 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2103 int err;
2104
2105 if (radio->enabled)
2106 return;
2107
2108 switch (phy->type) {
2109 case BCM43xx_PHYTYPE_A:
2110 bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
2111 bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
2112 bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
2113 bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
2114 bcm43xx_radio_init2060(bcm);
2115 break;
2116 case BCM43xx_PHYTYPE_B:
2117 case BCM43xx_PHYTYPE_G:
2118 bcm43xx_phy_write(bcm, 0x0015, 0x8000);
2119 bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
2120 bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
2121 err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
2122 assert(err == 0);
2123 break;
2124 default:
2125 assert(0);
2126 }
2127 radio->enabled = 1;
2128 dprintk(KERN_INFO PFX "Radio turned on\n");
2129 bcm43xx_leds_update(bcm, 0);
2130}
2131
2132void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
2133{
2134 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2135 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2136
2137 if (phy->type == BCM43xx_PHYTYPE_A) {
2138 bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
2139 bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
2140 bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
2141 bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
2142 }
2143 if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
2144 bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
2145 bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
2146 } else
2147 bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
2148 radio->enabled = 0;
2149 dprintk(KERN_INFO PFX "Radio initialized\n");
2150 bcm43xx_leds_update(bcm, 0);
2151}
2152
2153void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
2154{
2155 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2156
2157 switch (phy->type) {
2158 case BCM43xx_PHYTYPE_A:
2159 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
2160 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
2161 break;
2162 case BCM43xx_PHYTYPE_B:
2163 case BCM43xx_PHYTYPE_G:
2164 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
2165 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
2166 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
2167 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
2168 break;
2169 }
2170}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
deleted file mode 100644
index 77a98a53a2e2..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
+++ /dev/null
@@ -1,115 +0,0 @@
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#ifndef BCM43xx_RADIO_H_
32#define BCM43xx_RADIO_H_
33
34#include "bcm43xx.h"
35
36
37#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36
38#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6
39
40/* Force antenna 0. */
41#define BCM43xx_RADIO_TXANTENNA_0 0
42/* Force antenna 1. */
43#define BCM43xx_RADIO_TXANTENNA_1 1
44/* Use the RX antenna, that was selected for the most recently
45 * received good PLCP header.
46 */
47#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3
48#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP
49
50#define BCM43xx_RADIO_INTERFMODE_NONE 0
51#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1
52#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2
53#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3
54
55
56void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
57void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
58
59u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
60void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
61
62u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
63void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
64
65void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
66void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
67
68static inline
69int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm)
70{
71 /* function to return state of hardware enable of radio
72 * returns 0 if radio disabled, 1 if radio enabled
73 */
74 if (bcm->current_core->rev >= 3)
75 return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI)
76 & BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK)
77 == 0) ? 1 : 0;
78 else
79 return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO)
80 & BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK)
81 == 0) ? 0 : 1;
82}
83
84int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
85 int synthetic_pu_workaround);
86
87void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
88void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
89 u16 baseband_attenuation, u16 attenuation,
90 u16 txpower);
91
92u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
93u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
94u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
95
96void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
97
98void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
99
100u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
101u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
102
103int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
104
105void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
106void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
107s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
108void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
109void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
110void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
111
112void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
113u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
114
115#endif /* BCM43xx_RADIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
deleted file mode 100644
index 8ab5f93d192a..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ /dev/null
@@ -1,471 +0,0 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 SYSFS support routines
6
7 Copyright (c) 2006 Michael Buesch <mbuesch@freenet.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26#include "bcm43xx_sysfs.h"
27#include "bcm43xx.h"
28#include "bcm43xx_main.h"
29#include "bcm43xx_radio.h"
30
31#include <linux/capability.h>
32
33
34#define GENERIC_FILESIZE 64
35
36
37static int get_integer(const char *buf, size_t count)
38{
39 char tmp[10 + 1] = { 0 };
40 int ret = -EINVAL;
41
42 if (count == 0)
43 goto out;
44 count = min(count, (size_t)10);
45 memcpy(tmp, buf, count);
46 ret = simple_strtol(tmp, NULL, 10);
47out:
48 return ret;
49}
50
51static int get_boolean(const char *buf, size_t count)
52{
53 if (count != 0) {
54 if (buf[0] == '1')
55 return 1;
56 if (buf[0] == '0')
57 return 0;
58 if (count >= 4 && memcmp(buf, "true", 4) == 0)
59 return 1;
60 if (count >= 5 && memcmp(buf, "false", 5) == 0)
61 return 0;
62 if (count >= 3 && memcmp(buf, "yes", 3) == 0)
63 return 1;
64 if (count >= 2 && memcmp(buf, "no", 2) == 0)
65 return 0;
66 if (count >= 2 && memcmp(buf, "on", 2) == 0)
67 return 1;
68 if (count >= 3 && memcmp(buf, "off", 3) == 0)
69 return 0;
70 }
71 return -EINVAL;
72}
73
74static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
75{
76 int i, pos = 0;
77
78 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
79 pos += snprintf(buf + pos, buf_len - pos - 1,
80 "%04X", swab16(sprom[i]) & 0xFFFF);
81 }
82 pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
83
84 return pos + 1;
85}
86
87static int hex2sprom(u16 *sprom, const char *dump, size_t len)
88{
89 char tmp[5] = { 0 };
90 int cnt = 0;
91 unsigned long parsed;
92
93 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
94 return -EINVAL;
95
96 while (cnt < BCM43xx_SPROM_SIZE) {
97 memcpy(tmp, dump, 4);
98 dump += 4;
99 parsed = simple_strtoul(tmp, NULL, 16);
100 sprom[cnt++] = swab16((u16)parsed);
101 }
102
103 return 0;
104}
105
106static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
107 struct device_attribute *attr,
108 char *buf)
109{
110 struct bcm43xx_private *bcm = dev_to_bcm(dev);
111 u16 *sprom;
112 unsigned long flags;
113 int err;
114
115 if (!capable(CAP_NET_ADMIN))
116 return -EPERM;
117
118 assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
119 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
120 GFP_KERNEL);
121 if (!sprom)
122 return -ENOMEM;
123 mutex_lock(&bcm->mutex);
124 spin_lock_irqsave(&bcm->irq_lock, flags);
125 err = bcm43xx_sprom_read(bcm, sprom);
126 if (!err)
127 err = sprom2hex(sprom, buf, PAGE_SIZE);
128 mmiowb();
129 spin_unlock_irqrestore(&bcm->irq_lock, flags);
130 mutex_unlock(&bcm->mutex);
131 kfree(sprom);
132
133 return err;
134}
135
136static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
137 struct device_attribute *attr,
138 const char *buf, size_t count)
139{
140 struct bcm43xx_private *bcm = dev_to_bcm(dev);
141 u16 *sprom;
142 unsigned long flags;
143 int err;
144
145 if (!capable(CAP_NET_ADMIN))
146 return -EPERM;
147
148 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
149 GFP_KERNEL);
150 if (!sprom)
151 return -ENOMEM;
152 err = hex2sprom(sprom, buf, count);
153 if (err)
154 goto out_kfree;
155 mutex_lock(&bcm->mutex);
156 spin_lock_irqsave(&bcm->irq_lock, flags);
157 spin_lock(&bcm->leds_lock);
158 err = bcm43xx_sprom_write(bcm, sprom);
159 mmiowb();
160 spin_unlock(&bcm->leds_lock);
161 spin_unlock_irqrestore(&bcm->irq_lock, flags);
162 mutex_unlock(&bcm->mutex);
163out_kfree:
164 kfree(sprom);
165
166 return err ? err : count;
167
168}
169
170static DEVICE_ATTR(sprom, 0600,
171 bcm43xx_attr_sprom_show,
172 bcm43xx_attr_sprom_store);
173
174static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
175 struct device_attribute *attr,
176 char *buf)
177{
178 struct bcm43xx_private *bcm = dev_to_bcm(dev);
179 ssize_t count = 0;
180
181 if (!capable(CAP_NET_ADMIN))
182 return -EPERM;
183
184 mutex_lock(&bcm->mutex);
185
186 switch (bcm43xx_current_radio(bcm)->interfmode) {
187 case BCM43xx_RADIO_INTERFMODE_NONE:
188 count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
189 break;
190 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
191 count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
192 break;
193 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
194 count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
195 break;
196 default:
197 assert(0);
198 }
199
200 mutex_unlock(&bcm->mutex);
201
202 return count;
203
204}
205
206static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
207 struct device_attribute *attr,
208 const char *buf, size_t count)
209{
210 struct bcm43xx_private *bcm = dev_to_bcm(dev);
211 unsigned long flags;
212 int err;
213 int mode;
214
215 if (!capable(CAP_NET_ADMIN))
216 return -EPERM;
217
218 mode = get_integer(buf, count);
219 switch (mode) {
220 case 0:
221 mode = BCM43xx_RADIO_INTERFMODE_NONE;
222 break;
223 case 1:
224 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
225 break;
226 case 2:
227 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
228 break;
229 case 3:
230 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
231 break;
232 default:
233 return -EINVAL;
234 }
235
236 mutex_lock(&bcm->mutex);
237 spin_lock_irqsave(&bcm->irq_lock, flags);
238
239 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
240 if (err) {
241 printk(KERN_ERR PFX "Interference Mitigation not "
242 "supported by device\n");
243 }
244 mmiowb();
245 spin_unlock_irqrestore(&bcm->irq_lock, flags);
246 mutex_unlock(&bcm->mutex);
247
248 return err ? err : count;
249}
250
251static DEVICE_ATTR(interference, 0644,
252 bcm43xx_attr_interfmode_show,
253 bcm43xx_attr_interfmode_store);
254
255static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
256 struct device_attribute *attr,
257 char *buf)
258{
259 struct bcm43xx_private *bcm = dev_to_bcm(dev);
260 ssize_t count;
261
262 if (!capable(CAP_NET_ADMIN))
263 return -EPERM;
264
265 mutex_lock(&bcm->mutex);
266
267 if (bcm->short_preamble)
268 count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
269 else
270 count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
271
272 mutex_unlock(&bcm->mutex);
273
274 return count;
275}
276
277static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
278 struct device_attribute *attr,
279 const char *buf, size_t count)
280{
281 struct bcm43xx_private *bcm = dev_to_bcm(dev);
282 unsigned long flags;
283 int value;
284
285 if (!capable(CAP_NET_ADMIN))
286 return -EPERM;
287
288 value = get_boolean(buf, count);
289 if (value < 0)
290 return value;
291 mutex_lock(&bcm->mutex);
292 spin_lock_irqsave(&bcm->irq_lock, flags);
293
294 bcm->short_preamble = !!value;
295
296 spin_unlock_irqrestore(&bcm->irq_lock, flags);
297 mutex_unlock(&bcm->mutex);
298
299 return count;
300}
301
302static DEVICE_ATTR(shortpreamble, 0644,
303 bcm43xx_attr_preamble_show,
304 bcm43xx_attr_preamble_store);
305
306static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
307 struct device_attribute *attr,
308 const char *buf, size_t count)
309{
310 struct bcm43xx_private *bcm = dev_to_bcm(dev);
311 int phytype;
312 int err = -EINVAL;
313
314 if (count < 1)
315 goto out;
316 switch (buf[0]) {
317 case 'a': case 'A':
318 phytype = BCM43xx_PHYTYPE_A;
319 break;
320 case 'b': case 'B':
321 phytype = BCM43xx_PHYTYPE_B;
322 break;
323 case 'g': case 'G':
324 phytype = BCM43xx_PHYTYPE_G;
325 break;
326 default:
327 goto out;
328 }
329
330 bcm43xx_cancel_work(bcm);
331 mutex_lock(&(bcm)->mutex);
332 err = bcm43xx_select_wireless_core(bcm, phytype);
333 if (!err)
334 bcm43xx_periodic_tasks_setup(bcm);
335 mutex_unlock(&(bcm)->mutex);
336 if (err == -ESRCH)
337 err = -ENODEV;
338
339out:
340 return err ? err : count;
341}
342
343static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
344 struct device_attribute *attr,
345 char *buf)
346{
347 struct bcm43xx_private *bcm = dev_to_bcm(dev);
348 ssize_t count = 0;
349
350 mutex_lock(&(bcm)->mutex);
351 switch (bcm43xx_current_phy(bcm)->type) {
352 case BCM43xx_PHYTYPE_A:
353 snprintf(buf, PAGE_SIZE, "A");
354 break;
355 case BCM43xx_PHYTYPE_B:
356 snprintf(buf, PAGE_SIZE, "B");
357 break;
358 case BCM43xx_PHYTYPE_G:
359 snprintf(buf, PAGE_SIZE, "G");
360 break;
361 default:
362 assert(0);
363 }
364 mutex_unlock(&(bcm)->mutex);
365
366 return count;
367}
368
369static DEVICE_ATTR(phymode, 0644,
370 bcm43xx_attr_phymode_show,
371 bcm43xx_attr_phymode_store);
372
373static ssize_t bcm43xx_attr_microcode_show(struct device *dev,
374 struct device_attribute *attr,
375 char *buf)
376{
377 unsigned long flags;
378 struct bcm43xx_private *bcm = dev_to_bcm(dev);
379 ssize_t count = 0;
380 u16 status;
381
382 if (!capable(CAP_NET_ADMIN))
383 return -EPERM;
384
385 mutex_lock(&(bcm)->mutex);
386 spin_lock_irqsave(&bcm->irq_lock, flags);
387 status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
388 BCM43xx_UCODE_STATUS);
389
390 spin_unlock_irqrestore(&bcm->irq_lock, flags);
391 mutex_unlock(&(bcm)->mutex);
392 switch (status) {
393 case 0x0000:
394 count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n",
395 status);
396 break;
397 case 0x0001:
398 count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n",
399 status);
400 break;
401 case 0x0002:
402 count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n",
403 status);
404 break;
405 case 0x0003:
406 count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n",
407 status);
408 break;
409 case 0x0004:
410 count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n",
411 status);
412 break;
413 default:
414 count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n",
415 status);
416 break;
417 }
418
419 return count;
420}
421
422static DEVICE_ATTR(microcodestatus, 0444,
423 bcm43xx_attr_microcode_show,
424 NULL);
425
426int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
427{
428 struct device *dev = &bcm->pci_dev->dev;
429 int err;
430
431 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
432
433 err = device_create_file(dev, &dev_attr_sprom);
434 if (err)
435 goto out;
436 err = device_create_file(dev, &dev_attr_interference);
437 if (err)
438 goto err_remove_sprom;
439 err = device_create_file(dev, &dev_attr_shortpreamble);
440 if (err)
441 goto err_remove_interfmode;
442 err = device_create_file(dev, &dev_attr_phymode);
443 if (err)
444 goto err_remove_shortpreamble;
445 err = device_create_file(dev, &dev_attr_microcodestatus);
446 if (err)
447 goto err_remove_phymode;
448
449out:
450 return err;
451err_remove_phymode:
452 device_remove_file(dev, &dev_attr_phymode);
453err_remove_shortpreamble:
454 device_remove_file(dev, &dev_attr_shortpreamble);
455err_remove_interfmode:
456 device_remove_file(dev, &dev_attr_interference);
457err_remove_sprom:
458 device_remove_file(dev, &dev_attr_sprom);
459 goto out;
460}
461
462void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
463{
464 struct device *dev = &bcm->pci_dev->dev;
465
466 device_remove_file(dev, &dev_attr_microcodestatus);
467 device_remove_file(dev, &dev_attr_phymode);
468 device_remove_file(dev, &dev_attr_shortpreamble);
469 device_remove_file(dev, &dev_attr_interference);
470 device_remove_file(dev, &dev_attr_sprom);
471}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
deleted file mode 100644
index cc701df71e2a..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#ifndef BCM43xx_SYSFS_H_
2#define BCM43xx_SYSFS_H_
3
4struct bcm43xx_private;
5
6int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
7void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
8
9#endif /* BCM43xx_SYSFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
deleted file mode 100644
index 6acfdc49dccd..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ /dev/null
@@ -1,1035 +0,0 @@
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/wireless.h>
32#include <net/iw_handler.h>
33#include <net/ieee80211softmac.h>
34#include <net/ieee80211softmac_wx.h>
35#include <linux/capability.h>
36#include <linux/delay.h>
37
38#include "bcm43xx.h"
39#include "bcm43xx_wx.h"
40#include "bcm43xx_main.h"
41#include "bcm43xx_radio.h"
42#include "bcm43xx_phy.h"
43
44
45/* The WIRELESS_EXT version, which is implemented by this driver. */
46#define BCM43xx_WX_VERSION 18
47
48#define MAX_WX_STRING 80
49
50static int bcm43xx_wx_get_name(struct net_device *net_dev,
51 struct iw_request_info *info,
52 union iwreq_data *data,
53 char *extra)
54{
55 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
56 int i;
57 struct bcm43xx_phyinfo *phy;
58 char suffix[7] = { 0 };
59 int have_a = 0, have_b = 0, have_g = 0;
60
61 mutex_lock(&bcm->mutex);
62 for (i = 0; i < bcm->nr_80211_available; i++) {
63 phy = &(bcm->core_80211_ext[i].phy);
64 switch (phy->type) {
65 case BCM43xx_PHYTYPE_A:
66 have_a = 1;
67 break;
68 case BCM43xx_PHYTYPE_G:
69 have_g = 1;
70 case BCM43xx_PHYTYPE_B:
71 have_b = 1;
72 break;
73 default:
74 assert(0);
75 }
76 }
77 mutex_unlock(&bcm->mutex);
78
79 i = 0;
80 if (have_a) {
81 suffix[i++] = 'a';
82 suffix[i++] = '/';
83 }
84 if (have_b) {
85 suffix[i++] = 'b';
86 suffix[i++] = '/';
87 }
88 if (have_g) {
89 suffix[i++] = 'g';
90 suffix[i++] = '/';
91 }
92 if (i != 0)
93 suffix[i - 1] = '\0';
94
95 snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
96
97 return 0;
98}
99
100static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
101 struct iw_request_info *info,
102 union iwreq_data *data,
103 char *extra)
104{
105 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
106 unsigned long flags;
107 u8 channel;
108 s8 expon;
109 int freq;
110 int err = -EINVAL;
111
112 mutex_lock(&bcm->mutex);
113 spin_lock_irqsave(&bcm->irq_lock, flags);
114
115 if ((data->freq.e == 0) &&
116 (data->freq.m >= 0) && (data->freq.m <= 1000)) {
117 channel = data->freq.m;
118 freq = bcm43xx_channel_to_freq(bcm, channel);
119 } else {
120 freq = data->freq.m;
121 expon = 6 - data->freq.e;
122 while (--expon >= 0) /* scale down the frequency to MHz */
123 freq /= 10;
124 assert(freq > 1000);
125 channel = bcm43xx_freq_to_channel(bcm, freq);
126 }
127 if (!ieee80211_is_valid_channel(bcm->ieee, channel))
128 goto out_unlock;
129 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
130 //ieee80211softmac_disassoc(softmac, $REASON);
131 bcm43xx_mac_suspend(bcm);
132 err = bcm43xx_radio_selectchannel(bcm, channel, 0);
133 bcm43xx_mac_enable(bcm);
134 } else {
135 bcm43xx_current_radio(bcm)->initial_channel = channel;
136 err = 0;
137 }
138out_unlock:
139 spin_unlock_irqrestore(&bcm->irq_lock, flags);
140 mutex_unlock(&bcm->mutex);
141
142 return err;
143}
144
145static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
146 struct iw_request_info *info,
147 union iwreq_data *data,
148 char *extra)
149{
150 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
151 struct bcm43xx_radioinfo *radio;
152 int err = -ENODEV;
153 u16 channel;
154
155 mutex_lock(&bcm->mutex);
156 radio = bcm43xx_current_radio(bcm);
157 channel = radio->channel;
158 if (channel == 0xFF) {
159 channel = radio->initial_channel;
160 if (channel == 0xFF)
161 goto out_unlock;
162 }
163 assert(channel > 0 && channel <= 1000);
164 data->freq.e = 1;
165 data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
166 data->freq.flags = 1;
167
168 err = 0;
169out_unlock:
170 mutex_unlock(&bcm->mutex);
171
172 return err;
173}
174
175static int bcm43xx_wx_set_mode(struct net_device *net_dev,
176 struct iw_request_info *info,
177 union iwreq_data *data,
178 char *extra)
179{
180 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
181 unsigned long flags;
182 int mode;
183
184 mode = data->mode;
185 if (mode == IW_MODE_AUTO)
186 mode = BCM43xx_INITIAL_IWMODE;
187
188 mutex_lock(&bcm->mutex);
189 spin_lock_irqsave(&bcm->irq_lock, flags);
190 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
191 if (bcm->ieee->iw_mode != mode)
192 bcm43xx_set_iwmode(bcm, mode);
193 } else
194 bcm->ieee->iw_mode = mode;
195 spin_unlock_irqrestore(&bcm->irq_lock, flags);
196 mutex_unlock(&bcm->mutex);
197
198 return 0;
199}
200
201static int bcm43xx_wx_get_mode(struct net_device *net_dev,
202 struct iw_request_info *info,
203 union iwreq_data *data,
204 char *extra)
205{
206 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
207
208 mutex_lock(&bcm->mutex);
209 data->mode = bcm->ieee->iw_mode;
210 mutex_unlock(&bcm->mutex);
211
212 return 0;
213}
214
215static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
216 struct iw_request_info *info,
217 union iwreq_data *data,
218 char *extra)
219{
220 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
221 struct iw_range *range = (struct iw_range *)extra;
222 const struct ieee80211_geo *geo;
223 int i, j;
224 struct bcm43xx_phyinfo *phy;
225
226 data->data.length = sizeof(*range);
227 memset(range, 0, sizeof(*range));
228
229 //TODO: What about 802.11b?
230 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
231 range->throughput = 27 * 1000 * 1000;
232
233 range->max_qual.qual = 100;
234 range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */
235 range->max_qual.noise = 146;
236 range->max_qual.updated = IW_QUAL_ALL_UPDATED;
237
238 range->avg_qual.qual = 50;
239 range->avg_qual.level = 0;
240 range->avg_qual.noise = 0;
241 range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
242
243 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
244 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
245 range->min_frag = MIN_FRAG_THRESHOLD;
246 range->max_frag = MAX_FRAG_THRESHOLD;
247
248 range->encoding_size[0] = 5;
249 range->encoding_size[1] = 13;
250 range->num_encoding_sizes = 2;
251 range->max_encoding_tokens = WEP_KEYS;
252
253 range->we_version_compiled = WIRELESS_EXT;
254 range->we_version_source = BCM43xx_WX_VERSION;
255
256 range->enc_capa = IW_ENC_CAPA_WPA |
257 IW_ENC_CAPA_WPA2 |
258 IW_ENC_CAPA_CIPHER_TKIP |
259 IW_ENC_CAPA_CIPHER_CCMP;
260
261 mutex_lock(&bcm->mutex);
262 phy = bcm43xx_current_phy(bcm);
263
264 range->num_bitrates = 0;
265 i = 0;
266 if (phy->type == BCM43xx_PHYTYPE_A ||
267 phy->type == BCM43xx_PHYTYPE_G) {
268 range->num_bitrates = 8;
269 range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
270 range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
271 range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
272 range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
273 range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
274 range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
275 range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
276 range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
277 }
278 if (phy->type == BCM43xx_PHYTYPE_B ||
279 phy->type == BCM43xx_PHYTYPE_G) {
280 range->num_bitrates += 4;
281 range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
282 range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
283 range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
284 range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
285 }
286
287 geo = ieee80211_get_geo(bcm->ieee);
288 range->num_channels = geo->a_channels + geo->bg_channels;
289 j = 0;
290 for (i = 0; i < geo->a_channels; i++) {
291 if (j == IW_MAX_FREQUENCIES)
292 break;
293 range->freq[j].i = j + 1;
294 range->freq[j].m = geo->a[i].freq * 100000;
295 range->freq[j].e = 1;
296 j++;
297 }
298 for (i = 0; i < geo->bg_channels; i++) {
299 if (j == IW_MAX_FREQUENCIES)
300 break;
301 range->freq[j].i = j + 1;
302 range->freq[j].m = geo->bg[i].freq * 100000;
303 range->freq[j].e = 1;
304 j++;
305 }
306 range->num_frequency = j;
307
308 mutex_unlock(&bcm->mutex);
309
310 return 0;
311}
312
313static int bcm43xx_wx_set_nick(struct net_device *net_dev,
314 struct iw_request_info *info,
315 union iwreq_data *data,
316 char *extra)
317{
318 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
319 size_t len;
320
321 mutex_lock(&bcm->mutex);
322 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
323 memcpy(bcm->nick, extra, len);
324 bcm->nick[len] = '\0';
325 mutex_unlock(&bcm->mutex);
326
327 return 0;
328}
329
330static int bcm43xx_wx_get_nick(struct net_device *net_dev,
331 struct iw_request_info *info,
332 union iwreq_data *data,
333 char *extra)
334{
335 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
336 size_t len;
337
338 mutex_lock(&bcm->mutex);
339 len = strlen(bcm->nick);
340 memcpy(extra, bcm->nick, len);
341 data->data.length = (__u16)len;
342 data->data.flags = 1;
343 mutex_unlock(&bcm->mutex);
344
345 return 0;
346}
347
348static int bcm43xx_wx_set_rts(struct net_device *net_dev,
349 struct iw_request_info *info,
350 union iwreq_data *data,
351 char *extra)
352{
353 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
354 unsigned long flags;
355 int err = -EINVAL;
356
357 mutex_lock(&bcm->mutex);
358 spin_lock_irqsave(&bcm->irq_lock, flags);
359 if (data->rts.disabled) {
360 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
361 err = 0;
362 } else {
363 if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
364 data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
365 bcm->rts_threshold = data->rts.value;
366 err = 0;
367 }
368 }
369 spin_unlock_irqrestore(&bcm->irq_lock, flags);
370 mutex_unlock(&bcm->mutex);
371
372 return err;
373}
374
375static int bcm43xx_wx_get_rts(struct net_device *net_dev,
376 struct iw_request_info *info,
377 union iwreq_data *data,
378 char *extra)
379{
380 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
381
382 mutex_lock(&bcm->mutex);
383 data->rts.value = bcm->rts_threshold;
384 data->rts.fixed = 0;
385 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
386 mutex_unlock(&bcm->mutex);
387
388 return 0;
389}
390
391static int bcm43xx_wx_set_frag(struct net_device *net_dev,
392 struct iw_request_info *info,
393 union iwreq_data *data,
394 char *extra)
395{
396 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
397 unsigned long flags;
398 int err = -EINVAL;
399
400 mutex_lock(&bcm->mutex);
401 spin_lock_irqsave(&bcm->irq_lock, flags);
402 if (data->frag.disabled) {
403 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
404 err = 0;
405 } else {
406 if (data->frag.value >= MIN_FRAG_THRESHOLD &&
407 data->frag.value <= MAX_FRAG_THRESHOLD) {
408 bcm->ieee->fts = data->frag.value & ~0x1;
409 err = 0;
410 }
411 }
412 spin_unlock_irqrestore(&bcm->irq_lock, flags);
413 mutex_unlock(&bcm->mutex);
414
415 return err;
416}
417
418static int bcm43xx_wx_get_frag(struct net_device *net_dev,
419 struct iw_request_info *info,
420 union iwreq_data *data,
421 char *extra)
422{
423 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
424
425 mutex_lock(&bcm->mutex);
426 data->frag.value = bcm->ieee->fts;
427 data->frag.fixed = 0;
428 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
429 mutex_unlock(&bcm->mutex);
430
431 return 0;
432}
433
434static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
435 struct iw_request_info *info,
436 union iwreq_data *data,
437 char *extra)
438{
439 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
440 struct bcm43xx_radioinfo *radio;
441 struct bcm43xx_phyinfo *phy;
442 unsigned long flags;
443 int err = -ENODEV;
444 u16 maxpower;
445
446 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
447 printk(KERN_ERR PFX "TX power not in dBm.\n");
448 return -EOPNOTSUPP;
449 }
450
451 mutex_lock(&bcm->mutex);
452 spin_lock_irqsave(&bcm->irq_lock, flags);
453 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
454 goto out_unlock;
455 radio = bcm43xx_current_radio(bcm);
456 phy = bcm43xx_current_phy(bcm);
457 if (data->txpower.disabled != (!(radio->enabled))) {
458 if (data->txpower.disabled)
459 bcm43xx_radio_turn_off(bcm);
460 else
461 bcm43xx_radio_turn_on(bcm);
462 }
463 if (data->txpower.value > 0) {
464 /* desired and maxpower dBm values are in Q5.2 */
465 if (phy->type == BCM43xx_PHYTYPE_A)
466 maxpower = bcm->sprom.maxpower_aphy;
467 else
468 maxpower = bcm->sprom.maxpower_bgphy;
469 radio->txpower_desired = limit_value(data->txpower.value << 2,
470 0, maxpower);
471 bcm43xx_phy_xmitpower(bcm);
472 }
473 err = 0;
474
475out_unlock:
476 spin_unlock_irqrestore(&bcm->irq_lock, flags);
477 mutex_unlock(&bcm->mutex);
478
479 return err;
480}
481
482static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
483 struct iw_request_info *info,
484 union iwreq_data *data,
485 char *extra)
486{
487 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
488 struct bcm43xx_radioinfo *radio;
489 int err = -ENODEV;
490
491 mutex_lock(&bcm->mutex);
492 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
493 goto out_unlock;
494 radio = bcm43xx_current_radio(bcm);
495 /* desired dBm value is in Q5.2 */
496 data->txpower.value = radio->txpower_desired >> 2;
497 data->txpower.fixed = 1;
498 data->txpower.flags = IW_TXPOW_DBM;
499 data->txpower.disabled = !(radio->enabled);
500
501 err = 0;
502out_unlock:
503 mutex_unlock(&bcm->mutex);
504
505 return err;
506}
507
508static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
509 struct iw_request_info *info,
510 union iwreq_data *data,
511 char *extra)
512{
513 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
514 int err;
515
516 err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
517
518 return err;
519}
520
521static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
522 struct iw_request_info *info,
523 union iwreq_data *data,
524 char *extra)
525{
526 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
527 int err;
528
529 err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
530
531 return err;
532}
533
534static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
535 struct iw_request_info *info,
536 union iwreq_data *data,
537 char *extra)
538{
539 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
540 int err;
541
542 err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
543
544 return err;
545}
546
547static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
548 struct iw_request_info *info,
549 union iwreq_data *data,
550 char *extra)
551{
552 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
553 int err;
554
555 err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
556
557 return err;
558}
559
560static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
561 struct iw_request_info *info,
562 union iwreq_data *data,
563 char *extra)
564{
565 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
566 unsigned long flags;
567 int mode, err = 0;
568
569 mode = *((int *)extra);
570 switch (mode) {
571 case 0:
572 mode = BCM43xx_RADIO_INTERFMODE_NONE;
573 break;
574 case 1:
575 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
576 break;
577 case 2:
578 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
579 break;
580 case 3:
581 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
582 break;
583 default:
584 printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
585 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
586 "3 => Auto-WLAN\n");
587 return -EINVAL;
588 }
589
590 mutex_lock(&bcm->mutex);
591 spin_lock_irqsave(&bcm->irq_lock, flags);
592 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
593 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
594 if (err) {
595 printk(KERN_ERR PFX "Interference Mitigation not "
596 "supported by device\n");
597 }
598 } else {
599 if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
600 printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
601 "not supported while the interface is down.\n");
602 err = -ENODEV;
603 } else
604 bcm43xx_current_radio(bcm)->interfmode = mode;
605 }
606 spin_unlock_irqrestore(&bcm->irq_lock, flags);
607 mutex_unlock(&bcm->mutex);
608
609 return err;
610}
611
612static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
613 struct iw_request_info *info,
614 union iwreq_data *data,
615 char *extra)
616{
617 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
618 int mode;
619
620 mutex_lock(&bcm->mutex);
621 mode = bcm43xx_current_radio(bcm)->interfmode;
622 mutex_unlock(&bcm->mutex);
623
624 switch (mode) {
625 case BCM43xx_RADIO_INTERFMODE_NONE:
626 strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
627 break;
628 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
629 strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
630 break;
631 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
632 strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
633 break;
634 default:
635 assert(0);
636 }
637 data->data.length = strlen(extra) + 1;
638
639 return 0;
640}
641
642static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
643 struct iw_request_info *info,
644 union iwreq_data *data,
645 char *extra)
646{
647 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
648 unsigned long flags;
649 int on;
650
651 on = *((int *)extra);
652 mutex_lock(&bcm->mutex);
653 spin_lock_irqsave(&bcm->irq_lock, flags);
654 bcm->short_preamble = !!on;
655 spin_unlock_irqrestore(&bcm->irq_lock, flags);
656 mutex_unlock(&bcm->mutex);
657
658 return 0;
659}
660
661static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
662 struct iw_request_info *info,
663 union iwreq_data *data,
664 char *extra)
665{
666 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
667 int on;
668
669 mutex_lock(&bcm->mutex);
670 on = bcm->short_preamble;
671 mutex_unlock(&bcm->mutex);
672
673 if (on)
674 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
675 else
676 strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
677 data->data.length = strlen(extra) + 1;
678
679 return 0;
680}
681
682static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
683 struct iw_request_info *info,
684 union iwreq_data *data,
685 char *extra)
686{
687 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
688 unsigned long flags;
689 int on;
690
691 on = *((int *)extra);
692
693 mutex_lock(&bcm->mutex);
694 spin_lock_irqsave(&bcm->irq_lock, flags);
695 bcm->ieee->host_encrypt = !!on;
696 bcm->ieee->host_decrypt = !!on;
697 bcm->ieee->host_build_iv = !on;
698 bcm->ieee->host_strip_iv_icv = !on;
699 spin_unlock_irqrestore(&bcm->irq_lock, flags);
700 mutex_unlock(&bcm->mutex);
701
702 return 0;
703}
704
705static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
706 struct iw_request_info *info,
707 union iwreq_data *data,
708 char *extra)
709{
710 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
711 int on;
712
713 mutex_lock(&bcm->mutex);
714 on = bcm->ieee->host_encrypt;
715 mutex_unlock(&bcm->mutex);
716
717 if (on)
718 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
719 else
720 strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
721 data->data.length = strlen(extra + 1);
722
723 return 0;
724}
725
726/* Enough buffer to hold a hexdump of the sprom data. */
727#define SPROM_BUFFERSIZE 512
728
729static int sprom2hex(const u16 *sprom, char *dump)
730{
731 int i, pos = 0;
732
733 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
734 pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
735 "%04X", swab16(sprom[i]) & 0xFFFF);
736 }
737
738 return pos + 1;
739}
740
741static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
742{
743 char tmp[5] = { 0 };
744 int cnt = 0;
745 unsigned long parsed;
746
747 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
748 return -EINVAL;
749 while (cnt < BCM43xx_SPROM_SIZE) {
750 memcpy(tmp, dump, 4);
751 dump += 4;
752 parsed = simple_strtoul(tmp, NULL, 16);
753 sprom[cnt++] = swab16((u16)parsed);
754 }
755
756 return 0;
757}
758
759static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
760 struct iw_request_info *info,
761 union iwreq_data *data,
762 char *extra)
763{
764 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
765 int err = -EPERM;
766 u16 *sprom;
767 unsigned long flags;
768
769 if (!capable(CAP_SYS_RAWIO))
770 goto out;
771
772 err = -ENOMEM;
773 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
774 GFP_KERNEL);
775 if (!sprom)
776 goto out;
777
778 mutex_lock(&bcm->mutex);
779 spin_lock_irqsave(&bcm->irq_lock, flags);
780 err = -ENODEV;
781 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
782 err = bcm43xx_sprom_read(bcm, sprom);
783 spin_unlock_irqrestore(&bcm->irq_lock, flags);
784 mutex_unlock(&bcm->mutex);
785 if (!err)
786 data->data.length = sprom2hex(sprom, extra);
787 kfree(sprom);
788out:
789 return err;
790}
791
792static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
793 struct iw_request_info *info,
794 union iwreq_data *data,
795 char *extra)
796{
797 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
798 int err = -EPERM;
799 u16 *sprom;
800 unsigned long flags;
801 char *input;
802 unsigned int len;
803
804 if (!capable(CAP_SYS_RAWIO))
805 goto out;
806
807 err = -ENOMEM;
808 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
809 GFP_KERNEL);
810 if (!sprom)
811 goto out;
812
813 len = data->data.length;
814 extra[len - 1] = '\0';
815 input = strchr(extra, ':');
816 if (input) {
817 input++;
818 len -= input - extra;
819 } else
820 input = extra;
821 err = hex2sprom(sprom, input, len);
822 if (err)
823 goto out_kfree;
824
825 mutex_lock(&bcm->mutex);
826 spin_lock_irqsave(&bcm->irq_lock, flags);
827 spin_lock(&bcm->leds_lock);
828 err = -ENODEV;
829 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
830 err = bcm43xx_sprom_write(bcm, sprom);
831 spin_unlock(&bcm->leds_lock);
832 spin_unlock_irqrestore(&bcm->irq_lock, flags);
833 mutex_unlock(&bcm->mutex);
834out_kfree:
835 kfree(sprom);
836out:
837 return err;
838}
839
840/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
841
842static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
843{
844 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
845 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
846 struct iw_statistics *wstats;
847 struct ieee80211_network *network = NULL;
848 static int tmp_level = 0;
849 static int tmp_qual = 0;
850 unsigned long flags;
851
852 wstats = &bcm->stats.wstats;
853 if (!mac->associnfo.associated) {
854 wstats->miss.beacon = 0;
855// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
856 wstats->discard.retries = 0;
857// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
858 wstats->discard.nwid = 0;
859// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
860 wstats->discard.code = 0;
861// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
862 wstats->discard.fragment = 0;
863 wstats->discard.misc = 0;
864 wstats->qual.qual = 0;
865 wstats->qual.level = 0;
866 wstats->qual.noise = 0;
867 wstats->qual.updated = 7;
868 wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
869 return wstats;
870 }
871 /* fill in the real statistics when iface associated */
872 spin_lock_irqsave(&mac->ieee->lock, flags);
873 list_for_each_entry(network, &mac->ieee->network_list, list) {
874 if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
875 if (!tmp_level) { /* get initial values */
876 tmp_level = network->stats.signal;
877 tmp_qual = network->stats.rssi;
878 } else { /* smooth results */
879 tmp_level = (15 * tmp_level + network->stats.signal)/16;
880 tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
881 }
882 break;
883 }
884 }
885 spin_unlock_irqrestore(&mac->ieee->lock, flags);
886 wstats->qual.level = tmp_level;
887 wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
888 wstats->qual.noise = bcm->stats.noise;
889 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
890 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
891 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
892 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
893 wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
894 wstats->discard.misc = 0; // FIXME
895 wstats->miss.beacon = 0; // FIXME
896 return wstats;
897}
898
899
900#ifdef WX
901# undef WX
902#endif
903#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
904static const iw_handler bcm43xx_wx_handlers[] = {
905 /* Wireless Identification */
906 WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
907 /* Basic operations */
908 WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
909 WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
910 WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
911 WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
912 /* Informative stuff */
913 WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
914 /* Access Point manipulation */
915 WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
916 WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
917 WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
918 WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
919 /* 802.11 specific support */
920 WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
921 WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
922 WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
923 WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
924 /* Other parameters */
925 WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
926 WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
927 WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
928 WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
929 WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
930 WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
931 WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
932 WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
933//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
934//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
935 /* Encoding */
936 WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
937 WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
938 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
939 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
940 /* Power saving */
941//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
942//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
943 WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
944 WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
945 WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
946 WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
947};
948#undef WX
949
950static const iw_handler bcm43xx_priv_wx_handlers[] = {
951 /* Set Interference Mitigation Mode. */
952 bcm43xx_wx_set_interfmode,
953 /* Get Interference Mitigation Mode. */
954 bcm43xx_wx_get_interfmode,
955 /* Enable/Disable Short Preamble mode. */
956 bcm43xx_wx_set_shortpreamble,
957 /* Get Short Preamble mode. */
958 bcm43xx_wx_get_shortpreamble,
959 /* Enable/Disable Software Encryption mode */
960 bcm43xx_wx_set_swencryption,
961 /* Get Software Encryption mode */
962 bcm43xx_wx_get_swencryption,
963 /* Write SRPROM data. */
964 bcm43xx_wx_sprom_write,
965 /* Read SPROM data. */
966 bcm43xx_wx_sprom_read,
967};
968
969#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
970#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
971#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
972#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
973#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
974#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
975#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
976#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
977
978#define PRIV_WX_DUMMY(ioctl) \
979 { \
980 .cmd = (ioctl), \
981 .name = "__unused" \
982 }
983
984static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
985 {
986 .cmd = PRIV_WX_SET_INTERFMODE,
987 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
988 .name = "set_interfmode",
989 },
990 {
991 .cmd = PRIV_WX_GET_INTERFMODE,
992 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
993 .name = "get_interfmode",
994 },
995 {
996 .cmd = PRIV_WX_SET_SHORTPREAMBLE,
997 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
998 .name = "set_shortpreamb",
999 },
1000 {
1001 .cmd = PRIV_WX_GET_SHORTPREAMBLE,
1002 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
1003 .name = "get_shortpreamb",
1004 },
1005 {
1006 .cmd = PRIV_WX_SET_SWENCRYPTION,
1007 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1008 .name = "set_swencrypt",
1009 },
1010 {
1011 .cmd = PRIV_WX_GET_SWENCRYPTION,
1012 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
1013 .name = "get_swencrypt",
1014 },
1015 {
1016 .cmd = PRIV_WX_SPROM_WRITE,
1017 .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
1018 .name = "write_sprom",
1019 },
1020 {
1021 .cmd = PRIV_WX_SPROM_READ,
1022 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
1023 .name = "read_sprom",
1024 },
1025};
1026
1027const struct iw_handler_def bcm43xx_wx_handlers_def = {
1028 .standard = bcm43xx_wx_handlers,
1029 .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
1030 .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
1031 .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
1032 .private = bcm43xx_priv_wx_handlers,
1033 .private_args = bcm43xx_priv_wx_args,
1034 .get_wireless_stats = bcm43xx_get_wireless_stats,
1035};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
deleted file mode 100644
index 1f29ff3aa4c3..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
+++ /dev/null
@@ -1,36 +0,0 @@
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#ifndef BCM43xx_WX_H_
32#define BCM43xx_WX_H_
33
34extern const struct iw_handler_def bcm43xx_wx_handlers_def;
35
36#endif /* BCM43xx_WX_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
deleted file mode 100644
index f79fe11f9e81..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ /dev/null
@@ -1,565 +0,0 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Transmission (TX/RX) related functions.
6
7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
8 Stefano Brivio <st3@riseup.net>
9 Michael Buesch <mbuesch@freenet.de>
10 Danny van Dyk <kugelfang@gentoo.org>
11 Andreas Jaggi <andreas.jaggi@waterwave.ch>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
27
28*/
29
30#include "bcm43xx_xmit.h"
31
32#include <linux/etherdevice.h>
33
34
35/* Extract the bitrate out of a CCK PLCP header. */
36static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
37{
38 switch (plcp->raw[0]) {
39 case 0x0A:
40 return IEEE80211_CCK_RATE_1MB;
41 case 0x14:
42 return IEEE80211_CCK_RATE_2MB;
43 case 0x37:
44 return IEEE80211_CCK_RATE_5MB;
45 case 0x6E:
46 return IEEE80211_CCK_RATE_11MB;
47 }
48 assert(0);
49 return 0;
50}
51
52/* Extract the bitrate out of an OFDM PLCP header. */
53static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
54{
55 switch (plcp->raw[0] & 0xF) {
56 case 0xB:
57 return IEEE80211_OFDM_RATE_6MB;
58 case 0xF:
59 return IEEE80211_OFDM_RATE_9MB;
60 case 0xA:
61 return IEEE80211_OFDM_RATE_12MB;
62 case 0xE:
63 return IEEE80211_OFDM_RATE_18MB;
64 case 0x9:
65 return IEEE80211_OFDM_RATE_24MB;
66 case 0xD:
67 return IEEE80211_OFDM_RATE_36MB;
68 case 0x8:
69 return IEEE80211_OFDM_RATE_48MB;
70 case 0xC:
71 return IEEE80211_OFDM_RATE_54MB;
72 }
73 assert(0);
74 return 0;
75}
76
77u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
78{
79 switch (bitrate) {
80 case IEEE80211_CCK_RATE_1MB:
81 return 0x0A;
82 case IEEE80211_CCK_RATE_2MB:
83 return 0x14;
84 case IEEE80211_CCK_RATE_5MB:
85 return 0x37;
86 case IEEE80211_CCK_RATE_11MB:
87 return 0x6E;
88 }
89 assert(0);
90 return 0;
91}
92
93u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
94{
95 switch (bitrate) {
96 case IEEE80211_OFDM_RATE_6MB:
97 return 0xB;
98 case IEEE80211_OFDM_RATE_9MB:
99 return 0xF;
100 case IEEE80211_OFDM_RATE_12MB:
101 return 0xA;
102 case IEEE80211_OFDM_RATE_18MB:
103 return 0xE;
104 case IEEE80211_OFDM_RATE_24MB:
105 return 0x9;
106 case IEEE80211_OFDM_RATE_36MB:
107 return 0xD;
108 case IEEE80211_OFDM_RATE_48MB:
109 return 0x8;
110 case IEEE80211_OFDM_RATE_54MB:
111 return 0xC;
112 }
113 assert(0);
114 return 0;
115}
116
117static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
118 const u16 octets, const u8 bitrate,
119 const int ofdm_modulation)
120{
121 __le32 *data = &(plcp->data);
122 __u8 *raw = plcp->raw;
123
124 if (ofdm_modulation) {
125 u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
126 assert(!(octets & 0xF000));
127 val |= (octets << 5);
128 *data = cpu_to_le32(val);
129 } else {
130 u32 plen;
131
132 plen = octets * 16 / bitrate;
133 if ((octets * 16 % bitrate) > 0) {
134 plen++;
135 if ((bitrate == IEEE80211_CCK_RATE_11MB)
136 && ((octets * 8 % 11) < 4)) {
137 raw[1] = 0x84;
138 } else
139 raw[1] = 0x04;
140 } else
141 raw[1] = 0x04;
142 *data |= cpu_to_le32(plen << 16);
143 raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
144 }
145}
146
147static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
148{
149 switch (bitrate) {
150 case IEEE80211_CCK_RATE_1MB:
151 return IEEE80211_CCK_RATE_1MB;
152 case IEEE80211_CCK_RATE_2MB:
153 return IEEE80211_CCK_RATE_1MB;
154 case IEEE80211_CCK_RATE_5MB:
155 return IEEE80211_CCK_RATE_2MB;
156 case IEEE80211_CCK_RATE_11MB:
157 return IEEE80211_CCK_RATE_5MB;
158 case IEEE80211_OFDM_RATE_6MB:
159 return IEEE80211_CCK_RATE_5MB;
160 case IEEE80211_OFDM_RATE_9MB:
161 return IEEE80211_OFDM_RATE_6MB;
162 case IEEE80211_OFDM_RATE_12MB:
163 return IEEE80211_OFDM_RATE_9MB;
164 case IEEE80211_OFDM_RATE_18MB:
165 return IEEE80211_OFDM_RATE_12MB;
166 case IEEE80211_OFDM_RATE_24MB:
167 return IEEE80211_OFDM_RATE_18MB;
168 case IEEE80211_OFDM_RATE_36MB:
169 return IEEE80211_OFDM_RATE_24MB;
170 case IEEE80211_OFDM_RATE_48MB:
171 return IEEE80211_OFDM_RATE_36MB;
172 case IEEE80211_OFDM_RATE_54MB:
173 return IEEE80211_OFDM_RATE_48MB;
174 }
175 assert(0);
176 return 0;
177}
178
179static
180__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
181 u8 bitrate)
182{
183 const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
184 __le16 duration_id = wireless_header->duration_id;
185
186 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
187 case IEEE80211_FTYPE_DATA:
188 case IEEE80211_FTYPE_MGMT:
189 //TODO: Steal the code from ieee80211, once it is completed there.
190 break;
191 case IEEE80211_FTYPE_CTL:
192 /* Use the original duration/id. */
193 break;
194 default:
195 assert(0);
196 }
197
198 return duration_id;
199}
200
201static inline
202u16 ceiling_div(u16 dividend, u16 divisor)
203{
204 return ((dividend + divisor - 1) / divisor);
205}
206
207static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
208 struct bcm43xx_txhdr *txhdr,
209 u16 *flags,
210 u8 bitrate,
211 const struct ieee80211_hdr_4addr *wlhdr)
212{
213 u16 fctl;
214 u16 dur;
215 u8 fallback_bitrate;
216 int ofdm_modulation;
217 int fallback_ofdm_modulation;
218// u8 *sa, *da;
219 u16 flen;
220
221//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
222//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
223 fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
224 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
225 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
226
227 flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
228 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
229 flen, bitrate,
230 !ieee80211_is_cck_rate(bitrate));
231 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
232 flen, fallback_bitrate,
233 !ieee80211_is_cck_rate(fallback_bitrate));
234 fctl = IEEE80211_FTYPE_CTL;
235 fctl |= IEEE80211_STYPE_RTS;
236 dur = le16_to_cpu(wlhdr->duration_id);
237/*FIXME: should we test for dur==0 here and let it unmodified in this case?
238 * The following assert checks for this case...
239 */
240assert(dur);
241/*FIXME: The duration calculation is not really correct.
242 * I am not 100% sure which bitrate to use. We use the RTS rate here,
243 * but this is likely to be wrong.
244 */
245 if (phy->type == BCM43xx_PHYTYPE_A) {
246 /* Three times SIFS */
247 dur += 16 * 3;
248 /* Add ACK duration. */
249 dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
250 bitrate * 4);
251 /* Add CTS duration. */
252 dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
253 bitrate * 4);
254 } else {
255 /* Three times SIFS */
256 dur += 10 * 3;
257 /* Add ACK duration. */
258 dur += ceiling_div(8 * (14 /*bytes*/) * 10,
259 bitrate);
260 /* Add CTS duration. */
261 dur += ceiling_div(8 * (14 /*bytes*/) * 10,
262 bitrate);
263 }
264
265 txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
266 txhdr->rts_cts_dur = cpu_to_le16(dur);
267//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
268//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
269 memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
270// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
271
272 *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
273 *flags |= BCM43xx_TXHDRFLAG_RTS;
274 if (ofdm_modulation)
275 *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
276 if (fallback_ofdm_modulation)
277 *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
278}
279
280void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
281 struct bcm43xx_txhdr *txhdr,
282 const unsigned char *fragment_data,
283 const unsigned int fragment_len,
284 const int is_first_fragment,
285 const u16 cookie)
286{
287 const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
288 const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
289 const struct ieee80211_security *secinfo = &bcm->ieee->sec;
290 u8 bitrate;
291 u8 fallback_bitrate;
292 int ofdm_modulation;
293 int fallback_ofdm_modulation;
294 u16 plcp_fragment_len = fragment_len;
295 u16 flags = 0;
296 u16 control = 0;
297 u16 wsec_rate = 0;
298 u16 encrypt_frame;
299 const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
300 const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
301
302 /* Now construct the TX header. */
303 memset(txhdr, 0, sizeof(*txhdr));
304
305 bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
306 is_multicast_ether_addr(wireless_header->addr1), is_mgt);
307 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
308 fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
309 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
310
311 /* Set Frame Control from 80211 header. */
312 txhdr->frame_control = wireless_header->frame_ctl;
313 /* Copy address1 from 80211 header. */
314 memcpy(txhdr->mac1, wireless_header->addr1, 6);
315 /* Set the fallback duration ID. */
316 txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
317 fallback_bitrate);
318 /* Set the cookie (used as driver internal ID for the frame) */
319 txhdr->cookie = cpu_to_le16(cookie);
320
321 /* Hardware appends FCS. */
322 plcp_fragment_len += IEEE80211_FCS_LEN;
323
324 /* Hardware encryption. */
325 encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
326 if (encrypt_frame && !bcm->ieee->host_encrypt) {
327 const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
328 memcpy(txhdr->wep_iv, hdr->payload, 4);
329 /* Hardware appends ICV. */
330 plcp_fragment_len += 4;
331
332 wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
333 & BCM43xx_TXHDR_WSEC_ALGO_MASK;
334 wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
335 & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
336 }
337
338 /* Generate the PLCP header and the fallback PLCP header. */
339 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
340 plcp_fragment_len,
341 bitrate, ofdm_modulation);
342 bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
343 fallback_bitrate, fallback_ofdm_modulation);
344
345 /* Set the CONTROL field */
346 if (ofdm_modulation)
347 control |= BCM43xx_TXHDRCTL_OFDM;
348 if (bcm->short_preamble) //FIXME: could be the other way around, please test
349 control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
350 control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
351 & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
352
353 /* Set the FLAGS field */
354 if (!is_multicast_ether_addr(wireless_header->addr1) &&
355 !is_broadcast_ether_addr(wireless_header->addr1))
356 flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
357 if (1 /* FIXME: PS poll?? */)
358 flags |= 0x10; // FIXME: unknown meaning.
359 if (fallback_ofdm_modulation)
360 flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
361 if (is_first_fragment)
362 flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
363
364 /* Set WSEC/RATE field */
365 wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
366 & BCM43xx_TXHDR_RATE_MASK;
367
368 /* Generate the RTS/CTS packet, if required. */
369 /* FIXME: We should first try with CTS-to-self,
370 * if we are on 80211g. If we get too many
371 * failures (hidden nodes), we should switch back to RTS/CTS.
372 */
373 if (0/*FIXME txctl->use_rts_cts*/) {
374 bcm43xx_generate_rts(phy, txhdr, &flags,
375 0/*FIXME txctl->rts_cts_rate*/,
376 wireless_header);
377 }
378
379 txhdr->flags = cpu_to_le16(flags);
380 txhdr->control = cpu_to_le16(control);
381 txhdr->wsec_rate = cpu_to_le16(wsec_rate);
382}
383
384static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
385 u8 in_rssi, int ofdm,
386 int adjust_2053, int adjust_2050)
387{
388 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
389 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
390 s32 tmp;
391
392 switch (radio->version) {
393 case 0x2050:
394 if (ofdm) {
395 tmp = in_rssi;
396 if (tmp > 127)
397 tmp -= 256;
398 tmp *= 73;
399 tmp /= 64;
400 if (adjust_2050)
401 tmp += 25;
402 else
403 tmp -= 3;
404 } else {
405 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
406 if (in_rssi > 63)
407 in_rssi = 63;
408 tmp = radio->nrssi_lt[in_rssi];
409 tmp = 31 - tmp;
410 tmp *= -131;
411 tmp /= 128;
412 tmp -= 57;
413 } else {
414 tmp = in_rssi;
415 tmp = 31 - tmp;
416 tmp *= -149;
417 tmp /= 128;
418 tmp -= 68;
419 }
420 if (phy->type == BCM43xx_PHYTYPE_G &&
421 adjust_2050)
422 tmp += 25;
423 }
424 break;
425 case 0x2060:
426 if (in_rssi > 127)
427 tmp = in_rssi - 256;
428 else
429 tmp = in_rssi;
430 break;
431 default:
432 tmp = in_rssi;
433 tmp -= 11;
434 tmp *= 103;
435 tmp /= 64;
436 if (adjust_2053)
437 tmp -= 109;
438 else
439 tmp -= 83;
440 }
441
442 return (s8)tmp;
443}
444
445//TODO
446#if 0
447static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
448 u8 in_rssi)
449{
450 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
451 s8 ret;
452
453 if (phy->type == BCM43xx_PHYTYPE_A) {
454 //TODO: Incomplete specs.
455 ret = 0;
456 } else
457 ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
458
459 return ret;
460}
461#endif
462
463int bcm43xx_rx(struct bcm43xx_private *bcm,
464 struct sk_buff *skb,
465 struct bcm43xx_rxhdr *rxhdr)
466{
467 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
468 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
469 struct bcm43xx_plcp_hdr4 *plcp;
470 struct ieee80211_rx_stats stats;
471 struct ieee80211_hdr_4addr *wlhdr;
472 u16 frame_ctl;
473 int is_packet_for_us = 0;
474 int err = -EINVAL;
475 const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
476 const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
477 const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
478 const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
479
480 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
481 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
482 /* Skip two unknown bytes and the PLCP header. */
483 skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
484 } else {
485 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
486 /* Skip the PLCP header. */
487 skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
488 }
489 /* The SKB contains the PAYLOAD (wireless header + data)
490 * at this point. The FCS at the end is stripped.
491 */
492
493 memset(&stats, 0, sizeof(stats));
494 stats.mac_time = le16_to_cpu(rxhdr->mactime);
495 stats.rssi = rxhdr->rssi;
496 stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
497 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
498 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
499 stats.noise = bcm->stats.noise;
500 if (is_ofdm)
501 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
502 else
503 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
504 stats.received_channel = radio->channel;
505 stats.mask = IEEE80211_STATMASK_SIGNAL |
506 IEEE80211_STATMASK_NOISE |
507 IEEE80211_STATMASK_RATE |
508 IEEE80211_STATMASK_RSSI;
509 if (phy->type == BCM43xx_PHYTYPE_A)
510 stats.freq = IEEE80211_52GHZ_BAND;
511 else
512 stats.freq = IEEE80211_24GHZ_BAND;
513 stats.len = skb->len;
514
515 bcm->stats.last_rx = jiffies;
516 if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
517 err = ieee80211_rx(bcm->ieee, skb, &stats);
518 return (err == 0) ? -EINVAL : 0;
519 }
520
521 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
522
523 switch (bcm->ieee->iw_mode) {
524 case IW_MODE_ADHOC:
525 if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
526 memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
527 is_broadcast_ether_addr(wlhdr->addr1) ||
528 is_multicast_ether_addr(wlhdr->addr1) ||
529 bcm->net_dev->flags & IFF_PROMISC)
530 is_packet_for_us = 1;
531 break;
532 case IW_MODE_INFRA:
533 default:
534 /* When receiving multicast or broadcast packets, filter out
535 the packets we send ourself; we shouldn't see those */
536 if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
537 memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
538 (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
539 (is_broadcast_ether_addr(wlhdr->addr1) ||
540 is_multicast_ether_addr(wlhdr->addr1) ||
541 bcm->net_dev->flags & IFF_PROMISC)))
542 is_packet_for_us = 1;
543 break;
544 }
545
546 frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
547 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
548 case IEEE80211_FTYPE_MGMT:
549 ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
550 break;
551 case IEEE80211_FTYPE_DATA:
552 if (is_packet_for_us) {
553 err = ieee80211_rx(bcm->ieee, skb, &stats);
554 err = (err == 0) ? -EINVAL : 0;
555 }
556 break;
557 case IEEE80211_FTYPE_CTL:
558 break;
559 default:
560 assert(0);
561 return -EINVAL;
562 }
563
564 return err;
565}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
deleted file mode 100644
index 47c135a7f4dc..000000000000
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+++ /dev/null
@@ -1,150 +0,0 @@
1#ifndef BCM43xx_XMIT_H_
2#define BCM43xx_XMIT_H_
3
4#include "bcm43xx_main.h"
5
6
7#define _bcm43xx_declare_plcp_hdr(size) \
8 struct bcm43xx_plcp_hdr##size { \
9 union { \
10 __le32 data; \
11 __u8 raw[size]; \
12 } __attribute__((__packed__)); \
13 } __attribute__((__packed__))
14
15/* struct bcm43xx_plcp_hdr4 */
16_bcm43xx_declare_plcp_hdr(4);
17/* struct bcm43xx_plcp_hdr6 */
18_bcm43xx_declare_plcp_hdr(6);
19
20#undef _bcm43xx_declare_plcp_hdr
21
22/* Device specific TX header. To be prepended to TX frames. */
23struct bcm43xx_txhdr {
24 union {
25 struct {
26 __le16 flags;
27 __le16 wsec_rate;
28 __le16 frame_control;
29 u16 unknown_zeroed_0;
30 __le16 control;
31 u8 wep_iv[10];
32 u8 unknown_wsec_tkip_data[3]; //FIXME
33 PAD_BYTES(3);
34 u8 mac1[6];
35 u16 unknown_zeroed_1;
36 struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
37 __le16 rts_cts_dur_fallback;
38 struct bcm43xx_plcp_hdr4 fallback_plcp;
39 __le16 fallback_dur_id;
40 PAD_BYTES(2);
41 __le16 cookie;
42 __le16 unknown_scb_stuff; //FIXME
43 struct bcm43xx_plcp_hdr6 rts_cts_plcp;
44 __le16 rts_cts_frame_control;
45 __le16 rts_cts_dur;
46 u8 rts_cts_mac1[6];
47 u8 rts_cts_mac2[6];
48 PAD_BYTES(2);
49 struct bcm43xx_plcp_hdr6 plcp;
50 } __attribute__((__packed__));
51 u8 raw[82];
52 } __attribute__((__packed__));
53} __attribute__((__packed__));
54
55/* Values/Masks for the device TX header */
56#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
57#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
58#define BCM43xx_TXHDRFLAG_RTS 0x0004
59#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
60#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
61#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
62#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
63#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
64#define BCM43xx_TXHDRFLAG_CTS 0x0400
65#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
66
67#define BCM43xx_TXHDRCTL_OFDM 0x0001
68#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
69#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
70#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
71
72#define BCM43xx_TXHDR_RATE_MASK 0x0F00
73#define BCM43xx_TXHDR_RATE_SHIFT 8
74#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
75#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
76#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
77#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
78#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
79#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
80
81void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
82 struct bcm43xx_txhdr *txhdr,
83 const unsigned char *fragment_data,
84 const unsigned int fragment_len,
85 const int is_first_fragment,
86 const u16 cookie);
87
88/* RX header as received from the hardware. */
89struct bcm43xx_rxhdr {
90 /* Frame Length. Must be generated explicitly in PIO mode. */
91 __le16 frame_length;
92 PAD_BYTES(2);
93 /* Flags field 1 */
94 __le16 flags1;
95 u8 rssi;
96 u8 signal_quality;
97 PAD_BYTES(2);
98 /* Flags field 3 */
99 __le16 flags3;
100 /* Flags field 2 */
101 __le16 flags2;
102 /* Lower 16bits of the TSF at the time the frame started. */
103 __le16 mactime;
104 PAD_BYTES(14);
105} __attribute__((__packed__));
106
107#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
108/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
109#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
110#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
111
112#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
113#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
114/*FIXME: WEP related flags */
115
116#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
117
118/* Transmit Status as received from the hardware. */
119struct bcm43xx_hwxmitstatus {
120 PAD_BYTES(4);
121 __le16 cookie;
122 u8 flags;
123 u8 cnt1:4,
124 cnt2:4;
125 PAD_BYTES(2);
126 __le16 seq;
127 __le16 unknown; //FIXME
128} __attribute__((__packed__));
129
130/* Transmit Status in CPU byteorder. */
131struct bcm43xx_xmitstatus {
132 u16 cookie;
133 u8 flags;
134 u8 cnt1:4,
135 cnt2:4;
136 u16 seq;
137 u16 unknown; //FIXME
138};
139
140#define BCM43xx_TXSTAT_FLAG_AMPDU 0x10
141#define BCM43xx_TXSTAT_FLAG_INTER 0x20
142
143u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
144u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
145
146int bcm43xx_rx(struct bcm43xx_private *bcm,
147 struct sk_buff *skb,
148 struct bcm43xx_rxhdr *rxhdr);
149
150#endif /* BCM43xx_XMIT_H_ */