aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/b43/Kconfig119
-rw-r--r--drivers/net/wireless/b43/Makefile17
-rw-r--r--drivers/net/wireless/b43/b43.h845
-rw-r--r--drivers/net/wireless/b43/debugfs.c654
-rw-r--r--drivers/net/wireless/b43/debugfs.h89
-rw-r--r--drivers/net/wireless/b43/dma.c1494
-rw-r--r--drivers/net/wireless/b43/dma.h337
-rw-r--r--drivers/net/wireless/b43/leds.c299
-rw-r--r--drivers/net/wireless/b43/leds.h55
-rw-r--r--drivers/net/wireless/b43/lo.c1261
-rw-r--r--drivers/net/wireless/b43/lo.h112
-rw-r--r--drivers/net/wireless/b43/main.c4091
-rw-r--r--drivers/net/wireless/b43/main.h142
-rw-r--r--drivers/net/wireless/b43/pcmcia.c157
-rw-r--r--drivers/net/wireless/b43/pcmcia.h20
-rw-r--r--drivers/net/wireless/b43/phy.c4351
-rw-r--r--drivers/net/wireless/b43/phy.h297
-rw-r--r--drivers/net/wireless/b43/pio.c650
-rw-r--r--drivers/net/wireless/b43/pio.h153
-rw-r--r--drivers/net/wireless/b43/sysfs.c235
-rw-r--r--drivers/net/wireless/b43/sysfs.h9
-rw-r--r--drivers/net/wireless/b43/tables.c375
-rw-r--r--drivers/net/wireless/b43/tables.h28
-rw-r--r--drivers/net/wireless/b43/xmit.c648
-rw-r--r--drivers/net/wireless/b43/xmit.h250
27 files changed, 16690 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 8d1541bbe257..7bed87e63da2 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -579,6 +579,7 @@ config ADM8211
579 579
580source "drivers/net/wireless/hostap/Kconfig" 580source "drivers/net/wireless/hostap/Kconfig"
581source "drivers/net/wireless/bcm43xx/Kconfig" 581source "drivers/net/wireless/bcm43xx/Kconfig"
582source "drivers/net/wireless/b43/Kconfig"
582source "drivers/net/wireless/zd1211rw/Kconfig" 583source "drivers/net/wireless/zd1211rw/Kconfig"
583 584
584endmenu 585endmenu
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index e9bffdae0a04..765dbbcf54be 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_PRISM54) += prism54/
36 36
37obj-$(CONFIG_HOSTAP) += hostap/ 37obj-$(CONFIG_HOSTAP) += hostap/
38obj-$(CONFIG_BCM43XX) += bcm43xx/ 38obj-$(CONFIG_BCM43XX) += bcm43xx/
39obj-$(CONFIG_B43) += b43/
39obj-$(CONFIG_ZD1211RW) += zd1211rw/ 40obj-$(CONFIG_ZD1211RW) += zd1211rw/
40 41
41# 16-bit wireless PCMCIA client drivers 42# 16-bit wireless PCMCIA client drivers
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
new file mode 100644
index 000000000000..4620119891f2
--- /dev/null
+++ b/drivers/net/wireless/b43/Kconfig
@@ -0,0 +1,119 @@
1config B43
2 tristate "Broadcom 43xx wireless support (mac80211 stack)"
3 depends on SSB_POSSIBLE && MAC80211 && WLAN_80211
4 select SSB
5 select FW_LOADER
6 select HW_RANDOM
7 ---help---
8 b43 is a driver for the Broadcom 43xx series wireless devices.
9
10 Check "lspci" for something like
11 "Broadcom Corporation BCM43XX 802.11 Wireless LAN Controller"
12 to determine whether you own such a device.
13
14 This driver supports the new BCM43xx IEEE 802.11G devices, but not
15 the old IEEE 802.11B devices. Old devices are supported by
16 the b43legacy driver.
17 Note that this has nothing to do with the standard that your AccessPoint
18 supports (A, B, G or a combination).
19 IEEE 802.11G devices can talk to IEEE 802.11B AccessPoints.
20
21 It is safe to include both b43 and b43legacy as the underlying glue
22 layer will automatically load the correct version for your device.
23
24 This driver uses V4 firmware, which must be installed separately using
25 b43-fwcutter.
26
27 This driver can be built as a module (recommended) that will be called "b43".
28 If unsure, say M.
29
30# Auto-select SSB PCI-HOST support, if possible
31config B43_PCI_AUTOSELECT
32 bool
33 depends on B43 && SSB_PCIHOST_POSSIBLE
34 select SSB_PCIHOST
35 default y
36
37# Auto-select SSB PCICORE driver, if possible
38config B43_PCICORE_AUTOSELECT
39 bool
40 depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE
41 select SSB_DRIVER_PCICORE
42 default y
43
44config B43_PCMCIA
45 bool "Broadcom 43xx PCMCIA device support (EXPERIMENTAL)"
46 depends on B43 && SSB_PCMCIAHOST_POSSIBLE && EXPERIMENTAL
47 select SSB_PCMCIAHOST
48 ---help---
49 Broadcom 43xx PCMCIA device support.
50
51 Support for 16bit PCMCIA devices.
52 Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA
53 devices, but 32bit CardBUS devices. CardBUS devices are supported
54 out of the box by b43.
55
56 With this config option you can drive b43 cards in
57 CompactFlash formfactor in a PCMCIA adaptor.
58 CF b43 cards can sometimes be found in handheld PCs.
59
60 It's safe to select Y here, even if you don't have a B43 PCMCIA device.
61
62 If unsure, say N.
63
64config B43_DEBUG
65 bool "Broadcom 43xx debugging"
66 depends on B43
67 ---help---
68 Broadcom 43xx debugging messages.
69
70 Say Y, if you want to find out why the driver does not
71 work for you.
72
73config B43_DMA
74 bool
75 depends on B43
76config B43_PIO
77 bool
78 depends on B43
79
80choice
81 prompt "Broadcom 43xx data transfer mode"
82 depends on B43
83 default B43_DMA_AND_PIO_MODE
84
85config B43_DMA_AND_PIO_MODE
86 bool "DMA + PIO"
87 select B43_DMA
88 select B43_PIO
89 ---help---
90 Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
91 data transfer modes.
92 The actually used mode is selectable through the module
93 parameter "pio". If the module parameter is pio=0, DMA is used.
94 Otherwise PIO is used. DMA is default.
95
96 If unsure, choose this option.
97
98config B43_DMA_MODE
99 bool "DMA (Direct Memory Access) only"
100 select B43_DMA
101 ---help---
102 Only include Direct Memory Access (DMA).
103 This reduces the size of the driver module, by omitting the PIO code.
104
105config B43_PIO_MODE
106 bool "PIO (Programmed I/O) only"
107 select B43_PIO
108 ---help---
109 Only include Programmed I/O (PIO).
110 This reduces the size of the driver module, by omitting the DMA code.
111 Please note that PIO transfers are slow (compared to DMA).
112
113 Also note that not all devices of the 43xx series support PIO.
114 The 4306 (Apple Airport Extreme and others) supports PIO, while
115 the 4318 is known to _not_ support PIO.
116
117 Only use PIO, if DMA does not work for you.
118
119endchoice
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
new file mode 100644
index 000000000000..370935b84c5e
--- /dev/null
+++ b/drivers/net/wireless/b43/Makefile
@@ -0,0 +1,17 @@
1# b43 core
2b43-y += main.o
3b43-y += tables.o
4b43-y += phy.o
5b43-y += sysfs.o
6b43-y += leds.o
7b43-y += xmit.o
8b43-y += lo.o
9# b43 PCMCIA support
10b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
11# b43 debugging
12b43-$(CONFIG_B43_DEBUG) += debugfs.o
13# b43 DMA and PIO
14b43-$(CONFIG_B43_DMA) += dma.o
15b43-$(CONFIG_B43_PIO) += pio.o
16
17obj-$(CONFIG_B43) += b43.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
new file mode 100644
index 000000000000..270a2112de2a
--- /dev/null
+++ b/drivers/net/wireless/b43/b43.h
@@ -0,0 +1,845 @@
1#ifndef B43_H_
2#define B43_H_
3
4#include <linux/kernel.h>
5#include <linux/spinlock.h>
6#include <linux/interrupt.h>
7#include <linux/hw_random.h>
8#include <linux/ssb/ssb.h>
9#include <net/mac80211.h>
10
11#include "debugfs.h"
12#include "leds.h"
13#include "lo.h"
14#include "phy.h"
15
16#ifdef CONFIG_B43_DEBUG
17# define B43_DEBUG 1
18#else
19# define B43_DEBUG 0
20#endif
21
22#define B43_RX_MAX_SSI 60
23
24/* MMIO offsets */
25#define B43_MMIO_DMA0_REASON 0x20
26#define B43_MMIO_DMA0_IRQ_MASK 0x24
27#define B43_MMIO_DMA1_REASON 0x28
28#define B43_MMIO_DMA1_IRQ_MASK 0x2C
29#define B43_MMIO_DMA2_REASON 0x30
30#define B43_MMIO_DMA2_IRQ_MASK 0x34
31#define B43_MMIO_DMA3_REASON 0x38
32#define B43_MMIO_DMA3_IRQ_MASK 0x3C
33#define B43_MMIO_DMA4_REASON 0x40
34#define B43_MMIO_DMA4_IRQ_MASK 0x44
35#define B43_MMIO_DMA5_REASON 0x48
36#define B43_MMIO_DMA5_IRQ_MASK 0x4C
37#define B43_MMIO_MACCTL 0x120
38#define B43_MMIO_STATUS2_BITFIELD 0x124
39#define B43_MMIO_GEN_IRQ_REASON 0x128
40#define B43_MMIO_GEN_IRQ_MASK 0x12C
41#define B43_MMIO_RAM_CONTROL 0x130
42#define B43_MMIO_RAM_DATA 0x134
43#define B43_MMIO_PS_STATUS 0x140
44#define B43_MMIO_RADIO_HWENABLED_HI 0x158
45#define B43_MMIO_SHM_CONTROL 0x160
46#define B43_MMIO_SHM_DATA 0x164
47#define B43_MMIO_SHM_DATA_UNALIGNED 0x166
48#define B43_MMIO_XMITSTAT_0 0x170
49#define B43_MMIO_XMITSTAT_1 0x174
50#define B43_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
51#define B43_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
52
53/* 32-bit DMA */
54#define B43_MMIO_DMA32_BASE0 0x200
55#define B43_MMIO_DMA32_BASE1 0x220
56#define B43_MMIO_DMA32_BASE2 0x240
57#define B43_MMIO_DMA32_BASE3 0x260
58#define B43_MMIO_DMA32_BASE4 0x280
59#define B43_MMIO_DMA32_BASE5 0x2A0
60/* 64-bit DMA */
61#define B43_MMIO_DMA64_BASE0 0x200
62#define B43_MMIO_DMA64_BASE1 0x240
63#define B43_MMIO_DMA64_BASE2 0x280
64#define B43_MMIO_DMA64_BASE3 0x2C0
65#define B43_MMIO_DMA64_BASE4 0x300
66#define B43_MMIO_DMA64_BASE5 0x340
67/* PIO */
68#define B43_MMIO_PIO1_BASE 0x300
69#define B43_MMIO_PIO2_BASE 0x310
70#define B43_MMIO_PIO3_BASE 0x320
71#define B43_MMIO_PIO4_BASE 0x330
72
73#define B43_MMIO_PHY_VER 0x3E0
74#define B43_MMIO_PHY_RADIO 0x3E2
75#define B43_MMIO_PHY0 0x3E6
76#define B43_MMIO_ANTENNA 0x3E8
77#define B43_MMIO_CHANNEL 0x3F0
78#define B43_MMIO_CHANNEL_EXT 0x3F4
79#define B43_MMIO_RADIO_CONTROL 0x3F6
80#define B43_MMIO_RADIO_DATA_HIGH 0x3F8
81#define B43_MMIO_RADIO_DATA_LOW 0x3FA
82#define B43_MMIO_PHY_CONTROL 0x3FC
83#define B43_MMIO_PHY_DATA 0x3FE
84#define B43_MMIO_MACFILTER_CONTROL 0x420
85#define B43_MMIO_MACFILTER_DATA 0x422
86#define B43_MMIO_RCMTA_COUNT 0x43C
87#define B43_MMIO_RADIO_HWENABLED_LO 0x49A
88#define B43_MMIO_GPIO_CONTROL 0x49C
89#define B43_MMIO_GPIO_MASK 0x49E
90#define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
91#define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
92#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
93#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
94#define B43_MMIO_RNG 0x65A
95#define B43_MMIO_POWERUP_DELAY 0x6A8
96
97/* SPROM boardflags_lo values */
98#define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
99#define B43_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
100#define B43_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */
101#define B43_BFL_RSSI 0x0008 /* software calculates nrssi slope. */
102#define B43_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */
103#define B43_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */
104#define B43_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */
105#define B43_BFL_ENETADM 0x0080 /* has ADMtek switch */
106#define B43_BFL_ENETVLAN 0x0100 /* can do vlan */
107#define B43_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */
108#define B43_BFL_NOPCI 0x0400 /* leaves PCI floating */
109#define B43_BFL_FEM 0x0800 /* supports the Front End Module */
110#define B43_BFL_EXTLNA 0x1000 /* has an external LNA */
111#define B43_BFL_HGPA 0x2000 /* had high gain PA */
112#define B43_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
113#define B43_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
114
115/* GPIO register offset, in both ChipCommon and PCI core. */
116#define B43_GPIO_CONTROL 0x6c
117
118/* SHM Routing */
119enum {
120 B43_SHM_UCODE, /* Microcode memory */
121 B43_SHM_SHARED, /* Shared memory */
122 B43_SHM_SCRATCH, /* Scratch memory */
123 B43_SHM_HW, /* Internal hardware register */
124 B43_SHM_RCMTA, /* Receive match transmitter address (rev >= 5 only) */
125};
126/* SHM Routing modifiers */
127#define B43_SHM_AUTOINC_R 0x0200 /* Auto-increment address on read */
128#define B43_SHM_AUTOINC_W 0x0100 /* Auto-increment address on write */
129#define B43_SHM_AUTOINC_RW (B43_SHM_AUTOINC_R | \
130 B43_SHM_AUTOINC_W)
131
132/* Misc SHM_SHARED offsets */
133#define B43_SHM_SH_WLCOREREV 0x0016 /* 802.11 core revision */
134#define B43_SHM_SH_PCTLWDPOS 0x0008
135#define B43_SHM_SH_RXPADOFF 0x0034 /* RX Padding data offset (PIO only) */
136#define B43_SHM_SH_PHYVER 0x0050 /* PHY version */
137#define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
138#define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
139#define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
140#define B43_SHM_SH_HOSTFHI 0x0060 /* Hostflags for ucode options (high) */
141#define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */
142#define B43_SHM_SH_RADAR 0x0066 /* Radar register */
143#define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
144#define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */
145#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
146#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */
147#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
148/* SHM_SHARED TX FIFO variables */
149#define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */
150#define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */
151#define B43_SHM_SH_SIZE45 0x009C /* TX FIFO size for FIFO 4 and 5 */
152#define B43_SHM_SH_SIZE67 0x009E /* TX FIFO size for FIFO 6 and 7 */
153/* SHM_SHARED background noise */
154#define B43_SHM_SH_JSSI0 0x0088 /* Measure JSSI 0 */
155#define B43_SHM_SH_JSSI1 0x008A /* Measure JSSI 1 */
156#define B43_SHM_SH_JSSIAUX 0x008C /* Measure JSSI AUX */
157/* SHM_SHARED crypto engine */
158#define B43_SHM_SH_DEFAULTIV 0x003C /* Default IV location */
159#define B43_SHM_SH_NRRXTRANS 0x003E /* # of soft RX transmitter addresses (max 8) */
160#define B43_SHM_SH_KTP 0x0056 /* Key table pointer */
161#define B43_SHM_SH_TKIPTSCTTAK 0x0318
162#define B43_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block (v4 firmware) */
163#define B43_SHM_SH_PSM 0x05F4 /* PSM transmitter address match block (rev < 5) */
164/* SHM_SHARED WME variables */
165#define B43_SHM_SH_EDCFSTAT 0x000E /* EDCF status */
166#define B43_SHM_SH_TXFCUR 0x0030 /* TXF current index */
167#define B43_SHM_SH_EDCFQ 0x0240 /* EDCF Q info */
168/* SHM_SHARED powersave mode related */
169#define B43_SHM_SH_SLOTT 0x0010 /* Slot time */
170#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */
171#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */
172/* SHM_SHARED beacon variables */
173#define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
174#define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
175#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
176#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */
177#define B43_SHM_SH_SFFBLIM 0x0044 /* Short frame fallback retry limit */
178#define B43_SHM_SH_LFFBLIM 0x0046 /* Long frame fallback retry limit */
179#define B43_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word (see PHY TX control) */
180/* SHM_SHARED ACK/CTS control */
181#define B43_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word (see PHY TX control) */
182/* SHM_SHARED probe response variables */
183#define B43_SHM_SH_PRSSID 0x0160 /* Probe Response SSID */
184#define B43_SHM_SH_PRSSIDLEN 0x0048 /* Probe Response SSID length */
185#define B43_SHM_SH_PRTLEN 0x004A /* Probe Response template length */
186#define B43_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
187#define B43_SHM_SH_PRPHYCTL 0x0188 /* Probe Response PHY TX control word */
188/* SHM_SHARED rate tables */
189#define B43_SHM_SH_OFDMDIRECT 0x01C0 /* Pointer to OFDM direct map */
190#define B43_SHM_SH_OFDMBASIC 0x01E0 /* Pointer to OFDM basic rate map */
191#define B43_SHM_SH_CCKDIRECT 0x0200 /* Pointer to CCK direct map */
192#define B43_SHM_SH_CCKBASIC 0x0220 /* Pointer to CCK basic rate map */
193/* SHM_SHARED microcode soft registers */
194#define B43_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
195#define B43_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */
196#define B43_SHM_SH_UCODEDATE 0x0004 /* Microcode date */
197#define B43_SHM_SH_UCODETIME 0x0006 /* Microcode time */
198#define B43_SHM_SH_UCODESTAT 0x0040 /* Microcode debug status code */
199#define B43_SHM_SH_UCODESTAT_INVALID 0
200#define B43_SHM_SH_UCODESTAT_INIT 1
201#define B43_SHM_SH_UCODESTAT_ACTIVE 2
202#define B43_SHM_SH_UCODESTAT_SUSP 3 /* suspended */
203#define B43_SHM_SH_UCODESTAT_SLEEP 4 /* asleep (PS) */
204#define B43_SHM_SH_MAXBFRAMES 0x0080 /* Maximum number of frames in a burst */
205#define B43_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */
206#define B43_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */
207
208/* SHM_SCRATCH offsets */
209#define B43_SHM_SC_MINCONT 0x0003 /* Minimum contention window */
210#define B43_SHM_SC_MAXCONT 0x0004 /* Maximum contention window */
211#define B43_SHM_SC_CURCONT 0x0005 /* Current contention window */
212#define B43_SHM_SC_SRLIMIT 0x0006 /* Short retry count limit */
213#define B43_SHM_SC_LRLIMIT 0x0007 /* Long retry count limit */
214#define B43_SHM_SC_DTIMC 0x0008 /* Current DTIM count */
215#define B43_SHM_SC_BTL0LEN 0x0015 /* Beacon 0 template length */
216#define B43_SHM_SC_BTL1LEN 0x0016 /* Beacon 1 template length */
217#define B43_SHM_SC_SCFB 0x0017 /* Short frame transmit count threshold for rate fallback */
218#define B43_SHM_SC_LCFB 0x0018 /* Long frame transmit count threshold for rate fallback */
219
220/* Hardware Radio Enable masks */
221#define B43_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
222#define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
223
224/* HostFlags. See b43_hf_read/write() */
225#define B43_HF_ANTDIVHELP 0x00000001 /* ucode antenna div helper */
226#define B43_HF_SYMW 0x00000002 /* G-PHY SYM workaround */
227#define B43_HF_RXPULLW 0x00000004 /* RX pullup workaround */
228#define B43_HF_CCKBOOST 0x00000008 /* 4dB CCK power boost (exclusive with OFDM boost) */
229#define B43_HF_BTCOEX 0x00000010 /* Bluetooth coexistance */
230#define B43_HF_GDCW 0x00000020 /* G-PHY DV canceller filter bw workaround */
231#define B43_HF_OFDMPABOOST 0x00000040 /* Enable PA gain boost for OFDM */
232#define B43_HF_ACPR 0x00000080 /* Disable for Japan, channel 14 */
233#define B43_HF_EDCF 0x00000100 /* on if WME and MAC suspended */
234#define B43_HF_TSSIRPSMW 0x00000200 /* TSSI reset PSM ucode workaround */
235#define B43_HF_DSCRQ 0x00000400 /* Disable slow clock request in ucode */
236#define B43_HF_ACIW 0x00000800 /* ACI workaround: shift bits by 2 on PHY CRS */
237#define B43_HF_2060W 0x00001000 /* 2060 radio workaround */
238#define B43_HF_RADARW 0x00002000 /* Radar workaround */
239#define B43_HF_USEDEFKEYS 0x00004000 /* Enable use of default keys */
240#define B43_HF_BT4PRIOCOEX 0x00010000 /* Bluetooth 2-priority coexistance */
241#define B43_HF_FWKUP 0x00020000 /* Fast wake-up ucode */
242#define B43_HF_VCORECALC 0x00040000 /* Force VCO recalculation when powering up synthpu */
243#define B43_HF_PCISCW 0x00080000 /* PCI slow clock workaround */
244#define B43_HF_4318TSSI 0x00200000 /* 4318 TSSI */
245#define B43_HF_FBCMCFIFO 0x00400000 /* Flush bcast/mcast FIFO immediately */
246#define B43_HF_HWPCTL 0x00800000 /* Enable hardwarre power control */
247#define B43_HF_BTCOEXALT 0x01000000 /* Bluetooth coexistance in alternate pins */
248#define B43_HF_TXBTCHECK 0x02000000 /* Bluetooth check during transmission */
249#define B43_HF_SKCFPUP 0x04000000 /* Skip CFP update */
250
251/* MacFilter offsets. */
252#define B43_MACFILTER_SELF 0x0000
253#define B43_MACFILTER_BSSID 0x0003
254
255/* PowerControl */
256#define B43_PCTL_IN 0xB0
257#define B43_PCTL_OUT 0xB4
258#define B43_PCTL_OUTENABLE 0xB8
259#define B43_PCTL_XTAL_POWERUP 0x40
260#define B43_PCTL_PLL_POWERDOWN 0x80
261
262/* PowerControl Clock Modes */
263#define B43_PCTL_CLK_FAST 0x00
264#define B43_PCTL_CLK_SLOW 0x01
265#define B43_PCTL_CLK_DYNAMIC 0x02
266
267#define B43_PCTL_FORCE_SLOW 0x0800
268#define B43_PCTL_FORCE_PLL 0x1000
269#define B43_PCTL_DYN_XTAL 0x2000
270
271/* PHYVersioning */
272#define B43_PHYTYPE_A 0x00
273#define B43_PHYTYPE_B 0x01
274#define B43_PHYTYPE_G 0x02
275
276/* PHYRegisters */
277#define B43_PHY_ILT_A_CTRL 0x0072
278#define B43_PHY_ILT_A_DATA1 0x0073
279#define B43_PHY_ILT_A_DATA2 0x0074
280#define B43_PHY_G_LO_CONTROL 0x0810
281#define B43_PHY_ILT_G_CTRL 0x0472
282#define B43_PHY_ILT_G_DATA1 0x0473
283#define B43_PHY_ILT_G_DATA2 0x0474
284#define B43_PHY_A_PCTL 0x007B
285#define B43_PHY_G_PCTL 0x0029
286#define B43_PHY_A_CRS 0x0029
287#define B43_PHY_RADIO_BITFIELD 0x0401
288#define B43_PHY_G_CRS 0x0429
289#define B43_PHY_NRSSILT_CTRL 0x0803
290#define B43_PHY_NRSSILT_DATA 0x0804
291
292/* RadioRegisters */
293#define B43_RADIOCTL_ID 0x01
294
295/* MAC Control bitfield */
296#define B43_MACCTL_ENABLED 0x00000001 /* MAC Enabled */
297#define B43_MACCTL_PSM_RUN 0x00000002 /* Run Microcode */
298#define B43_MACCTL_PSM_JMP0 0x00000004 /* Microcode jump to 0 */
299#define B43_MACCTL_SHM_ENABLED 0x00000100 /* SHM Enabled */
300#define B43_MACCTL_SHM_UPPER 0x00000200 /* SHM Upper */
301#define B43_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */
302#define B43_MACCTL_PSM_DBG 0x00002000 /* Microcode debugging enabled */
303#define B43_MACCTL_GPOUTSMSK 0x0000C000 /* GPOUT Select Mask */
304#define B43_MACCTL_BE 0x00010000 /* Big Endian mode */
305#define B43_MACCTL_INFRA 0x00020000 /* Infrastructure mode */
306#define B43_MACCTL_AP 0x00040000 /* AccessPoint mode */
307#define B43_MACCTL_RADIOLOCK 0x00080000 /* Radio lock */
308#define B43_MACCTL_BEACPROMISC 0x00100000 /* Beacon Promiscuous */
309#define B43_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep frames with bad PLCP */
310#define B43_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */
311#define B43_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */
312#define B43_MACCTL_PROMISC 0x01000000 /* Promiscuous mode */
313#define B43_MACCTL_HWPS 0x02000000 /* Hardware Power Saving */
314#define B43_MACCTL_AWAKE 0x04000000 /* Device is awake */
315#define B43_MACCTL_CLOSEDNET 0x08000000 /* Closed net (no SSID bcast) */
316#define B43_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */
317#define B43_MACCTL_DISCTXSTAT 0x20000000 /* Discard TX status */
318#define B43_MACCTL_DISCPMQ 0x40000000 /* Discard Power Management Queue */
319#define B43_MACCTL_GMODE 0x80000000 /* G Mode */
320
321/* 802.11 core specific TM State Low flags */
322#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
323#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select */
324#define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */
325#define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */
326#define B43_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */
327
328/* 802.11 core specific TM State High flags */
329#define B43_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available (rev >= 5) */
330#define B43_TMSHIGH_APHY 0x00020000 /* A-PHY available (rev >= 5) */
331#define B43_TMSHIGH_GPHY 0x00010000 /* G-PHY available (rev >= 5) */
332
333/* Generic-Interrupt reasons. */
334#define B43_IRQ_MAC_SUSPENDED 0x00000001
335#define B43_IRQ_BEACON 0x00000002
336#define B43_IRQ_TBTT_INDI 0x00000004
337#define B43_IRQ_BEACON_TX_OK 0x00000008
338#define B43_IRQ_BEACON_CANCEL 0x00000010
339#define B43_IRQ_ATIM_END 0x00000020
340#define B43_IRQ_PMQ 0x00000040
341#define B43_IRQ_PIO_WORKAROUND 0x00000100
342#define B43_IRQ_MAC_TXERR 0x00000200
343#define B43_IRQ_PHY_TXERR 0x00000800
344#define B43_IRQ_PMEVENT 0x00001000
345#define B43_IRQ_TIMER0 0x00002000
346#define B43_IRQ_TIMER1 0x00004000
347#define B43_IRQ_DMA 0x00008000
348#define B43_IRQ_TXFIFO_FLUSH_OK 0x00010000
349#define B43_IRQ_CCA_MEASURE_OK 0x00020000
350#define B43_IRQ_NOISESAMPLE_OK 0x00040000
351#define B43_IRQ_UCODE_DEBUG 0x08000000
352#define B43_IRQ_RFKILL 0x10000000
353#define B43_IRQ_TX_OK 0x20000000
354#define B43_IRQ_PHY_G_CHANGED 0x40000000
355#define B43_IRQ_TIMEOUT 0x80000000
356
357#define B43_IRQ_ALL 0xFFFFFFFF
358#define B43_IRQ_MASKTEMPLATE (B43_IRQ_MAC_SUSPENDED | \
359 B43_IRQ_BEACON | \
360 B43_IRQ_TBTT_INDI | \
361 B43_IRQ_ATIM_END | \
362 B43_IRQ_PMQ | \
363 B43_IRQ_MAC_TXERR | \
364 B43_IRQ_PHY_TXERR | \
365 B43_IRQ_DMA | \
366 B43_IRQ_TXFIFO_FLUSH_OK | \
367 B43_IRQ_NOISESAMPLE_OK | \
368 B43_IRQ_UCODE_DEBUG | \
369 B43_IRQ_RFKILL | \
370 B43_IRQ_TX_OK)
371
372/* Device specific rate values.
373 * The actual values defined here are (rate_in_mbps * 2).
374 * Some code depends on this. Don't change it. */
375#define B43_CCK_RATE_1MB 0x02
376#define B43_CCK_RATE_2MB 0x04
377#define B43_CCK_RATE_5MB 0x0B
378#define B43_CCK_RATE_11MB 0x16
379#define B43_OFDM_RATE_6MB 0x0C
380#define B43_OFDM_RATE_9MB 0x12
381#define B43_OFDM_RATE_12MB 0x18
382#define B43_OFDM_RATE_18MB 0x24
383#define B43_OFDM_RATE_24MB 0x30
384#define B43_OFDM_RATE_36MB 0x48
385#define B43_OFDM_RATE_48MB 0x60
386#define B43_OFDM_RATE_54MB 0x6C
387/* Convert a b43 rate value to a rate in 100kbps */
388#define B43_RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
389
390#define B43_DEFAULT_SHORT_RETRY_LIMIT 7
391#define B43_DEFAULT_LONG_RETRY_LIMIT 4
392
393/* Max size of a security key */
394#define B43_SEC_KEYSIZE 16
395/* Security algorithms. */
396enum {
397 B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
398 B43_SEC_ALGO_WEP40,
399 B43_SEC_ALGO_TKIP,
400 B43_SEC_ALGO_AES,
401 B43_SEC_ALGO_WEP104,
402 B43_SEC_ALGO_AES_LEGACY,
403};
404
405struct b43_dmaring;
406struct b43_pioqueue;
407
408/* The firmware file header */
409#define B43_FW_TYPE_UCODE 'u'
410#define B43_FW_TYPE_PCM 'p'
411#define B43_FW_TYPE_IV 'i'
412struct b43_fw_header {
413 /* File type */
414 u8 type;
415 /* File format version */
416 u8 ver;
417 u8 __padding[2];
418 /* Size of the data. For ucode and PCM this is in bytes.
419 * For IV this is number-of-ivs. */
420 __be32 size;
421} __attribute__((__packed__));
422
423/* Initial Value file format */
424#define B43_IV_OFFSET_MASK 0x7FFF
425#define B43_IV_32BIT 0x8000
426struct b43_iv {
427 __be16 offset_size;
428 union {
429 __be16 d16;
430 __be32 d32;
431 } data __attribute__((__packed__));
432} __attribute__((__packed__));
433
434
435#define B43_PHYMODE(phytype) (1 << (phytype))
436#define B43_PHYMODE_A B43_PHYMODE(B43_PHYTYPE_A)
437#define B43_PHYMODE_B B43_PHYMODE(B43_PHYTYPE_B)
438#define B43_PHYMODE_G B43_PHYMODE(B43_PHYTYPE_G)
439
440struct b43_phy {
441 /* Possible PHYMODEs on this PHY */
442 u8 possible_phymodes;
443 /* GMODE bit enabled? */
444 bool gmode;
445 /* Possible ieee80211 subsystem hwmodes for this PHY.
446 * Which mode is selected, depends on thr GMODE enabled bit */
447#define B43_MAX_PHYHWMODES 2
448 struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES];
449
450 /* Analog Type */
451 u8 analog;
452 /* B43_PHYTYPE_ */
453 u8 type;
454 /* PHY revision number. */
455 u8 rev;
456
457 /* Radio versioning */
458 u16 radio_manuf; /* Radio manufacturer */
459 u16 radio_ver; /* Radio version */
460 u8 radio_rev; /* Radio revision */
461
462 bool radio_on; /* Radio switched on/off */
463 bool locked; /* Only used in b43_phy_{un}lock() */
464 bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
465
466 /* ACI (adjacent channel interference) flags. */
467 bool aci_enable;
468 bool aci_wlan_automatic;
469 bool aci_hw_rssi;
470
471 u16 minlowsig[2];
472 u16 minlowsigpos[2];
473
474 /* TSSI to dBm table in use */
475 const s8 *tssi2dbm;
476 /* Target idle TSSI */
477 int tgt_idle_tssi;
478 /* Current idle TSSI */
479 int cur_idle_tssi;
480
481 /* LocalOscillator control values. */
482 struct b43_txpower_lo_control *lo_control;
483 /* Values from b43_calc_loopback_gain() */
484 s16 max_lb_gain; /* Maximum Loopback gain in hdB */
485 s16 trsw_rx_gain; /* TRSW RX gain in hdB */
486 s16 lna_lod_gain; /* LNA lod */
487 s16 lna_gain; /* LNA */
488 s16 pga_gain; /* PGA */
489
490 /* PHY lock for core.rev < 3
491 * This lock is only used by b43_phy_{un}lock()
492 */
493 spinlock_t lock;
494
495 /* Desired TX power level (in dBm).
496 * This is set by the user and adjusted in b43_phy_xmitpower(). */
497 u8 power_level;
498 /* A-PHY TX Power control value. */
499 u16 txpwr_offset;
500
501 /* Current TX power level attenuation control values */
502 struct b43_bbatt bbatt;
503 struct b43_rfatt rfatt;
504 u8 tx_control; /* B43_TXCTL_XXX */
505#ifdef CONFIG_B43_DEBUG
506 bool manual_txpower_control; /* Manual TX-power control enabled? */
507#endif
508 /* Hardware Power Control enabled? */
509 bool hardware_power_control;
510
511 /* Current Interference Mitigation mode */
512 int interfmode;
513 /* Stack of saved values from the Interference Mitigation code.
514 * Each value in the stack is layed out as follows:
515 * bit 0-11: offset
516 * bit 12-15: register ID
517 * bit 16-32: value
518 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
519 */
520#define B43_INTERFSTACK_SIZE 26
521 u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure
522
523 /* Saved values from the NRSSI Slope calculation */
524 s16 nrssi[2];
525 s32 nrssislope;
526 /* In memory nrssi lookup table. */
527 s8 nrssi_lt[64];
528
529 /* current channel */
530 u8 channel;
531
532 u16 lofcal;
533
534 u16 initval; //FIXME rename?
535};
536
537/* Data structures for DMA transmission, per 80211 core. */
538struct b43_dma {
539 struct b43_dmaring *tx_ring0;
540 struct b43_dmaring *tx_ring1;
541 struct b43_dmaring *tx_ring2;
542 struct b43_dmaring *tx_ring3;
543 struct b43_dmaring *tx_ring4;
544 struct b43_dmaring *tx_ring5;
545
546 struct b43_dmaring *rx_ring0;
547 struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */
548};
549
550/* Data structures for PIO transmission, per 80211 core. */
551struct b43_pio {
552 struct b43_pioqueue *queue0;
553 struct b43_pioqueue *queue1;
554 struct b43_pioqueue *queue2;
555 struct b43_pioqueue *queue3;
556};
557
558/* Context information for a noise calculation (Link Quality). */
559struct b43_noise_calculation {
560 u8 channel_at_start;
561 bool calculation_running;
562 u8 nr_samples;
563 s8 samples[8][4];
564};
565
566struct b43_stats {
567 u8 link_noise;
568 /* Store the last TX/RX times here for updating the leds. */
569 unsigned long last_tx;
570 unsigned long last_rx;
571};
572
573struct b43_key {
574 /* If keyconf is NULL, this key is disabled.
575 * keyconf is a cookie. Don't derefenrence it outside of the set_key
576 * path, because b43 doesn't own it. */
577 struct ieee80211_key_conf *keyconf;
578 u8 algorithm;
579};
580
581struct b43_wldev;
582
583/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
584struct b43_wl {
585 /* Pointer to the active wireless device on this chip */
586 struct b43_wldev *current_dev;
587 /* Pointer to the ieee80211 hardware data structure */
588 struct ieee80211_hw *hw;
589
590 spinlock_t irq_lock;
591 struct mutex mutex;
592 spinlock_t leds_lock;
593
594 /* We can only have one operating interface (802.11 core)
595 * at a time. General information about this interface follows.
596 */
597
598 /* Opaque ID of the operating interface (!= monitor
599 * interface) from the ieee80211 subsystem.
600 * Do not modify.
601 */
602 int if_id;
603 /* The MAC address of the operating interface. */
604 u8 mac_addr[ETH_ALEN];
605 /* Current BSSID */
606 u8 bssid[ETH_ALEN];
607 /* Interface type. (IEEE80211_IF_TYPE_XXX) */
608 int if_type;
609 /* Counter of active monitor interfaces. */
610 int monitor;
611 /* Is the card operating in AP, STA or IBSS mode? */
612 bool operating;
613 /* Promisc mode active?
614 * Note that (monitor != 0) implies promisc.
615 */
616 bool promisc;
617 /* Stats about the wireless interface */
618 struct ieee80211_low_level_stats ieee_stats;
619
620 struct hwrng rng;
621 u8 rng_initialized;
622 char rng_name[30 + 1];
623
624 /* List of all wireless devices on this chip */
625 struct list_head devlist;
626 u8 nr_devs;
627};
628
629/* Pointers to the firmware data and meta information about it. */
630struct b43_firmware {
631 /* Microcode */
632 const struct firmware *ucode;
633 /* PCM code */
634 const struct firmware *pcm;
635 /* Initial MMIO values for the firmware */
636 const struct firmware *initvals;
637 /* Initial MMIO values for the firmware, band-specific */
638 const struct firmware *initvals_band;
639 /* Firmware revision */
640 u16 rev;
641 /* Firmware patchlevel */
642 u16 patch;
643};
644
645/* Device (802.11 core) initialization status. */
646enum {
647 B43_STAT_UNINIT = 0, /* Uninitialized. */
648 B43_STAT_INITIALIZED = 1, /* Initialized, but not started, yet. */
649 B43_STAT_STARTED = 2, /* Up and running. */
650};
651#define b43_status(wldev) atomic_read(&(wldev)->__init_status)
652#define b43_set_status(wldev, stat) do { \
653 atomic_set(&(wldev)->__init_status, (stat)); \
654 smp_wmb(); \
655 } while (0)
656
657/* XXX--- HOW LOCKING WORKS IN B43 ---XXX
658 *
659 * You should always acquire both, wl->mutex and wl->irq_lock unless:
660 * - You don't need to acquire wl->irq_lock, if the interface is stopped.
661 * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet
662 * and packet TX path (and _ONLY_ there.)
663 */
664
665/* Data structure for one wireless device (802.11 core) */
666struct b43_wldev {
667 struct ssb_device *dev;
668 struct b43_wl *wl;
669
670 /* The device initialization status.
671 * Use b43_status() to query. */
672 atomic_t __init_status;
673 /* Saved init status for handling suspend. */
674 int suspend_init_status;
675
676 bool __using_pio; /* Internal, use b43_using_pio(). */
677 bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
678 bool reg124_set_0x4; /* Some variable to keep track of IRQ stuff. */
679 bool short_preamble; /* TRUE, if short preamble is enabled. */
680 bool short_slot; /* TRUE, if short slot timing is enabled. */
681 bool radio_hw_enable; /* saved state of radio hardware enabled state */
682
683 /* PHY/Radio device. */
684 struct b43_phy phy;
685 union {
686 /* DMA engines. */
687 struct b43_dma dma;
688 /* PIO engines. */
689 struct b43_pio pio;
690 };
691
692 /* Various statistics about the physical device. */
693 struct b43_stats stats;
694
695#define B43_NR_LEDS 4
696 struct b43_led leds[B43_NR_LEDS];
697
698 /* Reason code of the last interrupt. */
699 u32 irq_reason;
700 u32 dma_reason[6];
701 /* saved irq enable/disable state bitfield. */
702 u32 irq_savedstate;
703 /* Link Quality calculation context. */
704 struct b43_noise_calculation noisecalc;
705 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
706 int mac_suspended;
707
708 /* Interrupt Service Routine tasklet (bottom-half) */
709 struct tasklet_struct isr_tasklet;
710
711 /* Periodic tasks */
712 struct delayed_work periodic_work;
713 unsigned int periodic_state;
714
715 struct work_struct restart_work;
716
717 /* encryption/decryption */
718 u16 ktp; /* Key table pointer */
719 u8 max_nr_keys;
720 struct b43_key key[58];
721
722 /* Cached beacon template while uploading the template. */
723 struct sk_buff *cached_beacon;
724
725 /* Firmware data */
726 struct b43_firmware fw;
727
728 /* Devicelist in struct b43_wl (all 802.11 cores) */
729 struct list_head list;
730
731 /* Debugging stuff follows. */
732#ifdef CONFIG_B43_DEBUG
733 struct b43_dfsentry *dfsentry;
734#endif
735};
736
737static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
738{
739 return hw->priv;
740}
741
742/* Helper function, which returns a boolean.
743 * TRUE, if PIO is used; FALSE, if DMA is used.
744 */
745#if defined(CONFIG_B43_DMA) && defined(CONFIG_B43_PIO)
746static inline int b43_using_pio(struct b43_wldev *dev)
747{
748 return dev->__using_pio;
749}
750#elif defined(CONFIG_B43_DMA)
751static inline int b43_using_pio(struct b43_wldev *dev)
752{
753 return 0;
754}
755#elif defined(CONFIG_B43_PIO)
756static inline int b43_using_pio(struct b43_wldev *dev)
757{
758 return 1;
759}
760#else
761# error "Using neither DMA nor PIO? Confused..."
762#endif
763
764static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev)
765{
766 struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
767 return ssb_get_drvdata(ssb_dev);
768}
769
770/* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */
771static inline int b43_is_mode(struct b43_wl *wl, int type)
772{
773 if (type == IEEE80211_IF_TYPE_MNTR)
774 return !!(wl->monitor);
775 return (wl->operating && wl->if_type == type);
776}
777
778static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
779{
780 return ssb_read16(dev->dev, offset);
781}
782
783static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
784{
785 ssb_write16(dev->dev, offset, value);
786}
787
788static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
789{
790 return ssb_read32(dev->dev, offset);
791}
792
793static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
794{
795 ssb_write32(dev->dev, offset, value);
796}
797
798/* Message printing */
799void b43info(struct b43_wl *wl, const char *fmt, ...)
800 __attribute__ ((format(printf, 2, 3)));
801void b43err(struct b43_wl *wl, const char *fmt, ...)
802 __attribute__ ((format(printf, 2, 3)));
803void b43warn(struct b43_wl *wl, const char *fmt, ...)
804 __attribute__ ((format(printf, 2, 3)));
805#if B43_DEBUG
806void b43dbg(struct b43_wl *wl, const char *fmt, ...)
807 __attribute__ ((format(printf, 2, 3)));
808#else /* DEBUG */
809# define b43dbg(wl, fmt...) do { /* nothing */ } while (0)
810#endif /* DEBUG */
811
812/* A WARN_ON variant that vanishes when b43 debugging is disabled.
813 * This _also_ evaluates the arg with debugging disabled. */
814#if B43_DEBUG
815# define B43_WARN_ON(x) WARN_ON(x)
816#else
817static inline bool __b43_warn_on_dummy(bool x) { return x; }
818# define B43_WARN_ON(x) __b43_warn_on_dummy(unlikely(!!(x)))
819#endif
820
821/** Limit a value between two limits */
822#ifdef limit_value
823# undef limit_value
824#endif
825#define limit_value(value, min, max) \
826 ({ \
827 typeof(value) __value = (value); \
828 typeof(value) __min = (min); \
829 typeof(value) __max = (max); \
830 if (__value < __min) \
831 __value = __min; \
832 else if (__value > __max) \
833 __value = __max; \
834 __value; \
835 })
836
837/* Convert an integer to a Q5.2 value */
838#define INT_TO_Q52(i) ((i) << 2)
839/* Convert a Q5.2 value to an integer (precision loss!) */
840#define Q52_TO_INT(q52) ((q52) >> 2)
841/* Macros for printing a value in Q5.2 format */
842#define Q52_FMT "%u.%u"
843#define Q52_ARG(q52) Q52_TO_INT(q52), ((((q52) & 0x3) * 100) / 4)
844
845#endif /* B43_H_ */
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
new file mode 100644
index 000000000000..f82e3ef9bd73
--- /dev/null
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -0,0 +1,654 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 debugfs driver debugging code
6
7 Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.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 <linux/fs.h>
27#include <linux/debugfs.h>
28#include <linux/slab.h>
29#include <linux/netdevice.h>
30#include <linux/pci.h>
31#include <linux/mutex.h>
32
33#include "b43.h"
34#include "main.h"
35#include "debugfs.h"
36#include "dma.h"
37#include "pio.h"
38#include "xmit.h"
39
40
41/* The root directory. */
42struct dentry *rootdir;
43
44struct b43_debugfs_fops {
45 ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
46 int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
47 struct file_operations fops;
48 /* Offset of struct b43_dfs_file in struct b43_dfsentry */
49 size_t file_struct_offset;
50 /* Take wl->irq_lock before calling read/write? */
51 bool take_irqlock;
52};
53
54static inline
55struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev,
56 const struct b43_debugfs_fops *dfops)
57{
58 void *p;
59
60 p = dev->dfsentry;
61 p += dfops->file_struct_offset;
62
63 return p;
64}
65
66
67#define fappend(fmt, x...) \
68 do { \
69 if (bufsize - count) \
70 count += snprintf(buf + count, \
71 bufsize - count, \
72 fmt , ##x); \
73 else \
74 printk(KERN_ERR "b43: fappend overflow\n"); \
75 } while (0)
76
77
78/* wl->irq_lock is locked */
79ssize_t tsf_read_file(struct b43_wldev *dev, char *buf, size_t bufsize)
80{
81 ssize_t count = 0;
82 u64 tsf;
83
84 b43_tsf_read(dev, &tsf);
85 fappend("0x%08x%08x\n",
86 (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
87 (unsigned int)(tsf & 0xFFFFFFFFULL));
88
89 return count;
90}
91
92/* wl->irq_lock is locked */
93int tsf_write_file(struct b43_wldev *dev, const char *buf, size_t count)
94{
95 u64 tsf;
96
97 if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1)
98 return -EINVAL;
99 b43_tsf_write(dev, tsf);
100
101 return 0;
102}
103
104/* wl->irq_lock is locked */
105ssize_t ucode_regs_read_file(struct b43_wldev *dev, char *buf, size_t bufsize)
106{
107 ssize_t count = 0;
108 int i;
109
110 for (i = 0; i < 64; i++) {
111 fappend("r%d = 0x%04x\n", i,
112 b43_shm_read16(dev, B43_SHM_SCRATCH, i));
113 }
114
115 return count;
116}
117
118/* wl->irq_lock is locked */
119ssize_t shm_read_file(struct b43_wldev *dev, char *buf, size_t bufsize)
120{
121 ssize_t count = 0;
122 int i;
123 u16 tmp;
124 __le16 *le16buf = (__le16 *)buf;
125
126 for (i = 0; i < 0x1000; i++) {
127 if (bufsize <= 0)
128 break;
129 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i);
130 le16buf[i] = cpu_to_le16(tmp);
131 count += sizeof(tmp);
132 bufsize -= sizeof(tmp);
133 }
134
135 return count;
136}
137
138ssize_t txstat_read_file(struct b43_wldev *dev, char *buf, size_t bufsize)
139{
140 struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
141 ssize_t count = 0;
142 unsigned long flags;
143 int i, idx;
144 struct b43_txstatus *stat;
145
146 spin_lock_irqsave(&log->lock, flags);
147 if (log->end < 0) {
148 fappend("Nothing transmitted, yet\n");
149 goto out_unlock;
150 }
151 fappend("b43 TX status reports:\n\n"
152 "index | cookie | seq | phy_stat | frame_count | "
153 "rts_count | supp_reason | pm_indicated | "
154 "intermediate | for_ampdu | acked\n" "---\n");
155 i = log->end + 1;
156 idx = 0;
157 while (1) {
158 if (i == B43_NR_LOGGED_TXSTATUS)
159 i = 0;
160 stat = &(log->log[i]);
161 if (stat->cookie) {
162 fappend("%03d | "
163 "0x%04X | 0x%04X | 0x%02X | "
164 "0x%X | 0x%X | "
165 "%u | %u | "
166 "%u | %u | %u\n",
167 idx,
168 stat->cookie, stat->seq, stat->phy_stat,
169 stat->frame_count, stat->rts_count,
170 stat->supp_reason, stat->pm_indicated,
171 stat->intermediate, stat->for_ampdu,
172 stat->acked);
173 idx++;
174 }
175 if (i == log->end)
176 break;
177 i++;
178 }
179out_unlock:
180 spin_unlock_irqrestore(&log->lock, flags);
181
182 return count;
183}
184
185ssize_t txpower_g_read_file(struct b43_wldev *dev, char *buf, size_t bufsize)
186{
187 ssize_t count = 0;
188
189 if (dev->phy.type != B43_PHYTYPE_G) {
190 fappend("Device is not a G-PHY\n");
191 goto out;
192 }
193 fappend("Control: %s\n", dev->phy.manual_txpower_control ?
194 "MANUAL" : "AUTOMATIC");
195 fappend("Baseband attenuation: %u\n", dev->phy.bbatt.att);
196 fappend("Radio attenuation: %u\n", dev->phy.rfatt.att);
197 fappend("TX Mixer Gain: %s\n",
198 (dev->phy.tx_control & B43_TXCTL_TXMIX) ? "ON" : "OFF");
199 fappend("PA Gain 2dB: %s\n",
200 (dev->phy.tx_control & B43_TXCTL_PA2DB) ? "ON" : "OFF");
201 fappend("PA Gain 3dB: %s\n",
202 (dev->phy.tx_control & B43_TXCTL_PA3DB) ? "ON" : "OFF");
203 fappend("\n\n");
204 fappend("You can write to this file:\n");
205 fappend("Writing \"auto\" enables automatic txpower control.\n");
206 fappend
207 ("Writing the attenuation values as \"bbatt rfatt txmix pa2db pa3db\" "
208 "enables manual txpower control.\n");
209 fappend("Example: 5 4 0 0 1\n");
210 fappend("Enables manual control with Baseband attenuation 5, "
211 "Radio attenuation 4, No TX Mixer Gain, "
212 "No PA Gain 2dB, With PA Gain 3dB.\n");
213out:
214 return count;
215}
216
217int txpower_g_write_file(struct b43_wldev *dev, const char *buf, size_t count)
218{
219 unsigned long flags;
220 unsigned long phy_flags;
221 int err = 0;
222
223 spin_lock_irqsave(&dev->wl->irq_lock, flags);
224 if (dev->phy.type != B43_PHYTYPE_G) {
225 err = -ENODEV;
226 goto out_unlock;
227 }
228 if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) {
229 /* Automatic control */
230 dev->phy.manual_txpower_control = 0;
231 b43_phy_xmitpower(dev);
232 } else {
233 int bbatt = 0, rfatt = 0, txmix = 0, pa2db = 0, pa3db = 0;
234 /* Manual control */
235 if (sscanf(buf, "%d %d %d %d %d", &bbatt, &rfatt,
236 &txmix, &pa2db, &pa3db) != 5) {
237 err = -EINVAL;
238 goto out_unlock;
239 }
240 b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
241 dev->phy.manual_txpower_control = 1;
242 dev->phy.bbatt.att = bbatt;
243 dev->phy.rfatt.att = rfatt;
244 dev->phy.tx_control = 0;
245 if (txmix)
246 dev->phy.tx_control |= B43_TXCTL_TXMIX;
247 if (pa2db)
248 dev->phy.tx_control |= B43_TXCTL_PA2DB;
249 if (pa3db)
250 dev->phy.tx_control |= B43_TXCTL_PA3DB;
251 b43_phy_lock(dev, phy_flags);
252 b43_radio_lock(dev);
253 b43_set_txpower_g(dev, &dev->phy.bbatt,
254 &dev->phy.rfatt, dev->phy.tx_control);
255 b43_radio_unlock(dev);
256 b43_phy_unlock(dev, phy_flags);
257 }
258out_unlock:
259 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
260
261 return err;
262}
263
264/* wl->irq_lock is locked */
265int restart_write_file(struct b43_wldev *dev, const char *buf, size_t count)
266{
267 int err = 0;
268
269 if (count > 0 && buf[0] == '1') {
270 b43_controller_restart(dev, "manually restarted");
271 } else
272 err = -EINVAL;
273
274 return err;
275}
276
277static ssize_t append_lo_table(ssize_t count, char *buf, const size_t bufsize,
278 struct b43_loctl table[B43_NR_BB][B43_NR_RF])
279{
280 unsigned int i, j;
281 struct b43_loctl *ctl;
282
283 for (i = 0; i < B43_NR_BB; i++) {
284 for (j = 0; j < B43_NR_RF; j++) {
285 ctl = &(table[i][j]);
286 fappend("(bbatt %2u, rfatt %2u) -> "
287 "(I %+3d, Q %+3d, Used: %d, Calibrated: %d)\n",
288 i, j, ctl->i, ctl->q,
289 ctl->used,
290 b43_loctl_is_calibrated(ctl));
291 }
292 }
293
294 return count;
295}
296
297ssize_t loctls_read_file(struct b43_wldev *dev, char *buf, size_t bufsize)
298{
299 ssize_t count = 0;
300 struct b43_txpower_lo_control *lo;
301 int i, err = 0;
302
303 if (dev->phy.type != B43_PHYTYPE_G) {
304 fappend("Device is not a G-PHY\n");
305 err = -ENODEV;
306 goto out;
307 }
308 lo = dev->phy.lo_control;
309 fappend("-- Local Oscillator calibration data --\n\n");
310 fappend("Measured: %d, Rebuild: %d, HW-power-control: %d\n",
311 lo->lo_measured,
312 lo->rebuild,
313 dev->phy.hardware_power_control);
314 fappend("TX Bias: 0x%02X, TX Magn: 0x%02X\n",
315 lo->tx_bias, lo->tx_magn);
316 fappend("Power Vector: 0x%08X%08X\n",
317 (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32),
318 (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL));
319 fappend("\nControl table WITH PADMIX:\n");
320 count = append_lo_table(count, buf, bufsize, lo->with_padmix);
321 fappend("\nControl table WITHOUT PADMIX:\n");
322 count = append_lo_table(count, buf, bufsize, lo->no_padmix);
323 fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n");
324 for (i = 0; i < lo->rfatt_list.len; i++) {
325 fappend("%u(%d), ",
326 lo->rfatt_list.list[i].att,
327 lo->rfatt_list.list[i].with_padmix);
328 }
329 fappend("\n");
330 fappend("\nUsed Baseband attenuation values:\n");
331 for (i = 0; i < lo->bbatt_list.len; i++) {
332 fappend("%u, ",
333 lo->bbatt_list.list[i].att);
334 }
335 fappend("\n");
336
337out:
338 return err ? err : count;
339}
340
341#undef fappend
342
343static int b43_debugfs_open(struct inode *inode, struct file *file)
344{
345 file->private_data = inode->i_private;
346 return 0;
347}
348
349static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
350 size_t count, loff_t *ppos)
351{
352 struct b43_wldev *dev;
353 struct b43_debugfs_fops *dfops;
354 struct b43_dfs_file *dfile;
355 ssize_t ret;
356 char *buf;
357 const size_t bufsize = 1024 * 128;
358 const size_t buforder = get_order(bufsize);
359 int err = 0;
360
361 if (!count)
362 return 0;
363 dev = file->private_data;
364 if (!dev)
365 return -ENODEV;
366
367 mutex_lock(&dev->wl->mutex);
368 if (b43_status(dev) < B43_STAT_INITIALIZED) {
369 err = -ENODEV;
370 goto out_unlock;
371 }
372
373 dfops = container_of(file->f_op, struct b43_debugfs_fops, fops);
374 if (!dfops->read) {
375 err = -ENOSYS;
376 goto out_unlock;
377 }
378 dfile = fops_to_dfs_file(dev, dfops);
379
380 if (!dfile->buffer) {
381 buf = (char *)__get_free_pages(GFP_KERNEL, buforder);
382 if (!buf) {
383 err = -ENOMEM;
384 goto out_unlock;
385 }
386 memset(buf, 0, bufsize);
387 if (dfops->take_irqlock) {
388 spin_lock_irq(&dev->wl->irq_lock);
389 ret = dfops->read(dev, buf, bufsize);
390 spin_unlock_irq(&dev->wl->irq_lock);
391 } else
392 ret = dfops->read(dev, buf, bufsize);
393 if (ret <= 0) {
394 free_pages((unsigned long)buf, buforder);
395 err = ret;
396 goto out_unlock;
397 }
398 dfile->data_len = ret;
399 dfile->buffer = buf;
400 }
401
402 ret = simple_read_from_buffer(userbuf, count, ppos,
403 dfile->buffer,
404 dfile->data_len);
405 if (*ppos >= dfile->data_len) {
406 free_pages((unsigned long)dfile->buffer, buforder);
407 dfile->buffer = NULL;
408 dfile->data_len = 0;
409 }
410out_unlock:
411 mutex_unlock(&dev->wl->mutex);
412
413 return err ? err : ret;
414}
415
416static ssize_t b43_debugfs_write(struct file *file,
417 const char __user *userbuf,
418 size_t count, loff_t *ppos)
419{
420 struct b43_wldev *dev;
421 struct b43_debugfs_fops *dfops;
422 char *buf;
423 int err = 0;
424
425 if (!count)
426 return 0;
427 if (count > PAGE_SIZE)
428 return -E2BIG;
429 dev = file->private_data;
430 if (!dev)
431 return -ENODEV;
432
433 mutex_lock(&dev->wl->mutex);
434 if (b43_status(dev) < B43_STAT_INITIALIZED) {
435 err = -ENODEV;
436 goto out_unlock;
437 }
438
439 dfops = container_of(file->f_op, struct b43_debugfs_fops, fops);
440 if (!dfops->write) {
441 err = -ENOSYS;
442 goto out_unlock;
443 }
444
445 buf = (char *)get_zeroed_page(GFP_KERNEL);
446 if (!buf) {
447 err = -ENOMEM;
448 goto out_unlock;
449 }
450 if (copy_from_user(buf, userbuf, count)) {
451 err = -EFAULT;
452 goto out_freepage;
453 }
454 if (dfops->take_irqlock) {
455 spin_lock_irq(&dev->wl->irq_lock);
456 err = dfops->write(dev, buf, count);
457 spin_unlock_irq(&dev->wl->irq_lock);
458 } else
459 err = dfops->write(dev, buf, count);
460 if (err)
461 goto out_freepage;
462
463out_freepage:
464 free_page((unsigned long)buf);
465out_unlock:
466 mutex_unlock(&dev->wl->mutex);
467
468 return err ? err : count;
469}
470
471
472#define B43_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \
473 static struct b43_debugfs_fops fops_##name = { \
474 .read = _read, \
475 .write = _write, \
476 .fops = { \
477 .open = b43_debugfs_open, \
478 .read = b43_debugfs_read, \
479 .write = b43_debugfs_write, \
480 }, \
481 .file_struct_offset = offsetof(struct b43_dfsentry, \
482 file_##name), \
483 .take_irqlock = _take_irqlock, \
484 }
485
486B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
487B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1);
488B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1);
489B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
490B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0);
491B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
492B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);
493
494
495int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
496{
497 return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
498}
499
500static void b43_remove_dynamic_debug(struct b43_wldev *dev)
501{
502 struct b43_dfsentry *e = dev->dfsentry;
503 int i;
504
505 for (i = 0; i < __B43_NR_DYNDBG; i++)
506 debugfs_remove(e->dyn_debug_dentries[i]);
507}
508
509static void b43_add_dynamic_debug(struct b43_wldev *dev)
510{
511 struct b43_dfsentry *e = dev->dfsentry;
512 struct dentry *d;
513
514#define add_dyn_dbg(name, id, initstate) do { \
515 e->dyn_debug[id] = (initstate); \
516 d = debugfs_create_bool(name, 0600, e->subdir, \
517 &(e->dyn_debug[id])); \
518 if (!IS_ERR(d)) \
519 e->dyn_debug_dentries[id] = d; \
520 } while (0)
521
522 add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, 0);
523 add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, 0);
524 add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0);
525 add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0);
526 add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
527
528#undef add_dyn_dbg
529}
530
531void b43_debugfs_add_device(struct b43_wldev *dev)
532{
533 struct b43_dfsentry *e;
534 struct b43_txstatus_log *log;
535 char devdir[16];
536
537 B43_WARN_ON(!dev);
538 e = kzalloc(sizeof(*e), GFP_KERNEL);
539 if (!e) {
540 b43err(dev->wl, "debugfs: add device OOM\n");
541 return;
542 }
543 e->dev = dev;
544 log = &e->txstatlog;
545 log->log = kcalloc(B43_NR_LOGGED_TXSTATUS,
546 sizeof(struct b43_txstatus), GFP_KERNEL);
547 if (!log->log) {
548 b43err(dev->wl, "debugfs: add device txstatus OOM\n");
549 kfree(e);
550 return;
551 }
552 log->end = -1;
553 spin_lock_init(&log->lock);
554
555 dev->dfsentry = e;
556
557 snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
558 e->subdir = debugfs_create_dir(devdir, rootdir);
559 if (!e->subdir || IS_ERR(e->subdir)) {
560 if (e->subdir == ERR_PTR(-ENODEV)) {
561 b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not "
562 "enabled in kernel config\n");
563 } else {
564 b43err(dev->wl, "debugfs: cannot create %s directory\n",
565 devdir);
566 }
567 dev->dfsentry = NULL;
568 kfree(log->log);
569 kfree(e);
570 return;
571 }
572
573#define ADD_FILE(name, mode) \
574 do { \
575 struct dentry *d; \
576 d = debugfs_create_file(__stringify(name), \
577 mode, e->subdir, dev, \
578 &fops_##name.fops); \
579 e->file_##name.dentry = NULL; \
580 if (!IS_ERR(d)) \
581 e->file_##name.dentry = d; \
582 } while (0)
583
584
585 ADD_FILE(tsf, 0600);
586 ADD_FILE(ucode_regs, 0400);
587 ADD_FILE(shm, 0400);
588 ADD_FILE(txstat, 0400);
589 ADD_FILE(txpower_g, 0600);
590 ADD_FILE(restart, 0200);
591 ADD_FILE(loctls, 0400);
592
593#undef ADD_FILE
594
595 b43_add_dynamic_debug(dev);
596}
597
598void b43_debugfs_remove_device(struct b43_wldev *dev)
599{
600 struct b43_dfsentry *e;
601
602 if (!dev)
603 return;
604 e = dev->dfsentry;
605 if (!e)
606 return;
607 b43_remove_dynamic_debug(dev);
608
609 debugfs_remove(e->file_tsf.dentry);
610 debugfs_remove(e->file_ucode_regs.dentry);
611 debugfs_remove(e->file_shm.dentry);
612 debugfs_remove(e->file_txstat.dentry);
613 debugfs_remove(e->file_txpower_g.dentry);
614 debugfs_remove(e->file_restart.dentry);
615 debugfs_remove(e->file_loctls.dentry);
616
617 debugfs_remove(e->subdir);
618 kfree(e->txstatlog.log);
619 kfree(e);
620}
621
622void b43_debugfs_log_txstat(struct b43_wldev *dev,
623 const struct b43_txstatus *status)
624{
625 struct b43_dfsentry *e = dev->dfsentry;
626 struct b43_txstatus_log *log;
627 struct b43_txstatus *cur;
628 int i;
629
630 if (!e)
631 return;
632 log = &e->txstatlog;
633 B43_WARN_ON(!irqs_disabled());
634 spin_lock(&log->lock);
635 i = log->end + 1;
636 if (i == B43_NR_LOGGED_TXSTATUS)
637 i = 0;
638 log->end = i;
639 cur = &(log->log[i]);
640 memcpy(cur, status, sizeof(*cur));
641 spin_unlock(&log->lock);
642}
643
644void b43_debugfs_init(void)
645{
646 rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
647 if (IS_ERR(rootdir))
648 rootdir = NULL;
649}
650
651void b43_debugfs_exit(void)
652{
653 debugfs_remove(rootdir);
654}
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
new file mode 100644
index 000000000000..6eebe858db5a
--- /dev/null
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -0,0 +1,89 @@
1#ifndef B43_DEBUGFS_H_
2#define B43_DEBUGFS_H_
3
4struct b43_wldev;
5struct b43_txstatus;
6
7enum b43_dyndbg { /* Dynamic debugging features */
8 B43_DBG_XMITPOWER,
9 B43_DBG_DMAOVERFLOW,
10 B43_DBG_DMAVERBOSE,
11 B43_DBG_PWORK_FAST,
12 B43_DBG_PWORK_STOP,
13 __B43_NR_DYNDBG,
14};
15
16#ifdef CONFIG_B43_DEBUG
17
18struct dentry;
19
20#define B43_NR_LOGGED_TXSTATUS 100
21
22struct b43_txstatus_log {
23 struct b43_txstatus *log;
24 int end;
25 spinlock_t lock;
26};
27
28struct b43_dfs_file {
29 struct dentry *dentry;
30 char *buffer;
31 size_t data_len;
32};
33
34struct b43_dfsentry {
35 struct b43_wldev *dev;
36 struct dentry *subdir;
37
38 struct b43_dfs_file file_tsf;
39 struct b43_dfs_file file_ucode_regs;
40 struct b43_dfs_file file_shm;
41 struct b43_dfs_file file_txstat;
42 struct b43_dfs_file file_txpower_g;
43 struct b43_dfs_file file_restart;
44 struct b43_dfs_file file_loctls;
45
46 struct b43_txstatus_log txstatlog;
47
48 /* Enabled/Disabled list for the dynamic debugging features. */
49 u32 dyn_debug[__B43_NR_DYNDBG];
50 /* Dentries for the dynamic debugging entries. */
51 struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG];
52};
53
54int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature);
55
56void b43_debugfs_init(void);
57void b43_debugfs_exit(void);
58void b43_debugfs_add_device(struct b43_wldev *dev);
59void b43_debugfs_remove_device(struct b43_wldev *dev);
60void b43_debugfs_log_txstat(struct b43_wldev *dev,
61 const struct b43_txstatus *status);
62
63#else /* CONFIG_B43_DEBUG */
64
65static inline int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
66{
67 return 0;
68}
69
70static inline void b43_debugfs_init(void)
71{
72}
73static inline void b43_debugfs_exit(void)
74{
75}
76static inline void b43_debugfs_add_device(struct b43_wldev *dev)
77{
78}
79static inline void b43_debugfs_remove_device(struct b43_wldev *dev)
80{
81}
82static inline void b43_debugfs_log_txstat(struct b43_wldev *dev,
83 const struct b43_txstatus *status)
84{
85}
86
87#endif /* CONFIG_B43_DEBUG */
88
89#endif /* B43_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
new file mode 100644
index 000000000000..5e8f8ac0f1dd
--- /dev/null
+++ b/drivers/net/wireless/b43/dma.c
@@ -0,0 +1,1494 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 DMA ringbuffer and descriptor allocation/management
6
7 Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.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 "b43.h"
31#include "dma.h"
32#include "main.h"
33#include "debugfs.h"
34#include "xmit.h"
35
36#include <linux/dma-mapping.h>
37#include <linux/pci.h>
38#include <linux/delay.h>
39#include <linux/skbuff.h>
40
41/* 32bit DMA ops. */
42static
43struct b43_dmadesc_generic *op32_idx2desc(struct b43_dmaring *ring,
44 int slot,
45 struct b43_dmadesc_meta **meta)
46{
47 struct b43_dmadesc32 *desc;
48
49 *meta = &(ring->meta[slot]);
50 desc = ring->descbase;
51 desc = &(desc[slot]);
52
53 return (struct b43_dmadesc_generic *)desc;
54}
55
56static void op32_fill_descriptor(struct b43_dmaring *ring,
57 struct b43_dmadesc_generic *desc,
58 dma_addr_t dmaaddr, u16 bufsize,
59 int start, int end, int irq)
60{
61 struct b43_dmadesc32 *descbase = ring->descbase;
62 int slot;
63 u32 ctl;
64 u32 addr;
65 u32 addrext;
66
67 slot = (int)(&(desc->dma32) - descbase);
68 B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
69
70 addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
71 addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK)
72 >> SSB_DMA_TRANSLATION_SHIFT;
73 addr |= ssb_dma_translation(ring->dev->dev);
74 ctl = (bufsize - ring->frameoffset)
75 & B43_DMA32_DCTL_BYTECNT;
76 if (slot == ring->nr_slots - 1)
77 ctl |= B43_DMA32_DCTL_DTABLEEND;
78 if (start)
79 ctl |= B43_DMA32_DCTL_FRAMESTART;
80 if (end)
81 ctl |= B43_DMA32_DCTL_FRAMEEND;
82 if (irq)
83 ctl |= B43_DMA32_DCTL_IRQ;
84 ctl |= (addrext << B43_DMA32_DCTL_ADDREXT_SHIFT)
85 & B43_DMA32_DCTL_ADDREXT_MASK;
86
87 desc->dma32.control = cpu_to_le32(ctl);
88 desc->dma32.address = cpu_to_le32(addr);
89}
90
91static void op32_poke_tx(struct b43_dmaring *ring, int slot)
92{
93 b43_dma_write(ring, B43_DMA32_TXINDEX,
94 (u32) (slot * sizeof(struct b43_dmadesc32)));
95}
96
97static void op32_tx_suspend(struct b43_dmaring *ring)
98{
99 b43_dma_write(ring, B43_DMA32_TXCTL, b43_dma_read(ring, B43_DMA32_TXCTL)
100 | B43_DMA32_TXSUSPEND);
101}
102
103static void op32_tx_resume(struct b43_dmaring *ring)
104{
105 b43_dma_write(ring, B43_DMA32_TXCTL, b43_dma_read(ring, B43_DMA32_TXCTL)
106 & ~B43_DMA32_TXSUSPEND);
107}
108
109static int op32_get_current_rxslot(struct b43_dmaring *ring)
110{
111 u32 val;
112
113 val = b43_dma_read(ring, B43_DMA32_RXSTATUS);
114 val &= B43_DMA32_RXDPTR;
115
116 return (val / sizeof(struct b43_dmadesc32));
117}
118
119static void op32_set_current_rxslot(struct b43_dmaring *ring, int slot)
120{
121 b43_dma_write(ring, B43_DMA32_RXINDEX,
122 (u32) (slot * sizeof(struct b43_dmadesc32)));
123}
124
125static const struct b43_dma_ops dma32_ops = {
126 .idx2desc = op32_idx2desc,
127 .fill_descriptor = op32_fill_descriptor,
128 .poke_tx = op32_poke_tx,
129 .tx_suspend = op32_tx_suspend,
130 .tx_resume = op32_tx_resume,
131 .get_current_rxslot = op32_get_current_rxslot,
132 .set_current_rxslot = op32_set_current_rxslot,
133};
134
135/* 64bit DMA ops. */
136static
137struct b43_dmadesc_generic *op64_idx2desc(struct b43_dmaring *ring,
138 int slot,
139 struct b43_dmadesc_meta **meta)
140{
141 struct b43_dmadesc64 *desc;
142
143 *meta = &(ring->meta[slot]);
144 desc = ring->descbase;
145 desc = &(desc[slot]);
146
147 return (struct b43_dmadesc_generic *)desc;
148}
149
150static void op64_fill_descriptor(struct b43_dmaring *ring,
151 struct b43_dmadesc_generic *desc,
152 dma_addr_t dmaaddr, u16 bufsize,
153 int start, int end, int irq)
154{
155 struct b43_dmadesc64 *descbase = ring->descbase;
156 int slot;
157 u32 ctl0 = 0, ctl1 = 0;
158 u32 addrlo, addrhi;
159 u32 addrext;
160
161 slot = (int)(&(desc->dma64) - descbase);
162 B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
163
164 addrlo = (u32) (dmaaddr & 0xFFFFFFFF);
165 addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
166 addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
167 >> SSB_DMA_TRANSLATION_SHIFT;
168 addrhi |= ssb_dma_translation(ring->dev->dev);
169 if (slot == ring->nr_slots - 1)
170 ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
171 if (start)
172 ctl0 |= B43_DMA64_DCTL0_FRAMESTART;
173 if (end)
174 ctl0 |= B43_DMA64_DCTL0_FRAMEEND;
175 if (irq)
176 ctl0 |= B43_DMA64_DCTL0_IRQ;
177 ctl1 |= (bufsize - ring->frameoffset)
178 & B43_DMA64_DCTL1_BYTECNT;
179 ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT)
180 & B43_DMA64_DCTL1_ADDREXT_MASK;
181
182 desc->dma64.control0 = cpu_to_le32(ctl0);
183 desc->dma64.control1 = cpu_to_le32(ctl1);
184 desc->dma64.address_low = cpu_to_le32(addrlo);
185 desc->dma64.address_high = cpu_to_le32(addrhi);
186}
187
188static void op64_poke_tx(struct b43_dmaring *ring, int slot)
189{
190 b43_dma_write(ring, B43_DMA64_TXINDEX,
191 (u32) (slot * sizeof(struct b43_dmadesc64)));
192}
193
194static void op64_tx_suspend(struct b43_dmaring *ring)
195{
196 b43_dma_write(ring, B43_DMA64_TXCTL, b43_dma_read(ring, B43_DMA64_TXCTL)
197 | B43_DMA64_TXSUSPEND);
198}
199
200static void op64_tx_resume(struct b43_dmaring *ring)
201{
202 b43_dma_write(ring, B43_DMA64_TXCTL, b43_dma_read(ring, B43_DMA64_TXCTL)
203 & ~B43_DMA64_TXSUSPEND);
204}
205
206static int op64_get_current_rxslot(struct b43_dmaring *ring)
207{
208 u32 val;
209
210 val = b43_dma_read(ring, B43_DMA64_RXSTATUS);
211 val &= B43_DMA64_RXSTATDPTR;
212
213 return (val / sizeof(struct b43_dmadesc64));
214}
215
216static void op64_set_current_rxslot(struct b43_dmaring *ring, int slot)
217{
218 b43_dma_write(ring, B43_DMA64_RXINDEX,
219 (u32) (slot * sizeof(struct b43_dmadesc64)));
220}
221
222static const struct b43_dma_ops dma64_ops = {
223 .idx2desc = op64_idx2desc,
224 .fill_descriptor = op64_fill_descriptor,
225 .poke_tx = op64_poke_tx,
226 .tx_suspend = op64_tx_suspend,
227 .tx_resume = op64_tx_resume,
228 .get_current_rxslot = op64_get_current_rxslot,
229 .set_current_rxslot = op64_set_current_rxslot,
230};
231
232static inline int free_slots(struct b43_dmaring *ring)
233{
234 return (ring->nr_slots - ring->used_slots);
235}
236
237static inline int next_slot(struct b43_dmaring *ring, int slot)
238{
239 B43_WARN_ON(!(slot >= -1 && slot <= ring->nr_slots - 1));
240 if (slot == ring->nr_slots - 1)
241 return 0;
242 return slot + 1;
243}
244
245static inline int prev_slot(struct b43_dmaring *ring, int slot)
246{
247 B43_WARN_ON(!(slot >= 0 && slot <= ring->nr_slots - 1));
248 if (slot == 0)
249 return ring->nr_slots - 1;
250 return slot - 1;
251}
252
253#ifdef CONFIG_B43_DEBUG
254static void update_max_used_slots(struct b43_dmaring *ring,
255 int current_used_slots)
256{
257 if (current_used_slots <= ring->max_used_slots)
258 return;
259 ring->max_used_slots = current_used_slots;
260 if (b43_debug(ring->dev, B43_DBG_DMAVERBOSE)) {
261 b43dbg(ring->dev->wl,
262 "max_used_slots increased to %d on %s ring %d\n",
263 ring->max_used_slots,
264 ring->tx ? "TX" : "RX", ring->index);
265 }
266}
267#else
268static inline
269 void update_max_used_slots(struct b43_dmaring *ring, int current_used_slots)
270{
271}
272#endif /* DEBUG */
273
274/* Request a slot for usage. */
275static inline int request_slot(struct b43_dmaring *ring)
276{
277 int slot;
278
279 B43_WARN_ON(!ring->tx);
280 B43_WARN_ON(ring->stopped);
281 B43_WARN_ON(free_slots(ring) == 0);
282
283 slot = next_slot(ring, ring->current_slot);
284 ring->current_slot = slot;
285 ring->used_slots++;
286
287 update_max_used_slots(ring, ring->used_slots);
288
289 return slot;
290}
291
292/* Mac80211-queue to b43-ring mapping */
293static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
294 int queue_priority)
295{
296 struct b43_dmaring *ring;
297
298/*FIXME: For now we always run on TX-ring-1 */
299 return dev->dma.tx_ring1;
300
301 /* 0 = highest priority */
302 switch (queue_priority) {
303 default:
304 B43_WARN_ON(1);
305 /* fallthrough */
306 case 0:
307 ring = dev->dma.tx_ring3;
308 break;
309 case 1:
310 ring = dev->dma.tx_ring2;
311 break;
312 case 2:
313 ring = dev->dma.tx_ring1;
314 break;
315 case 3:
316 ring = dev->dma.tx_ring0;
317 break;
318 case 4:
319 ring = dev->dma.tx_ring4;
320 break;
321 case 5:
322 ring = dev->dma.tx_ring5;
323 break;
324 }
325
326 return ring;
327}
328
329/* Bcm43xx-ring to mac80211-queue mapping */
330static inline int txring_to_priority(struct b43_dmaring *ring)
331{
332 static const u8 idx_to_prio[] = { 3, 2, 1, 0, 4, 5, };
333
334/*FIXME: have only one queue, for now */
335 return 0;
336
337 return idx_to_prio[ring->index];
338}
339
340u16 b43_dmacontroller_base(int dma64bit, int controller_idx)
341{
342 static const u16 map64[] = {
343 B43_MMIO_DMA64_BASE0,
344 B43_MMIO_DMA64_BASE1,
345 B43_MMIO_DMA64_BASE2,
346 B43_MMIO_DMA64_BASE3,
347 B43_MMIO_DMA64_BASE4,
348 B43_MMIO_DMA64_BASE5,
349 };
350 static const u16 map32[] = {
351 B43_MMIO_DMA32_BASE0,
352 B43_MMIO_DMA32_BASE1,
353 B43_MMIO_DMA32_BASE2,
354 B43_MMIO_DMA32_BASE3,
355 B43_MMIO_DMA32_BASE4,
356 B43_MMIO_DMA32_BASE5,
357 };
358
359 if (dma64bit) {
360 B43_WARN_ON(!(controller_idx >= 0 &&
361 controller_idx < ARRAY_SIZE(map64)));
362 return map64[controller_idx];
363 }
364 B43_WARN_ON(!(controller_idx >= 0 &&
365 controller_idx < ARRAY_SIZE(map32)));
366 return map32[controller_idx];
367}
368
369static inline
370 dma_addr_t map_descbuffer(struct b43_dmaring *ring,
371 unsigned char *buf, size_t len, int tx)
372{
373 dma_addr_t dmaaddr;
374
375 if (tx) {
376 dmaaddr = dma_map_single(ring->dev->dev->dev,
377 buf, len, DMA_TO_DEVICE);
378 } else {
379 dmaaddr = dma_map_single(ring->dev->dev->dev,
380 buf, len, DMA_FROM_DEVICE);
381 }
382
383 return dmaaddr;
384}
385
386static inline
387 void unmap_descbuffer(struct b43_dmaring *ring,
388 dma_addr_t addr, size_t len, int tx)
389{
390 if (tx) {
391 dma_unmap_single(ring->dev->dev->dev, addr, len, DMA_TO_DEVICE);
392 } else {
393 dma_unmap_single(ring->dev->dev->dev,
394 addr, len, DMA_FROM_DEVICE);
395 }
396}
397
398static inline
399 void sync_descbuffer_for_cpu(struct b43_dmaring *ring,
400 dma_addr_t addr, size_t len)
401{
402 B43_WARN_ON(ring->tx);
403 dma_sync_single_for_cpu(ring->dev->dev->dev,
404 addr, len, DMA_FROM_DEVICE);
405}
406
407static inline
408 void sync_descbuffer_for_device(struct b43_dmaring *ring,
409 dma_addr_t addr, size_t len)
410{
411 B43_WARN_ON(ring->tx);
412 dma_sync_single_for_device(ring->dev->dev->dev,
413 addr, len, DMA_FROM_DEVICE);
414}
415
416static inline
417 void free_descriptor_buffer(struct b43_dmaring *ring,
418 struct b43_dmadesc_meta *meta)
419{
420 if (meta->skb) {
421 dev_kfree_skb_any(meta->skb);
422 meta->skb = NULL;
423 }
424}
425
426static int alloc_ringmemory(struct b43_dmaring *ring)
427{
428 struct device *dev = ring->dev->dev->dev;
429
430 ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE,
431 &(ring->dmabase), GFP_KERNEL);
432 if (!ring->descbase) {
433 b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
434 return -ENOMEM;
435 }
436 memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
437
438 return 0;
439}
440
441static void free_ringmemory(struct b43_dmaring *ring)
442{
443 struct device *dev = ring->dev->dev->dev;
444
445 dma_free_coherent(dev, B43_DMA_RINGMEMSIZE,
446 ring->descbase, ring->dmabase);
447}
448
449/* Reset the RX DMA channel */
450int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
451{
452 int i;
453 u32 value;
454 u16 offset;
455
456 might_sleep();
457
458 offset = dma64 ? B43_DMA64_RXCTL : B43_DMA32_RXCTL;
459 b43_write32(dev, mmio_base + offset, 0);
460 for (i = 0; i < 10; i++) {
461 offset = dma64 ? B43_DMA64_RXSTATUS : B43_DMA32_RXSTATUS;
462 value = b43_read32(dev, mmio_base + offset);
463 if (dma64) {
464 value &= B43_DMA64_RXSTAT;
465 if (value == B43_DMA64_RXSTAT_DISABLED) {
466 i = -1;
467 break;
468 }
469 } else {
470 value &= B43_DMA32_RXSTATE;
471 if (value == B43_DMA32_RXSTAT_DISABLED) {
472 i = -1;
473 break;
474 }
475 }
476 msleep(1);
477 }
478 if (i != -1) {
479 b43err(dev->wl, "DMA RX reset timed out\n");
480 return -ENODEV;
481 }
482
483 return 0;
484}
485
486/* Reset the RX DMA channel */
487int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
488{
489 int i;
490 u32 value;
491 u16 offset;
492
493 might_sleep();
494
495 for (i = 0; i < 10; i++) {
496 offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS;
497 value = b43_read32(dev, mmio_base + offset);
498 if (dma64) {
499 value &= B43_DMA64_TXSTAT;
500 if (value == B43_DMA64_TXSTAT_DISABLED ||
501 value == B43_DMA64_TXSTAT_IDLEWAIT ||
502 value == B43_DMA64_TXSTAT_STOPPED)
503 break;
504 } else {
505 value &= B43_DMA32_TXSTATE;
506 if (value == B43_DMA32_TXSTAT_DISABLED ||
507 value == B43_DMA32_TXSTAT_IDLEWAIT ||
508 value == B43_DMA32_TXSTAT_STOPPED)
509 break;
510 }
511 msleep(1);
512 }
513 offset = dma64 ? B43_DMA64_TXCTL : B43_DMA32_TXCTL;
514 b43_write32(dev, mmio_base + offset, 0);
515 for (i = 0; i < 10; i++) {
516 offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS;
517 value = b43_read32(dev, mmio_base + offset);
518 if (dma64) {
519 value &= B43_DMA64_TXSTAT;
520 if (value == B43_DMA64_TXSTAT_DISABLED) {
521 i = -1;
522 break;
523 }
524 } else {
525 value &= B43_DMA32_TXSTATE;
526 if (value == B43_DMA32_TXSTAT_DISABLED) {
527 i = -1;
528 break;
529 }
530 }
531 msleep(1);
532 }
533 if (i != -1) {
534 b43err(dev->wl, "DMA TX reset timed out\n");
535 return -ENODEV;
536 }
537 /* ensure the reset is completed. */
538 msleep(1);
539
540 return 0;
541}
542
543static int setup_rx_descbuffer(struct b43_dmaring *ring,
544 struct b43_dmadesc_generic *desc,
545 struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
546{
547 struct b43_rxhdr_fw4 *rxhdr;
548 struct b43_hwtxstatus *txstat;
549 dma_addr_t dmaaddr;
550 struct sk_buff *skb;
551
552 B43_WARN_ON(ring->tx);
553
554 skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
555 if (unlikely(!skb))
556 return -ENOMEM;
557 dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
558 if (dma_mapping_error(dmaaddr)) {
559 /* ugh. try to realloc in zone_dma */
560 gfp_flags |= GFP_DMA;
561
562 dev_kfree_skb_any(skb);
563
564 skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
565 if (unlikely(!skb))
566 return -ENOMEM;
567 dmaaddr = map_descbuffer(ring, skb->data,
568 ring->rx_buffersize, 0);
569 }
570
571 if (dma_mapping_error(dmaaddr)) {
572 dev_kfree_skb_any(skb);
573 return -EIO;
574 }
575
576 meta->skb = skb;
577 meta->dmaaddr = dmaaddr;
578 ring->ops->fill_descriptor(ring, desc, dmaaddr,
579 ring->rx_buffersize, 0, 0, 0);
580
581 rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
582 rxhdr->frame_len = 0;
583 txstat = (struct b43_hwtxstatus *)(skb->data);
584 txstat->cookie = 0;
585
586 return 0;
587}
588
589/* Allocate the initial descbuffers.
590 * This is used for an RX ring only.
591 */
592static int alloc_initial_descbuffers(struct b43_dmaring *ring)
593{
594 int i, err = -ENOMEM;
595 struct b43_dmadesc_generic *desc;
596 struct b43_dmadesc_meta *meta;
597
598 for (i = 0; i < ring->nr_slots; i++) {
599 desc = ring->ops->idx2desc(ring, i, &meta);
600
601 err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
602 if (err) {
603 b43err(ring->dev->wl,
604 "Failed to allocate initial descbuffers\n");
605 goto err_unwind;
606 }
607 }
608 mb();
609 ring->used_slots = ring->nr_slots;
610 err = 0;
611 out:
612 return err;
613
614 err_unwind:
615 for (i--; i >= 0; i--) {
616 desc = ring->ops->idx2desc(ring, i, &meta);
617
618 unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
619 dev_kfree_skb(meta->skb);
620 }
621 goto out;
622}
623
624/* Do initial setup of the DMA controller.
625 * Reset the controller, write the ring busaddress
626 * and switch the "enable" bit on.
627 */
628static int dmacontroller_setup(struct b43_dmaring *ring)
629{
630 int err = 0;
631 u32 value;
632 u32 addrext;
633 u32 trans = ssb_dma_translation(ring->dev->dev);
634
635 if (ring->tx) {
636 if (ring->dma64) {
637 u64 ringbase = (u64) (ring->dmabase);
638
639 addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
640 >> SSB_DMA_TRANSLATION_SHIFT;
641 value = B43_DMA64_TXENABLE;
642 value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
643 & B43_DMA64_TXADDREXT_MASK;
644 b43_dma_write(ring, B43_DMA64_TXCTL, value);
645 b43_dma_write(ring, B43_DMA64_TXRINGLO,
646 (ringbase & 0xFFFFFFFF));
647 b43_dma_write(ring, B43_DMA64_TXRINGHI,
648 ((ringbase >> 32) &
649 ~SSB_DMA_TRANSLATION_MASK)
650 | trans);
651 } else {
652 u32 ringbase = (u32) (ring->dmabase);
653
654 addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
655 >> SSB_DMA_TRANSLATION_SHIFT;
656 value = B43_DMA32_TXENABLE;
657 value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
658 & B43_DMA32_TXADDREXT_MASK;
659 b43_dma_write(ring, B43_DMA32_TXCTL, value);
660 b43_dma_write(ring, B43_DMA32_TXRING,
661 (ringbase & ~SSB_DMA_TRANSLATION_MASK)
662 | trans);
663 }
664 } else {
665 err = alloc_initial_descbuffers(ring);
666 if (err)
667 goto out;
668 if (ring->dma64) {
669 u64 ringbase = (u64) (ring->dmabase);
670
671 addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
672 >> SSB_DMA_TRANSLATION_SHIFT;
673 value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
674 value |= B43_DMA64_RXENABLE;
675 value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
676 & B43_DMA64_RXADDREXT_MASK;
677 b43_dma_write(ring, B43_DMA64_RXCTL, value);
678 b43_dma_write(ring, B43_DMA64_RXRINGLO,
679 (ringbase & 0xFFFFFFFF));
680 b43_dma_write(ring, B43_DMA64_RXRINGHI,
681 ((ringbase >> 32) &
682 ~SSB_DMA_TRANSLATION_MASK)
683 | trans);
684 b43_dma_write(ring, B43_DMA64_RXINDEX, 200);
685 } else {
686 u32 ringbase = (u32) (ring->dmabase);
687
688 addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
689 >> SSB_DMA_TRANSLATION_SHIFT;
690 value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT);
691 value |= B43_DMA32_RXENABLE;
692 value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
693 & B43_DMA32_RXADDREXT_MASK;
694 b43_dma_write(ring, B43_DMA32_RXCTL, value);
695 b43_dma_write(ring, B43_DMA32_RXRING,
696 (ringbase & ~SSB_DMA_TRANSLATION_MASK)
697 | trans);
698 b43_dma_write(ring, B43_DMA32_RXINDEX, 200);
699 }
700 }
701
702 out:
703 return err;
704}
705
706/* Shutdown the DMA controller. */
707static void dmacontroller_cleanup(struct b43_dmaring *ring)
708{
709 if (ring->tx) {
710 b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
711 ring->dma64);
712 if (ring->dma64) {
713 b43_dma_write(ring, B43_DMA64_TXRINGLO, 0);
714 b43_dma_write(ring, B43_DMA64_TXRINGHI, 0);
715 } else
716 b43_dma_write(ring, B43_DMA32_TXRING, 0);
717 } else {
718 b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
719 ring->dma64);
720 if (ring->dma64) {
721 b43_dma_write(ring, B43_DMA64_RXRINGLO, 0);
722 b43_dma_write(ring, B43_DMA64_RXRINGHI, 0);
723 } else
724 b43_dma_write(ring, B43_DMA32_RXRING, 0);
725 }
726}
727
728static void free_all_descbuffers(struct b43_dmaring *ring)
729{
730 struct b43_dmadesc_generic *desc;
731 struct b43_dmadesc_meta *meta;
732 int i;
733
734 if (!ring->used_slots)
735 return;
736 for (i = 0; i < ring->nr_slots; i++) {
737 desc = ring->ops->idx2desc(ring, i, &meta);
738
739 if (!meta->skb) {
740 B43_WARN_ON(!ring->tx);
741 continue;
742 }
743 if (ring->tx) {
744 unmap_descbuffer(ring, meta->dmaaddr,
745 meta->skb->len, 1);
746 } else {
747 unmap_descbuffer(ring, meta->dmaaddr,
748 ring->rx_buffersize, 0);
749 }
750 free_descriptor_buffer(ring, meta);
751 }
752}
753
754static u64 supported_dma_mask(struct b43_wldev *dev)
755{
756 u32 tmp;
757 u16 mmio_base;
758
759 tmp = b43_read32(dev, SSB_TMSHIGH);
760 if (tmp & SSB_TMSHIGH_DMA64)
761 return DMA_64BIT_MASK;
762 mmio_base = b43_dmacontroller_base(0, 0);
763 b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
764 tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
765 if (tmp & B43_DMA32_TXADDREXT_MASK)
766 return DMA_32BIT_MASK;
767
768 return DMA_30BIT_MASK;
769}
770
771/* Main initialization function. */
772static
773struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
774 int controller_index,
775 int for_tx, int dma64)
776{
777 struct b43_dmaring *ring;
778 int err;
779 int nr_slots;
780 dma_addr_t dma_test;
781
782 ring = kzalloc(sizeof(*ring), GFP_KERNEL);
783 if (!ring)
784 goto out;
785
786 nr_slots = B43_RXRING_SLOTS;
787 if (for_tx)
788 nr_slots = B43_TXRING_SLOTS;
789
790 ring->meta = kcalloc(nr_slots, sizeof(struct b43_dmadesc_meta),
791 GFP_KERNEL);
792 if (!ring->meta)
793 goto err_kfree_ring;
794 if (for_tx) {
795 ring->txhdr_cache = kcalloc(nr_slots,
796 sizeof(struct b43_txhdr_fw4),
797 GFP_KERNEL);
798 if (!ring->txhdr_cache)
799 goto err_kfree_meta;
800
801 /* test for ability to dma to txhdr_cache */
802 dma_test = dma_map_single(dev->dev->dev,
803 ring->txhdr_cache,
804 sizeof(struct b43_txhdr_fw4),
805 DMA_TO_DEVICE);
806
807 if (dma_mapping_error(dma_test)) {
808 /* ugh realloc */
809 kfree(ring->txhdr_cache);
810 ring->txhdr_cache = kcalloc(nr_slots,
811 sizeof(struct
812 b43_txhdr_fw4),
813 GFP_KERNEL | GFP_DMA);
814 if (!ring->txhdr_cache)
815 goto err_kfree_meta;
816
817 dma_test = dma_map_single(dev->dev->dev,
818 ring->txhdr_cache,
819 sizeof(struct b43_txhdr_fw4),
820 DMA_TO_DEVICE);
821
822 if (dma_mapping_error(dma_test))
823 goto err_kfree_txhdr_cache;
824 }
825
826 dma_unmap_single(dev->dev->dev,
827 dma_test, sizeof(struct b43_txhdr_fw4),
828 DMA_TO_DEVICE);
829 }
830
831 ring->dev = dev;
832 ring->nr_slots = nr_slots;
833 ring->mmio_base = b43_dmacontroller_base(dma64, controller_index);
834 ring->index = controller_index;
835 ring->dma64 = !!dma64;
836 if (dma64)
837 ring->ops = &dma64_ops;
838 else
839 ring->ops = &dma32_ops;
840 if (for_tx) {
841 ring->tx = 1;
842 ring->current_slot = -1;
843 } else {
844 if (ring->index == 0) {
845 ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE;
846 ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET;
847 } else if (ring->index == 3) {
848 ring->rx_buffersize = B43_DMA3_RX_BUFFERSIZE;
849 ring->frameoffset = B43_DMA3_RX_FRAMEOFFSET;
850 } else
851 B43_WARN_ON(1);
852 }
853 spin_lock_init(&ring->lock);
854#ifdef CONFIG_B43_DEBUG
855 ring->last_injected_overflow = jiffies;
856#endif
857
858 err = alloc_ringmemory(ring);
859 if (err)
860 goto err_kfree_txhdr_cache;
861 err = dmacontroller_setup(ring);
862 if (err)
863 goto err_free_ringmemory;
864
865 out:
866 return ring;
867
868 err_free_ringmemory:
869 free_ringmemory(ring);
870 err_kfree_txhdr_cache:
871 kfree(ring->txhdr_cache);
872 err_kfree_meta:
873 kfree(ring->meta);
874 err_kfree_ring:
875 kfree(ring);
876 ring = NULL;
877 goto out;
878}
879
880/* Main cleanup function. */
881static void b43_destroy_dmaring(struct b43_dmaring *ring)
882{
883 if (!ring)
884 return;
885
886 b43dbg(ring->dev->wl, "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
887 (ring->dma64) ? "64" : "32",
888 ring->mmio_base,
889 (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots);
890 /* Device IRQs are disabled prior entering this function,
891 * so no need to take care of concurrency with rx handler stuff.
892 */
893 dmacontroller_cleanup(ring);
894 free_all_descbuffers(ring);
895 free_ringmemory(ring);
896
897 kfree(ring->txhdr_cache);
898 kfree(ring->meta);
899 kfree(ring);
900}
901
902void b43_dma_free(struct b43_wldev *dev)
903{
904 struct b43_dma *dma;
905
906 if (b43_using_pio(dev))
907 return;
908 dma = &dev->dma;
909
910 b43_destroy_dmaring(dma->rx_ring3);
911 dma->rx_ring3 = NULL;
912 b43_destroy_dmaring(dma->rx_ring0);
913 dma->rx_ring0 = NULL;
914
915 b43_destroy_dmaring(dma->tx_ring5);
916 dma->tx_ring5 = NULL;
917 b43_destroy_dmaring(dma->tx_ring4);
918 dma->tx_ring4 = NULL;
919 b43_destroy_dmaring(dma->tx_ring3);
920 dma->tx_ring3 = NULL;
921 b43_destroy_dmaring(dma->tx_ring2);
922 dma->tx_ring2 = NULL;
923 b43_destroy_dmaring(dma->tx_ring1);
924 dma->tx_ring1 = NULL;
925 b43_destroy_dmaring(dma->tx_ring0);
926 dma->tx_ring0 = NULL;
927}
928
929int b43_dma_init(struct b43_wldev *dev)
930{
931 struct b43_dma *dma = &dev->dma;
932 struct b43_dmaring *ring;
933 int err;
934 u64 dmamask;
935 int dma64 = 0;
936
937 dmamask = supported_dma_mask(dev);
938 if (dmamask == DMA_64BIT_MASK)
939 dma64 = 1;
940
941 err = ssb_dma_set_mask(dev->dev, dmamask);
942 if (err) {
943#ifdef B43_PIO
944 b43warn(dev->wl, "DMA for this device not supported. "
945 "Falling back to PIO\n");
946 dev->__using_pio = 1;
947 return -EAGAIN;
948#else
949 b43err(dev->wl, "DMA for this device not supported and "
950 "no PIO support compiled in\n");
951 return -EOPNOTSUPP;
952#endif
953 }
954
955 err = -ENOMEM;
956 /* setup TX DMA channels. */
957 ring = b43_setup_dmaring(dev, 0, 1, dma64);
958 if (!ring)
959 goto out;
960 dma->tx_ring0 = ring;
961
962 ring = b43_setup_dmaring(dev, 1, 1, dma64);
963 if (!ring)
964 goto err_destroy_tx0;
965 dma->tx_ring1 = ring;
966
967 ring = b43_setup_dmaring(dev, 2, 1, dma64);
968 if (!ring)
969 goto err_destroy_tx1;
970 dma->tx_ring2 = ring;
971
972 ring = b43_setup_dmaring(dev, 3, 1, dma64);
973 if (!ring)
974 goto err_destroy_tx2;
975 dma->tx_ring3 = ring;
976
977 ring = b43_setup_dmaring(dev, 4, 1, dma64);
978 if (!ring)
979 goto err_destroy_tx3;
980 dma->tx_ring4 = ring;
981
982 ring = b43_setup_dmaring(dev, 5, 1, dma64);
983 if (!ring)
984 goto err_destroy_tx4;
985 dma->tx_ring5 = ring;
986
987 /* setup RX DMA channels. */
988 ring = b43_setup_dmaring(dev, 0, 0, dma64);
989 if (!ring)
990 goto err_destroy_tx5;
991 dma->rx_ring0 = ring;
992
993 if (dev->dev->id.revision < 5) {
994 ring = b43_setup_dmaring(dev, 3, 0, dma64);
995 if (!ring)
996 goto err_destroy_rx0;
997 dma->rx_ring3 = ring;
998 }
999
1000 b43dbg(dev->wl, "%d-bit DMA initialized\n",
1001 (dmamask == DMA_64BIT_MASK) ? 64 :
1002 (dmamask == DMA_32BIT_MASK) ? 32 : 30);
1003 err = 0;
1004 out:
1005 return err;
1006
1007 err_destroy_rx0:
1008 b43_destroy_dmaring(dma->rx_ring0);
1009 dma->rx_ring0 = NULL;
1010 err_destroy_tx5:
1011 b43_destroy_dmaring(dma->tx_ring5);
1012 dma->tx_ring5 = NULL;
1013 err_destroy_tx4:
1014 b43_destroy_dmaring(dma->tx_ring4);
1015 dma->tx_ring4 = NULL;
1016 err_destroy_tx3:
1017 b43_destroy_dmaring(dma->tx_ring3);
1018 dma->tx_ring3 = NULL;
1019 err_destroy_tx2:
1020 b43_destroy_dmaring(dma->tx_ring2);
1021 dma->tx_ring2 = NULL;
1022 err_destroy_tx1:
1023 b43_destroy_dmaring(dma->tx_ring1);
1024 dma->tx_ring1 = NULL;
1025 err_destroy_tx0:
1026 b43_destroy_dmaring(dma->tx_ring0);
1027 dma->tx_ring0 = NULL;
1028 goto out;
1029}
1030
1031/* Generate a cookie for the TX header. */
1032static u16 generate_cookie(struct b43_dmaring *ring, int slot)
1033{
1034 u16 cookie = 0x1000;
1035
1036 /* Use the upper 4 bits of the cookie as
1037 * DMA controller ID and store the slot number
1038 * in the lower 12 bits.
1039 * Note that the cookie must never be 0, as this
1040 * is a special value used in RX path.
1041 */
1042 switch (ring->index) {
1043 case 0:
1044 cookie = 0xA000;
1045 break;
1046 case 1:
1047 cookie = 0xB000;
1048 break;
1049 case 2:
1050 cookie = 0xC000;
1051 break;
1052 case 3:
1053 cookie = 0xD000;
1054 break;
1055 case 4:
1056 cookie = 0xE000;
1057 break;
1058 case 5:
1059 cookie = 0xF000;
1060 break;
1061 }
1062 B43_WARN_ON(slot & ~0x0FFF);
1063 cookie |= (u16) slot;
1064
1065 return cookie;
1066}
1067
1068/* Inspect a cookie and find out to which controller/slot it belongs. */
1069static
1070struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
1071{
1072 struct b43_dma *dma = &dev->dma;
1073 struct b43_dmaring *ring = NULL;
1074
1075 switch (cookie & 0xF000) {
1076 case 0xA000:
1077 ring = dma->tx_ring0;
1078 break;
1079 case 0xB000:
1080 ring = dma->tx_ring1;
1081 break;
1082 case 0xC000:
1083 ring = dma->tx_ring2;
1084 break;
1085 case 0xD000:
1086 ring = dma->tx_ring3;
1087 break;
1088 case 0xE000:
1089 ring = dma->tx_ring4;
1090 break;
1091 case 0xF000:
1092 ring = dma->tx_ring5;
1093 break;
1094 default:
1095 B43_WARN_ON(1);
1096 }
1097 *slot = (cookie & 0x0FFF);
1098 B43_WARN_ON(!(ring && *slot >= 0 && *slot < ring->nr_slots));
1099
1100 return ring;
1101}
1102
1103static int dma_tx_fragment(struct b43_dmaring *ring,
1104 struct sk_buff *skb,
1105 struct ieee80211_tx_control *ctl)
1106{
1107 const struct b43_dma_ops *ops = ring->ops;
1108 u8 *header;
1109 int slot;
1110 int err;
1111 struct b43_dmadesc_generic *desc;
1112 struct b43_dmadesc_meta *meta;
1113 struct b43_dmadesc_meta *meta_hdr;
1114 struct sk_buff *bounce_skb;
1115
1116#define SLOTS_PER_PACKET 2
1117 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
1118
1119 /* Get a slot for the header. */
1120 slot = request_slot(ring);
1121 desc = ops->idx2desc(ring, slot, &meta_hdr);
1122 memset(meta_hdr, 0, sizeof(*meta_hdr));
1123
1124 header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]);
1125 b43_generate_txhdr(ring->dev, header,
1126 skb->data, skb->len, ctl,
1127 generate_cookie(ring, slot));
1128
1129 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
1130 sizeof(struct b43_txhdr_fw4), 1);
1131 if (dma_mapping_error(meta_hdr->dmaaddr))
1132 return -EIO;
1133 ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
1134 sizeof(struct b43_txhdr_fw4), 1, 0, 0);
1135
1136 /* Get a slot for the payload. */
1137 slot = request_slot(ring);
1138 desc = ops->idx2desc(ring, slot, &meta);
1139 memset(meta, 0, sizeof(*meta));
1140
1141 memcpy(&meta->txstat.control, ctl, sizeof(*ctl));
1142 meta->skb = skb;
1143 meta->is_last_fragment = 1;
1144
1145 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1146 /* create a bounce buffer in zone_dma on mapping failure. */
1147 if (dma_mapping_error(meta->dmaaddr)) {
1148 bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
1149 if (!bounce_skb) {
1150 err = -ENOMEM;
1151 goto out_unmap_hdr;
1152 }
1153
1154 memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
1155 dev_kfree_skb_any(skb);
1156 skb = bounce_skb;
1157 meta->skb = skb;
1158 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1159 if (dma_mapping_error(meta->dmaaddr)) {
1160 err = -EIO;
1161 goto out_free_bounce;
1162 }
1163 }
1164
1165 ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1);
1166
1167 /* Now transfer the whole frame. */
1168 wmb();
1169 ops->poke_tx(ring, next_slot(ring, slot));
1170 return 0;
1171
1172 out_free_bounce:
1173 dev_kfree_skb_any(skb);
1174 out_unmap_hdr:
1175 unmap_descbuffer(ring, meta_hdr->dmaaddr,
1176 sizeof(struct b43_txhdr_fw4), 1);
1177 return err;
1178}
1179
1180static inline int should_inject_overflow(struct b43_dmaring *ring)
1181{
1182#ifdef CONFIG_B43_DEBUG
1183 if (unlikely(b43_debug(ring->dev, B43_DBG_DMAOVERFLOW))) {
1184 /* Check if we should inject another ringbuffer overflow
1185 * to test handling of this situation in the stack. */
1186 unsigned long next_overflow;
1187
1188 next_overflow = ring->last_injected_overflow + HZ;
1189 if (time_after(jiffies, next_overflow)) {
1190 ring->last_injected_overflow = jiffies;
1191 b43dbg(ring->dev->wl,
1192 "Injecting TX ring overflow on "
1193 "DMA controller %d\n", ring->index);
1194 return 1;
1195 }
1196 }
1197#endif /* CONFIG_B43_DEBUG */
1198 return 0;
1199}
1200
1201int b43_dma_tx(struct b43_wldev *dev,
1202 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
1203{
1204 struct b43_dmaring *ring;
1205 int err = 0;
1206 unsigned long flags;
1207
1208 ring = priority_to_txring(dev, ctl->queue);
1209 spin_lock_irqsave(&ring->lock, flags);
1210 B43_WARN_ON(!ring->tx);
1211 if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
1212 b43warn(dev->wl, "DMA queue overflow\n");
1213 err = -ENOSPC;
1214 goto out_unlock;
1215 }
1216 /* Check if the queue was stopped in mac80211,
1217 * but we got called nevertheless.
1218 * That would be a mac80211 bug. */
1219 B43_WARN_ON(ring->stopped);
1220
1221 err = dma_tx_fragment(ring, skb, ctl);
1222 if (unlikely(err)) {
1223 b43err(dev->wl, "DMA tx mapping failure\n");
1224 goto out_unlock;
1225 }
1226 ring->nr_tx_packets++;
1227 if ((free_slots(ring) < SLOTS_PER_PACKET) ||
1228 should_inject_overflow(ring)) {
1229 /* This TX ring is full. */
1230 ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
1231 ring->stopped = 1;
1232 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
1233 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
1234 }
1235 }
1236 out_unlock:
1237 spin_unlock_irqrestore(&ring->lock, flags);
1238
1239 return err;
1240}
1241
1242void b43_dma_handle_txstatus(struct b43_wldev *dev,
1243 const struct b43_txstatus *status)
1244{
1245 const struct b43_dma_ops *ops;
1246 struct b43_dmaring *ring;
1247 struct b43_dmadesc_generic *desc;
1248 struct b43_dmadesc_meta *meta;
1249 int slot;
1250
1251 ring = parse_cookie(dev, status->cookie, &slot);
1252 if (unlikely(!ring))
1253 return;
1254 B43_WARN_ON(!irqs_disabled());
1255 spin_lock(&ring->lock);
1256
1257 B43_WARN_ON(!ring->tx);
1258 ops = ring->ops;
1259 while (1) {
1260 B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
1261 desc = ops->idx2desc(ring, slot, &meta);
1262
1263 if (meta->skb)
1264 unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len,
1265 1);
1266 else
1267 unmap_descbuffer(ring, meta->dmaaddr,
1268 sizeof(struct b43_txhdr_fw4), 1);
1269
1270 if (meta->is_last_fragment) {
1271 B43_WARN_ON(!meta->skb);
1272 /* Call back to inform the ieee80211 subsystem about the
1273 * status of the transmission.
1274 * Some fields of txstat are already filled in dma_tx().
1275 */
1276 if (status->acked) {
1277 meta->txstat.flags |= IEEE80211_TX_STATUS_ACK;
1278 } else {
1279 if (!(meta->txstat.control.flags
1280 & IEEE80211_TXCTL_NO_ACK))
1281 meta->txstat.excessive_retries = 1;
1282 }
1283 if (status->frame_count == 0) {
1284 /* The frame was not transmitted at all. */
1285 meta->txstat.retry_count = 0;
1286 } else
1287 meta->txstat.retry_count = status->frame_count - 1;
1288 ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
1289 &(meta->txstat));
1290 /* skb is freed by ieee80211_tx_status_irqsafe() */
1291 meta->skb = NULL;
1292 } else {
1293 /* No need to call free_descriptor_buffer here, as
1294 * this is only the txhdr, which is not allocated.
1295 */
1296 B43_WARN_ON(meta->skb);
1297 }
1298
1299 /* Everything unmapped and free'd. So it's not used anymore. */
1300 ring->used_slots--;
1301
1302 if (meta->is_last_fragment)
1303 break;
1304 slot = next_slot(ring, slot);
1305 }
1306 dev->stats.last_tx = jiffies;
1307 if (ring->stopped) {
1308 B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
1309 ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
1310 ring->stopped = 0;
1311 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
1312 b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
1313 }
1314 }
1315
1316 spin_unlock(&ring->lock);
1317}
1318
1319void b43_dma_get_tx_stats(struct b43_wldev *dev,
1320 struct ieee80211_tx_queue_stats *stats)
1321{
1322 const int nr_queues = dev->wl->hw->queues;
1323 struct b43_dmaring *ring;
1324 struct ieee80211_tx_queue_stats_data *data;
1325 unsigned long flags;
1326 int i;
1327
1328 for (i = 0; i < nr_queues; i++) {
1329 data = &(stats->data[i]);
1330 ring = priority_to_txring(dev, i);
1331
1332 spin_lock_irqsave(&ring->lock, flags);
1333 data->len = ring->used_slots / SLOTS_PER_PACKET;
1334 data->limit = ring->nr_slots / SLOTS_PER_PACKET;
1335 data->count = ring->nr_tx_packets;
1336 spin_unlock_irqrestore(&ring->lock, flags);
1337 }
1338}
1339
1340static void dma_rx(struct b43_dmaring *ring, int *slot)
1341{
1342 const struct b43_dma_ops *ops = ring->ops;
1343 struct b43_dmadesc_generic *desc;
1344 struct b43_dmadesc_meta *meta;
1345 struct b43_rxhdr_fw4 *rxhdr;
1346 struct sk_buff *skb;
1347 u16 len;
1348 int err;
1349 dma_addr_t dmaaddr;
1350
1351 desc = ops->idx2desc(ring, *slot, &meta);
1352
1353 sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
1354 skb = meta->skb;
1355
1356 if (ring->index == 3) {
1357 /* We received an xmit status. */
1358 struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data;
1359 int i = 0;
1360
1361 while (hw->cookie == 0) {
1362 if (i > 100)
1363 break;
1364 i++;
1365 udelay(2);
1366 barrier();
1367 }
1368 b43_handle_hwtxstatus(ring->dev, hw);
1369 /* recycle the descriptor buffer. */
1370 sync_descbuffer_for_device(ring, meta->dmaaddr,
1371 ring->rx_buffersize);
1372
1373 return;
1374 }
1375 rxhdr = (struct b43_rxhdr_fw4 *)skb->data;
1376 len = le16_to_cpu(rxhdr->frame_len);
1377 if (len == 0) {
1378 int i = 0;
1379
1380 do {
1381 udelay(2);
1382 barrier();
1383 len = le16_to_cpu(rxhdr->frame_len);
1384 } while (len == 0 && i++ < 5);
1385 if (unlikely(len == 0)) {
1386 /* recycle the descriptor buffer. */
1387 sync_descbuffer_for_device(ring, meta->dmaaddr,
1388 ring->rx_buffersize);
1389 goto drop;
1390 }
1391 }
1392 if (unlikely(len > ring->rx_buffersize)) {
1393 /* The data did not fit into one descriptor buffer
1394 * and is split over multiple buffers.
1395 * This should never happen, as we try to allocate buffers
1396 * big enough. So simply ignore this packet.
1397 */
1398 int cnt = 0;
1399 s32 tmp = len;
1400
1401 while (1) {
1402 desc = ops->idx2desc(ring, *slot, &meta);
1403 /* recycle the descriptor buffer. */
1404 sync_descbuffer_for_device(ring, meta->dmaaddr,
1405 ring->rx_buffersize);
1406 *slot = next_slot(ring, *slot);
1407 cnt++;
1408 tmp -= ring->rx_buffersize;
1409 if (tmp <= 0)
1410 break;
1411 }
1412 b43err(ring->dev->wl, "DMA RX buffer too small "
1413 "(len: %u, buffer: %u, nr-dropped: %d)\n",
1414 len, ring->rx_buffersize, cnt);
1415 goto drop;
1416 }
1417
1418 dmaaddr = meta->dmaaddr;
1419 err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
1420 if (unlikely(err)) {
1421 b43dbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer() failed\n");
1422 sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
1423 goto drop;
1424 }
1425
1426 unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
1427 skb_put(skb, len + ring->frameoffset);
1428 skb_pull(skb, ring->frameoffset);
1429
1430 b43_rx(ring->dev, skb, rxhdr);
1431 drop:
1432 return;
1433}
1434
1435void b43_dma_rx(struct b43_dmaring *ring)
1436{
1437 const struct b43_dma_ops *ops = ring->ops;
1438 int slot, current_slot;
1439 int used_slots = 0;
1440
1441 B43_WARN_ON(ring->tx);
1442 current_slot = ops->get_current_rxslot(ring);
1443 B43_WARN_ON(!(current_slot >= 0 && current_slot < ring->nr_slots));
1444
1445 slot = ring->current_slot;
1446 for (; slot != current_slot; slot = next_slot(ring, slot)) {
1447 dma_rx(ring, &slot);
1448 update_max_used_slots(ring, ++used_slots);
1449 }
1450 ops->set_current_rxslot(ring, slot);
1451 ring->current_slot = slot;
1452}
1453
1454static void b43_dma_tx_suspend_ring(struct b43_dmaring *ring)
1455{
1456 unsigned long flags;
1457
1458 spin_lock_irqsave(&ring->lock, flags);
1459 B43_WARN_ON(!ring->tx);
1460 ring->ops->tx_suspend(ring);
1461 spin_unlock_irqrestore(&ring->lock, flags);
1462}
1463
1464static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
1465{
1466 unsigned long flags;
1467
1468 spin_lock_irqsave(&ring->lock, flags);
1469 B43_WARN_ON(!ring->tx);
1470 ring->ops->tx_resume(ring);
1471 spin_unlock_irqrestore(&ring->lock, flags);
1472}
1473
1474void b43_dma_tx_suspend(struct b43_wldev *dev)
1475{
1476 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
1477 b43_dma_tx_suspend_ring(dev->dma.tx_ring0);
1478 b43_dma_tx_suspend_ring(dev->dma.tx_ring1);
1479 b43_dma_tx_suspend_ring(dev->dma.tx_ring2);
1480 b43_dma_tx_suspend_ring(dev->dma.tx_ring3);
1481 b43_dma_tx_suspend_ring(dev->dma.tx_ring4);
1482 b43_dma_tx_suspend_ring(dev->dma.tx_ring5);
1483}
1484
1485void b43_dma_tx_resume(struct b43_wldev *dev)
1486{
1487 b43_dma_tx_resume_ring(dev->dma.tx_ring5);
1488 b43_dma_tx_resume_ring(dev->dma.tx_ring4);
1489 b43_dma_tx_resume_ring(dev->dma.tx_ring3);
1490 b43_dma_tx_resume_ring(dev->dma.tx_ring2);
1491 b43_dma_tx_resume_ring(dev->dma.tx_ring1);
1492 b43_dma_tx_resume_ring(dev->dma.tx_ring0);
1493 b43_power_saving_ctl_bits(dev, 0);
1494}
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
new file mode 100644
index 000000000000..3eed185be725
--- /dev/null
+++ b/drivers/net/wireless/b43/dma.h
@@ -0,0 +1,337 @@
1#ifndef B43_DMA_H_
2#define B43_DMA_H_
3
4#include <linux/list.h>
5#include <linux/spinlock.h>
6#include <linux/workqueue.h>
7#include <linux/linkage.h>
8#include <asm/atomic.h>
9
10#include "b43.h"
11
12/* DMA-Interrupt reasons. */
13#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
14 | (1 << 14) | (1 << 15))
15#define B43_DMAIRQ_NONFATALMASK (1 << 13)
16#define B43_DMAIRQ_RX_DONE (1 << 16)
17
18/*** 32-bit DMA Engine. ***/
19
20/* 32-bit DMA controller registers. */
21#define B43_DMA32_TXCTL 0x00
22#define B43_DMA32_TXENABLE 0x00000001
23#define B43_DMA32_TXSUSPEND 0x00000002
24#define B43_DMA32_TXLOOPBACK 0x00000004
25#define B43_DMA32_TXFLUSH 0x00000010
26#define B43_DMA32_TXADDREXT_MASK 0x00030000
27#define B43_DMA32_TXADDREXT_SHIFT 16
28#define B43_DMA32_TXRING 0x04
29#define B43_DMA32_TXINDEX 0x08
30#define B43_DMA32_TXSTATUS 0x0C
31#define B43_DMA32_TXDPTR 0x00000FFF
32#define B43_DMA32_TXSTATE 0x0000F000
33#define B43_DMA32_TXSTAT_DISABLED 0x00000000
34#define B43_DMA32_TXSTAT_ACTIVE 0x00001000
35#define B43_DMA32_TXSTAT_IDLEWAIT 0x00002000
36#define B43_DMA32_TXSTAT_STOPPED 0x00003000
37#define B43_DMA32_TXSTAT_SUSP 0x00004000
38#define B43_DMA32_TXERROR 0x000F0000
39#define B43_DMA32_TXERR_NOERR 0x00000000
40#define B43_DMA32_TXERR_PROT 0x00010000
41#define B43_DMA32_TXERR_UNDERRUN 0x00020000
42#define B43_DMA32_TXERR_BUFREAD 0x00030000
43#define B43_DMA32_TXERR_DESCREAD 0x00040000
44#define B43_DMA32_TXACTIVE 0xFFF00000
45#define B43_DMA32_RXCTL 0x10
46#define B43_DMA32_RXENABLE 0x00000001
47#define B43_DMA32_RXFROFF_MASK 0x000000FE
48#define B43_DMA32_RXFROFF_SHIFT 1
49#define B43_DMA32_RXDIRECTFIFO 0x00000100
50#define B43_DMA32_RXADDREXT_MASK 0x00030000
51#define B43_DMA32_RXADDREXT_SHIFT 16
52#define B43_DMA32_RXRING 0x14
53#define B43_DMA32_RXINDEX 0x18
54#define B43_DMA32_RXSTATUS 0x1C
55#define B43_DMA32_RXDPTR 0x00000FFF
56#define B43_DMA32_RXSTATE 0x0000F000
57#define B43_DMA32_RXSTAT_DISABLED 0x00000000
58#define B43_DMA32_RXSTAT_ACTIVE 0x00001000
59#define B43_DMA32_RXSTAT_IDLEWAIT 0x00002000
60#define B43_DMA32_RXSTAT_STOPPED 0x00003000
61#define B43_DMA32_RXERROR 0x000F0000
62#define B43_DMA32_RXERR_NOERR 0x00000000
63#define B43_DMA32_RXERR_PROT 0x00010000
64#define B43_DMA32_RXERR_OVERFLOW 0x00020000
65#define B43_DMA32_RXERR_BUFWRITE 0x00030000
66#define B43_DMA32_RXERR_DESCREAD 0x00040000
67#define B43_DMA32_RXACTIVE 0xFFF00000
68
69/* 32-bit DMA descriptor. */
70struct b43_dmadesc32 {
71 __le32 control;
72 __le32 address;
73} __attribute__ ((__packed__));
74#define B43_DMA32_DCTL_BYTECNT 0x00001FFF
75#define B43_DMA32_DCTL_ADDREXT_MASK 0x00030000
76#define B43_DMA32_DCTL_ADDREXT_SHIFT 16
77#define B43_DMA32_DCTL_DTABLEEND 0x10000000
78#define B43_DMA32_DCTL_IRQ 0x20000000
79#define B43_DMA32_DCTL_FRAMEEND 0x40000000
80#define B43_DMA32_DCTL_FRAMESTART 0x80000000
81
82/*** 64-bit DMA Engine. ***/
83
84/* 64-bit DMA controller registers. */
85#define B43_DMA64_TXCTL 0x00
86#define B43_DMA64_TXENABLE 0x00000001
87#define B43_DMA64_TXSUSPEND 0x00000002
88#define B43_DMA64_TXLOOPBACK 0x00000004
89#define B43_DMA64_TXFLUSH 0x00000010
90#define B43_DMA64_TXADDREXT_MASK 0x00030000
91#define B43_DMA64_TXADDREXT_SHIFT 16
92#define B43_DMA64_TXINDEX 0x04
93#define B43_DMA64_TXRINGLO 0x08
94#define B43_DMA64_TXRINGHI 0x0C
95#define B43_DMA64_TXSTATUS 0x10
96#define B43_DMA64_TXSTATDPTR 0x00001FFF
97#define B43_DMA64_TXSTAT 0xF0000000
98#define B43_DMA64_TXSTAT_DISABLED 0x00000000
99#define B43_DMA64_TXSTAT_ACTIVE 0x10000000
100#define B43_DMA64_TXSTAT_IDLEWAIT 0x20000000
101#define B43_DMA64_TXSTAT_STOPPED 0x30000000
102#define B43_DMA64_TXSTAT_SUSP 0x40000000
103#define B43_DMA64_TXERROR 0x14
104#define B43_DMA64_TXERRDPTR 0x0001FFFF
105#define B43_DMA64_TXERR 0xF0000000
106#define B43_DMA64_TXERR_NOERR 0x00000000
107#define B43_DMA64_TXERR_PROT 0x10000000
108#define B43_DMA64_TXERR_UNDERRUN 0x20000000
109#define B43_DMA64_TXERR_TRANSFER 0x30000000
110#define B43_DMA64_TXERR_DESCREAD 0x40000000
111#define B43_DMA64_TXERR_CORE 0x50000000
112#define B43_DMA64_RXCTL 0x20
113#define B43_DMA64_RXENABLE 0x00000001
114#define B43_DMA64_RXFROFF_MASK 0x000000FE
115#define B43_DMA64_RXFROFF_SHIFT 1
116#define B43_DMA64_RXDIRECTFIFO 0x00000100
117#define B43_DMA64_RXADDREXT_MASK 0x00030000
118#define B43_DMA64_RXADDREXT_SHIFT 16
119#define B43_DMA64_RXINDEX 0x24
120#define B43_DMA64_RXRINGLO 0x28
121#define B43_DMA64_RXRINGHI 0x2C
122#define B43_DMA64_RXSTATUS 0x30
123#define B43_DMA64_RXSTATDPTR 0x00001FFF
124#define B43_DMA64_RXSTAT 0xF0000000
125#define B43_DMA64_RXSTAT_DISABLED 0x00000000
126#define B43_DMA64_RXSTAT_ACTIVE 0x10000000
127#define B43_DMA64_RXSTAT_IDLEWAIT 0x20000000
128#define B43_DMA64_RXSTAT_STOPPED 0x30000000
129#define B43_DMA64_RXSTAT_SUSP 0x40000000
130#define B43_DMA64_RXERROR 0x34
131#define B43_DMA64_RXERRDPTR 0x0001FFFF
132#define B43_DMA64_RXERR 0xF0000000
133#define B43_DMA64_RXERR_NOERR 0x00000000
134#define B43_DMA64_RXERR_PROT 0x10000000
135#define B43_DMA64_RXERR_UNDERRUN 0x20000000
136#define B43_DMA64_RXERR_TRANSFER 0x30000000
137#define B43_DMA64_RXERR_DESCREAD 0x40000000
138#define B43_DMA64_RXERR_CORE 0x50000000
139
140/* 64-bit DMA descriptor. */
141struct b43_dmadesc64 {
142 __le32 control0;
143 __le32 control1;
144 __le32 address_low;
145 __le32 address_high;
146} __attribute__ ((__packed__));
147#define B43_DMA64_DCTL0_DTABLEEND 0x10000000
148#define B43_DMA64_DCTL0_IRQ 0x20000000
149#define B43_DMA64_DCTL0_FRAMEEND 0x40000000
150#define B43_DMA64_DCTL0_FRAMESTART 0x80000000
151#define B43_DMA64_DCTL1_BYTECNT 0x00001FFF
152#define B43_DMA64_DCTL1_ADDREXT_MASK 0x00030000
153#define B43_DMA64_DCTL1_ADDREXT_SHIFT 16
154
155struct b43_dmadesc_generic {
156 union {
157 struct b43_dmadesc32 dma32;
158 struct b43_dmadesc64 dma64;
159 } __attribute__ ((__packed__));
160} __attribute__ ((__packed__));
161
162/* Misc DMA constants */
163#define B43_DMA_RINGMEMSIZE PAGE_SIZE
164#define B43_DMA0_RX_FRAMEOFFSET 30
165#define B43_DMA3_RX_FRAMEOFFSET 0
166
167/* DMA engine tuning knobs */
168#define B43_TXRING_SLOTS 128
169#define B43_RXRING_SLOTS 64
170#define B43_DMA0_RX_BUFFERSIZE (2304 + 100)
171#define B43_DMA3_RX_BUFFERSIZE 16
172
173#ifdef CONFIG_B43_DMA
174
175struct sk_buff;
176struct b43_private;
177struct b43_txstatus;
178
179struct b43_dmadesc_meta {
180 /* The kernel DMA-able buffer. */
181 struct sk_buff *skb;
182 /* DMA base bus-address of the descriptor buffer. */
183 dma_addr_t dmaaddr;
184 /* ieee80211 TX status. Only used once per 802.11 frag. */
185 bool is_last_fragment;
186 struct ieee80211_tx_status txstat;
187};
188
189struct b43_dmaring;
190
191/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
192struct b43_dma_ops {
193 struct b43_dmadesc_generic *(*idx2desc) (struct b43_dmaring * ring,
194 int slot,
195 struct b43_dmadesc_meta **
196 meta);
197 void (*fill_descriptor) (struct b43_dmaring * ring,
198 struct b43_dmadesc_generic * desc,
199 dma_addr_t dmaaddr, u16 bufsize, int start,
200 int end, int irq);
201 void (*poke_tx) (struct b43_dmaring * ring, int slot);
202 void (*tx_suspend) (struct b43_dmaring * ring);
203 void (*tx_resume) (struct b43_dmaring * ring);
204 int (*get_current_rxslot) (struct b43_dmaring * ring);
205 void (*set_current_rxslot) (struct b43_dmaring * ring, int slot);
206};
207
208struct b43_dmaring {
209 /* Lowlevel DMA ops. */
210 const struct b43_dma_ops *ops;
211 /* Kernel virtual base address of the ring memory. */
212 void *descbase;
213 /* Meta data about all descriptors. */
214 struct b43_dmadesc_meta *meta;
215 /* Cache of TX headers for each slot.
216 * This is to avoid an allocation on each TX.
217 * This is NULL for an RX ring.
218 */
219 u8 *txhdr_cache;
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 /* Total number of packets sent. Statistics only. */
229 unsigned int nr_tx_packets;
230 /* Frameoffset in octets. */
231 u32 frameoffset;
232 /* Descriptor buffer size. */
233 u16 rx_buffersize;
234 /* The MMIO base register of the DMA controller. */
235 u16 mmio_base;
236 /* DMA controller index number (0-5). */
237 int index;
238 /* Boolean. Is this a TX ring? */
239 bool tx;
240 /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
241 bool dma64;
242 /* Boolean. Is this ring stopped at ieee80211 level? */
243 bool stopped;
244 /* Lock, only used for TX. */
245 spinlock_t lock;
246 struct b43_wldev *dev;
247#ifdef CONFIG_B43_DEBUG
248 /* Maximum number of used slots. */
249 int max_used_slots;
250 /* Last time we injected a ring overflow. */
251 unsigned long last_injected_overflow;
252#endif /* CONFIG_B43_DEBUG */
253};
254
255static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
256{
257 return b43_read32(ring->dev, ring->mmio_base + offset);
258}
259
260static inline
261 void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value)
262{
263 b43_write32(ring->dev, ring->mmio_base + offset, value);
264}
265
266int b43_dma_init(struct b43_wldev *dev);
267void b43_dma_free(struct b43_wldev *dev);
268
269int b43_dmacontroller_rx_reset(struct b43_wldev *dev,
270 u16 dmacontroller_mmio_base, int dma64);
271int b43_dmacontroller_tx_reset(struct b43_wldev *dev,
272 u16 dmacontroller_mmio_base, int dma64);
273
274u16 b43_dmacontroller_base(int dma64bit, int dmacontroller_idx);
275
276void b43_dma_tx_suspend(struct b43_wldev *dev);
277void b43_dma_tx_resume(struct b43_wldev *dev);
278
279void b43_dma_get_tx_stats(struct b43_wldev *dev,
280 struct ieee80211_tx_queue_stats *stats);
281
282int b43_dma_tx(struct b43_wldev *dev,
283 struct sk_buff *skb, struct ieee80211_tx_control *ctl);
284void b43_dma_handle_txstatus(struct b43_wldev *dev,
285 const struct b43_txstatus *status);
286
287void b43_dma_rx(struct b43_dmaring *ring);
288
289#else /* CONFIG_B43_DMA */
290
291static inline int b43_dma_init(struct b43_wldev *dev)
292{
293 return 0;
294}
295static inline void b43_dma_free(struct b43_wldev *dev)
296{
297}
298static inline
299 int b43_dmacontroller_rx_reset(struct b43_wldev *dev,
300 u16 dmacontroller_mmio_base, int dma64)
301{
302 return 0;
303}
304static inline
305 int b43_dmacontroller_tx_reset(struct b43_wldev *dev,
306 u16 dmacontroller_mmio_base, int dma64)
307{
308 return 0;
309}
310static inline
311 void b43_dma_get_tx_stats(struct b43_wldev *dev,
312 struct ieee80211_tx_queue_stats *stats)
313{
314}
315static inline
316 int b43_dma_tx(struct b43_wldev *dev,
317 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
318{
319 return 0;
320}
321static inline
322 void b43_dma_handle_txstatus(struct b43_wldev *dev,
323 const struct b43_txstatus *status)
324{
325}
326static inline void b43_dma_rx(struct b43_dmaring *ring)
327{
328}
329static inline void b43_dma_tx_suspend(struct b43_wldev *dev)
330{
331}
332static inline void b43_dma_tx_resume(struct b43_wldev *dev)
333{
334}
335
336#endif /* CONFIG_B43_DMA */
337#endif /* B43_DMA_H_ */
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
new file mode 100644
index 000000000000..535f960412d7
--- /dev/null
+++ b/drivers/net/wireless/b43/leds.c
@@ -0,0 +1,299 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mb@bu3sch.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 "b43.h"
29#include "leds.h"
30#include "main.h"
31
32static void b43_led_changestate(struct b43_led *led)
33{
34 struct b43_wldev *dev = led->dev;
35 const int index = b43_led_index(led);
36 const u16 mask = (1 << index);
37 u16 ledctl;
38
39 B43_WARN_ON(!(index >= 0 && index < B43_NR_LEDS));
40 B43_WARN_ON(!led->blink_interval);
41 ledctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
42 ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
43 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ledctl);
44}
45
46static void b43_led_blink(unsigned long d)
47{
48 struct b43_led *led = (struct b43_led *)d;
49 struct b43_wldev *dev = led->dev;
50 unsigned long flags;
51
52 spin_lock_irqsave(&dev->wl->leds_lock, flags);
53 if (led->blink_interval) {
54 b43_led_changestate(led);
55 mod_timer(&led->blink_timer, jiffies + led->blink_interval);
56 }
57 spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
58}
59
60static void b43_led_blink_start(struct b43_led *led, unsigned long interval)
61{
62 if (led->blink_interval)
63 return;
64 led->blink_interval = interval;
65 b43_led_changestate(led);
66 led->blink_timer.expires = jiffies + interval;
67 add_timer(&led->blink_timer);
68}
69
70static void b43_led_blink_stop(struct b43_led *led, int sync)
71{
72 struct b43_wldev *dev = led->dev;
73 const int index = b43_led_index(led);
74 u16 ledctl;
75
76 if (!led->blink_interval)
77 return;
78 if (unlikely(sync))
79 del_timer_sync(&led->blink_timer);
80 else
81 del_timer(&led->blink_timer);
82 led->blink_interval = 0;
83
84 /* Make sure the LED is turned off. */
85 B43_WARN_ON(!(index >= 0 && index < B43_NR_LEDS));
86 ledctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
87 if (led->activelow)
88 ledctl |= (1 << index);
89 else
90 ledctl &= ~(1 << index);
91 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ledctl);
92}
93
94static void b43_led_init_hardcoded(struct b43_wldev *dev,
95 struct b43_led *led, int led_index)
96{
97 struct ssb_bus *bus = dev->dev->bus;
98
99 /* This function is called, if the behaviour (and activelow)
100 * information for a LED is missing in the SPROM.
101 * We hardcode the behaviour values for various devices here.
102 * Note that the B43_LED_TEST_XXX behaviour values can
103 * be used to figure out which led is mapped to which index.
104 */
105
106 switch (led_index) {
107 case 0:
108 led->behaviour = B43_LED_ACTIVITY;
109 led->activelow = 1;
110 if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
111 led->behaviour = B43_LED_RADIO_ALL;
112 break;
113 case 1:
114 led->behaviour = B43_LED_RADIO_B;
115 if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
116 led->behaviour = B43_LED_ASSOC;
117 break;
118 case 2:
119 led->behaviour = B43_LED_RADIO_A;
120 break;
121 case 3:
122 led->behaviour = B43_LED_OFF;
123 break;
124 default:
125 B43_WARN_ON(1);
126 }
127}
128
129int b43_leds_init(struct b43_wldev *dev)
130{
131 struct b43_led *led;
132 u8 sprom[4];
133 int i;
134
135 sprom[0] = dev->dev->bus->sprom.r1.gpio0;
136 sprom[1] = dev->dev->bus->sprom.r1.gpio1;
137 sprom[2] = dev->dev->bus->sprom.r1.gpio2;
138 sprom[3] = dev->dev->bus->sprom.r1.gpio3;
139
140 for (i = 0; i < B43_NR_LEDS; i++) {
141 led = &(dev->leds[i]);
142 led->dev = dev;
143 setup_timer(&led->blink_timer,
144 b43_led_blink, (unsigned long)led);
145
146 if (sprom[i] == 0xFF) {
147 b43_led_init_hardcoded(dev, led, i);
148 } else {
149 led->behaviour = sprom[i] & B43_LED_BEHAVIOUR;
150 led->activelow = !!(sprom[i] & B43_LED_ACTIVELOW);
151 }
152 }
153
154 return 0;
155}
156
157void b43_leds_exit(struct b43_wldev *dev)
158{
159 struct b43_led *led;
160 int i;
161
162 for (i = 0; i < B43_NR_LEDS; i++) {
163 led = &(dev->leds[i]);
164 b43_led_blink_stop(led, 1);
165 }
166 b43_leds_switch_all(dev, 0);
167}
168
169void b43_leds_update(struct b43_wldev *dev, int activity)
170{
171 struct b43_led *led;
172 struct b43_phy *phy = &dev->phy;
173 const int transferring =
174 (jiffies - dev->stats.last_tx) < B43_LED_XFER_THRES;
175 int i, turn_on;
176 unsigned long interval = 0;
177 u16 ledctl;
178 unsigned long flags;
179
180 spin_lock_irqsave(&dev->wl->leds_lock, flags);
181 ledctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
182 for (i = 0; i < B43_NR_LEDS; i++) {
183 led = &(dev->leds[i]);
184
185 turn_on = 0;
186 switch (led->behaviour) {
187 case B43_LED_INACTIVE:
188 continue;
189 case B43_LED_OFF:
190 break;
191 case B43_LED_ON:
192 turn_on = 1;
193 break;
194 case B43_LED_ACTIVITY:
195 turn_on = activity;
196 break;
197 case B43_LED_RADIO_ALL:
198 turn_on = phy->radio_on && b43_is_hw_radio_enabled(dev);
199 break;
200 case B43_LED_RADIO_A:
201 turn_on = (phy->radio_on && b43_is_hw_radio_enabled(dev)
202 && phy->type == B43_PHYTYPE_A);
203 break;
204 case B43_LED_RADIO_B:
205 turn_on = (phy->radio_on && b43_is_hw_radio_enabled(dev)
206 && (phy->type == B43_PHYTYPE_B
207 || phy->type == B43_PHYTYPE_G));
208 break;
209 case B43_LED_MODE_BG:
210 if (phy->type == B43_PHYTYPE_G
211 && b43_is_hw_radio_enabled(dev)
212 && 1 /*FIXME: using G rates. */ )
213 turn_on = 1;
214 break;
215 case B43_LED_TRANSFER:
216 if (transferring)
217 b43_led_blink_start(led, B43_LEDBLINK_MEDIUM);
218 else
219 b43_led_blink_stop(led, 0);
220 continue;
221 case B43_LED_APTRANSFER:
222 if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
223 if (transferring) {
224 interval = B43_LEDBLINK_FAST;
225 turn_on = 1;
226 }
227 } else {
228 turn_on = 1;
229 if (0 /*TODO: not assoc */ )
230 interval = B43_LEDBLINK_SLOW;
231 else if (transferring)
232 interval = B43_LEDBLINK_FAST;
233 else
234 turn_on = 0;
235 }
236 if (turn_on)
237 b43_led_blink_start(led, interval);
238 else
239 b43_led_blink_stop(led, 0);
240 continue;
241 case B43_LED_WEIRD:
242 //TODO
243 break;
244 case B43_LED_ASSOC:
245 if (1 /*dev->softmac->associated */ )
246 turn_on = 1;
247 break;
248#ifdef CONFIG_B43_DEBUG
249 case B43_LED_TEST_BLINKSLOW:
250 b43_led_blink_start(led, B43_LEDBLINK_SLOW);
251 continue;
252 case B43_LED_TEST_BLINKMEDIUM:
253 b43_led_blink_start(led, B43_LEDBLINK_MEDIUM);
254 continue;
255 case B43_LED_TEST_BLINKFAST:
256 b43_led_blink_start(led, B43_LEDBLINK_FAST);
257 continue;
258#endif /* CONFIG_B43_DEBUG */
259 default:
260 B43_WARN_ON(1);
261 };
262
263 if (led->activelow)
264 turn_on = !turn_on;
265 if (turn_on)
266 ledctl |= (1 << i);
267 else
268 ledctl &= ~(1 << i);
269 }
270 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ledctl);
271 spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
272}
273
274void b43_leds_switch_all(struct b43_wldev *dev, int on)
275{
276 struct b43_led *led;
277 u16 ledctl;
278 int i;
279 int bit_on;
280 unsigned long flags;
281
282 spin_lock_irqsave(&dev->wl->leds_lock, flags);
283 ledctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
284 for (i = 0; i < B43_NR_LEDS; i++) {
285 led = &(dev->leds[i]);
286 if (led->behaviour == B43_LED_INACTIVE)
287 continue;
288 if (on)
289 bit_on = led->activelow ? 0 : 1;
290 else
291 bit_on = led->activelow ? 1 : 0;
292 if (bit_on)
293 ledctl |= (1 << i);
294 else
295 ledctl &= ~(1 << i);
296 }
297 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ledctl);
298 spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
299}
diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h
new file mode 100644
index 000000000000..36b46cfda220
--- /dev/null
+++ b/drivers/net/wireless/b43/leds.h
@@ -0,0 +1,55 @@
1#ifndef B43_LEDS_H_
2#define B43_LEDS_H_
3
4#include <linux/types.h>
5#include <linux/timer.h>
6
7struct b43_led {
8 u8 behaviour:7;
9 u8 activelow:1;
10
11 struct b43_wldev *dev;
12 struct timer_list blink_timer;
13 unsigned long blink_interval;
14};
15#define b43_led_index(led) ((int)((led) - (led)->dev->leds))
16
17/* Delay between state changes when blinking in jiffies */
18#define B43_LEDBLINK_SLOW (HZ / 1)
19#define B43_LEDBLINK_MEDIUM (HZ / 4)
20#define B43_LEDBLINK_FAST (HZ / 8)
21
22#define B43_LED_XFER_THRES (HZ / 100)
23
24#define B43_LED_BEHAVIOUR 0x7F
25#define B43_LED_ACTIVELOW 0x80
26enum { /* LED behaviour values */
27 B43_LED_OFF,
28 B43_LED_ON,
29 B43_LED_ACTIVITY,
30 B43_LED_RADIO_ALL,
31 B43_LED_RADIO_A,
32 B43_LED_RADIO_B,
33 B43_LED_MODE_BG,
34 B43_LED_TRANSFER,
35 B43_LED_APTRANSFER,
36 B43_LED_WEIRD, //FIXME
37 B43_LED_ASSOC,
38 B43_LED_INACTIVE,
39
40 /* Behaviour values for testing.
41 * With these values it is easier to figure out
42 * the real behaviour of leds, in case the SPROM
43 * is missing information.
44 */
45 B43_LED_TEST_BLINKSLOW,
46 B43_LED_TEST_BLINKMEDIUM,
47 B43_LED_TEST_BLINKFAST,
48};
49
50int b43_leds_init(struct b43_wldev *dev);
51void b43_leds_exit(struct b43_wldev *dev);
52void b43_leds_update(struct b43_wldev *dev, int activity);
53void b43_leds_switch_all(struct b43_wldev *dev, int on);
54
55#endif /* B43_LEDS_H_ */
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
new file mode 100644
index 000000000000..b14a1753a0d7
--- /dev/null
+++ b/drivers/net/wireless/b43/lo.c
@@ -0,0 +1,1261 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 G PHY LO (LocalOscillator) Measuring and Control routines
6
7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
8 Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>
9 Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
10 Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
11 Copyright (c) 2005, 2006 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 "b43.h"
31#include "lo.h"
32#include "phy.h"
33#include "main.h"
34
35#include <linux/delay.h>
36#include <linux/sched.h>
37
38
39/* Define to 1 to always calibrate all possible LO control pairs.
40 * This is a workaround until we fix the partial LO calibration optimization. */
41#define B43_CALIB_ALL_LOCTLS 1
42
43
44/* Write the LocalOscillator Control (adjust) value-pair. */
45static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control)
46{
47 struct b43_phy *phy = &dev->phy;
48 u16 value;
49 u16 reg;
50
51 if (B43_DEBUG) {
52 if (unlikely(abs(control->i) > 16 || abs(control->q) > 16)) {
53 b43dbg(dev->wl, "Invalid LO control pair "
54 "(I: %d, Q: %d)\n", control->i, control->q);
55 dump_stack();
56 return;
57 }
58 }
59
60 value = (u8) (control->q);
61 value |= ((u8) (control->i)) << 8;
62
63 reg = (phy->type == B43_PHYTYPE_B) ? 0x002F : B43_PHY_LO_CTL;
64 b43_phy_write(dev, reg, value);
65}
66
67static int assert_rfatt_and_bbatt(const struct b43_rfatt *rfatt,
68 const struct b43_bbatt *bbatt,
69 struct b43_wldev *dev)
70{
71 int err = 0;
72
73 /* Check the attenuation values against the LO control array sizes. */
74 if (unlikely(rfatt->att >= B43_NR_RF)) {
75 b43err(dev->wl, "rfatt(%u) >= size of LO array\n", rfatt->att);
76 err = -EINVAL;
77 }
78 if (unlikely(bbatt->att >= B43_NR_BB)) {
79 b43err(dev->wl, "bbatt(%u) >= size of LO array\n", bbatt->att);
80 err = -EINVAL;
81 }
82
83 return err;
84}
85
86#if !B43_CALIB_ALL_LOCTLS
87static
88struct b43_loctl *b43_get_lo_g_ctl_nopadmix(struct b43_wldev *dev,
89 const struct b43_rfatt *rfatt,
90 const struct b43_bbatt *bbatt)
91{
92 struct b43_phy *phy = &dev->phy;
93 struct b43_txpower_lo_control *lo = phy->lo_control;
94
95 if (assert_rfatt_and_bbatt(rfatt, bbatt, dev))
96 return &(lo->no_padmix[0][0]); /* Just prevent a crash */
97 return &(lo->no_padmix[bbatt->att][rfatt->att]);
98}
99#endif /* !B43_CALIB_ALL_LOCTLS */
100
101struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev,
102 const struct b43_rfatt *rfatt,
103 const struct b43_bbatt *bbatt)
104{
105 struct b43_phy *phy = &dev->phy;
106 struct b43_txpower_lo_control *lo = phy->lo_control;
107
108 if (assert_rfatt_and_bbatt(rfatt, bbatt, dev))
109 return &(lo->no_padmix[0][0]); /* Just prevent a crash */
110 if (rfatt->with_padmix)
111 return &(lo->with_padmix[bbatt->att][rfatt->att]);
112 return &(lo->no_padmix[bbatt->att][rfatt->att]);
113}
114
115/* Call a function for every possible LO control value-pair. */
116static void b43_call_for_each_loctl(struct b43_wldev *dev,
117 void (*func) (struct b43_wldev *,
118 struct b43_loctl *))
119{
120 struct b43_phy *phy = &dev->phy;
121 struct b43_txpower_lo_control *ctl = phy->lo_control;
122 int i, j;
123
124 for (i = 0; i < B43_NR_BB; i++) {
125 for (j = 0; j < B43_NR_RF; j++)
126 func(dev, &(ctl->with_padmix[i][j]));
127 }
128 for (i = 0; i < B43_NR_BB; i++) {
129 for (j = 0; j < B43_NR_RF; j++)
130 func(dev, &(ctl->no_padmix[i][j]));
131 }
132}
133
134static u16 lo_b_r15_loop(struct b43_wldev *dev)
135{
136 int i;
137 u16 ret = 0;
138
139 for (i = 0; i < 10; i++) {
140 b43_phy_write(dev, 0x0015, 0xAFA0);
141 udelay(1);
142 b43_phy_write(dev, 0x0015, 0xEFA0);
143 udelay(10);
144 b43_phy_write(dev, 0x0015, 0xFFA0);
145 udelay(40);
146 ret += b43_phy_read(dev, 0x002C);
147 }
148
149 return ret;
150}
151
152void b43_lo_b_measure(struct b43_wldev *dev)
153{
154 struct b43_phy *phy = &dev->phy;
155 u16 regstack[12] = { 0 };
156 u16 mls;
157 u16 fval;
158 int i, j;
159
160 regstack[0] = b43_phy_read(dev, 0x0015);
161 regstack[1] = b43_radio_read16(dev, 0x0052) & 0xFFF0;
162
163 if (phy->radio_ver == 0x2053) {
164 regstack[2] = b43_phy_read(dev, 0x000A);
165 regstack[3] = b43_phy_read(dev, 0x002A);
166 regstack[4] = b43_phy_read(dev, 0x0035);
167 regstack[5] = b43_phy_read(dev, 0x0003);
168 regstack[6] = b43_phy_read(dev, 0x0001);
169 regstack[7] = b43_phy_read(dev, 0x0030);
170
171 regstack[8] = b43_radio_read16(dev, 0x0043);
172 regstack[9] = b43_radio_read16(dev, 0x007A);
173 regstack[10] = b43_read16(dev, 0x03EC);
174 regstack[11] = b43_radio_read16(dev, 0x0052) & 0x00F0;
175
176 b43_phy_write(dev, 0x0030, 0x00FF);
177 b43_write16(dev, 0x03EC, 0x3F3F);
178 b43_phy_write(dev, 0x0035, regstack[4] & 0xFF7F);
179 b43_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0);
180 }
181 b43_phy_write(dev, 0x0015, 0xB000);
182 b43_phy_write(dev, 0x002B, 0x0004);
183
184 if (phy->radio_ver == 0x2053) {
185 b43_phy_write(dev, 0x002B, 0x0203);
186 b43_phy_write(dev, 0x002A, 0x08A3);
187 }
188
189 phy->minlowsig[0] = 0xFFFF;
190
191 for (i = 0; i < 4; i++) {
192 b43_radio_write16(dev, 0x0052, regstack[1] | i);
193 lo_b_r15_loop(dev);
194 }
195 for (i = 0; i < 10; i++) {
196 b43_radio_write16(dev, 0x0052, regstack[1] | i);
197 mls = lo_b_r15_loop(dev) / 10;
198 if (mls < phy->minlowsig[0]) {
199 phy->minlowsig[0] = mls;
200 phy->minlowsigpos[0] = i;
201 }
202 }
203 b43_radio_write16(dev, 0x0052, regstack[1] | phy->minlowsigpos[0]);
204
205 phy->minlowsig[1] = 0xFFFF;
206
207 for (i = -4; i < 5; i += 2) {
208 for (j = -4; j < 5; j += 2) {
209 if (j < 0)
210 fval = (0x0100 * i) + j + 0x0100;
211 else
212 fval = (0x0100 * i) + j;
213 b43_phy_write(dev, 0x002F, fval);
214 mls = lo_b_r15_loop(dev) / 10;
215 if (mls < phy->minlowsig[1]) {
216 phy->minlowsig[1] = mls;
217 phy->minlowsigpos[1] = fval;
218 }
219 }
220 }
221 phy->minlowsigpos[1] += 0x0101;
222
223 b43_phy_write(dev, 0x002F, phy->minlowsigpos[1]);
224 if (phy->radio_ver == 0x2053) {
225 b43_phy_write(dev, 0x000A, regstack[2]);
226 b43_phy_write(dev, 0x002A, regstack[3]);
227 b43_phy_write(dev, 0x0035, regstack[4]);
228 b43_phy_write(dev, 0x0003, regstack[5]);
229 b43_phy_write(dev, 0x0001, regstack[6]);
230 b43_phy_write(dev, 0x0030, regstack[7]);
231
232 b43_radio_write16(dev, 0x0043, regstack[8]);
233 b43_radio_write16(dev, 0x007A, regstack[9]);
234
235 b43_radio_write16(dev, 0x0052,
236 (b43_radio_read16(dev, 0x0052) & 0x000F)
237 | regstack[11]);
238
239 b43_write16(dev, 0x03EC, regstack[10]);
240 }
241 b43_phy_write(dev, 0x0015, regstack[0]);
242}
243
244static u16 lo_measure_feedthrough(struct b43_wldev *dev,
245 u16 lna, u16 pga, u16 trsw_rx)
246{
247 struct b43_phy *phy = &dev->phy;
248 u16 rfover;
249 u16 feedthrough;
250
251 if (phy->gmode) {
252 lna <<= B43_PHY_RFOVERVAL_LNA_SHIFT;
253 pga <<= B43_PHY_RFOVERVAL_PGA_SHIFT;
254
255 B43_WARN_ON(lna & ~B43_PHY_RFOVERVAL_LNA);
256 B43_WARN_ON(pga & ~B43_PHY_RFOVERVAL_PGA);
257/*FIXME This assertion fails B43_WARN_ON(trsw_rx & ~(B43_PHY_RFOVERVAL_TRSWRX |
258 B43_PHY_RFOVERVAL_BW));
259*/
260 trsw_rx &= (B43_PHY_RFOVERVAL_TRSWRX | B43_PHY_RFOVERVAL_BW);
261
262 /* Construct the RF Override Value */
263 rfover = B43_PHY_RFOVERVAL_UNK;
264 rfover |= pga;
265 rfover |= lna;
266 rfover |= trsw_rx;
267 if ((dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_EXTLNA) &&
268 phy->rev > 6)
269 rfover |= B43_PHY_RFOVERVAL_EXTLNA;
270
271 b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
272 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover);
273 udelay(10);
274 rfover |= B43_PHY_RFOVERVAL_BW_LBW;
275 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover);
276 udelay(10);
277 rfover |= B43_PHY_RFOVERVAL_BW_LPF;
278 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover);
279 udelay(10);
280 b43_phy_write(dev, B43_PHY_PGACTL, 0xF300);
281 } else {
282 pga |= B43_PHY_PGACTL_UNKNOWN;
283 b43_phy_write(dev, B43_PHY_PGACTL, pga);
284 udelay(10);
285 pga |= B43_PHY_PGACTL_LOWBANDW;
286 b43_phy_write(dev, B43_PHY_PGACTL, pga);
287 udelay(10);
288 pga |= B43_PHY_PGACTL_LPF;
289 b43_phy_write(dev, B43_PHY_PGACTL, pga);
290 }
291 udelay(21);
292 feedthrough = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
293
294 /* This is a good place to check if we need to relax a bit,
295 * as this is the main function called regularly
296 * in the LO calibration. */
297 cond_resched();
298
299 return feedthrough;
300}
301
302/* TXCTL Register and Value Table.
303 * Returns the "TXCTL Register".
304 * "value" is the "TXCTL Value".
305 * "pad_mix_gain" is the PAD Mixer Gain.
306 */
307static u16 lo_txctl_register_table(struct b43_wldev *dev,
308 u16 * value, u16 * pad_mix_gain)
309{
310 struct b43_phy *phy = &dev->phy;
311 u16 reg, v, padmix;
312
313 if (phy->type == B43_PHYTYPE_B) {
314 v = 0x30;
315 if (phy->radio_rev <= 5) {
316 reg = 0x43;
317 padmix = 0;
318 } else {
319 reg = 0x52;
320 padmix = 5;
321 }
322 } else {
323 if (phy->rev >= 2 && phy->radio_rev == 8) {
324 reg = 0x43;
325 v = 0x10;
326 padmix = 2;
327 } else {
328 reg = 0x52;
329 v = 0x30;
330 padmix = 5;
331 }
332 }
333 if (value)
334 *value = v;
335 if (pad_mix_gain)
336 *pad_mix_gain = padmix;
337
338 return reg;
339}
340
341static void lo_measure_txctl_values(struct b43_wldev *dev)
342{
343 struct b43_phy *phy = &dev->phy;
344 struct b43_txpower_lo_control *lo = phy->lo_control;
345 u16 reg, mask;
346 u16 trsw_rx, pga;
347 u16 radio_pctl_reg;
348
349 static const u8 tx_bias_values[] = {
350 0x09, 0x08, 0x0A, 0x01, 0x00,
351 0x02, 0x05, 0x04, 0x06,
352 };
353 static const u8 tx_magn_values[] = {
354 0x70, 0x40,
355 };
356
357 if (!has_loopback_gain(phy)) {
358 radio_pctl_reg = 6;
359 trsw_rx = 2;
360 pga = 0;
361 } else {
362 int lb_gain; /* Loopback gain (in dB) */
363
364 trsw_rx = 0;
365 lb_gain = phy->max_lb_gain / 2;
366 if (lb_gain > 10) {
367 radio_pctl_reg = 0;
368 pga = abs(10 - lb_gain) / 6;
369 pga = limit_value(pga, 0, 15);
370 } else {
371 int cmp_val;
372 int tmp;
373
374 pga = 0;
375 cmp_val = 0x24;
376 if ((phy->rev >= 2) &&
377 (phy->radio_ver == 0x2050) && (phy->radio_rev == 8))
378 cmp_val = 0x3C;
379 tmp = lb_gain;
380 if ((10 - lb_gain) < cmp_val)
381 tmp = (10 - lb_gain);
382 if (tmp < 0)
383 tmp += 6;
384 else
385 tmp += 3;
386 cmp_val /= 4;
387 tmp /= 4;
388 if (tmp >= cmp_val)
389 radio_pctl_reg = cmp_val;
390 else
391 radio_pctl_reg = tmp;
392 }
393 }
394 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
395 & 0xFFF0) | radio_pctl_reg);
396 b43_phy_set_baseband_attenuation(dev, 2);
397
398 reg = lo_txctl_register_table(dev, &mask, NULL);
399 mask = ~mask;
400 b43_radio_write16(dev, reg, b43_radio_read16(dev, reg)
401 & mask);
402
403 if (has_tx_magnification(phy)) {
404 int i, j;
405 int feedthrough;
406 int min_feedth = 0xFFFF;
407 u8 tx_magn, tx_bias;
408
409 for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) {
410 tx_magn = tx_magn_values[i];
411 b43_radio_write16(dev, 0x52,
412 (b43_radio_read16(dev, 0x52)
413 & 0xFF0F) | tx_magn);
414 for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) {
415 tx_bias = tx_bias_values[j];
416 b43_radio_write16(dev, 0x52,
417 (b43_radio_read16(dev, 0x52)
418 & 0xFFF0) | tx_bias);
419 feedthrough =
420 lo_measure_feedthrough(dev, 0, pga,
421 trsw_rx);
422 if (feedthrough < min_feedth) {
423 lo->tx_bias = tx_bias;
424 lo->tx_magn = tx_magn;
425 min_feedth = feedthrough;
426 }
427 if (lo->tx_bias == 0)
428 break;
429 }
430 b43_radio_write16(dev, 0x52,
431 (b43_radio_read16(dev, 0x52)
432 & 0xFF00) | lo->tx_bias | lo->
433 tx_magn);
434 }
435 } else {
436 lo->tx_magn = 0;
437 lo->tx_bias = 0;
438 b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52)
439 & 0xFFF0); /* TX bias == 0 */
440 }
441}
442
443static void lo_read_power_vector(struct b43_wldev *dev)
444{
445 struct b43_phy *phy = &dev->phy;
446 struct b43_txpower_lo_control *lo = phy->lo_control;
447 u16 i;
448 u64 tmp;
449 u64 power_vector = 0;
450 int rf_offset, bb_offset;
451 struct b43_loctl *loctl;
452
453 for (i = 0; i < 8; i += 2) {
454 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i);
455 /* Clear the top byte. We get holes in the bitmap... */
456 tmp &= 0xFF;
457 power_vector |= (tmp << (i * 8));
458 /* Clear the vector on the device. */
459 b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0);
460 }
461
462 if (power_vector)
463 lo->power_vector = power_vector;
464 power_vector = lo->power_vector;
465
466 for (i = 0; i < 64; i++) {
467 if (power_vector & ((u64) 1ULL << i)) {
468 /* Now figure out which b43_loctl corresponds
469 * to this bit.
470 */
471 rf_offset = i / lo->rfatt_list.len;
472 bb_offset = i % lo->rfatt_list.len; //FIXME?
473 loctl =
474 b43_get_lo_g_ctl(dev,
475 &lo->rfatt_list.list[rf_offset],
476 &lo->bbatt_list.list[bb_offset]);
477 /* And mark it as "used", as the device told us
478 * through the bitmap it is using it.
479 */
480 loctl->used = 1;
481 }
482 }
483}
484
485/* 802.11/LO/GPHY/MeasuringGains */
486static void lo_measure_gain_values(struct b43_wldev *dev,
487 s16 max_rx_gain, int use_trsw_rx)
488{
489 struct b43_phy *phy = &dev->phy;
490 u16 tmp;
491
492 if (max_rx_gain < 0)
493 max_rx_gain = 0;
494
495 if (has_loopback_gain(phy)) {
496 int trsw_rx = 0;
497 int trsw_rx_gain;
498
499 if (use_trsw_rx) {
500 trsw_rx_gain = phy->trsw_rx_gain / 2;
501 if (max_rx_gain >= trsw_rx_gain) {
502 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
503 trsw_rx = 0x20;
504 }
505 } else
506 trsw_rx_gain = max_rx_gain;
507 if (trsw_rx_gain < 9) {
508 phy->lna_lod_gain = 0;
509 } else {
510 phy->lna_lod_gain = 1;
511 trsw_rx_gain -= 8;
512 }
513 trsw_rx_gain = limit_value(trsw_rx_gain, 0, 0x2D);
514 phy->pga_gain = trsw_rx_gain / 3;
515 if (phy->pga_gain >= 5) {
516 phy->pga_gain -= 5;
517 phy->lna_gain = 2;
518 } else
519 phy->lna_gain = 0;
520 } else {
521 phy->lna_gain = 0;
522 phy->trsw_rx_gain = 0x20;
523 if (max_rx_gain >= 0x14) {
524 phy->lna_lod_gain = 1;
525 phy->pga_gain = 2;
526 } else if (max_rx_gain >= 0x12) {
527 phy->lna_lod_gain = 1;
528 phy->pga_gain = 1;
529 } else if (max_rx_gain >= 0xF) {
530 phy->lna_lod_gain = 1;
531 phy->pga_gain = 0;
532 } else {
533 phy->lna_lod_gain = 0;
534 phy->pga_gain = 0;
535 }
536 }
537
538 tmp = b43_radio_read16(dev, 0x7A);
539 if (phy->lna_lod_gain == 0)
540 tmp &= ~0x0008;
541 else
542 tmp |= 0x0008;
543 b43_radio_write16(dev, 0x7A, tmp);
544}
545
546struct lo_g_saved_values {
547 u8 old_channel;
548
549 /* Core registers */
550 u16 reg_3F4;
551 u16 reg_3E2;
552
553 /* PHY registers */
554 u16 phy_lo_mask;
555 u16 phy_extg_01;
556 u16 phy_dacctl_hwpctl;
557 u16 phy_dacctl;
558 u16 phy_base_14;
559 u16 phy_hpwr_tssictl;
560 u16 phy_analogover;
561 u16 phy_analogoverval;
562 u16 phy_rfover;
563 u16 phy_rfoverval;
564 u16 phy_classctl;
565 u16 phy_base_3E;
566 u16 phy_crs0;
567 u16 phy_pgactl;
568 u16 phy_base_2A;
569 u16 phy_syncctl;
570 u16 phy_base_30;
571 u16 phy_base_06;
572
573 /* Radio registers */
574 u16 radio_43;
575 u16 radio_7A;
576 u16 radio_52;
577};
578
579static void lo_measure_setup(struct b43_wldev *dev,
580 struct lo_g_saved_values *sav)
581{
582 struct ssb_sprom *sprom = &dev->dev->bus->sprom;
583 struct b43_phy *phy = &dev->phy;
584 struct b43_txpower_lo_control *lo = phy->lo_control;
585 u16 tmp;
586
587 if (b43_has_hardware_pctl(phy)) {
588 sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
589 sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01));
590 sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL);
591 sav->phy_base_14 = b43_phy_read(dev, B43_PHY_BASE(0x14));
592 sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL);
593
594 b43_phy_write(dev, B43_PHY_HPWR_TSSICTL,
595 b43_phy_read(dev, B43_PHY_HPWR_TSSICTL)
596 | 0x100);
597 b43_phy_write(dev, B43_PHY_EXTG(0x01),
598 b43_phy_read(dev, B43_PHY_EXTG(0x01))
599 | 0x40);
600 b43_phy_write(dev, B43_PHY_DACCTL,
601 b43_phy_read(dev, B43_PHY_DACCTL)
602 | 0x40);
603 b43_phy_write(dev, B43_PHY_BASE(0x14),
604 b43_phy_read(dev, B43_PHY_BASE(0x14))
605 | 0x200);
606 }
607 if (phy->type == B43_PHYTYPE_B &&
608 phy->radio_ver == 0x2050 && phy->radio_rev < 6) {
609 b43_phy_write(dev, B43_PHY_BASE(0x16), 0x410);
610 b43_phy_write(dev, B43_PHY_BASE(0x17), 0x820);
611 }
612 if (!lo->rebuild && b43_has_hardware_pctl(phy))
613 lo_read_power_vector(dev);
614 if (phy->rev >= 2) {
615 sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER);
616 sav->phy_analogoverval =
617 b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
618 sav->phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);
619 sav->phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
620 sav->phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL);
621 sav->phy_base_3E = b43_phy_read(dev, B43_PHY_BASE(0x3E));
622 sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);
623
624 b43_phy_write(dev, B43_PHY_CLASSCTL,
625 b43_phy_read(dev, B43_PHY_CLASSCTL)
626 & 0xFFFC);
627 b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0)
628 & 0x7FFF);
629 b43_phy_write(dev, B43_PHY_ANALOGOVER,
630 b43_phy_read(dev, B43_PHY_ANALOGOVER)
631 | 0x0003);
632 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
633 b43_phy_read(dev, B43_PHY_ANALOGOVERVAL)
634 & 0xFFFC);
635 if (phy->type == B43_PHYTYPE_G) {
636 if ((phy->rev >= 7) &&
637 (sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
638 b43_phy_write(dev, B43_PHY_RFOVER, 0x933);
639 } else {
640 b43_phy_write(dev, B43_PHY_RFOVER, 0x133);
641 }
642 } else {
643 b43_phy_write(dev, B43_PHY_RFOVER, 0);
644 }
645 b43_phy_write(dev, B43_PHY_BASE(0x3E), 0);
646 }
647 sav->reg_3F4 = b43_read16(dev, 0x3F4);
648 sav->reg_3E2 = b43_read16(dev, 0x3E2);
649 sav->radio_43 = b43_radio_read16(dev, 0x43);
650 sav->radio_7A = b43_radio_read16(dev, 0x7A);
651 sav->phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);
652 sav->phy_base_2A = b43_phy_read(dev, B43_PHY_BASE(0x2A));
653 sav->phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL);
654 sav->phy_dacctl = b43_phy_read(dev, B43_PHY_DACCTL);
655
656 if (!has_tx_magnification(phy)) {
657 sav->radio_52 = b43_radio_read16(dev, 0x52);
658 sav->radio_52 &= 0x00F0;
659 }
660 if (phy->type == B43_PHYTYPE_B) {
661 sav->phy_base_30 = b43_phy_read(dev, B43_PHY_BASE(0x30));
662 sav->phy_base_06 = b43_phy_read(dev, B43_PHY_BASE(0x06));
663 b43_phy_write(dev, B43_PHY_BASE(0x30), 0x00FF);
664 b43_phy_write(dev, B43_PHY_BASE(0x06), 0x3F3F);
665 } else {
666 b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2)
667 | 0x8000);
668 }
669 b43_write16(dev, 0x3F4, b43_read16(dev, 0x3F4)
670 & 0xF000);
671
672 tmp =
673 (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_BASE(0x2E);
674 b43_phy_write(dev, tmp, 0x007F);
675
676 tmp = sav->phy_syncctl;
677 b43_phy_write(dev, B43_PHY_SYNCCTL, tmp & 0xFF7F);
678 tmp = sav->radio_7A;
679 b43_radio_write16(dev, 0x007A, tmp & 0xFFF0);
680
681 b43_phy_write(dev, B43_PHY_BASE(0x2A), 0x8A3);
682 if (phy->type == B43_PHYTYPE_G ||
683 (phy->type == B43_PHYTYPE_B &&
684 phy->radio_ver == 0x2050 && phy->radio_rev >= 6)) {
685 b43_phy_write(dev, B43_PHY_BASE(0x2B), 0x1003);
686 } else
687 b43_phy_write(dev, B43_PHY_BASE(0x2B), 0x0802);
688 if (phy->rev >= 2)
689 b43_dummy_transmission(dev);
690 b43_radio_selectchannel(dev, 6, 0);
691 b43_radio_read16(dev, 0x51); /* dummy read */
692 if (phy->type == B43_PHYTYPE_G)
693 b43_phy_write(dev, B43_PHY_BASE(0x2F), 0);
694 if (lo->rebuild)
695 lo_measure_txctl_values(dev);
696 if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) {
697 b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078);
698 } else {
699 if (phy->type == B43_PHYTYPE_B)
700 b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8078);
701 else
702 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
703 }
704}
705
706static void lo_measure_restore(struct b43_wldev *dev,
707 struct lo_g_saved_values *sav)
708{
709 struct b43_phy *phy = &dev->phy;
710 struct b43_txpower_lo_control *lo = phy->lo_control;
711 u16 tmp;
712
713 if (phy->rev >= 2) {
714 b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
715 tmp = (phy->pga_gain << 8);
716 b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0);
717 udelay(5);
718 b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2);
719 udelay(2);
720 b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3);
721 } else {
722 tmp = (phy->pga_gain | 0xEFA0);
723 b43_phy_write(dev, B43_PHY_PGACTL, tmp);
724 }
725 if (b43_has_hardware_pctl(phy)) {
726 b43_gphy_dc_lt_init(dev);
727 } else {
728 if (lo->rebuild)
729 b43_lo_g_adjust_to(dev, 3, 2, 0);
730 else
731 b43_lo_g_adjust(dev);
732 }
733 if (phy->type == B43_PHYTYPE_G) {
734 if (phy->rev >= 3)
735 b43_phy_write(dev, B43_PHY_BASE(0x2E), 0xC078);
736 else
737 b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8078);
738 if (phy->rev >= 2)
739 b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x0202);
740 else
741 b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x0101);
742 }
743 b43_write16(dev, 0x3F4, sav->reg_3F4);
744 b43_phy_write(dev, B43_PHY_PGACTL, sav->phy_pgactl);
745 b43_phy_write(dev, B43_PHY_BASE(0x2A), sav->phy_base_2A);
746 b43_phy_write(dev, B43_PHY_SYNCCTL, sav->phy_syncctl);
747 b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl);
748 b43_radio_write16(dev, 0x43, sav->radio_43);
749 b43_radio_write16(dev, 0x7A, sav->radio_7A);
750 if (!has_tx_magnification(phy)) {
751 tmp = sav->radio_52;
752 b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)
753 & 0xFF0F) | tmp);
754 }
755 b43_write16(dev, 0x3E2, sav->reg_3E2);
756 if (phy->type == B43_PHYTYPE_B &&
757 phy->radio_ver == 0x2050 && phy->radio_rev <= 5) {
758 b43_phy_write(dev, B43_PHY_BASE(0x30), sav->phy_base_30);
759 b43_phy_write(dev, B43_PHY_BASE(0x06), sav->phy_base_06);
760 }
761 if (phy->rev >= 2) {
762 b43_phy_write(dev, B43_PHY_ANALOGOVER, sav->phy_analogover);
763 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
764 sav->phy_analogoverval);
765 b43_phy_write(dev, B43_PHY_CLASSCTL, sav->phy_classctl);
766 b43_phy_write(dev, B43_PHY_RFOVER, sav->phy_rfover);
767 b43_phy_write(dev, B43_PHY_RFOVERVAL, sav->phy_rfoverval);
768 b43_phy_write(dev, B43_PHY_BASE(0x3E), sav->phy_base_3E);
769 b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0);
770 }
771 if (b43_has_hardware_pctl(phy)) {
772 tmp = (sav->phy_lo_mask & 0xBFFF);
773 b43_phy_write(dev, B43_PHY_LO_MASK, tmp);
774 b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01);
775 b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl_hwpctl);
776 b43_phy_write(dev, B43_PHY_BASE(0x14), sav->phy_base_14);
777 b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
778 }
779 b43_radio_selectchannel(dev, sav->old_channel, 1);
780}
781
782struct b43_lo_g_statemachine {
783 int current_state;
784 int nr_measured;
785 int state_val_multiplier;
786 u16 lowest_feedth;
787 struct b43_loctl min_loctl;
788};
789
790/* Loop over each possible value in this state. */
791static int lo_probe_possible_loctls(struct b43_wldev *dev,
792 struct b43_loctl *probe_loctl,
793 struct b43_lo_g_statemachine *d)
794{
795 struct b43_phy *phy = &dev->phy;
796 struct b43_txpower_lo_control *lo = phy->lo_control;
797 struct b43_loctl test_loctl;
798 struct b43_loctl orig_loctl;
799 struct b43_loctl prev_loctl = {
800 .i = -100,
801 .q = -100,
802 };
803 int i;
804 int begin, end;
805 int found_lower = 0;
806 u16 feedth;
807
808 static const struct b43_loctl modifiers[] = {
809 {.i = 1,.q = 1,},
810 {.i = 1,.q = 0,},
811 {.i = 1,.q = -1,},
812 {.i = 0,.q = -1,},
813 {.i = -1,.q = -1,},
814 {.i = -1,.q = 0,},
815 {.i = -1,.q = 1,},
816 {.i = 0,.q = 1,},
817 };
818
819 if (d->current_state == 0) {
820 begin = 1;
821 end = 8;
822 } else if (d->current_state % 2 == 0) {
823 begin = d->current_state - 1;
824 end = d->current_state + 1;
825 } else {
826 begin = d->current_state - 2;
827 end = d->current_state + 2;
828 }
829 if (begin < 1)
830 begin += 8;
831 if (end > 8)
832 end -= 8;
833
834 memcpy(&orig_loctl, probe_loctl, sizeof(struct b43_loctl));
835 i = begin;
836 d->current_state = i;
837 while (1) {
838 B43_WARN_ON(!(i >= 1 && i <= 8));
839 memcpy(&test_loctl, &orig_loctl, sizeof(struct b43_loctl));
840 test_loctl.i += modifiers[i - 1].i * d->state_val_multiplier;
841 test_loctl.q += modifiers[i - 1].q * d->state_val_multiplier;
842 if ((test_loctl.i != prev_loctl.i ||
843 test_loctl.q != prev_loctl.q) &&
844 (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) {
845 b43_lo_write(dev, &test_loctl);
846 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
847 phy->pga_gain,
848 phy->trsw_rx_gain);
849 if (feedth < d->lowest_feedth) {
850 memcpy(probe_loctl, &test_loctl,
851 sizeof(struct b43_loctl));
852 found_lower = 1;
853 d->lowest_feedth = feedth;
854 if ((d->nr_measured < 2) &&
855 (!has_loopback_gain(phy) || lo->rebuild))
856 break;
857 }
858 }
859 memcpy(&prev_loctl, &test_loctl, sizeof(prev_loctl));
860 if (i == end)
861 break;
862 if (i == 8)
863 i = 1;
864 else
865 i++;
866 d->current_state = i;
867 }
868
869 return found_lower;
870}
871
872static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
873 struct b43_loctl *loctl,
874 int *max_rx_gain)
875{
876 struct b43_phy *phy = &dev->phy;
877 struct b43_txpower_lo_control *lo = phy->lo_control;
878 struct b43_lo_g_statemachine d;
879 u16 feedth;
880 int found_lower;
881 struct b43_loctl probe_loctl;
882 int max_repeat = 1, repeat_cnt = 0;
883
884 d.nr_measured = 0;
885 d.state_val_multiplier = 1;
886 if (has_loopback_gain(phy) && !lo->rebuild)
887 d.state_val_multiplier = 3;
888
889 memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl));
890 if (has_loopback_gain(phy) && lo->rebuild)
891 max_repeat = 4;
892 do {
893 b43_lo_write(dev, &d.min_loctl);
894 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
895 phy->pga_gain,
896 phy->trsw_rx_gain);
897 if (!lo->rebuild && feedth < 0x258) {
898 if (feedth >= 0x12C)
899 *max_rx_gain += 6;
900 else
901 *max_rx_gain += 3;
902 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
903 phy->pga_gain,
904 phy->trsw_rx_gain);
905 }
906 d.lowest_feedth = feedth;
907
908 d.current_state = 0;
909 do {
910 B43_WARN_ON(!
911 (d.current_state >= 0
912 && d.current_state <= 8));
913 memcpy(&probe_loctl, &d.min_loctl,
914 sizeof(struct b43_loctl));
915 found_lower =
916 lo_probe_possible_loctls(dev, &probe_loctl, &d);
917 if (!found_lower)
918 break;
919 if ((probe_loctl.i == d.min_loctl.i) &&
920 (probe_loctl.q == d.min_loctl.q))
921 break;
922 memcpy(&d.min_loctl, &probe_loctl,
923 sizeof(struct b43_loctl));
924 d.nr_measured++;
925 } while (d.nr_measured < 24);
926 memcpy(loctl, &d.min_loctl, sizeof(struct b43_loctl));
927
928 if (has_loopback_gain(phy)) {
929 if (d.lowest_feedth > 0x1194)
930 *max_rx_gain -= 6;
931 else if (d.lowest_feedth < 0x5DC)
932 *max_rx_gain += 3;
933 if (repeat_cnt == 0) {
934 if (d.lowest_feedth <= 0x5DC) {
935 d.state_val_multiplier = 1;
936 repeat_cnt++;
937 } else
938 d.state_val_multiplier = 2;
939 } else if (repeat_cnt == 2)
940 d.state_val_multiplier = 1;
941 }
942 lo_measure_gain_values(dev, *max_rx_gain,
943 has_loopback_gain(phy));
944 } while (++repeat_cnt < max_repeat);
945}
946
947#if B43_CALIB_ALL_LOCTLS
948static const struct b43_rfatt b43_full_rfatt_list_items[] = {
949 { .att = 0, .with_padmix = 0, },
950 { .att = 1, .with_padmix = 0, },
951 { .att = 2, .with_padmix = 0, },
952 { .att = 3, .with_padmix = 0, },
953 { .att = 4, .with_padmix = 0, },
954 { .att = 5, .with_padmix = 0, },
955 { .att = 6, .with_padmix = 0, },
956 { .att = 7, .with_padmix = 0, },
957 { .att = 8, .with_padmix = 0, },
958 { .att = 9, .with_padmix = 0, },
959 { .att = 10, .with_padmix = 0, },
960 { .att = 11, .with_padmix = 0, },
961 { .att = 12, .with_padmix = 0, },
962 { .att = 13, .with_padmix = 0, },
963 { .att = 14, .with_padmix = 0, },
964 { .att = 15, .with_padmix = 0, },
965 { .att = 0, .with_padmix = 1, },
966 { .att = 1, .with_padmix = 1, },
967 { .att = 2, .with_padmix = 1, },
968 { .att = 3, .with_padmix = 1, },
969 { .att = 4, .with_padmix = 1, },
970 { .att = 5, .with_padmix = 1, },
971 { .att = 6, .with_padmix = 1, },
972 { .att = 7, .with_padmix = 1, },
973 { .att = 8, .with_padmix = 1, },
974 { .att = 9, .with_padmix = 1, },
975 { .att = 10, .with_padmix = 1, },
976 { .att = 11, .with_padmix = 1, },
977 { .att = 12, .with_padmix = 1, },
978 { .att = 13, .with_padmix = 1, },
979 { .att = 14, .with_padmix = 1, },
980 { .att = 15, .with_padmix = 1, },
981};
982static const struct b43_rfatt_list b43_full_rfatt_list = {
983 .list = b43_full_rfatt_list_items,
984 .len = ARRAY_SIZE(b43_full_rfatt_list_items),
985};
986
987static const struct b43_bbatt b43_full_bbatt_list_items[] = {
988 { .att = 0, },
989 { .att = 1, },
990 { .att = 2, },
991 { .att = 3, },
992 { .att = 4, },
993 { .att = 5, },
994 { .att = 6, },
995 { .att = 7, },
996 { .att = 8, },
997 { .att = 9, },
998 { .att = 10, },
999 { .att = 11, },
1000};
1001static const struct b43_bbatt_list b43_full_bbatt_list = {
1002 .list = b43_full_bbatt_list_items,
1003 .len = ARRAY_SIZE(b43_full_bbatt_list_items),
1004};
1005#endif /* B43_CALIB_ALL_LOCTLS */
1006
1007static void lo_measure(struct b43_wldev *dev)
1008{
1009 struct b43_phy *phy = &dev->phy;
1010 struct b43_txpower_lo_control *lo = phy->lo_control;
1011 struct b43_loctl loctl = {
1012 .i = 0,
1013 .q = 0,
1014 };
1015 struct b43_loctl *ploctl;
1016 int max_rx_gain;
1017 int rfidx, bbidx;
1018 const struct b43_bbatt_list *bbatt_list;
1019 const struct b43_rfatt_list *rfatt_list;
1020
1021 /* Values from the "TXCTL Register and Value Table" */
1022 u16 txctl_reg;
1023 u16 txctl_value;
1024 u16 pad_mix_gain;
1025
1026 bbatt_list = &lo->bbatt_list;
1027 rfatt_list = &lo->rfatt_list;
1028#if B43_CALIB_ALL_LOCTLS
1029 bbatt_list = &b43_full_bbatt_list;
1030 rfatt_list = &b43_full_rfatt_list;
1031#endif
1032
1033 txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain);
1034
1035 for (rfidx = 0; rfidx < rfatt_list->len; rfidx++) {
1036
1037 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
1038 & 0xFFF0) |
1039 rfatt_list->list[rfidx].att);
1040 b43_radio_write16(dev, txctl_reg,
1041 (b43_radio_read16(dev, txctl_reg)
1042 & ~txctl_value)
1043 | (rfatt_list->list[rfidx].with_padmix ?
1044 txctl_value : 0));
1045
1046 for (bbidx = 0; bbidx < bbatt_list->len; bbidx++) {
1047 if (lo->rebuild) {
1048#if B43_CALIB_ALL_LOCTLS
1049 ploctl = b43_get_lo_g_ctl(dev,
1050 &rfatt_list->list[rfidx],
1051 &bbatt_list->list[bbidx]);
1052#else
1053 ploctl = b43_get_lo_g_ctl_nopadmix(dev,
1054 &rfatt_list->
1055 list[rfidx],
1056 &bbatt_list->
1057 list[bbidx]);
1058#endif
1059 } else {
1060 ploctl = b43_get_lo_g_ctl(dev,
1061 &rfatt_list->list[rfidx],
1062 &bbatt_list->list[bbidx]);
1063 if (!ploctl->used)
1064 continue;
1065 }
1066 memcpy(&loctl, ploctl, sizeof(loctl));
1067 loctl.i = 0;
1068 loctl.q = 0;
1069
1070 max_rx_gain = rfatt_list->list[rfidx].att * 2;
1071 max_rx_gain += bbatt_list->list[bbidx].att / 2;
1072 if (rfatt_list->list[rfidx].with_padmix)
1073 max_rx_gain -= pad_mix_gain;
1074 if (has_loopback_gain(phy))
1075 max_rx_gain += phy->max_lb_gain;
1076 lo_measure_gain_values(dev, max_rx_gain,
1077 has_loopback_gain(phy));
1078
1079 b43_phy_set_baseband_attenuation(dev,
1080 bbatt_list->list[bbidx].att);
1081 lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
1082 if (phy->type == B43_PHYTYPE_B) {
1083 loctl.i++;
1084 loctl.q++;
1085 }
1086 b43_loctl_set_calibrated(&loctl, 1);
1087 memcpy(ploctl, &loctl, sizeof(loctl));
1088 }
1089 }
1090}
1091
1092#if B43_DEBUG
1093static void do_validate_loctl(struct b43_wldev *dev, struct b43_loctl *control)
1094{
1095 const int is_initializing = (b43_status(dev) == B43_STAT_UNINIT);
1096 int i = control->i;
1097 int q = control->q;
1098
1099 if (b43_loctl_is_calibrated(control)) {
1100 if ((abs(i) > 16) || (abs(q) > 16))
1101 goto error;
1102 } else {
1103 if (control->used)
1104 goto error;
1105 if (dev->phy.lo_control->rebuild) {
1106 control->i = 0;
1107 control->q = 0;
1108 if ((i != B43_LOCTL_POISON) ||
1109 (q != B43_LOCTL_POISON))
1110 goto error;
1111 }
1112 }
1113 if (is_initializing && control->used)
1114 goto error;
1115
1116 return;
1117error:
1118 b43err(dev->wl, "LO control pair validation failed "
1119 "(I: %d, Q: %d, used %u, calib: %u, initing: %d)\n",
1120 i, q, control->used,
1121 b43_loctl_is_calibrated(control),
1122 is_initializing);
1123}
1124
1125static void validate_all_loctls(struct b43_wldev *dev)
1126{
1127 b43_call_for_each_loctl(dev, do_validate_loctl);
1128}
1129
1130static void do_reset_calib(struct b43_wldev *dev, struct b43_loctl *control)
1131{
1132 if (dev->phy.lo_control->rebuild ||
1133 control->used) {
1134 b43_loctl_set_calibrated(control, 0);
1135 control->i = B43_LOCTL_POISON;
1136 control->q = B43_LOCTL_POISON;
1137 }
1138}
1139
1140static void reset_all_loctl_calibration_states(struct b43_wldev *dev)
1141{
1142 b43_call_for_each_loctl(dev, do_reset_calib);
1143}
1144
1145#else /* B43_DEBUG */
1146static inline void validate_all_loctls(struct b43_wldev *dev) { }
1147static inline void reset_all_loctl_calibration_states(struct b43_wldev *dev) { }
1148#endif /* B43_DEBUG */
1149
1150void b43_lo_g_measure(struct b43_wldev *dev)
1151{
1152 struct b43_phy *phy = &dev->phy;
1153 struct lo_g_saved_values uninitialized_var(sav);
1154
1155 B43_WARN_ON((phy->type != B43_PHYTYPE_B) &&
1156 (phy->type != B43_PHYTYPE_G));
1157
1158 sav.old_channel = phy->channel;
1159 lo_measure_setup(dev, &sav);
1160 reset_all_loctl_calibration_states(dev);
1161 lo_measure(dev);
1162 lo_measure_restore(dev, &sav);
1163
1164 validate_all_loctls(dev);
1165
1166 phy->lo_control->lo_measured = 1;
1167 phy->lo_control->rebuild = 0;
1168}
1169
1170#if B43_DEBUG
1171static void validate_loctl_calibration(struct b43_wldev *dev,
1172 struct b43_loctl *loctl,
1173 struct b43_rfatt *rfatt,
1174 struct b43_bbatt *bbatt)
1175{
1176 if (b43_loctl_is_calibrated(loctl))
1177 return;
1178 if (!dev->phy.lo_control->lo_measured) {
1179 /* On init we set the attenuation values before we
1180 * calibrated the LO. I guess that's OK. */
1181 return;
1182 }
1183 b43err(dev->wl, "Adjusting Local Oscillator to an uncalibrated "
1184 "control pair: rfatt=%u,%spadmix bbatt=%u\n",
1185 rfatt->att,
1186 (rfatt->with_padmix) ? "" : "no-",
1187 bbatt->att);
1188}
1189#else
1190static inline void validate_loctl_calibration(struct b43_wldev *dev,
1191 struct b43_loctl *loctl,
1192 struct b43_rfatt *rfatt,
1193 struct b43_bbatt *bbatt)
1194{
1195}
1196#endif
1197
1198static inline void fixup_rfatt_for_txcontrol(struct b43_rfatt *rf,
1199 u8 tx_control)
1200{
1201 if (tx_control & B43_TXCTL_TXMIX) {
1202 if (rf->att < 5)
1203 rf->att = 4;
1204 }
1205}
1206
1207void b43_lo_g_adjust(struct b43_wldev *dev)
1208{
1209 struct b43_phy *phy = &dev->phy;
1210 struct b43_rfatt rf;
1211 struct b43_loctl *loctl;
1212
1213 memcpy(&rf, &phy->rfatt, sizeof(rf));
1214 fixup_rfatt_for_txcontrol(&rf, phy->tx_control);
1215
1216 loctl = b43_get_lo_g_ctl(dev, &rf, &phy->bbatt);
1217 validate_loctl_calibration(dev, loctl, &rf, &phy->bbatt);
1218 b43_lo_write(dev, loctl);
1219}
1220
1221void b43_lo_g_adjust_to(struct b43_wldev *dev,
1222 u16 rfatt, u16 bbatt, u16 tx_control)
1223{
1224 struct b43_rfatt rf;
1225 struct b43_bbatt bb;
1226 struct b43_loctl *loctl;
1227
1228 memset(&rf, 0, sizeof(rf));
1229 memset(&bb, 0, sizeof(bb));
1230 rf.att = rfatt;
1231 bb.att = bbatt;
1232 fixup_rfatt_for_txcontrol(&rf, tx_control);
1233 loctl = b43_get_lo_g_ctl(dev, &rf, &bb);
1234 validate_loctl_calibration(dev, loctl, &rf, &bb);
1235 b43_lo_write(dev, loctl);
1236}
1237
1238static void do_mark_unused(struct b43_wldev *dev, struct b43_loctl *control)
1239{
1240 control->used = 0;
1241}
1242
1243void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev)
1244{
1245 struct b43_phy *phy = &dev->phy;
1246 struct b43_txpower_lo_control *lo = phy->lo_control;
1247
1248 b43_call_for_each_loctl(dev, do_mark_unused);
1249 lo->rebuild = 1;
1250}
1251
1252void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev)
1253{
1254 struct b43_phy *phy = &dev->phy;
1255 struct b43_rfatt rf;
1256
1257 memcpy(&rf, &phy->rfatt, sizeof(rf));
1258 fixup_rfatt_for_txcontrol(&rf, phy->tx_control);
1259
1260 b43_get_lo_g_ctl(dev, &rf, &phy->bbatt)->used = 1;
1261}
diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h
new file mode 100644
index 000000000000..455615d1f8c6
--- /dev/null
+++ b/drivers/net/wireless/b43/lo.h
@@ -0,0 +1,112 @@
1#ifndef B43_LO_H_
2#define B43_LO_H_
3
4#include "phy.h"
5
6struct b43_wldev;
7
8/* Local Oscillator control value-pair. */
9struct b43_loctl {
10 /* Control values. */
11 s8 i;
12 s8 q;
13 /* "Used by hardware" flag. */
14 bool used;
15#ifdef CONFIG_B43_DEBUG
16 /* Is this lo-control-array entry calibrated? */
17 bool calibrated;
18#endif
19};
20
21/* Debugging: Poison value for i and q values. */
22#define B43_LOCTL_POISON 111
23
24/* loctl->calibrated debugging mechanism */
25#ifdef CONFIG_B43_DEBUG
26static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl,
27 bool calibrated)
28{
29 loctl->calibrated = calibrated;
30}
31static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl)
32{
33 return loctl->calibrated;
34}
35#else
36static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl,
37 bool calibrated)
38{
39}
40static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl)
41{
42 return 1;
43}
44#endif
45
46/* TX Power LO Control Array.
47 * Value-pairs to adjust the LocalOscillator are stored
48 * in this structure.
49 * There are two different set of values. One for "Flag is Set"
50 * and one for "Flag is Unset".
51 * By "Flag" the flag in struct b43_rfatt is meant.
52 * The Value arrays are two-dimensional. The first index
53 * is the baseband attenuation and the second index
54 * is the radio attenuation.
55 * Use b43_get_lo_g_ctl() to retrieve a value from the lists.
56 */
57struct b43_txpower_lo_control {
58#define B43_NR_BB 12
59#define B43_NR_RF 16
60 /* LO Control values, with PAD Mixer */
61 struct b43_loctl with_padmix[B43_NR_BB][B43_NR_RF];
62 /* LO Control values, without PAD Mixer */
63 struct b43_loctl no_padmix[B43_NR_BB][B43_NR_RF];
64
65 /* Flag to indicate a complete rebuild of the two tables above
66 * to the LO measuring code. */
67 bool rebuild;
68
69 /* Lists of valid RF and BB attenuation values for this device. */
70 struct b43_rfatt_list rfatt_list;
71 struct b43_bbatt_list bbatt_list;
72
73 /* Current TX Bias value */
74 u8 tx_bias;
75 /* Current TX Magnification Value (if used by the device) */
76 u8 tx_magn;
77
78 /* GPHY LO is measured. */
79 bool lo_measured;
80
81 /* Saved device PowerVector */
82 u64 power_vector;
83};
84
85/* Measure the BPHY Local Oscillator. */
86void b43_lo_b_measure(struct b43_wldev *dev);
87/* Measure the BPHY/GPHY Local Oscillator. */
88void b43_lo_g_measure(struct b43_wldev *dev);
89
90/* Adjust the Local Oscillator to the saved attenuation
91 * and txctl values.
92 */
93void b43_lo_g_adjust(struct b43_wldev *dev);
94/* Adjust to specific values. */
95void b43_lo_g_adjust_to(struct b43_wldev *dev,
96 u16 rfatt, u16 bbatt, u16 tx_control);
97
98/* Mark all possible b43_lo_g_ctl as "unused" */
99void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev);
100/* Mark the b43_lo_g_ctl corresponding to the current
101 * attenuation values as used.
102 */
103void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev);
104
105/* Get a reference to a LO Control value pair in the
106 * TX Power LO Control Array.
107 */
108struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev,
109 const struct b43_rfatt *rfatt,
110 const struct b43_bbatt *bbatt);
111
112#endif /* B43_LO_H_ */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
new file mode 100644
index 000000000000..184ebe3ed738
--- /dev/null
+++ b/drivers/net/wireless/b43/main.c
@@ -0,0 +1,4091 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
6 Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
7 Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
8 Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
9 Copyright (c) 2005 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 <asm/unaligned.h>
43
44#include "b43.h"
45#include "main.h"
46#include "debugfs.h"
47#include "phy.h"
48#include "dma.h"
49#include "pio.h"
50#include "sysfs.h"
51#include "xmit.h"
52#include "sysfs.h"
53#include "lo.h"
54#include "pcmcia.h"
55
56MODULE_DESCRIPTION("Broadcom B43 wireless driver");
57MODULE_AUTHOR("Martin Langer");
58MODULE_AUTHOR("Stefano Brivio");
59MODULE_AUTHOR("Michael Buesch");
60MODULE_LICENSE("GPL");
61
62extern char *nvram_get(char *name);
63
64#if defined(CONFIG_B43_DMA) && defined(CONFIG_B43_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_B43_DMA)
69# define modparam_pio 0
70#elif defined(CONFIG_B43_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,
77 "enable(1) / disable(0) Bad Frames Preemption");
78
79static int modparam_short_retry = B43_DEFAULT_SHORT_RETRY_LIMIT;
80module_param_named(short_retry, modparam_short_retry, int, 0444);
81MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
82
83static int modparam_long_retry = B43_DEFAULT_LONG_RETRY_LIMIT;
84module_param_named(long_retry, modparam_long_retry, int, 0444);
85MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
86
87static int modparam_noleds;
88module_param_named(noleds, modparam_noleds, int, 0444);
89MODULE_PARM_DESC(noleds, "Turn off all LED activity");
90
91static char modparam_fwpostfix[16];
92module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
93MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
94
95static int modparam_mon_keep_bad;
96module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444);
97MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode");
98
99static int modparam_mon_keep_badplcp;
100module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444);
101MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode");
102
103static int modparam_hwpctl;
104module_param_named(hwpctl, modparam_hwpctl, int, 0444);
105MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)");
106
107static int modparam_nohwcrypt;
108module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
109MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
110
111static const struct ssb_device_id b43_ssb_tbl[] = {
112 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
113 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
114 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
115 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
116 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
117 SSB_DEVTABLE_END
118};
119
120MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
121
122/* Channel and ratetables are shared for all devices.
123 * They can't be const, because ieee80211 puts some precalculated
124 * data in there. This data is the same for all devices, so we don't
125 * get concurrency issues */
126#define RATETAB_ENT(_rateid, _flags) \
127 { \
128 .rate = B43_RATE_TO_BASE100KBPS(_rateid), \
129 .val = (_rateid), \
130 .val2 = (_rateid), \
131 .flags = (_flags), \
132 }
133static struct ieee80211_rate __b43_ratetable[] = {
134 RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),
135 RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
136 RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
137 RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
138 RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
139 RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
140 RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
141 RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
142 RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
143 RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
144 RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
145 RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
146};
147
148#define b43_a_ratetable (__b43_ratetable + 4)
149#define b43_a_ratetable_size 8
150#define b43_b_ratetable (__b43_ratetable + 0)
151#define b43_b_ratetable_size 4
152#define b43_g_ratetable (__b43_ratetable + 0)
153#define b43_g_ratetable_size 12
154
155#define CHANTAB_ENT(_chanid, _freq) \
156 { \
157 .chan = (_chanid), \
158 .freq = (_freq), \
159 .val = (_chanid), \
160 .flag = IEEE80211_CHAN_W_SCAN | \
161 IEEE80211_CHAN_W_ACTIVE_SCAN | \
162 IEEE80211_CHAN_W_IBSS, \
163 .power_level = 0xFF, \
164 .antenna_max = 0xFF, \
165 }
166static struct ieee80211_channel b43_bg_chantable[] = {
167 CHANTAB_ENT(1, 2412),
168 CHANTAB_ENT(2, 2417),
169 CHANTAB_ENT(3, 2422),
170 CHANTAB_ENT(4, 2427),
171 CHANTAB_ENT(5, 2432),
172 CHANTAB_ENT(6, 2437),
173 CHANTAB_ENT(7, 2442),
174 CHANTAB_ENT(8, 2447),
175 CHANTAB_ENT(9, 2452),
176 CHANTAB_ENT(10, 2457),
177 CHANTAB_ENT(11, 2462),
178 CHANTAB_ENT(12, 2467),
179 CHANTAB_ENT(13, 2472),
180 CHANTAB_ENT(14, 2484),
181};
182
183#define b43_bg_chantable_size ARRAY_SIZE(b43_bg_chantable)
184static struct ieee80211_channel b43_a_chantable[] = {
185 CHANTAB_ENT(36, 5180),
186 CHANTAB_ENT(40, 5200),
187 CHANTAB_ENT(44, 5220),
188 CHANTAB_ENT(48, 5240),
189 CHANTAB_ENT(52, 5260),
190 CHANTAB_ENT(56, 5280),
191 CHANTAB_ENT(60, 5300),
192 CHANTAB_ENT(64, 5320),
193 CHANTAB_ENT(149, 5745),
194 CHANTAB_ENT(153, 5765),
195 CHANTAB_ENT(157, 5785),
196 CHANTAB_ENT(161, 5805),
197 CHANTAB_ENT(165, 5825),
198};
199
200#define b43_a_chantable_size ARRAY_SIZE(b43_a_chantable)
201
202static void b43_wireless_core_exit(struct b43_wldev *dev);
203static int b43_wireless_core_init(struct b43_wldev *dev);
204static void b43_wireless_core_stop(struct b43_wldev *dev);
205static int b43_wireless_core_start(struct b43_wldev *dev);
206
207static int b43_ratelimit(struct b43_wl *wl)
208{
209 if (!wl || !wl->current_dev)
210 return 1;
211 if (b43_status(wl->current_dev) < B43_STAT_STARTED)
212 return 1;
213 /* We are up and running.
214 * Ratelimit the messages to avoid DoS over the net. */
215 return net_ratelimit();
216}
217
218void b43info(struct b43_wl *wl, const char *fmt, ...)
219{
220 va_list args;
221
222 if (!b43_ratelimit(wl))
223 return;
224 va_start(args, fmt);
225 printk(KERN_INFO "b43-%s: ",
226 (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
227 vprintk(fmt, args);
228 va_end(args);
229}
230
231void b43err(struct b43_wl *wl, const char *fmt, ...)
232{
233 va_list args;
234
235 if (!b43_ratelimit(wl))
236 return;
237 va_start(args, fmt);
238 printk(KERN_ERR "b43-%s ERROR: ",
239 (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
240 vprintk(fmt, args);
241 va_end(args);
242}
243
244void b43warn(struct b43_wl *wl, const char *fmt, ...)
245{
246 va_list args;
247
248 if (!b43_ratelimit(wl))
249 return;
250 va_start(args, fmt);
251 printk(KERN_WARNING "b43-%s warning: ",
252 (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
253 vprintk(fmt, args);
254 va_end(args);
255}
256
257#if B43_DEBUG
258void b43dbg(struct b43_wl *wl, const char *fmt, ...)
259{
260 va_list args;
261
262 va_start(args, fmt);
263 printk(KERN_DEBUG "b43-%s debug: ",
264 (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
265 vprintk(fmt, args);
266 va_end(args);
267}
268#endif /* DEBUG */
269
270static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
271{
272 u32 macctl;
273
274 B43_WARN_ON(offset % 4 != 0);
275
276 macctl = b43_read32(dev, B43_MMIO_MACCTL);
277 if (macctl & B43_MACCTL_BE)
278 val = swab32(val);
279
280 b43_write32(dev, B43_MMIO_RAM_CONTROL, offset);
281 mmiowb();
282 b43_write32(dev, B43_MMIO_RAM_DATA, val);
283}
284
285static inline
286 void b43_shm_control_word(struct b43_wldev *dev, u16 routing, u16 offset)
287{
288 u32 control;
289
290 /* "offset" is the WORD offset. */
291
292 control = routing;
293 control <<= 16;
294 control |= offset;
295 b43_write32(dev, B43_MMIO_SHM_CONTROL, control);
296}
297
298u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
299{
300 u32 ret;
301
302 if (routing == B43_SHM_SHARED) {
303 B43_WARN_ON(offset & 0x0001);
304 if (offset & 0x0003) {
305 /* Unaligned access */
306 b43_shm_control_word(dev, routing, offset >> 2);
307 ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
308 ret <<= 16;
309 b43_shm_control_word(dev, routing, (offset >> 2) + 1);
310 ret |= b43_read16(dev, B43_MMIO_SHM_DATA);
311
312 return ret;
313 }
314 offset >>= 2;
315 }
316 b43_shm_control_word(dev, routing, offset);
317 ret = b43_read32(dev, B43_MMIO_SHM_DATA);
318
319 return ret;
320}
321
322u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
323{
324 u16 ret;
325
326 if (routing == B43_SHM_SHARED) {
327 B43_WARN_ON(offset & 0x0001);
328 if (offset & 0x0003) {
329 /* Unaligned access */
330 b43_shm_control_word(dev, routing, offset >> 2);
331 ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
332
333 return ret;
334 }
335 offset >>= 2;
336 }
337 b43_shm_control_word(dev, routing, offset);
338 ret = b43_read16(dev, B43_MMIO_SHM_DATA);
339
340 return ret;
341}
342
343void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
344{
345 if (routing == B43_SHM_SHARED) {
346 B43_WARN_ON(offset & 0x0001);
347 if (offset & 0x0003) {
348 /* Unaligned access */
349 b43_shm_control_word(dev, routing, offset >> 2);
350 mmiowb();
351 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
352 (value >> 16) & 0xffff);
353 mmiowb();
354 b43_shm_control_word(dev, routing, (offset >> 2) + 1);
355 mmiowb();
356 b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);
357 return;
358 }
359 offset >>= 2;
360 }
361 b43_shm_control_word(dev, routing, offset);
362 mmiowb();
363 b43_write32(dev, B43_MMIO_SHM_DATA, value);
364}
365
366void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
367{
368 if (routing == B43_SHM_SHARED) {
369 B43_WARN_ON(offset & 0x0001);
370 if (offset & 0x0003) {
371 /* Unaligned access */
372 b43_shm_control_word(dev, routing, offset >> 2);
373 mmiowb();
374 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value);
375 return;
376 }
377 offset >>= 2;
378 }
379 b43_shm_control_word(dev, routing, offset);
380 mmiowb();
381 b43_write16(dev, B43_MMIO_SHM_DATA, value);
382}
383
384/* Read HostFlags */
385u32 b43_hf_read(struct b43_wldev * dev)
386{
387 u32 ret;
388
389 ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
390 ret <<= 16;
391 ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
392
393 return ret;
394}
395
396/* Write HostFlags */
397void b43_hf_write(struct b43_wldev *dev, u32 value)
398{
399 b43_shm_write16(dev, B43_SHM_SHARED,
400 B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF));
401 b43_shm_write16(dev, B43_SHM_SHARED,
402 B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16));
403}
404
405void b43_tsf_read(struct b43_wldev *dev, u64 * tsf)
406{
407 /* We need to be careful. As we read the TSF from multiple
408 * registers, we should take care of register overflows.
409 * In theory, the whole tsf read process should be atomic.
410 * We try to be atomic here, by restaring the read process,
411 * if any of the high registers changed (overflew).
412 */
413 if (dev->dev->id.revision >= 3) {
414 u32 low, high, high2;
415
416 do {
417 high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
418 low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);
419 high2 = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
420 } while (unlikely(high != high2));
421
422 *tsf = high;
423 *tsf <<= 32;
424 *tsf |= low;
425 } else {
426 u64 tmp;
427 u16 v0, v1, v2, v3;
428 u16 test1, test2, test3;
429
430 do {
431 v3 = b43_read16(dev, B43_MMIO_TSF_3);
432 v2 = b43_read16(dev, B43_MMIO_TSF_2);
433 v1 = b43_read16(dev, B43_MMIO_TSF_1);
434 v0 = b43_read16(dev, B43_MMIO_TSF_0);
435
436 test3 = b43_read16(dev, B43_MMIO_TSF_3);
437 test2 = b43_read16(dev, B43_MMIO_TSF_2);
438 test1 = b43_read16(dev, B43_MMIO_TSF_1);
439 } while (v3 != test3 || v2 != test2 || v1 != test1);
440
441 *tsf = v3;
442 *tsf <<= 48;
443 tmp = v2;
444 tmp <<= 32;
445 *tsf |= tmp;
446 tmp = v1;
447 tmp <<= 16;
448 *tsf |= tmp;
449 *tsf |= v0;
450 }
451}
452
453static void b43_time_lock(struct b43_wldev *dev)
454{
455 u32 macctl;
456
457 macctl = b43_read32(dev, B43_MMIO_MACCTL);
458 macctl |= B43_MACCTL_TBTTHOLD;
459 b43_write32(dev, B43_MMIO_MACCTL, macctl);
460 /* Commit the write */
461 b43_read32(dev, B43_MMIO_MACCTL);
462}
463
464static void b43_time_unlock(struct b43_wldev *dev)
465{
466 u32 macctl;
467
468 macctl = b43_read32(dev, B43_MMIO_MACCTL);
469 macctl &= ~B43_MACCTL_TBTTHOLD;
470 b43_write32(dev, B43_MMIO_MACCTL, macctl);
471 /* Commit the write */
472 b43_read32(dev, B43_MMIO_MACCTL);
473}
474
475static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
476{
477 /* Be careful with the in-progress timer.
478 * First zero out the low register, so we have a full
479 * register-overflow duration to complete the operation.
480 */
481 if (dev->dev->id.revision >= 3) {
482 u32 lo = (tsf & 0x00000000FFFFFFFFULL);
483 u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
484
485 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, 0);
486 mmiowb();
487 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, hi);
488 mmiowb();
489 b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, lo);
490 } else {
491 u16 v0 = (tsf & 0x000000000000FFFFULL);
492 u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
493 u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
494 u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
495
496 b43_write16(dev, B43_MMIO_TSF_0, 0);
497 mmiowb();
498 b43_write16(dev, B43_MMIO_TSF_3, v3);
499 mmiowb();
500 b43_write16(dev, B43_MMIO_TSF_2, v2);
501 mmiowb();
502 b43_write16(dev, B43_MMIO_TSF_1, v1);
503 mmiowb();
504 b43_write16(dev, B43_MMIO_TSF_0, v0);
505 }
506}
507
508void b43_tsf_write(struct b43_wldev *dev, u64 tsf)
509{
510 b43_time_lock(dev);
511 b43_tsf_write_locked(dev, tsf);
512 b43_time_unlock(dev);
513}
514
515static
516void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 * mac)
517{
518 static const u8 zero_addr[ETH_ALEN] = { 0 };
519 u16 data;
520
521 if (!mac)
522 mac = zero_addr;
523
524 offset |= 0x0020;
525 b43_write16(dev, B43_MMIO_MACFILTER_CONTROL, offset);
526
527 data = mac[0];
528 data |= mac[1] << 8;
529 b43_write16(dev, B43_MMIO_MACFILTER_DATA, data);
530 data = mac[2];
531 data |= mac[3] << 8;
532 b43_write16(dev, B43_MMIO_MACFILTER_DATA, data);
533 data = mac[4];
534 data |= mac[5] << 8;
535 b43_write16(dev, B43_MMIO_MACFILTER_DATA, data);
536}
537
538static void b43_write_mac_bssid_templates(struct b43_wldev *dev)
539{
540 const u8 *mac;
541 const u8 *bssid;
542 u8 mac_bssid[ETH_ALEN * 2];
543 int i;
544 u32 tmp;
545
546 bssid = dev->wl->bssid;
547 mac = dev->wl->mac_addr;
548
549 b43_macfilter_set(dev, B43_MACFILTER_BSSID, bssid);
550
551 memcpy(mac_bssid, mac, ETH_ALEN);
552 memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
553
554 /* Write our MAC address and BSSID to template ram */
555 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) {
556 tmp = (u32) (mac_bssid[i + 0]);
557 tmp |= (u32) (mac_bssid[i + 1]) << 8;
558 tmp |= (u32) (mac_bssid[i + 2]) << 16;
559 tmp |= (u32) (mac_bssid[i + 3]) << 24;
560 b43_ram_write(dev, 0x20 + i, tmp);
561 }
562}
563
564static void b43_upload_card_macaddress(struct b43_wldev *dev,
565 const u8 * mac_addr)
566{
567 if (mac_addr)
568 memcpy(dev->wl->mac_addr, mac_addr, ETH_ALEN);
569 else
570 memset(dev->wl->mac_addr, 0, ETH_ALEN);
571 b43_write_mac_bssid_templates(dev);
572 b43_macfilter_set(dev, B43_MACFILTER_SELF, mac_addr);
573}
574
575static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
576{
577 /* slot_time is in usec. */
578 if (dev->phy.type != B43_PHYTYPE_G)
579 return;
580 b43_write16(dev, 0x684, 510 + slot_time);
581 b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time);
582}
583
584static void b43_short_slot_timing_enable(struct b43_wldev *dev)
585{
586 b43_set_slot_time(dev, 9);
587 dev->short_slot = 1;
588}
589
590static void b43_short_slot_timing_disable(struct b43_wldev *dev)
591{
592 b43_set_slot_time(dev, 20);
593 dev->short_slot = 0;
594}
595
596/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
597 * Returns the _previously_ enabled IRQ mask.
598 */
599static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask)
600{
601 u32 old_mask;
602
603 old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
604 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask);
605
606 return old_mask;
607}
608
609/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
610 * Returns the _previously_ enabled IRQ mask.
611 */
612static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask)
613{
614 u32 old_mask;
615
616 old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
617 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
618
619 return old_mask;
620}
621
622/* Synchronize IRQ top- and bottom-half.
623 * IRQs must be masked before calling this.
624 * This must not be called with the irq_lock held.
625 */
626static void b43_synchronize_irq(struct b43_wldev *dev)
627{
628 synchronize_irq(dev->dev->irq);
629 tasklet_kill(&dev->isr_tasklet);
630}
631
632/* DummyTransmission function, as documented on
633 * http://bcm-specs.sipsolutions.net/DummyTransmission
634 */
635void b43_dummy_transmission(struct b43_wldev *dev)
636{
637 struct b43_phy *phy = &dev->phy;
638 unsigned int i, max_loop;
639 u16 value;
640 u32 buffer[5] = {
641 0x00000000,
642 0x00D40000,
643 0x00000000,
644 0x01000000,
645 0x00000000,
646 };
647
648 switch (phy->type) {
649 case B43_PHYTYPE_A:
650 max_loop = 0x1E;
651 buffer[0] = 0x000201CC;
652 break;
653 case B43_PHYTYPE_B:
654 case B43_PHYTYPE_G:
655 max_loop = 0xFA;
656 buffer[0] = 0x000B846E;
657 break;
658 default:
659 B43_WARN_ON(1);
660 return;
661 }
662
663 for (i = 0; i < 5; i++)
664 b43_ram_write(dev, i * 4, buffer[i]);
665
666 /* Commit writes */
667 b43_read32(dev, B43_MMIO_MACCTL);
668
669 b43_write16(dev, 0x0568, 0x0000);
670 b43_write16(dev, 0x07C0, 0x0000);
671 value = ((phy->type == B43_PHYTYPE_A) ? 1 : 0);
672 b43_write16(dev, 0x050C, value);
673 b43_write16(dev, 0x0508, 0x0000);
674 b43_write16(dev, 0x050A, 0x0000);
675 b43_write16(dev, 0x054C, 0x0000);
676 b43_write16(dev, 0x056A, 0x0014);
677 b43_write16(dev, 0x0568, 0x0826);
678 b43_write16(dev, 0x0500, 0x0000);
679 b43_write16(dev, 0x0502, 0x0030);
680
681 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
682 b43_radio_write16(dev, 0x0051, 0x0017);
683 for (i = 0x00; i < max_loop; i++) {
684 value = b43_read16(dev, 0x050E);
685 if (value & 0x0080)
686 break;
687 udelay(10);
688 }
689 for (i = 0x00; i < 0x0A; i++) {
690 value = b43_read16(dev, 0x050E);
691 if (value & 0x0400)
692 break;
693 udelay(10);
694 }
695 for (i = 0x00; i < 0x0A; i++) {
696 value = b43_read16(dev, 0x0690);
697 if (!(value & 0x0100))
698 break;
699 udelay(10);
700 }
701 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
702 b43_radio_write16(dev, 0x0051, 0x0037);
703}
704
705static void key_write(struct b43_wldev *dev,
706 u8 index, u8 algorithm, const u8 * key)
707{
708 unsigned int i;
709 u32 offset;
710 u16 value;
711 u16 kidx;
712
713 /* Key index/algo block */
714 kidx = b43_kidx_to_fw(dev, index);
715 value = ((kidx << 4) | algorithm);
716 b43_shm_write16(dev, B43_SHM_SHARED,
717 B43_SHM_SH_KEYIDXBLOCK + (kidx * 2), value);
718
719 /* Write the key to the Key Table Pointer offset */
720 offset = dev->ktp + (index * B43_SEC_KEYSIZE);
721 for (i = 0; i < B43_SEC_KEYSIZE; i += 2) {
722 value = key[i];
723 value |= (u16) (key[i + 1]) << 8;
724 b43_shm_write16(dev, B43_SHM_SHARED, offset + i, value);
725 }
726}
727
728static void keymac_write(struct b43_wldev *dev, u8 index, const u8 * addr)
729{
730 u32 addrtmp[2] = { 0, 0, };
731 u8 per_sta_keys_start = 8;
732
733 if (b43_new_kidx_api(dev))
734 per_sta_keys_start = 4;
735
736 B43_WARN_ON(index < per_sta_keys_start);
737 /* We have two default TX keys and possibly two default RX keys.
738 * Physical mac 0 is mapped to physical key 4 or 8, depending
739 * on the firmware version.
740 * So we must adjust the index here.
741 */
742 index -= per_sta_keys_start;
743
744 if (addr) {
745 addrtmp[0] = addr[0];
746 addrtmp[0] |= ((u32) (addr[1]) << 8);
747 addrtmp[0] |= ((u32) (addr[2]) << 16);
748 addrtmp[0] |= ((u32) (addr[3]) << 24);
749 addrtmp[1] = addr[4];
750 addrtmp[1] |= ((u32) (addr[5]) << 8);
751 }
752
753 if (dev->dev->id.revision >= 5) {
754 /* Receive match transmitter address mechanism */
755 b43_shm_write32(dev, B43_SHM_RCMTA,
756 (index * 2) + 0, addrtmp[0]);
757 b43_shm_write16(dev, B43_SHM_RCMTA,
758 (index * 2) + 1, addrtmp[1]);
759 } else {
760 /* RXE (Receive Engine) and
761 * PSM (Programmable State Machine) mechanism
762 */
763 if (index < 8) {
764 /* TODO write to RCM 16, 19, 22 and 25 */
765 } else {
766 b43_shm_write32(dev, B43_SHM_SHARED,
767 B43_SHM_SH_PSM + (index * 6) + 0,
768 addrtmp[0]);
769 b43_shm_write16(dev, B43_SHM_SHARED,
770 B43_SHM_SH_PSM + (index * 6) + 4,
771 addrtmp[1]);
772 }
773 }
774}
775
776static void do_key_write(struct b43_wldev *dev,
777 u8 index, u8 algorithm,
778 const u8 * key, size_t key_len, const u8 * mac_addr)
779{
780 u8 buf[B43_SEC_KEYSIZE] = { 0, };
781 u8 per_sta_keys_start = 8;
782
783 if (b43_new_kidx_api(dev))
784 per_sta_keys_start = 4;
785
786 B43_WARN_ON(index >= dev->max_nr_keys);
787 B43_WARN_ON(key_len > B43_SEC_KEYSIZE);
788
789 if (index >= per_sta_keys_start)
790 keymac_write(dev, index, NULL); /* First zero out mac. */
791 if (key)
792 memcpy(buf, key, key_len);
793 key_write(dev, index, algorithm, buf);
794 if (index >= per_sta_keys_start)
795 keymac_write(dev, index, mac_addr);
796
797 dev->key[index].algorithm = algorithm;
798}
799
800static int b43_key_write(struct b43_wldev *dev,
801 int index, u8 algorithm,
802 const u8 * key, size_t key_len,
803 const u8 * mac_addr,
804 struct ieee80211_key_conf *keyconf)
805{
806 int i;
807 int sta_keys_start;
808
809 if (key_len > B43_SEC_KEYSIZE)
810 return -EINVAL;
811 for (i = 0; i < dev->max_nr_keys; i++) {
812 /* Check that we don't already have this key. */
813 B43_WARN_ON(dev->key[i].keyconf == keyconf);
814 }
815 if (index < 0) {
816 /* Either pairwise key or address is 00:00:00:00:00:00
817 * for transmit-only keys. Search the index. */
818 if (b43_new_kidx_api(dev))
819 sta_keys_start = 4;
820 else
821 sta_keys_start = 8;
822 for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
823 if (!dev->key[i].keyconf) {
824 /* found empty */
825 index = i;
826 break;
827 }
828 }
829 if (index < 0) {
830 b43err(dev->wl, "Out of hardware key memory\n");
831 return -ENOSPC;
832 }
833 } else
834 B43_WARN_ON(index > 3);
835
836 do_key_write(dev, index, algorithm, key, key_len, mac_addr);
837 if ((index <= 3) && !b43_new_kidx_api(dev)) {
838 /* Default RX key */
839 B43_WARN_ON(mac_addr);
840 do_key_write(dev, index + 4, algorithm, key, key_len, NULL);
841 }
842 keyconf->hw_key_idx = index;
843 dev->key[index].keyconf = keyconf;
844
845 return 0;
846}
847
848static int b43_key_clear(struct b43_wldev *dev, int index)
849{
850 if (B43_WARN_ON((index < 0) || (index >= dev->max_nr_keys)))
851 return -EINVAL;
852 do_key_write(dev, index, B43_SEC_ALGO_NONE,
853 NULL, B43_SEC_KEYSIZE, NULL);
854 if ((index <= 3) && !b43_new_kidx_api(dev)) {
855 do_key_write(dev, index + 4, B43_SEC_ALGO_NONE,
856 NULL, B43_SEC_KEYSIZE, NULL);
857 }
858 dev->key[index].keyconf = NULL;
859
860 return 0;
861}
862
863static void b43_clear_keys(struct b43_wldev *dev)
864{
865 int i;
866
867 for (i = 0; i < dev->max_nr_keys; i++)
868 b43_key_clear(dev, i);
869}
870
871void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
872{
873 u32 macctl;
874 u16 ucstat;
875 bool hwps;
876 bool awake;
877 int i;
878
879 B43_WARN_ON((ps_flags & B43_PS_ENABLED) &&
880 (ps_flags & B43_PS_DISABLED));
881 B43_WARN_ON((ps_flags & B43_PS_AWAKE) && (ps_flags & B43_PS_ASLEEP));
882
883 if (ps_flags & B43_PS_ENABLED) {
884 hwps = 1;
885 } else if (ps_flags & B43_PS_DISABLED) {
886 hwps = 0;
887 } else {
888 //TODO: If powersave is not off and FIXME is not set and we are not in adhoc
889 // and thus is not an AP and we are associated, set bit 25
890 }
891 if (ps_flags & B43_PS_AWAKE) {
892 awake = 1;
893 } else if (ps_flags & B43_PS_ASLEEP) {
894 awake = 0;
895 } else {
896 //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
897 // or we are associated, or FIXME, or the latest PS-Poll packet sent was
898 // successful, set bit26
899 }
900
901/* FIXME: For now we force awake-on and hwps-off */
902 hwps = 0;
903 awake = 1;
904
905 macctl = b43_read32(dev, B43_MMIO_MACCTL);
906 if (hwps)
907 macctl |= B43_MACCTL_HWPS;
908 else
909 macctl &= ~B43_MACCTL_HWPS;
910 if (awake)
911 macctl |= B43_MACCTL_AWAKE;
912 else
913 macctl &= ~B43_MACCTL_AWAKE;
914 b43_write32(dev, B43_MMIO_MACCTL, macctl);
915 /* Commit write */
916 b43_read32(dev, B43_MMIO_MACCTL);
917 if (awake && dev->dev->id.revision >= 5) {
918 /* Wait for the microcode to wake up. */
919 for (i = 0; i < 100; i++) {
920 ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
921 B43_SHM_SH_UCODESTAT);
922 if (ucstat != B43_SHM_SH_UCODESTAT_SLEEP)
923 break;
924 udelay(10);
925 }
926 }
927}
928
929/* Turn the Analog ON/OFF */
930static void b43_switch_analog(struct b43_wldev *dev, int on)
931{
932 b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
933}
934
935void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
936{
937 u32 tmslow;
938 u32 macctl;
939
940 flags |= B43_TMSLOW_PHYCLKEN;
941 flags |= B43_TMSLOW_PHYRESET;
942 ssb_device_enable(dev->dev, flags);
943 msleep(2); /* Wait for the PLL to turn on. */
944
945 /* Now take the PHY out of Reset again */
946 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
947 tmslow |= SSB_TMSLOW_FGC;
948 tmslow &= ~B43_TMSLOW_PHYRESET;
949 ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
950 ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
951 msleep(1);
952 tmslow &= ~SSB_TMSLOW_FGC;
953 ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
954 ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
955 msleep(1);
956
957 /* Turn Analog ON */
958 b43_switch_analog(dev, 1);
959
960 macctl = b43_read32(dev, B43_MMIO_MACCTL);
961 macctl &= ~B43_MACCTL_GMODE;
962 if (flags & B43_TMSLOW_GMODE)
963 macctl |= B43_MACCTL_GMODE;
964 macctl |= B43_MACCTL_IHR_ENABLED;
965 b43_write32(dev, B43_MMIO_MACCTL, macctl);
966}
967
968static void handle_irq_transmit_status(struct b43_wldev *dev)
969{
970 u32 v0, v1;
971 u16 tmp;
972 struct b43_txstatus stat;
973
974 while (1) {
975 v0 = b43_read32(dev, B43_MMIO_XMITSTAT_0);
976 if (!(v0 & 0x00000001))
977 break;
978 v1 = b43_read32(dev, B43_MMIO_XMITSTAT_1);
979
980 stat.cookie = (v0 >> 16);
981 stat.seq = (v1 & 0x0000FFFF);
982 stat.phy_stat = ((v1 & 0x00FF0000) >> 16);
983 tmp = (v0 & 0x0000FFFF);
984 stat.frame_count = ((tmp & 0xF000) >> 12);
985 stat.rts_count = ((tmp & 0x0F00) >> 8);
986 stat.supp_reason = ((tmp & 0x001C) >> 2);
987 stat.pm_indicated = !!(tmp & 0x0080);
988 stat.intermediate = !!(tmp & 0x0040);
989 stat.for_ampdu = !!(tmp & 0x0020);
990 stat.acked = !!(tmp & 0x0002);
991
992 b43_handle_txstatus(dev, &stat);
993 }
994}
995
996static void drain_txstatus_queue(struct b43_wldev *dev)
997{
998 u32 dummy;
999
1000 if (dev->dev->id.revision < 5)
1001 return;
1002 /* Read all entries from the microcode TXstatus FIFO
1003 * and throw them away.
1004 */
1005 while (1) {
1006 dummy = b43_read32(dev, B43_MMIO_XMITSTAT_0);
1007 if (!(dummy & 0x00000001))
1008 break;
1009 dummy = b43_read32(dev, B43_MMIO_XMITSTAT_1);
1010 }
1011}
1012
1013static u32 b43_jssi_read(struct b43_wldev *dev)
1014{
1015 u32 val = 0;
1016
1017 val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A);
1018 val <<= 16;
1019 val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088);
1020
1021 return val;
1022}
1023
1024static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
1025{
1026 b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF));
1027 b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16);
1028}
1029
1030static void b43_generate_noise_sample(struct b43_wldev *dev)
1031{
1032 b43_jssi_write(dev, 0x7F7F7F7F);
1033 b43_write32(dev, B43_MMIO_STATUS2_BITFIELD,
1034 b43_read32(dev, B43_MMIO_STATUS2_BITFIELD)
1035 | (1 << 4));
1036 B43_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel);
1037}
1038
1039static void b43_calculate_link_quality(struct b43_wldev *dev)
1040{
1041 /* Top half of Link Quality calculation. */
1042
1043 if (dev->noisecalc.calculation_running)
1044 return;
1045 dev->noisecalc.channel_at_start = dev->phy.channel;
1046 dev->noisecalc.calculation_running = 1;
1047 dev->noisecalc.nr_samples = 0;
1048
1049 b43_generate_noise_sample(dev);
1050}
1051
1052static void handle_irq_noise(struct b43_wldev *dev)
1053{
1054 struct b43_phy *phy = &dev->phy;
1055 u16 tmp;
1056 u8 noise[4];
1057 u8 i, j;
1058 s32 average;
1059
1060 /* Bottom half of Link Quality calculation. */
1061
1062 B43_WARN_ON(!dev->noisecalc.calculation_running);
1063 if (dev->noisecalc.channel_at_start != phy->channel)
1064 goto drop_calculation;
1065 *((u32 *) noise) = cpu_to_le32(b43_jssi_read(dev));
1066 if (noise[0] == 0x7F || noise[1] == 0x7F ||
1067 noise[2] == 0x7F || noise[3] == 0x7F)
1068 goto generate_new;
1069
1070 /* Get the noise samples. */
1071 B43_WARN_ON(dev->noisecalc.nr_samples >= 8);
1072 i = dev->noisecalc.nr_samples;
1073 noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
1074 noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
1075 noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
1076 noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
1077 dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
1078 dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
1079 dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
1080 dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]];
1081 dev->noisecalc.nr_samples++;
1082 if (dev->noisecalc.nr_samples == 8) {
1083 /* Calculate the Link Quality by the noise samples. */
1084 average = 0;
1085 for (i = 0; i < 8; i++) {
1086 for (j = 0; j < 4; j++)
1087 average += dev->noisecalc.samples[i][j];
1088 }
1089 average /= (8 * 4);
1090 average *= 125;
1091 average += 64;
1092 average /= 128;
1093 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x40C);
1094 tmp = (tmp / 128) & 0x1F;
1095 if (tmp >= 8)
1096 average += 2;
1097 else
1098 average -= 25;
1099 if (tmp == 8)
1100 average -= 72;
1101 else
1102 average -= 48;
1103
1104 dev->stats.link_noise = average;
1105 drop_calculation:
1106 dev->noisecalc.calculation_running = 0;
1107 return;
1108 }
1109 generate_new:
1110 b43_generate_noise_sample(dev);
1111}
1112
1113static void handle_irq_tbtt_indication(struct b43_wldev *dev)
1114{
1115 if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
1116 ///TODO: PS TBTT
1117 } else {
1118 if (1 /*FIXME: the last PSpoll frame was sent successfully */ )
1119 b43_power_saving_ctl_bits(dev, 0);
1120 }
1121 dev->reg124_set_0x4 = 0;
1122 if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
1123 dev->reg124_set_0x4 = 1;
1124}
1125
1126static void handle_irq_atim_end(struct b43_wldev *dev)
1127{
1128 if (!dev->reg124_set_0x4 /*FIXME rename this variable */ )
1129 return;
1130 b43_write32(dev, B43_MMIO_STATUS2_BITFIELD,
1131 b43_read32(dev, B43_MMIO_STATUS2_BITFIELD)
1132 | 0x4);
1133}
1134
1135static void handle_irq_pmq(struct b43_wldev *dev)
1136{
1137 u32 tmp;
1138
1139 //TODO: AP mode.
1140
1141 while (1) {
1142 tmp = b43_read32(dev, B43_MMIO_PS_STATUS);
1143 if (!(tmp & 0x00000008))
1144 break;
1145 }
1146 /* 16bit write is odd, but correct. */
1147 b43_write16(dev, B43_MMIO_PS_STATUS, 0x0002);
1148}
1149
1150static void b43_write_template_common(struct b43_wldev *dev,
1151 const u8 * data, u16 size,
1152 u16 ram_offset,
1153 u16 shm_size_offset, u8 rate)
1154{
1155 u32 i, tmp;
1156 struct b43_plcp_hdr4 plcp;
1157
1158 plcp.data = 0;
1159 b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
1160 b43_ram_write(dev, ram_offset, le32_to_cpu(plcp.data));
1161 ram_offset += sizeof(u32);
1162 /* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet.
1163 * So leave the first two bytes of the next write blank.
1164 */
1165 tmp = (u32) (data[0]) << 16;
1166 tmp |= (u32) (data[1]) << 24;
1167 b43_ram_write(dev, ram_offset, tmp);
1168 ram_offset += sizeof(u32);
1169 for (i = 2; i < size; i += sizeof(u32)) {
1170 tmp = (u32) (data[i + 0]);
1171 if (i + 1 < size)
1172 tmp |= (u32) (data[i + 1]) << 8;
1173 if (i + 2 < size)
1174 tmp |= (u32) (data[i + 2]) << 16;
1175 if (i + 3 < size)
1176 tmp |= (u32) (data[i + 3]) << 24;
1177 b43_ram_write(dev, ram_offset + i - 2, tmp);
1178 }
1179 b43_shm_write16(dev, B43_SHM_SHARED, shm_size_offset,
1180 size + sizeof(struct b43_plcp_hdr6));
1181}
1182
1183static void b43_write_beacon_template(struct b43_wldev *dev,
1184 u16 ram_offset,
1185 u16 shm_size_offset, u8 rate)
1186{
1187 int len;
1188 const u8 *data;
1189
1190 B43_WARN_ON(!dev->cached_beacon);
1191 len = min((size_t) dev->cached_beacon->len,
1192 0x200 - sizeof(struct b43_plcp_hdr6));
1193 data = (const u8 *)(dev->cached_beacon->data);
1194 b43_write_template_common(dev, data,
1195 len, ram_offset, shm_size_offset, rate);
1196}
1197
1198static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
1199 u16 shm_offset, u16 size, u8 rate)
1200{
1201 struct b43_plcp_hdr4 plcp;
1202 u32 tmp;
1203 __le16 dur;
1204
1205 plcp.data = 0;
1206 b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
1207 dur = ieee80211_generic_frame_duration(dev->wl->hw,
1208 dev->wl->if_id, size,
1209 B43_RATE_TO_BASE100KBPS(rate));
1210 /* Write PLCP in two parts and timing for packet transfer */
1211 tmp = le32_to_cpu(plcp.data);
1212 b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
1213 b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 2, tmp >> 16);
1214 b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, le16_to_cpu(dur));
1215}
1216
1217/* Instead of using custom probe response template, this function
1218 * just patches custom beacon template by:
1219 * 1) Changing packet type
1220 * 2) Patching duration field
1221 * 3) Stripping TIM
1222 */
1223static u8 *b43_generate_probe_resp(struct b43_wldev *dev,
1224 u16 * dest_size, u8 rate)
1225{
1226 const u8 *src_data;
1227 u8 *dest_data;
1228 u16 src_size, elem_size, src_pos, dest_pos;
1229 __le16 dur;
1230 struct ieee80211_hdr *hdr;
1231
1232 B43_WARN_ON(!dev->cached_beacon);
1233 src_size = dev->cached_beacon->len;
1234 src_data = (const u8 *)dev->cached_beacon->data;
1235
1236 if (unlikely(src_size < 0x24)) {
1237 b43dbg(dev->wl, "b43_generate_probe_resp: " "invalid beacon\n");
1238 return NULL;
1239 }
1240
1241 dest_data = kmalloc(src_size, GFP_ATOMIC);
1242 if (unlikely(!dest_data))
1243 return NULL;
1244
1245 /* 0x24 is offset of first variable-len Information-Element
1246 * in beacon frame.
1247 */
1248 memcpy(dest_data, src_data, 0x24);
1249 src_pos = dest_pos = 0x24;
1250 for (; src_pos < src_size - 2; src_pos += elem_size) {
1251 elem_size = src_data[src_pos + 1] + 2;
1252 if (src_data[src_pos] != 0x05) { /* TIM */
1253 memcpy(dest_data + dest_pos, src_data + src_pos,
1254 elem_size);
1255 dest_pos += elem_size;
1256 }
1257 }
1258 *dest_size = dest_pos;
1259 hdr = (struct ieee80211_hdr *)dest_data;
1260
1261 /* Set the frame control. */
1262 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1263 IEEE80211_STYPE_PROBE_RESP);
1264 dur = ieee80211_generic_frame_duration(dev->wl->hw,
1265 dev->wl->if_id, *dest_size,
1266 B43_RATE_TO_BASE100KBPS(rate));
1267 hdr->duration_id = dur;
1268
1269 return dest_data;
1270}
1271
1272static void b43_write_probe_resp_template(struct b43_wldev *dev,
1273 u16 ram_offset,
1274 u16 shm_size_offset, u8 rate)
1275{
1276 u8 *probe_resp_data;
1277 u16 size;
1278
1279 B43_WARN_ON(!dev->cached_beacon);
1280 size = dev->cached_beacon->len;
1281 probe_resp_data = b43_generate_probe_resp(dev, &size, rate);
1282 if (unlikely(!probe_resp_data))
1283 return;
1284
1285 /* Looks like PLCP headers plus packet timings are stored for
1286 * all possible basic rates
1287 */
1288 b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);
1289 b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);
1290 b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);
1291 b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);
1292
1293 size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
1294 b43_write_template_common(dev, probe_resp_data,
1295 size, ram_offset, shm_size_offset, rate);
1296 kfree(probe_resp_data);
1297}
1298
1299static int b43_refresh_cached_beacon(struct b43_wldev *dev,
1300 struct sk_buff *beacon)
1301{
1302 if (dev->cached_beacon)
1303 kfree_skb(dev->cached_beacon);
1304 dev->cached_beacon = beacon;
1305
1306 return 0;
1307}
1308
1309static void b43_update_templates(struct b43_wldev *dev)
1310{
1311 u32 status;
1312
1313 B43_WARN_ON(!dev->cached_beacon);
1314
1315 b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB);
1316 b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB);
1317 b43_write_probe_resp_template(dev, 0x268, 0x4A, B43_CCK_RATE_11MB);
1318
1319 status = b43_read32(dev, B43_MMIO_STATUS2_BITFIELD);
1320 status |= 0x03;
1321 b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);
1322}
1323
1324static void b43_refresh_templates(struct b43_wldev *dev, struct sk_buff *beacon)
1325{
1326 int err;
1327
1328 err = b43_refresh_cached_beacon(dev, beacon);
1329 if (unlikely(err))
1330 return;
1331 b43_update_templates(dev);
1332}
1333
1334static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
1335{
1336 u32 tmp;
1337 u16 i, len;
1338
1339 len = min((u16) ssid_len, (u16) 0x100);
1340 for (i = 0; i < len; i += sizeof(u32)) {
1341 tmp = (u32) (ssid[i + 0]);
1342 if (i + 1 < len)
1343 tmp |= (u32) (ssid[i + 1]) << 8;
1344 if (i + 2 < len)
1345 tmp |= (u32) (ssid[i + 2]) << 16;
1346 if (i + 3 < len)
1347 tmp |= (u32) (ssid[i + 3]) << 24;
1348 b43_shm_write32(dev, B43_SHM_SHARED, 0x380 + i, tmp);
1349 }
1350 b43_shm_write16(dev, B43_SHM_SHARED, 0x48, len);
1351}
1352
1353static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
1354{
1355 b43_time_lock(dev);
1356 if (dev->dev->id.revision >= 3) {
1357 b43_write32(dev, 0x188, (beacon_int << 16));
1358 } else {
1359 b43_write16(dev, 0x606, (beacon_int >> 6));
1360 b43_write16(dev, 0x610, beacon_int);
1361 }
1362 b43_time_unlock(dev);
1363}
1364
1365static void handle_irq_beacon(struct b43_wldev *dev)
1366{
1367 u32 status;
1368
1369 if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
1370 return;
1371
1372 dev->irq_savedstate &= ~B43_IRQ_BEACON;
1373 status = b43_read32(dev, B43_MMIO_STATUS2_BITFIELD);
1374
1375 if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
1376 /* ACK beacon IRQ. */
1377 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
1378 dev->irq_savedstate |= B43_IRQ_BEACON;
1379 if (dev->cached_beacon)
1380 kfree_skb(dev->cached_beacon);
1381 dev->cached_beacon = NULL;
1382 return;
1383 }
1384 if (!(status & 0x1)) {
1385 b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB);
1386 status |= 0x1;
1387 b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);
1388 }
1389 if (!(status & 0x2)) {
1390 b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB);
1391 status |= 0x2;
1392 b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);
1393 }
1394}
1395
1396static void handle_irq_ucode_debug(struct b43_wldev *dev)
1397{
1398 //TODO
1399}
1400
1401/* Interrupt handler bottom-half */
1402static void b43_interrupt_tasklet(struct b43_wldev *dev)
1403{
1404 u32 reason;
1405 u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
1406 u32 merged_dma_reason = 0;
1407 int i, activity = 0;
1408 unsigned long flags;
1409
1410 spin_lock_irqsave(&dev->wl->irq_lock, flags);
1411
1412 B43_WARN_ON(b43_status(dev) != B43_STAT_STARTED);
1413
1414 reason = dev->irq_reason;
1415 for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {
1416 dma_reason[i] = dev->dma_reason[i];
1417 merged_dma_reason |= dma_reason[i];
1418 }
1419
1420 if (unlikely(reason & B43_IRQ_MAC_TXERR))
1421 b43err(dev->wl, "MAC transmission error\n");
1422
1423 if (unlikely(reason & B43_IRQ_PHY_TXERR))
1424 b43err(dev->wl, "PHY transmission error\n");
1425
1426 if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
1427 B43_DMAIRQ_NONFATALMASK))) {
1428 if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {
1429 b43err(dev->wl, "Fatal DMA error: "
1430 "0x%08X, 0x%08X, 0x%08X, "
1431 "0x%08X, 0x%08X, 0x%08X\n",
1432 dma_reason[0], dma_reason[1],
1433 dma_reason[2], dma_reason[3],
1434 dma_reason[4], dma_reason[5]);
1435 b43_controller_restart(dev, "DMA error");
1436 mmiowb();
1437 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1438 return;
1439 }
1440 if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
1441 b43err(dev->wl, "DMA error: "
1442 "0x%08X, 0x%08X, 0x%08X, "
1443 "0x%08X, 0x%08X, 0x%08X\n",
1444 dma_reason[0], dma_reason[1],
1445 dma_reason[2], dma_reason[3],
1446 dma_reason[4], dma_reason[5]);
1447 }
1448 }
1449
1450 if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
1451 handle_irq_ucode_debug(dev);
1452 if (reason & B43_IRQ_TBTT_INDI)
1453 handle_irq_tbtt_indication(dev);
1454 if (reason & B43_IRQ_ATIM_END)
1455 handle_irq_atim_end(dev);
1456 if (reason & B43_IRQ_BEACON)
1457 handle_irq_beacon(dev);
1458 if (reason & B43_IRQ_PMQ)
1459 handle_irq_pmq(dev);
1460 if (reason & B43_IRQ_TXFIFO_FLUSH_OK) ;
1461 /*TODO*/ if (reason & B43_IRQ_NOISESAMPLE_OK)
1462 handle_irq_noise(dev);
1463
1464 /* Check the DMA reason registers for received data. */
1465 if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
1466 if (b43_using_pio(dev))
1467 b43_pio_rx(dev->pio.queue0);
1468 else
1469 b43_dma_rx(dev->dma.rx_ring0);
1470 /* We intentionally don't set "activity" to 1, here. */
1471 }
1472 B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
1473 B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
1474 if (dma_reason[3] & B43_DMAIRQ_RX_DONE) {
1475 if (b43_using_pio(dev))
1476 b43_pio_rx(dev->pio.queue3);
1477 else
1478 b43_dma_rx(dev->dma.rx_ring3);
1479 activity = 1;
1480 }
1481 B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
1482 B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
1483
1484 if (reason & B43_IRQ_TX_OK) {
1485 handle_irq_transmit_status(dev);
1486 activity = 1;
1487 //TODO: In AP mode, this also causes sending of powersave responses.
1488 }
1489
1490 if (!modparam_noleds)
1491 b43_leds_update(dev, activity);
1492 b43_interrupt_enable(dev, dev->irq_savedstate);
1493 mmiowb();
1494 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1495}
1496
1497static void pio_irq_workaround(struct b43_wldev *dev, u16 base, int queueidx)
1498{
1499 u16 rxctl;
1500
1501 rxctl = b43_read16(dev, base + B43_PIO_RXCTL);
1502 if (rxctl & B43_PIO_RXCTL_DATAAVAILABLE)
1503 dev->dma_reason[queueidx] |= B43_DMAIRQ_RX_DONE;
1504 else
1505 dev->dma_reason[queueidx] &= ~B43_DMAIRQ_RX_DONE;
1506}
1507
1508static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason)
1509{
1510 if (b43_using_pio(dev) &&
1511 (dev->dev->id.revision < 3) &&
1512 (!(reason & B43_IRQ_PIO_WORKAROUND))) {
1513 /* Apply a PIO specific workaround to the dma_reasons */
1514 pio_irq_workaround(dev, B43_MMIO_PIO1_BASE, 0);
1515 pio_irq_workaround(dev, B43_MMIO_PIO2_BASE, 1);
1516 pio_irq_workaround(dev, B43_MMIO_PIO3_BASE, 2);
1517 pio_irq_workaround(dev, B43_MMIO_PIO4_BASE, 3);
1518 }
1519
1520 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
1521
1522 b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
1523 b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);
1524 b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
1525 b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
1526 b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
1527 b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
1528}
1529
1530/* Interrupt handler top-half */
1531static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1532{
1533 irqreturn_t ret = IRQ_NONE;
1534 struct b43_wldev *dev = dev_id;
1535 u32 reason;
1536
1537 if (!dev)
1538 return IRQ_NONE;
1539
1540 spin_lock(&dev->wl->irq_lock);
1541
1542 if (b43_status(dev) < B43_STAT_STARTED)
1543 goto out;
1544 reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
1545 if (reason == 0xffffffff) /* shared IRQ */
1546 goto out;
1547 ret = IRQ_HANDLED;
1548 reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
1549 if (!reason)
1550 goto out;
1551
1552 dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
1553 & 0x0001DC00;
1554 dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
1555 & 0x0000DC00;
1556 dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
1557 & 0x0000DC00;
1558 dev->dma_reason[3] = b43_read32(dev, B43_MMIO_DMA3_REASON)
1559 & 0x0001DC00;
1560 dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
1561 & 0x0000DC00;
1562 dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
1563 & 0x0000DC00;
1564
1565 b43_interrupt_ack(dev, reason);
1566 /* disable all IRQs. They are enabled again in the bottom half. */
1567 dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
1568 /* save the reason code and call our bottom half. */
1569 dev->irq_reason = reason;
1570 tasklet_schedule(&dev->isr_tasklet);
1571 out:
1572 mmiowb();
1573 spin_unlock(&dev->wl->irq_lock);
1574
1575 return ret;
1576}
1577
1578static void b43_release_firmware(struct b43_wldev *dev)
1579{
1580 release_firmware(dev->fw.ucode);
1581 dev->fw.ucode = NULL;
1582 release_firmware(dev->fw.pcm);
1583 dev->fw.pcm = NULL;
1584 release_firmware(dev->fw.initvals);
1585 dev->fw.initvals = NULL;
1586 release_firmware(dev->fw.initvals_band);
1587 dev->fw.initvals_band = NULL;
1588}
1589
1590static void b43_print_fw_helptext(struct b43_wl *wl)
1591{
1592 b43err(wl, "You must go to "
1593 "http://linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware "
1594 "and download the correct firmware (version 4).\n");
1595}
1596
1597static int do_request_fw(struct b43_wldev *dev,
1598 const char *name,
1599 const struct firmware **fw)
1600{
1601 const size_t plen = sizeof(modparam_fwpostfix) + 32;
1602 char path[plen];
1603 struct b43_fw_header *hdr;
1604 u32 size;
1605 int err;
1606
1607 if (!name)
1608 return 0;
1609
1610 snprintf(path, ARRAY_SIZE(path),
1611 "b43%s/%s.fw",
1612 modparam_fwpostfix, name);
1613 err = request_firmware(fw, path, dev->dev->dev);
1614 if (err) {
1615 b43err(dev->wl, "Firmware file \"%s\" not found "
1616 "or load failed.\n", path);
1617 return err;
1618 }
1619 if ((*fw)->size < sizeof(struct b43_fw_header))
1620 goto err_format;
1621 hdr = (struct b43_fw_header *)((*fw)->data);
1622 switch (hdr->type) {
1623 case B43_FW_TYPE_UCODE:
1624 case B43_FW_TYPE_PCM:
1625 size = be32_to_cpu(hdr->size);
1626 if (size != (*fw)->size - sizeof(struct b43_fw_header))
1627 goto err_format;
1628 /* fallthrough */
1629 case B43_FW_TYPE_IV:
1630 if (hdr->ver != 1)
1631 goto err_format;
1632 break;
1633 default:
1634 goto err_format;
1635 }
1636
1637 return err;
1638
1639err_format:
1640 b43err(dev->wl, "Firmware file \"%s\" format error.\n", path);
1641 return -EPROTO;
1642}
1643
1644static int b43_request_firmware(struct b43_wldev *dev)
1645{
1646 struct b43_firmware *fw = &dev->fw;
1647 const u8 rev = dev->dev->id.revision;
1648 const char *filename;
1649 u32 tmshigh;
1650 int err;
1651
1652 tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
1653 if (!fw->ucode) {
1654 if ((rev >= 5) && (rev <= 10))
1655 filename = "ucode5";
1656 else if ((rev >= 11) && (rev <= 12))
1657 filename = "ucode11";
1658 else if (rev >= 13)
1659 filename = "ucode13";
1660 else
1661 goto err_no_ucode;
1662 err = do_request_fw(dev, filename, &fw->ucode);
1663 if (err)
1664 goto err_load;
1665 }
1666 if (!fw->pcm) {
1667 if ((rev >= 5) && (rev <= 10))
1668 filename = "pcm5";
1669 else if (rev >= 11)
1670 filename = NULL;
1671 else
1672 goto err_no_pcm;
1673 err = do_request_fw(dev, filename, &fw->pcm);
1674 if (err)
1675 goto err_load;
1676 }
1677 if (!fw->initvals) {
1678 switch (dev->phy.type) {
1679 case B43_PHYTYPE_A:
1680 if ((rev >= 5) && (rev <= 10)) {
1681 if (tmshigh & B43_TMSHIGH_GPHY)
1682 filename = "a0g1initvals5";
1683 else
1684 filename = "a0g0initvals5";
1685 } else
1686 goto err_no_initvals;
1687 break;
1688 case B43_PHYTYPE_G:
1689 if ((rev >= 5) && (rev <= 10))
1690 filename = "b0g0initvals5";
1691 else if (rev >= 13)
1692 filename = "lp0initvals13";
1693 else
1694 goto err_no_initvals;
1695 break;
1696 default:
1697 goto err_no_initvals;
1698 }
1699 err = do_request_fw(dev, filename, &fw->initvals);
1700 if (err)
1701 goto err_load;
1702 }
1703 if (!fw->initvals_band) {
1704 switch (dev->phy.type) {
1705 case B43_PHYTYPE_A:
1706 if ((rev >= 5) && (rev <= 10)) {
1707 if (tmshigh & B43_TMSHIGH_GPHY)
1708 filename = "a0g1bsinitvals5";
1709 else
1710 filename = "a0g0bsinitvals5";
1711 } else if (rev >= 11)
1712 filename = NULL;
1713 else
1714 goto err_no_initvals;
1715 break;
1716 case B43_PHYTYPE_G:
1717 if ((rev >= 5) && (rev <= 10))
1718 filename = "b0g0bsinitvals5";
1719 else if (rev >= 11)
1720 filename = NULL;
1721 else
1722 goto err_no_initvals;
1723 break;
1724 default:
1725 goto err_no_initvals;
1726 }
1727 err = do_request_fw(dev, filename, &fw->initvals_band);
1728 if (err)
1729 goto err_load;
1730 }
1731
1732 return 0;
1733
1734err_load:
1735 b43_print_fw_helptext(dev->wl);
1736 goto error;
1737
1738err_no_ucode:
1739 err = -ENODEV;
1740 b43err(dev->wl, "No microcode available for core rev %u\n", rev);
1741 goto error;
1742
1743err_no_pcm:
1744 err = -ENODEV;
1745 b43err(dev->wl, "No PCM available for core rev %u\n", rev);
1746 goto error;
1747
1748err_no_initvals:
1749 err = -ENODEV;
1750 b43err(dev->wl, "No Initial Values firmware file for PHY %u, "
1751 "core rev %u\n", dev->phy.type, rev);
1752 goto error;
1753
1754error:
1755 b43_release_firmware(dev);
1756 return err;
1757}
1758
1759static int b43_upload_microcode(struct b43_wldev *dev)
1760{
1761 const size_t hdr_len = sizeof(struct b43_fw_header);
1762 const __be32 *data;
1763 unsigned int i, len;
1764 u16 fwrev, fwpatch, fwdate, fwtime;
1765 u32 tmp;
1766 int err = 0;
1767
1768 /* Upload Microcode. */
1769 data = (__be32 *) (dev->fw.ucode->data + hdr_len);
1770 len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
1771 b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000);
1772 for (i = 0; i < len; i++) {
1773 b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
1774 udelay(10);
1775 }
1776
1777 if (dev->fw.pcm) {
1778 /* Upload PCM data. */
1779 data = (__be32 *) (dev->fw.pcm->data + hdr_len);
1780 len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32);
1781 b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);
1782 b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);
1783 /* No need for autoinc bit in SHM_HW */
1784 b43_shm_control_word(dev, B43_SHM_HW, 0x01EB);
1785 for (i = 0; i < len; i++) {
1786 b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
1787 udelay(10);
1788 }
1789 }
1790
1791 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
1792 b43_write32(dev, B43_MMIO_MACCTL,
1793 B43_MACCTL_PSM_RUN |
1794 B43_MACCTL_IHR_ENABLED | B43_MACCTL_INFRA);
1795
1796 /* Wait for the microcode to load and respond */
1797 i = 0;
1798 while (1) {
1799 tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
1800 if (tmp == B43_IRQ_MAC_SUSPENDED)
1801 break;
1802 i++;
1803 if (i >= 50) {
1804 b43err(dev->wl, "Microcode not responding\n");
1805 b43_print_fw_helptext(dev->wl);
1806 err = -ENODEV;
1807 goto out;
1808 }
1809 udelay(10);
1810 }
1811 b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); /* dummy read */
1812
1813 /* Get and check the revisions. */
1814 fwrev = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEREV);
1815 fwpatch = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEPATCH);
1816 fwdate = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEDATE);
1817 fwtime = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODETIME);
1818
1819 if (fwrev <= 0x128) {
1820 b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from "
1821 "binary drivers older than version 4.x is unsupported. "
1822 "You must upgrade your firmware files.\n");
1823 b43_print_fw_helptext(dev->wl);
1824 b43_write32(dev, B43_MMIO_MACCTL, 0);
1825 err = -EOPNOTSUPP;
1826 goto out;
1827 }
1828 b43dbg(dev->wl, "Loading firmware version %u.%u "
1829 "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
1830 fwrev, fwpatch,
1831 (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
1832 (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
1833
1834 dev->fw.rev = fwrev;
1835 dev->fw.patch = fwpatch;
1836
1837 out:
1838 return err;
1839}
1840
1841static int b43_write_initvals(struct b43_wldev *dev,
1842 const struct b43_iv *ivals,
1843 size_t count,
1844 size_t array_size)
1845{
1846 const struct b43_iv *iv;
1847 u16 offset;
1848 size_t i;
1849 bool bit32;
1850
1851 BUILD_BUG_ON(sizeof(struct b43_iv) != 6);
1852 iv = ivals;
1853 for (i = 0; i < count; i++) {
1854 if (array_size < sizeof(iv->offset_size))
1855 goto err_format;
1856 array_size -= sizeof(iv->offset_size);
1857 offset = be16_to_cpu(iv->offset_size);
1858 bit32 = !!(offset & B43_IV_32BIT);
1859 offset &= B43_IV_OFFSET_MASK;
1860 if (offset >= 0x1000)
1861 goto err_format;
1862 if (bit32) {
1863 u32 value;
1864
1865 if (array_size < sizeof(iv->data.d32))
1866 goto err_format;
1867 array_size -= sizeof(iv->data.d32);
1868
1869 value = be32_to_cpu(get_unaligned(&iv->data.d32));
1870 b43_write32(dev, offset, value);
1871
1872 iv = (const struct b43_iv *)((const uint8_t *)iv +
1873 sizeof(__be16) +
1874 sizeof(__be32));
1875 } else {
1876 u16 value;
1877
1878 if (array_size < sizeof(iv->data.d16))
1879 goto err_format;
1880 array_size -= sizeof(iv->data.d16);
1881
1882 value = be16_to_cpu(iv->data.d16);
1883 b43_write16(dev, offset, value);
1884
1885 iv = (const struct b43_iv *)((const uint8_t *)iv +
1886 sizeof(__be16) +
1887 sizeof(__be16));
1888 }
1889 }
1890 if (array_size)
1891 goto err_format;
1892
1893 return 0;
1894
1895err_format:
1896 b43err(dev->wl, "Initial Values Firmware file-format error.\n");
1897 b43_print_fw_helptext(dev->wl);
1898
1899 return -EPROTO;
1900}
1901
1902static int b43_upload_initvals(struct b43_wldev *dev)
1903{
1904 const size_t hdr_len = sizeof(struct b43_fw_header);
1905 const struct b43_fw_header *hdr;
1906 struct b43_firmware *fw = &dev->fw;
1907 const struct b43_iv *ivals;
1908 size_t count;
1909 int err;
1910
1911 hdr = (const struct b43_fw_header *)(fw->initvals->data);
1912 ivals = (const struct b43_iv *)(fw->initvals->data + hdr_len);
1913 count = be32_to_cpu(hdr->size);
1914 err = b43_write_initvals(dev, ivals, count,
1915 fw->initvals->size - hdr_len);
1916 if (err)
1917 goto out;
1918 if (fw->initvals_band) {
1919 hdr = (const struct b43_fw_header *)(fw->initvals_band->data);
1920 ivals = (const struct b43_iv *)(fw->initvals_band->data + hdr_len);
1921 count = be32_to_cpu(hdr->size);
1922 err = b43_write_initvals(dev, ivals, count,
1923 fw->initvals_band->size - hdr_len);
1924 if (err)
1925 goto out;
1926 }
1927out:
1928
1929 return err;
1930}
1931
1932/* Initialize the GPIOs
1933 * http://bcm-specs.sipsolutions.net/GPIO
1934 */
1935static int b43_gpio_init(struct b43_wldev *dev)
1936{
1937 struct ssb_bus *bus = dev->dev->bus;
1938 struct ssb_device *gpiodev, *pcidev = NULL;
1939 u32 mask, set;
1940
1941 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
1942 & ~B43_MACCTL_GPOUTSMSK);
1943
1944 b43_leds_switch_all(dev, 0);
1945 b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)
1946 | 0x000F);
1947
1948 mask = 0x0000001F;
1949 set = 0x0000000F;
1950 if (dev->dev->bus->chip_id == 0x4301) {
1951 mask |= 0x0060;
1952 set |= 0x0060;
1953 }
1954 if (0 /* FIXME: conditional unknown */ ) {
1955 b43_write16(dev, B43_MMIO_GPIO_MASK,
1956 b43_read16(dev, B43_MMIO_GPIO_MASK)
1957 | 0x0100);
1958 mask |= 0x0180;
1959 set |= 0x0180;
1960 }
1961 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL) {
1962 b43_write16(dev, B43_MMIO_GPIO_MASK,
1963 b43_read16(dev, B43_MMIO_GPIO_MASK)
1964 | 0x0200);
1965 mask |= 0x0200;
1966 set |= 0x0200;
1967 }
1968 if (dev->dev->id.revision >= 2)
1969 mask |= 0x0010; /* FIXME: This is redundant. */
1970
1971#ifdef CONFIG_SSB_DRIVER_PCICORE
1972 pcidev = bus->pcicore.dev;
1973#endif
1974 gpiodev = bus->chipco.dev ? : pcidev;
1975 if (!gpiodev)
1976 return 0;
1977 ssb_write32(gpiodev, B43_GPIO_CONTROL,
1978 (ssb_read32(gpiodev, B43_GPIO_CONTROL)
1979 & mask) | set);
1980
1981 return 0;
1982}
1983
1984/* Turn off all GPIO stuff. Call this on module unload, for example. */
1985static void b43_gpio_cleanup(struct b43_wldev *dev)
1986{
1987 struct ssb_bus *bus = dev->dev->bus;
1988 struct ssb_device *gpiodev, *pcidev = NULL;
1989
1990#ifdef CONFIG_SSB_DRIVER_PCICORE
1991 pcidev = bus->pcicore.dev;
1992#endif
1993 gpiodev = bus->chipco.dev ? : pcidev;
1994 if (!gpiodev)
1995 return;
1996 ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
1997}
1998
1999/* http://bcm-specs.sipsolutions.net/EnableMac */
2000void b43_mac_enable(struct b43_wldev *dev)
2001{
2002 dev->mac_suspended--;
2003 B43_WARN_ON(dev->mac_suspended < 0);
2004 if (dev->mac_suspended == 0) {
2005 b43_write32(dev, B43_MMIO_MACCTL,
2006 b43_read32(dev, B43_MMIO_MACCTL)
2007 | B43_MACCTL_ENABLED);
2008 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON,
2009 B43_IRQ_MAC_SUSPENDED);
2010 /* Commit writes */
2011 b43_read32(dev, B43_MMIO_MACCTL);
2012 b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
2013 b43_power_saving_ctl_bits(dev, 0);
2014 }
2015}
2016
2017/* http://bcm-specs.sipsolutions.net/SuspendMAC */
2018void b43_mac_suspend(struct b43_wldev *dev)
2019{
2020 int i;
2021 u32 tmp;
2022
2023 B43_WARN_ON(dev->mac_suspended < 0);
2024 if (dev->mac_suspended == 0) {
2025 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
2026 b43_write32(dev, B43_MMIO_MACCTL,
2027 b43_read32(dev, B43_MMIO_MACCTL)
2028 & ~B43_MACCTL_ENABLED);
2029 /* force pci to flush the write */
2030 b43_read32(dev, B43_MMIO_MACCTL);
2031 for (i = 10000; i; i--) {
2032 tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
2033 if (tmp & B43_IRQ_MAC_SUSPENDED)
2034 goto out;
2035 udelay(1);
2036 }
2037 b43err(dev->wl, "MAC suspend failed\n");
2038 }
2039 out:
2040 dev->mac_suspended++;
2041}
2042
2043static void b43_adjust_opmode(struct b43_wldev *dev)
2044{
2045 struct b43_wl *wl = dev->wl;
2046 u32 ctl;
2047 u16 cfp_pretbtt;
2048
2049 ctl = b43_read32(dev, B43_MMIO_MACCTL);
2050 /* Reset status to STA infrastructure mode. */
2051 ctl &= ~B43_MACCTL_AP;
2052 ctl &= ~B43_MACCTL_KEEP_CTL;
2053 ctl &= ~B43_MACCTL_KEEP_BADPLCP;
2054 ctl &= ~B43_MACCTL_KEEP_BAD;
2055 ctl &= ~B43_MACCTL_PROMISC;
2056 ctl |= B43_MACCTL_INFRA;
2057
2058 if (wl->operating) {
2059 switch (wl->if_type) {
2060 case IEEE80211_IF_TYPE_AP:
2061 ctl |= B43_MACCTL_AP;
2062 break;
2063 case IEEE80211_IF_TYPE_IBSS:
2064 ctl &= ~B43_MACCTL_INFRA;
2065 break;
2066 case IEEE80211_IF_TYPE_STA:
2067 case IEEE80211_IF_TYPE_MNTR:
2068 case IEEE80211_IF_TYPE_WDS:
2069 break;
2070 default:
2071 B43_WARN_ON(1);
2072 }
2073 }
2074 if (wl->monitor) {
2075 ctl |= B43_MACCTL_KEEP_CTL;
2076 if (modparam_mon_keep_bad)
2077 ctl |= B43_MACCTL_KEEP_BAD;
2078 if (modparam_mon_keep_badplcp)
2079 ctl |= B43_MACCTL_KEEP_BADPLCP;
2080 }
2081 if (wl->promisc)
2082 ctl |= B43_MACCTL_PROMISC;
2083 /* Workaround: On old hardware the HW-MAC-address-filter
2084 * doesn't work properly, so always run promisc in filter
2085 * it in software. */
2086 if (dev->dev->id.revision <= 4)
2087 ctl |= B43_MACCTL_PROMISC;
2088
2089 b43_write32(dev, B43_MMIO_MACCTL, ctl);
2090
2091 cfp_pretbtt = 2;
2092 if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
2093 if (dev->dev->bus->chip_id == 0x4306 &&
2094 dev->dev->bus->chip_rev == 3)
2095 cfp_pretbtt = 100;
2096 else
2097 cfp_pretbtt = 50;
2098 }
2099 b43_write16(dev, 0x612, cfp_pretbtt);
2100}
2101
2102static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
2103{
2104 u16 offset;
2105
2106 if (is_ofdm) {
2107 offset = 0x480;
2108 offset += (b43_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
2109 } else {
2110 offset = 0x4C0;
2111 offset += (b43_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
2112 }
2113 b43_shm_write16(dev, B43_SHM_SHARED, offset + 0x20,
2114 b43_shm_read16(dev, B43_SHM_SHARED, offset));
2115}
2116
2117static void b43_rate_memory_init(struct b43_wldev *dev)
2118{
2119 switch (dev->phy.type) {
2120 case B43_PHYTYPE_A:
2121 case B43_PHYTYPE_G:
2122 b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
2123 b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
2124 b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
2125 b43_rate_memory_write(dev, B43_OFDM_RATE_24MB, 1);
2126 b43_rate_memory_write(dev, B43_OFDM_RATE_36MB, 1);
2127 b43_rate_memory_write(dev, B43_OFDM_RATE_48MB, 1);
2128 b43_rate_memory_write(dev, B43_OFDM_RATE_54MB, 1);
2129 if (dev->phy.type == B43_PHYTYPE_A)
2130 break;
2131 /* fallthrough */
2132 case B43_PHYTYPE_B:
2133 b43_rate_memory_write(dev, B43_CCK_RATE_1MB, 0);
2134 b43_rate_memory_write(dev, B43_CCK_RATE_2MB, 0);
2135 b43_rate_memory_write(dev, B43_CCK_RATE_5MB, 0);
2136 b43_rate_memory_write(dev, B43_CCK_RATE_11MB, 0);
2137 break;
2138 default:
2139 B43_WARN_ON(1);
2140 }
2141}
2142
2143/* Set the TX-Antenna for management frames sent by firmware. */
2144static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
2145{
2146 u16 ant = 0;
2147 u16 tmp;
2148
2149 switch (antenna) {
2150 case B43_ANTENNA0:
2151 ant |= B43_TX4_PHY_ANT0;
2152 break;
2153 case B43_ANTENNA1:
2154 ant |= B43_TX4_PHY_ANT1;
2155 break;
2156 case B43_ANTENNA_AUTO:
2157 ant |= B43_TX4_PHY_ANTLAST;
2158 break;
2159 default:
2160 B43_WARN_ON(1);
2161 }
2162
2163 /* FIXME We also need to set the other flags of the PHY control field somewhere. */
2164
2165 /* For Beacons */
2166 tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
2167 tmp = (tmp & ~B43_TX4_PHY_ANT) | ant;
2168 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp);
2169 /* For ACK/CTS */
2170 tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
2171 tmp = (tmp & ~B43_TX4_PHY_ANT) | ant;
2172 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, tmp);
2173 /* For Probe Resposes */
2174 tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL);
2175 tmp = (tmp & ~B43_TX4_PHY_ANT) | ant;
2176 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
2177}
2178
2179/* This is the opposite of b43_chip_init() */
2180static void b43_chip_exit(struct b43_wldev *dev)
2181{
2182 b43_radio_turn_off(dev);
2183 if (!modparam_noleds)
2184 b43_leds_exit(dev);
2185 b43_gpio_cleanup(dev);
2186 /* firmware is released later */
2187}
2188
2189/* Initialize the chip
2190 * http://bcm-specs.sipsolutions.net/ChipInit
2191 */
2192static int b43_chip_init(struct b43_wldev *dev)
2193{
2194 struct b43_phy *phy = &dev->phy;
2195 int err, tmp;
2196 u32 value32;
2197 u16 value16;
2198
2199 b43_write32(dev, B43_MMIO_MACCTL,
2200 B43_MACCTL_PSM_JMP0 | B43_MACCTL_IHR_ENABLED);
2201
2202 err = b43_request_firmware(dev);
2203 if (err)
2204 goto out;
2205 err = b43_upload_microcode(dev);
2206 if (err)
2207 goto out; /* firmware is released later */
2208
2209 err = b43_gpio_init(dev);
2210 if (err)
2211 goto out; /* firmware is released later */
2212 err = b43_upload_initvals(dev);
2213 if (err)
2214 goto err_gpio_cleanup;
2215 b43_radio_turn_on(dev);
2216 dev->radio_hw_enable = b43_is_hw_radio_enabled(dev);
2217 b43dbg(dev->wl, "Radio %s by hardware\n",
2218 (dev->radio_hw_enable == 0) ? "disabled" : "enabled");
2219
2220 b43_write16(dev, 0x03E6, 0x0000);
2221 err = b43_phy_init(dev);
2222 if (err)
2223 goto err_radio_off;
2224
2225 /* Select initial Interference Mitigation. */
2226 tmp = phy->interfmode;
2227 phy->interfmode = B43_INTERFMODE_NONE;
2228 b43_radio_set_interference_mitigation(dev, tmp);
2229
2230 b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
2231 b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
2232
2233 if (phy->type == B43_PHYTYPE_B) {
2234 value16 = b43_read16(dev, 0x005E);
2235 value16 |= 0x0004;
2236 b43_write16(dev, 0x005E, value16);
2237 }
2238 b43_write32(dev, 0x0100, 0x01000000);
2239 if (dev->dev->id.revision < 5)
2240 b43_write32(dev, 0x010C, 0x01000000);
2241
2242 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
2243 & ~B43_MACCTL_INFRA);
2244 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
2245 | B43_MACCTL_INFRA);
2246 /* Let beacons come through */
2247 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
2248 | B43_MACCTL_BEACPROMISC);
2249
2250 if (b43_using_pio(dev)) {
2251 b43_write32(dev, 0x0210, 0x00000100);
2252 b43_write32(dev, 0x0230, 0x00000100);
2253 b43_write32(dev, 0x0250, 0x00000100);
2254 b43_write32(dev, 0x0270, 0x00000100);
2255 b43_shm_write16(dev, B43_SHM_SHARED, 0x0034, 0x0000);
2256 }
2257
2258 /* Probe Response Timeout value */
2259 /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
2260 b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000);
2261
2262 /* Initially set the wireless operation mode. */
2263 b43_adjust_opmode(dev);
2264
2265 if (dev->dev->id.revision < 3) {
2266 b43_write16(dev, 0x060E, 0x0000);
2267 b43_write16(dev, 0x0610, 0x8000);
2268 b43_write16(dev, 0x0604, 0x0000);
2269 b43_write16(dev, 0x0606, 0x0200);
2270 } else {
2271 b43_write32(dev, 0x0188, 0x80000000);
2272 b43_write32(dev, 0x018C, 0x02000000);
2273 }
2274 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
2275 b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
2276 b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
2277 b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
2278 b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
2279 b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
2280 b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
2281
2282 value32 = ssb_read32(dev->dev, SSB_TMSLOW);
2283 value32 |= 0x00100000;
2284 ssb_write32(dev->dev, SSB_TMSLOW, value32);
2285
2286 b43_write16(dev, B43_MMIO_POWERUP_DELAY,
2287 dev->dev->bus->chipco.fast_pwrup_delay);
2288
2289 err = 0;
2290 b43dbg(dev->wl, "Chip initialized\n");
2291 out:
2292 return err;
2293
2294 err_radio_off:
2295 b43_radio_turn_off(dev);
2296 err_gpio_cleanup:
2297 b43_gpio_cleanup(dev);
2298 goto out;
2299}
2300
2301static void b43_periodic_every120sec(struct b43_wldev *dev)
2302{
2303 struct b43_phy *phy = &dev->phy;
2304
2305 if (phy->type != B43_PHYTYPE_G || phy->rev < 2)
2306 return;
2307
2308 b43_mac_suspend(dev);
2309 b43_lo_g_measure(dev);
2310 b43_mac_enable(dev);
2311 if (b43_has_hardware_pctl(phy))
2312 b43_lo_g_ctl_mark_all_unused(dev);
2313}
2314
2315static void b43_periodic_every60sec(struct b43_wldev *dev)
2316{
2317 struct b43_phy *phy = &dev->phy;
2318
2319 if (!b43_has_hardware_pctl(phy))
2320 b43_lo_g_ctl_mark_all_unused(dev);
2321 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
2322 b43_mac_suspend(dev);
2323 b43_calc_nrssi_slope(dev);
2324 if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
2325 u8 old_chan = phy->channel;
2326
2327 /* VCO Calibration */
2328 if (old_chan >= 8)
2329 b43_radio_selectchannel(dev, 1, 0);
2330 else
2331 b43_radio_selectchannel(dev, 13, 0);
2332 b43_radio_selectchannel(dev, old_chan, 0);
2333 }
2334 b43_mac_enable(dev);
2335 }
2336}
2337
2338static void b43_periodic_every30sec(struct b43_wldev *dev)
2339{
2340 /* Update device statistics. */
2341 b43_calculate_link_quality(dev);
2342}
2343
2344static void b43_periodic_every15sec(struct b43_wldev *dev)
2345{
2346 struct b43_phy *phy = &dev->phy;
2347
2348 if (phy->type == B43_PHYTYPE_G) {
2349 //TODO: update_aci_moving_average
2350 if (phy->aci_enable && phy->aci_wlan_automatic) {
2351 b43_mac_suspend(dev);
2352 if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) {
2353 if (0 /*TODO: bunch of conditions */ ) {
2354 b43_radio_set_interference_mitigation
2355 (dev, B43_INTERFMODE_MANUALWLAN);
2356 }
2357 } else if (1 /*TODO*/) {
2358 /*
2359 if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) {
2360 b43_radio_set_interference_mitigation(dev,
2361 B43_INTERFMODE_NONE);
2362 }
2363 */
2364 }
2365 b43_mac_enable(dev);
2366 } else if (phy->interfmode == B43_INTERFMODE_NONWLAN &&
2367 phy->rev == 1) {
2368 //TODO: implement rev1 workaround
2369 }
2370 }
2371 b43_phy_xmitpower(dev); //FIXME: unless scanning?
2372 //TODO for APHY (temperature?)
2373}
2374
2375static void b43_periodic_every1sec(struct b43_wldev *dev)
2376{
2377 int radio_hw_enable;
2378
2379 /* check if radio hardware enabled status changed */
2380 radio_hw_enable = b43_is_hw_radio_enabled(dev);
2381 if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
2382 dev->radio_hw_enable = radio_hw_enable;
2383 b43dbg(dev->wl, "Radio hardware status changed to %s\n",
2384 (radio_hw_enable == 0) ? "disabled" : "enabled");
2385 b43_leds_update(dev, 0);
2386 }
2387}
2388
2389static void do_periodic_work(struct b43_wldev *dev)
2390{
2391 unsigned int state;
2392
2393 state = dev->periodic_state;
2394 if (state % 120 == 0)
2395 b43_periodic_every120sec(dev);
2396 if (state % 60 == 0)
2397 b43_periodic_every60sec(dev);
2398 if (state % 30 == 0)
2399 b43_periodic_every30sec(dev);
2400 if (state % 15 == 0)
2401 b43_periodic_every15sec(dev);
2402 b43_periodic_every1sec(dev);
2403}
2404
2405/* Estimate a "Badness" value based on the periodic work
2406 * state-machine state. "Badness" is worse (bigger), if the
2407 * periodic work will take longer.
2408 */
2409static int estimate_periodic_work_badness(unsigned int state)
2410{
2411 int badness = 0;
2412
2413 if (state % 120 == 0) /* every 120 sec */
2414 badness += 10;
2415 if (state % 60 == 0) /* every 60 sec */
2416 badness += 5;
2417 if (state % 30 == 0) /* every 30 sec */
2418 badness += 1;
2419 if (state % 15 == 0) /* every 15 sec */
2420 badness += 1;
2421
2422#define BADNESS_LIMIT 4
2423 return badness;
2424}
2425
2426static void b43_periodic_work_handler(struct work_struct *work)
2427{
2428 struct b43_wldev *dev =
2429 container_of(work, struct b43_wldev, periodic_work.work);
2430 unsigned long flags, delay;
2431 u32 savedirqs = 0;
2432 int badness;
2433
2434 mutex_lock(&dev->wl->mutex);
2435
2436 if (unlikely(b43_status(dev) != B43_STAT_STARTED))
2437 goto out;
2438 if (b43_debug(dev, B43_DBG_PWORK_STOP))
2439 goto out_requeue;
2440
2441 badness = estimate_periodic_work_badness(dev->periodic_state);
2442 if (badness > BADNESS_LIMIT) {
2443 spin_lock_irqsave(&dev->wl->irq_lock, flags);
2444 /* Suspend TX as we don't want to transmit packets while
2445 * we recalibrate the hardware. */
2446 b43_tx_suspend(dev);
2447 savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
2448 /* Periodic work will take a long time, so we want it to
2449 * be preemtible and release the spinlock. */
2450 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
2451 b43_synchronize_irq(dev);
2452
2453 do_periodic_work(dev);
2454
2455 spin_lock_irqsave(&dev->wl->irq_lock, flags);
2456 b43_interrupt_enable(dev, savedirqs);
2457 b43_tx_resume(dev);
2458 mmiowb();
2459 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
2460 } else {
2461 /* Take the global driver lock. This will lock any operation. */
2462 spin_lock_irqsave(&dev->wl->irq_lock, flags);
2463
2464 do_periodic_work(dev);
2465
2466 mmiowb();
2467 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
2468 }
2469 dev->periodic_state++;
2470 out_requeue:
2471 if (b43_debug(dev, B43_DBG_PWORK_FAST))
2472 delay = msecs_to_jiffies(50);
2473 else
2474 delay = round_jiffies(HZ);
2475 queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay);
2476 out:
2477 mutex_unlock(&dev->wl->mutex);
2478}
2479
2480static void b43_periodic_tasks_setup(struct b43_wldev *dev)
2481{
2482 struct delayed_work *work = &dev->periodic_work;
2483
2484 dev->periodic_state = 0;
2485 INIT_DELAYED_WORK(work, b43_periodic_work_handler);
2486 queue_delayed_work(dev->wl->hw->workqueue, work, 0);
2487}
2488
2489/* Validate access to the chip (SHM) */
2490static int b43_validate_chipaccess(struct b43_wldev *dev)
2491{
2492 u32 value;
2493 u32 shm_backup;
2494
2495 shm_backup = b43_shm_read32(dev, B43_SHM_SHARED, 0);
2496 b43_shm_write32(dev, B43_SHM_SHARED, 0, 0xAA5555AA);
2497 if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
2498 goto error;
2499 b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
2500 if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0x55AAAA55)
2501 goto error;
2502 b43_shm_write32(dev, B43_SHM_SHARED, 0, shm_backup);
2503
2504 value = b43_read32(dev, B43_MMIO_MACCTL);
2505 if ((value | B43_MACCTL_GMODE) !=
2506 (B43_MACCTL_GMODE | B43_MACCTL_IHR_ENABLED))
2507 goto error;
2508
2509 value = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
2510 if (value)
2511 goto error;
2512
2513 return 0;
2514 error:
2515 b43err(dev->wl, "Failed to validate the chipaccess\n");
2516 return -ENODEV;
2517}
2518
2519static void b43_security_init(struct b43_wldev *dev)
2520{
2521 dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20;
2522 B43_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key));
2523 dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP);
2524 /* KTP is a word address, but we address SHM bytewise.
2525 * So multiply by two.
2526 */
2527 dev->ktp *= 2;
2528 if (dev->dev->id.revision >= 5) {
2529 /* Number of RCMTA address slots */
2530 b43_write16(dev, B43_MMIO_RCMTA_COUNT, dev->max_nr_keys - 8);
2531 }
2532 b43_clear_keys(dev);
2533}
2534
2535static int b43_rng_read(struct hwrng *rng, u32 * data)
2536{
2537 struct b43_wl *wl = (struct b43_wl *)rng->priv;
2538 unsigned long flags;
2539
2540 /* Don't take wl->mutex here, as it could deadlock with
2541 * hwrng internal locking. It's not needed to take
2542 * wl->mutex here, anyway. */
2543
2544 spin_lock_irqsave(&wl->irq_lock, flags);
2545 *data = b43_read16(wl->current_dev, B43_MMIO_RNG);
2546 spin_unlock_irqrestore(&wl->irq_lock, flags);
2547
2548 return (sizeof(u16));
2549}
2550
2551static void b43_rng_exit(struct b43_wl *wl)
2552{
2553 if (wl->rng_initialized)
2554 hwrng_unregister(&wl->rng);
2555}
2556
2557static int b43_rng_init(struct b43_wl *wl)
2558{
2559 int err;
2560
2561 snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
2562 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
2563 wl->rng.name = wl->rng_name;
2564 wl->rng.data_read = b43_rng_read;
2565 wl->rng.priv = (unsigned long)wl;
2566 wl->rng_initialized = 1;
2567 err = hwrng_register(&wl->rng);
2568 if (err) {
2569 wl->rng_initialized = 0;
2570 b43err(wl, "Failed to register the random "
2571 "number generator (%d)\n", err);
2572 }
2573
2574 return err;
2575}
2576
2577static int b43_tx(struct ieee80211_hw *hw,
2578 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
2579{
2580 struct b43_wl *wl = hw_to_b43_wl(hw);
2581 struct b43_wldev *dev = wl->current_dev;
2582 int err = -ENODEV;
2583 unsigned long flags;
2584
2585 if (unlikely(!dev))
2586 goto out;
2587 if (unlikely(b43_status(dev) < B43_STAT_STARTED))
2588 goto out;
2589 /* DMA-TX is done without a global lock. */
2590 if (b43_using_pio(dev)) {
2591 spin_lock_irqsave(&wl->irq_lock, flags);
2592 err = b43_pio_tx(dev, skb, ctl);
2593 spin_unlock_irqrestore(&wl->irq_lock, flags);
2594 } else
2595 err = b43_dma_tx(dev, skb, ctl);
2596 out:
2597 if (unlikely(err))
2598 return NETDEV_TX_BUSY;
2599 return NETDEV_TX_OK;
2600}
2601
2602static int b43_conf_tx(struct ieee80211_hw *hw,
2603 int queue,
2604 const struct ieee80211_tx_queue_params *params)
2605{
2606 return 0;
2607}
2608
2609static int b43_get_tx_stats(struct ieee80211_hw *hw,
2610 struct ieee80211_tx_queue_stats *stats)
2611{
2612 struct b43_wl *wl = hw_to_b43_wl(hw);
2613 struct b43_wldev *dev = wl->current_dev;
2614 unsigned long flags;
2615 int err = -ENODEV;
2616
2617 if (!dev)
2618 goto out;
2619 spin_lock_irqsave(&wl->irq_lock, flags);
2620 if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
2621 if (b43_using_pio(dev))
2622 b43_pio_get_tx_stats(dev, stats);
2623 else
2624 b43_dma_get_tx_stats(dev, stats);
2625 err = 0;
2626 }
2627 spin_unlock_irqrestore(&wl->irq_lock, flags);
2628 out:
2629 return err;
2630}
2631
2632static int b43_get_stats(struct ieee80211_hw *hw,
2633 struct ieee80211_low_level_stats *stats)
2634{
2635 struct b43_wl *wl = hw_to_b43_wl(hw);
2636 unsigned long flags;
2637
2638 spin_lock_irqsave(&wl->irq_lock, flags);
2639 memcpy(stats, &wl->ieee_stats, sizeof(*stats));
2640 spin_unlock_irqrestore(&wl->irq_lock, flags);
2641
2642 return 0;
2643}
2644
2645static const char *phymode_to_string(unsigned int phymode)
2646{
2647 switch (phymode) {
2648 case B43_PHYMODE_A:
2649 return "A";
2650 case B43_PHYMODE_B:
2651 return "B";
2652 case B43_PHYMODE_G:
2653 return "G";
2654 default:
2655 B43_WARN_ON(1);
2656 }
2657 return "";
2658}
2659
2660static int find_wldev_for_phymode(struct b43_wl *wl,
2661 unsigned int phymode,
2662 struct b43_wldev **dev, bool * gmode)
2663{
2664 struct b43_wldev *d;
2665
2666 list_for_each_entry(d, &wl->devlist, list) {
2667 if (d->phy.possible_phymodes & phymode) {
2668 /* Ok, this device supports the PHY-mode.
2669 * Now figure out how the gmode bit has to be
2670 * set to support it. */
2671 if (phymode == B43_PHYMODE_A)
2672 *gmode = 0;
2673 else
2674 *gmode = 1;
2675 *dev = d;
2676
2677 return 0;
2678 }
2679 }
2680
2681 return -ESRCH;
2682}
2683
2684static void b43_put_phy_into_reset(struct b43_wldev *dev)
2685{
2686 struct ssb_device *sdev = dev->dev;
2687 u32 tmslow;
2688
2689 tmslow = ssb_read32(sdev, SSB_TMSLOW);
2690 tmslow &= ~B43_TMSLOW_GMODE;
2691 tmslow |= B43_TMSLOW_PHYRESET;
2692 tmslow |= SSB_TMSLOW_FGC;
2693 ssb_write32(sdev, SSB_TMSLOW, tmslow);
2694 msleep(1);
2695
2696 tmslow = ssb_read32(sdev, SSB_TMSLOW);
2697 tmslow &= ~SSB_TMSLOW_FGC;
2698 tmslow |= B43_TMSLOW_PHYRESET;
2699 ssb_write32(sdev, SSB_TMSLOW, tmslow);
2700 msleep(1);
2701}
2702
2703/* Expects wl->mutex locked */
2704static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
2705{
2706 struct b43_wldev *up_dev;
2707 struct b43_wldev *down_dev;
2708 int err;
2709 bool gmode = 0;
2710 int prev_status;
2711
2712 err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
2713 if (err) {
2714 b43err(wl, "Could not find a device for %s-PHY mode\n",
2715 phymode_to_string(new_mode));
2716 return err;
2717 }
2718 if ((up_dev == wl->current_dev) &&
2719 (!!wl->current_dev->phy.gmode == !!gmode)) {
2720 /* This device is already running. */
2721 return 0;
2722 }
2723 b43dbg(wl, "Reconfiguring PHYmode to %s-PHY\n",
2724 phymode_to_string(new_mode));
2725 down_dev = wl->current_dev;
2726
2727 prev_status = b43_status(down_dev);
2728 /* Shutdown the currently running core. */
2729 if (prev_status >= B43_STAT_STARTED)
2730 b43_wireless_core_stop(down_dev);
2731 if (prev_status >= B43_STAT_INITIALIZED)
2732 b43_wireless_core_exit(down_dev);
2733
2734 if (down_dev != up_dev) {
2735 /* We switch to a different core, so we put PHY into
2736 * RESET on the old core. */
2737 b43_put_phy_into_reset(down_dev);
2738 }
2739
2740 /* Now start the new core. */
2741 up_dev->phy.gmode = gmode;
2742 if (prev_status >= B43_STAT_INITIALIZED) {
2743 err = b43_wireless_core_init(up_dev);
2744 if (err) {
2745 b43err(wl, "Fatal: Could not initialize device for "
2746 "newly selected %s-PHY mode\n",
2747 phymode_to_string(new_mode));
2748 goto init_failure;
2749 }
2750 }
2751 if (prev_status >= B43_STAT_STARTED) {
2752 err = b43_wireless_core_start(up_dev);
2753 if (err) {
2754 b43err(wl, "Fatal: Coult not start device for "
2755 "newly selected %s-PHY mode\n",
2756 phymode_to_string(new_mode));
2757 b43_wireless_core_exit(up_dev);
2758 goto init_failure;
2759 }
2760 }
2761 B43_WARN_ON(b43_status(up_dev) != prev_status);
2762
2763 wl->current_dev = up_dev;
2764
2765 return 0;
2766 init_failure:
2767 /* Whoops, failed to init the new core. No core is operating now. */
2768 wl->current_dev = NULL;
2769 return err;
2770}
2771
2772static int b43_antenna_from_ieee80211(u8 antenna)
2773{
2774 switch (antenna) {
2775 case 0: /* default/diversity */
2776 return B43_ANTENNA_DEFAULT;
2777 case 1: /* Antenna 0 */
2778 return B43_ANTENNA0;
2779 case 2: /* Antenna 1 */
2780 return B43_ANTENNA1;
2781 default:
2782 return B43_ANTENNA_DEFAULT;
2783 }
2784}
2785
2786static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
2787{
2788 struct b43_wl *wl = hw_to_b43_wl(hw);
2789 struct b43_wldev *dev;
2790 struct b43_phy *phy;
2791 unsigned long flags;
2792 unsigned int new_phymode = 0xFFFF;
2793 int antenna_tx;
2794 int antenna_rx;
2795 int err = 0;
2796 u32 savedirqs;
2797
2798 antenna_tx = b43_antenna_from_ieee80211(conf->antenna_sel_tx);
2799 antenna_rx = b43_antenna_from_ieee80211(conf->antenna_sel_rx);
2800
2801 mutex_lock(&wl->mutex);
2802
2803 /* Switch the PHY mode (if necessary). */
2804 switch (conf->phymode) {
2805 case MODE_IEEE80211A:
2806 new_phymode = B43_PHYMODE_A;
2807 break;
2808 case MODE_IEEE80211B:
2809 new_phymode = B43_PHYMODE_B;
2810 break;
2811 case MODE_IEEE80211G:
2812 new_phymode = B43_PHYMODE_G;
2813 break;
2814 default:
2815 B43_WARN_ON(1);
2816 }
2817 err = b43_switch_phymode(wl, new_phymode);
2818 if (err)
2819 goto out_unlock_mutex;
2820 dev = wl->current_dev;
2821 phy = &dev->phy;
2822
2823 /* Disable IRQs while reconfiguring the device.
2824 * This makes it possible to drop the spinlock throughout
2825 * the reconfiguration process. */
2826 spin_lock_irqsave(&wl->irq_lock, flags);
2827 if (b43_status(dev) < B43_STAT_STARTED) {
2828 spin_unlock_irqrestore(&wl->irq_lock, flags);
2829 goto out_unlock_mutex;
2830 }
2831 savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
2832 spin_unlock_irqrestore(&wl->irq_lock, flags);
2833 b43_synchronize_irq(dev);
2834
2835 /* Switch to the requested channel.
2836 * The firmware takes care of races with the TX handler. */
2837 if (conf->channel_val != phy->channel)
2838 b43_radio_selectchannel(dev, conf->channel_val, 0);
2839
2840 /* Enable/Disable ShortSlot timing. */
2841 if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
2842 dev->short_slot) {
2843 B43_WARN_ON(phy->type != B43_PHYTYPE_G);
2844 if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
2845 b43_short_slot_timing_enable(dev);
2846 else
2847 b43_short_slot_timing_disable(dev);
2848 }
2849
2850 /* Adjust the desired TX power level. */
2851 if (conf->power_level != 0) {
2852 if (conf->power_level != phy->power_level) {
2853 phy->power_level = conf->power_level;
2854 b43_phy_xmitpower(dev);
2855 }
2856 }
2857
2858 /* Antennas for RX and management frame TX. */
2859 b43_mgmtframe_txantenna(dev, antenna_tx);
2860 b43_set_rx_antenna(dev, antenna_rx);
2861
2862 /* Update templates for AP mode. */
2863 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
2864 b43_set_beacon_int(dev, conf->beacon_int);
2865
2866 spin_lock_irqsave(&wl->irq_lock, flags);
2867 b43_interrupt_enable(dev, savedirqs);
2868 mmiowb();
2869 spin_unlock_irqrestore(&wl->irq_lock, flags);
2870 out_unlock_mutex:
2871 mutex_unlock(&wl->mutex);
2872
2873 return err;
2874}
2875
2876static int b43_dev_set_key(struct ieee80211_hw *hw,
2877 set_key_cmd cmd, const u8 *local_addr,
2878 const u8 *addr, struct ieee80211_key_conf *key)
2879{
2880 struct b43_wl *wl = hw_to_b43_wl(hw);
2881 struct b43_wldev *dev = wl->current_dev;
2882 unsigned long flags;
2883 u8 algorithm;
2884 u8 index;
2885 int err = -EINVAL;
2886
2887 if (modparam_nohwcrypt)
2888 return -ENOSPC; /* User disabled HW-crypto */
2889
2890 if (!dev)
2891 return -ENODEV;
2892 switch (key->alg) {
2893 case ALG_NONE:
2894 algorithm = B43_SEC_ALGO_NONE;
2895 break;
2896 case ALG_WEP:
2897 if (key->keylen == 5)
2898 algorithm = B43_SEC_ALGO_WEP40;
2899 else
2900 algorithm = B43_SEC_ALGO_WEP104;
2901 break;
2902 case ALG_TKIP:
2903 algorithm = B43_SEC_ALGO_TKIP;
2904 break;
2905 case ALG_CCMP:
2906 algorithm = B43_SEC_ALGO_AES;
2907 break;
2908 default:
2909 B43_WARN_ON(1);
2910 goto out;
2911 }
2912
2913 index = (u8) (key->keyidx);
2914 if (index > 3)
2915 goto out;
2916
2917 mutex_lock(&wl->mutex);
2918 spin_lock_irqsave(&wl->irq_lock, flags);
2919
2920 if (b43_status(dev) < B43_STAT_INITIALIZED) {
2921 err = -ENODEV;
2922 goto out_unlock;
2923 }
2924
2925 switch (cmd) {
2926 case SET_KEY:
2927 if (algorithm == B43_SEC_ALGO_TKIP) {
2928 /* FIXME: No TKIP hardware encryption for now. */
2929 err = -EOPNOTSUPP;
2930 goto out_unlock;
2931 }
2932
2933 if (is_broadcast_ether_addr(addr)) {
2934 /* addr is FF:FF:FF:FF:FF:FF for default keys */
2935 err = b43_key_write(dev, index, algorithm,
2936 key->key, key->keylen, NULL, key);
2937 } else {
2938 /*
2939 * either pairwise key or address is 00:00:00:00:00:00
2940 * for transmit-only keys
2941 */
2942 err = b43_key_write(dev, -1, algorithm,
2943 key->key, key->keylen, addr, key);
2944 }
2945 if (err)
2946 goto out_unlock;
2947
2948 if (algorithm == B43_SEC_ALGO_WEP40 ||
2949 algorithm == B43_SEC_ALGO_WEP104) {
2950 b43_hf_write(dev, b43_hf_read(dev) | B43_HF_USEDEFKEYS);
2951 } else {
2952 b43_hf_write(dev,
2953 b43_hf_read(dev) & ~B43_HF_USEDEFKEYS);
2954 }
2955 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
2956 break;
2957 case DISABLE_KEY: {
2958 err = b43_key_clear(dev, key->hw_key_idx);
2959 if (err)
2960 goto out_unlock;
2961 break;
2962 }
2963 default:
2964 B43_WARN_ON(1);
2965 }
2966out_unlock:
2967 spin_unlock_irqrestore(&wl->irq_lock, flags);
2968 mutex_unlock(&wl->mutex);
2969out:
2970 if (!err) {
2971 b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
2972 "mac: " MAC_FMT "\n",
2973 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
2974 MAC_ARG(addr));
2975 }
2976 return err;
2977}
2978
2979static void b43_set_multicast_list(struct ieee80211_hw *hw,
2980 unsigned short netflags, int mc_count)
2981{
2982 struct b43_wl *wl = hw_to_b43_wl(hw);
2983 struct b43_wldev *dev = wl->current_dev;
2984 unsigned long flags;
2985
2986 if (!dev)
2987 return;
2988 spin_lock_irqsave(&wl->irq_lock, flags);
2989 if (wl->promisc != !!(netflags & IFF_PROMISC)) {
2990 wl->promisc = !!(netflags & IFF_PROMISC);
2991 if (b43_status(dev) >= B43_STAT_INITIALIZED)
2992 b43_adjust_opmode(dev);
2993 }
2994 spin_unlock_irqrestore(&wl->irq_lock, flags);
2995}
2996
2997static int b43_config_interface(struct ieee80211_hw *hw,
2998 int if_id, struct ieee80211_if_conf *conf)
2999{
3000 struct b43_wl *wl = hw_to_b43_wl(hw);
3001 struct b43_wldev *dev = wl->current_dev;
3002 unsigned long flags;
3003
3004 if (!dev)
3005 return -ENODEV;
3006 mutex_lock(&wl->mutex);
3007 spin_lock_irqsave(&wl->irq_lock, flags);
3008 if (conf->type != IEEE80211_IF_TYPE_MNTR) {
3009 B43_WARN_ON(wl->if_id != if_id);
3010 if (conf->bssid)
3011 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
3012 else
3013 memset(wl->bssid, 0, ETH_ALEN);
3014 if (b43_status(dev) >= B43_STAT_INITIALIZED) {
3015 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
3016 B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
3017 b43_set_ssid(dev, conf->ssid, conf->ssid_len);
3018 if (conf->beacon)
3019 b43_refresh_templates(dev, conf->beacon);
3020 }
3021 b43_write_mac_bssid_templates(dev);
3022 }
3023 }
3024 spin_unlock_irqrestore(&wl->irq_lock, flags);
3025 mutex_unlock(&wl->mutex);
3026
3027 return 0;
3028}
3029
3030/* Locking: wl->mutex */
3031static void b43_wireless_core_stop(struct b43_wldev *dev)
3032{
3033 struct b43_wl *wl = dev->wl;
3034 unsigned long flags;
3035
3036 if (b43_status(dev) < B43_STAT_STARTED)
3037 return;
3038 b43_set_status(dev, B43_STAT_INITIALIZED);
3039
3040 mutex_unlock(&wl->mutex);
3041 /* Must unlock as it would otherwise deadlock. No races here.
3042 * Cancel the possibly running self-rearming periodic work. */
3043 cancel_delayed_work_sync(&dev->periodic_work);
3044 mutex_lock(&wl->mutex);
3045
3046 ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy.
3047
3048 /* Disable and sync interrupts. */
3049 spin_lock_irqsave(&wl->irq_lock, flags);
3050 dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
3051 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
3052 spin_unlock_irqrestore(&wl->irq_lock, flags);
3053 b43_synchronize_irq(dev);
3054
3055 b43_mac_suspend(dev);
3056 free_irq(dev->dev->irq, dev);
3057 b43dbg(wl, "Wireless interface stopped\n");
3058}
3059
3060/* Locking: wl->mutex */
3061static int b43_wireless_core_start(struct b43_wldev *dev)
3062{
3063 int err;
3064
3065 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
3066
3067 drain_txstatus_queue(dev);
3068 err = request_irq(dev->dev->irq, b43_interrupt_handler,
3069 IRQF_SHARED, KBUILD_MODNAME, dev);
3070 if (err) {
3071 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
3072 goto out;
3073 }
3074
3075 /* We are ready to run. */
3076 b43_set_status(dev, B43_STAT_STARTED);
3077
3078 /* Start data flow (TX/RX). */
3079 b43_mac_enable(dev);
3080 b43_interrupt_enable(dev, dev->irq_savedstate);
3081 ieee80211_start_queues(dev->wl->hw);
3082
3083 /* Start maintainance work */
3084 b43_periodic_tasks_setup(dev);
3085
3086 b43dbg(dev->wl, "Wireless interface started\n");
3087 out:
3088 return err;
3089}
3090
3091/* Get PHY and RADIO versioning numbers */
3092static int b43_phy_versioning(struct b43_wldev *dev)
3093{
3094 struct b43_phy *phy = &dev->phy;
3095 u32 tmp;
3096 u8 analog_type;
3097 u8 phy_type;
3098 u8 phy_rev;
3099 u16 radio_manuf;
3100 u16 radio_ver;
3101 u16 radio_rev;
3102 int unsupported = 0;
3103
3104 /* Get PHY versioning */
3105 tmp = b43_read16(dev, B43_MMIO_PHY_VER);
3106 analog_type = (tmp & B43_PHYVER_ANALOG) >> B43_PHYVER_ANALOG_SHIFT;
3107 phy_type = (tmp & B43_PHYVER_TYPE) >> B43_PHYVER_TYPE_SHIFT;
3108 phy_rev = (tmp & B43_PHYVER_VERSION);
3109 switch (phy_type) {
3110 case B43_PHYTYPE_A:
3111 if (phy_rev >= 4)
3112 unsupported = 1;
3113 break;
3114 case B43_PHYTYPE_B:
3115 if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6
3116 && phy_rev != 7)
3117 unsupported = 1;
3118 break;
3119 case B43_PHYTYPE_G:
3120 if (phy_rev > 8)
3121 unsupported = 1;
3122 break;
3123 default:
3124 unsupported = 1;
3125 };
3126 if (unsupported) {
3127 b43err(dev->wl, "FOUND UNSUPPORTED PHY "
3128 "(Analog %u, Type %u, Revision %u)\n",
3129 analog_type, phy_type, phy_rev);
3130 return -EOPNOTSUPP;
3131 }
3132 b43dbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n",
3133 analog_type, phy_type, phy_rev);
3134
3135 /* Get RADIO versioning */
3136 if (dev->dev->bus->chip_id == 0x4317) {
3137 if (dev->dev->bus->chip_rev == 0)
3138 tmp = 0x3205017F;
3139 else if (dev->dev->bus->chip_rev == 1)
3140 tmp = 0x4205017F;
3141 else
3142 tmp = 0x5205017F;
3143 } else {
3144 b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
3145 tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH);
3146 tmp <<= 16;
3147 b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
3148 tmp |= b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
3149 }
3150 radio_manuf = (tmp & 0x00000FFF);
3151 radio_ver = (tmp & 0x0FFFF000) >> 12;
3152 radio_rev = (tmp & 0xF0000000) >> 28;
3153 switch (phy_type) {
3154 case B43_PHYTYPE_A:
3155 if (radio_ver != 0x2060)
3156 unsupported = 1;
3157 if (radio_rev != 1)
3158 unsupported = 1;
3159 if (radio_manuf != 0x17F)
3160 unsupported = 1;
3161 break;
3162 case B43_PHYTYPE_B:
3163 if ((radio_ver & 0xFFF0) != 0x2050)
3164 unsupported = 1;
3165 break;
3166 case B43_PHYTYPE_G:
3167 if (radio_ver != 0x2050)
3168 unsupported = 1;
3169 break;
3170 default:
3171 B43_WARN_ON(1);
3172 }
3173 if (unsupported) {
3174 b43err(dev->wl, "FOUND UNSUPPORTED RADIO "
3175 "(Manuf 0x%X, Version 0x%X, Revision %u)\n",
3176 radio_manuf, radio_ver, radio_rev);
3177 return -EOPNOTSUPP;
3178 }
3179 b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n",
3180 radio_manuf, radio_ver, radio_rev);
3181
3182 phy->radio_manuf = radio_manuf;
3183 phy->radio_ver = radio_ver;
3184 phy->radio_rev = radio_rev;
3185
3186 phy->analog = analog_type;
3187 phy->type = phy_type;
3188 phy->rev = phy_rev;
3189
3190 return 0;
3191}
3192
3193static void setup_struct_phy_for_init(struct b43_wldev *dev,
3194 struct b43_phy *phy)
3195{
3196 struct b43_txpower_lo_control *lo;
3197 int i;
3198
3199 memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
3200 memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
3201
3202 /* Flags */
3203 phy->locked = 0;
3204
3205 phy->aci_enable = 0;
3206 phy->aci_wlan_automatic = 0;
3207 phy->aci_hw_rssi = 0;
3208
3209 lo = phy->lo_control;
3210 if (lo) {
3211 memset(lo, 0, sizeof(*(phy->lo_control)));
3212 lo->rebuild = 1;
3213 lo->tx_bias = 0xFF;
3214 }
3215 phy->max_lb_gain = 0;
3216 phy->trsw_rx_gain = 0;
3217 phy->txpwr_offset = 0;
3218
3219 /* NRSSI */
3220 phy->nrssislope = 0;
3221 for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++)
3222 phy->nrssi[i] = -1000;
3223 for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++)
3224 phy->nrssi_lt[i] = i;
3225
3226 phy->lofcal = 0xFFFF;
3227 phy->initval = 0xFFFF;
3228
3229 spin_lock_init(&phy->lock);
3230 phy->interfmode = B43_INTERFMODE_NONE;
3231 phy->channel = 0xFF;
3232
3233 phy->hardware_power_control = !!modparam_hwpctl;
3234}
3235
3236static void setup_struct_wldev_for_init(struct b43_wldev *dev)
3237{
3238 /* Flags */
3239 dev->reg124_set_0x4 = 0;
3240
3241 /* Stats */
3242 memset(&dev->stats, 0, sizeof(dev->stats));
3243
3244 setup_struct_phy_for_init(dev, &dev->phy);
3245
3246 /* IRQ related flags */
3247 dev->irq_reason = 0;
3248 memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
3249 dev->irq_savedstate = B43_IRQ_MASKTEMPLATE;
3250
3251 dev->mac_suspended = 1;
3252
3253 /* Noise calculation context */
3254 memset(&dev->noisecalc, 0, sizeof(dev->noisecalc));
3255}
3256
3257static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
3258{
3259 struct ssb_sprom *sprom = &dev->dev->bus->sprom;
3260 u32 hf;
3261
3262 if (!(sprom->r1.boardflags_lo & B43_BFL_BTCOEXIST))
3263 return;
3264 if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
3265 return;
3266
3267 hf = b43_hf_read(dev);
3268 if (sprom->r1.boardflags_lo & B43_BFL_BTCMOD)
3269 hf |= B43_HF_BTCOEXALT;
3270 else
3271 hf |= B43_HF_BTCOEX;
3272 b43_hf_write(dev, hf);
3273 //TODO
3274}
3275
3276static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
3277{ //TODO
3278}
3279
3280static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
3281{
3282#ifdef CONFIG_SSB_DRIVER_PCICORE
3283 struct ssb_bus *bus = dev->dev->bus;
3284 u32 tmp;
3285
3286 if (bus->pcicore.dev &&
3287 bus->pcicore.dev->id.coreid == SSB_DEV_PCI &&
3288 bus->pcicore.dev->id.revision <= 5) {
3289 /* IMCFGLO timeouts workaround. */
3290 tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
3291 tmp &= ~SSB_IMCFGLO_REQTO;
3292 tmp &= ~SSB_IMCFGLO_SERTO;
3293 switch (bus->bustype) {
3294 case SSB_BUSTYPE_PCI:
3295 case SSB_BUSTYPE_PCMCIA:
3296 tmp |= 0x32;
3297 break;
3298 case SSB_BUSTYPE_SSB:
3299 tmp |= 0x53;
3300 break;
3301 }
3302 ssb_write32(dev->dev, SSB_IMCFGLO, tmp);
3303 }
3304#endif /* CONFIG_SSB_DRIVER_PCICORE */
3305}
3306
3307/* Shutdown a wireless core */
3308/* Locking: wl->mutex */
3309static void b43_wireless_core_exit(struct b43_wldev *dev)
3310{
3311 struct b43_phy *phy = &dev->phy;
3312
3313 B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
3314 if (b43_status(dev) != B43_STAT_INITIALIZED)
3315 return;
3316 b43_set_status(dev, B43_STAT_UNINIT);
3317
3318 b43_rng_exit(dev->wl);
3319 b43_pio_free(dev);
3320 b43_dma_free(dev);
3321 b43_chip_exit(dev);
3322 b43_radio_turn_off(dev);
3323 b43_switch_analog(dev, 0);
3324 if (phy->dyn_tssi_tbl)
3325 kfree(phy->tssi2dbm);
3326 kfree(phy->lo_control);
3327 phy->lo_control = NULL;
3328 ssb_device_disable(dev->dev, 0);
3329 ssb_bus_may_powerdown(dev->dev->bus);
3330}
3331
3332/* Initialize a wireless core */
3333static int b43_wireless_core_init(struct b43_wldev *dev)
3334{
3335 struct b43_wl *wl = dev->wl;
3336 struct ssb_bus *bus = dev->dev->bus;
3337 struct ssb_sprom *sprom = &bus->sprom;
3338 struct b43_phy *phy = &dev->phy;
3339 int err;
3340 u32 hf, tmp;
3341
3342 B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
3343
3344 err = ssb_bus_powerup(bus, 0);
3345 if (err)
3346 goto out;
3347 if (!ssb_device_is_enabled(dev->dev)) {
3348 tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
3349 b43_wireless_core_reset(dev, tmp);
3350 }
3351
3352 if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) {
3353 phy->lo_control =
3354 kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL);
3355 if (!phy->lo_control) {
3356 err = -ENOMEM;
3357 goto err_busdown;
3358 }
3359 }
3360 setup_struct_wldev_for_init(dev);
3361
3362 err = b43_phy_init_tssi2dbm_table(dev);
3363 if (err)
3364 goto err_kfree_lo_control;
3365
3366 /* Enable IRQ routing to this device. */
3367 ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
3368
3369 b43_imcfglo_timeouts_workaround(dev);
3370 b43_bluetooth_coext_disable(dev);
3371 b43_phy_early_init(dev);
3372 err = b43_chip_init(dev);
3373 if (err)
3374 goto err_kfree_tssitbl;
3375 b43_shm_write16(dev, B43_SHM_SHARED,
3376 B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
3377 hf = b43_hf_read(dev);
3378 if (phy->type == B43_PHYTYPE_G) {
3379 hf |= B43_HF_SYMW;
3380 if (phy->rev == 1)
3381 hf |= B43_HF_GDCW;
3382 if (sprom->r1.boardflags_lo & B43_BFL_PACTRL)
3383 hf |= B43_HF_OFDMPABOOST;
3384 } else if (phy->type == B43_PHYTYPE_B) {
3385 hf |= B43_HF_SYMW;
3386 if (phy->rev >= 2 && phy->radio_ver == 0x2050)
3387 hf &= ~B43_HF_GDCW;
3388 }
3389 b43_hf_write(dev, hf);
3390
3391 /* Short/Long Retry Limit.
3392 * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
3393 * the chip-internal counter.
3394 */
3395 tmp = limit_value(modparam_short_retry, 0, 0xF);
3396 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, tmp);
3397 tmp = limit_value(modparam_long_retry, 0, 0xF);
3398 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, tmp);
3399
3400 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SFFBLIM, 3);
3401 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_LFFBLIM, 2);
3402
3403 /* Disable sending probe responses from firmware.
3404 * Setting the MaxTime to one usec will always trigger
3405 * a timeout, so we never send any probe resp.
3406 * A timeout of zero is infinite. */
3407 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1);
3408
3409 b43_rate_memory_init(dev);
3410
3411 /* Minimum Contention Window */
3412 if (phy->type == B43_PHYTYPE_B) {
3413 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F);
3414 } else {
3415 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF);
3416 }
3417 /* Maximum Contention Window */
3418 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
3419
3420 do {
3421 if (b43_using_pio(dev)) {
3422 err = b43_pio_init(dev);
3423 } else {
3424 err = b43_dma_init(dev);
3425 if (!err)
3426 b43_qos_init(dev);
3427 }
3428 } while (err == -EAGAIN);
3429 if (err)
3430 goto err_chip_exit;
3431
3432//FIXME
3433#if 1
3434 b43_write16(dev, 0x0612, 0x0050);
3435 b43_shm_write16(dev, B43_SHM_SHARED, 0x0416, 0x0050);
3436 b43_shm_write16(dev, B43_SHM_SHARED, 0x0414, 0x01F4);
3437#endif
3438
3439 b43_bluetooth_coext_enable(dev);
3440
3441 ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
3442 memset(wl->bssid, 0, ETH_ALEN);
3443 b43_upload_card_macaddress(dev, NULL);
3444 b43_security_init(dev);
3445 b43_rng_init(wl);
3446
3447 b43_set_status(dev, B43_STAT_INITIALIZED);
3448
3449 out:
3450 return err;
3451
3452 err_chip_exit:
3453 b43_chip_exit(dev);
3454 err_kfree_tssitbl:
3455 if (phy->dyn_tssi_tbl)
3456 kfree(phy->tssi2dbm);
3457 err_kfree_lo_control:
3458 kfree(phy->lo_control);
3459 phy->lo_control = NULL;
3460 err_busdown:
3461 ssb_bus_may_powerdown(bus);
3462 B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
3463 return err;
3464}
3465
3466static int b43_add_interface(struct ieee80211_hw *hw,
3467 struct ieee80211_if_init_conf *conf)
3468{
3469 struct b43_wl *wl = hw_to_b43_wl(hw);
3470 struct b43_wldev *dev;
3471 unsigned long flags;
3472 int err = -EOPNOTSUPP;
3473 int did_init = 0;
3474
3475 mutex_lock(&wl->mutex);
3476 if ((conf->type != IEEE80211_IF_TYPE_MNTR) && wl->operating)
3477 goto out_mutex_unlock;
3478
3479 b43dbg(wl, "Adding Interface type %d\n", conf->type);
3480
3481 dev = wl->current_dev;
3482 if (b43_status(dev) < B43_STAT_INITIALIZED) {
3483 err = b43_wireless_core_init(dev);
3484 if (err)
3485 goto out_mutex_unlock;
3486 did_init = 1;
3487 }
3488 if (b43_status(dev) < B43_STAT_STARTED) {
3489 err = b43_wireless_core_start(dev);
3490 if (err) {
3491 if (did_init)
3492 b43_wireless_core_exit(dev);
3493 goto out_mutex_unlock;
3494 }
3495 }
3496
3497 spin_lock_irqsave(&wl->irq_lock, flags);
3498 switch (conf->type) {
3499 case IEEE80211_IF_TYPE_MNTR:
3500 wl->monitor++;
3501 break;
3502 default:
3503 wl->operating = 1;
3504 wl->if_id = conf->if_id;
3505 wl->if_type = conf->type;
3506 b43_upload_card_macaddress(dev, conf->mac_addr);
3507 }
3508 b43_adjust_opmode(dev);
3509 spin_unlock_irqrestore(&wl->irq_lock, flags);
3510
3511 err = 0;
3512 out_mutex_unlock:
3513 mutex_unlock(&wl->mutex);
3514
3515 return err;
3516}
3517
3518static void b43_remove_interface(struct ieee80211_hw *hw,
3519 struct ieee80211_if_init_conf *conf)
3520{
3521 struct b43_wl *wl = hw_to_b43_wl(hw);
3522 struct b43_wldev *dev;
3523 unsigned long flags;
3524
3525 b43dbg(wl, "Removing Interface type %d\n", conf->type);
3526
3527 mutex_lock(&wl->mutex);
3528 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
3529 wl->monitor--;
3530 B43_WARN_ON(wl->monitor < 0);
3531 } else {
3532 B43_WARN_ON(!wl->operating);
3533 wl->operating = 0;
3534 }
3535
3536 dev = wl->current_dev;
3537 if (!wl->operating && wl->monitor == 0) {
3538 /* No interface left. */
3539 if (b43_status(dev) >= B43_STAT_STARTED)
3540 b43_wireless_core_stop(dev);
3541 b43_wireless_core_exit(dev);
3542 } else {
3543 /* Just monitor interfaces left. */
3544 spin_lock_irqsave(&wl->irq_lock, flags);
3545 b43_adjust_opmode(dev);
3546 if (!wl->operating)
3547 b43_upload_card_macaddress(dev, NULL);
3548 spin_unlock_irqrestore(&wl->irq_lock, flags);
3549 }
3550 mutex_unlock(&wl->mutex);
3551}
3552
3553static const struct ieee80211_ops b43_hw_ops = {
3554 .tx = b43_tx,
3555 .conf_tx = b43_conf_tx,
3556 .add_interface = b43_add_interface,
3557 .remove_interface = b43_remove_interface,
3558 .config = b43_dev_config,
3559 .config_interface = b43_config_interface,
3560 .set_multicast_list = b43_set_multicast_list,
3561 .set_key = b43_dev_set_key,
3562 .get_stats = b43_get_stats,
3563 .get_tx_stats = b43_get_tx_stats,
3564};
3565
3566/* Hard-reset the chip. Do not call this directly.
3567 * Use b43_controller_restart()
3568 */
3569static void b43_chip_reset(struct work_struct *work)
3570{
3571 struct b43_wldev *dev =
3572 container_of(work, struct b43_wldev, restart_work);
3573 struct b43_wl *wl = dev->wl;
3574 int err = 0;
3575 int prev_status;
3576
3577 mutex_lock(&wl->mutex);
3578
3579 prev_status = b43_status(dev);
3580 /* Bring the device down... */
3581 if (prev_status >= B43_STAT_STARTED)
3582 b43_wireless_core_stop(dev);
3583 if (prev_status >= B43_STAT_INITIALIZED)
3584 b43_wireless_core_exit(dev);
3585
3586 /* ...and up again. */
3587 if (prev_status >= B43_STAT_INITIALIZED) {
3588 err = b43_wireless_core_init(dev);
3589 if (err)
3590 goto out;
3591 }
3592 if (prev_status >= B43_STAT_STARTED) {
3593 err = b43_wireless_core_start(dev);
3594 if (err) {
3595 b43_wireless_core_exit(dev);
3596 goto out;
3597 }
3598 }
3599 out:
3600 mutex_unlock(&wl->mutex);
3601 if (err)
3602 b43err(wl, "Controller restart FAILED\n");
3603 else
3604 b43info(wl, "Controller restarted\n");
3605}
3606
3607static int b43_setup_modes(struct b43_wldev *dev,
3608 int have_aphy, int have_bphy, int have_gphy)
3609{
3610 struct ieee80211_hw *hw = dev->wl->hw;
3611 struct ieee80211_hw_mode *mode;
3612 struct b43_phy *phy = &dev->phy;
3613 int cnt = 0;
3614 int err;
3615
3616/*FIXME: Don't tell ieee80211 about an A-PHY, because we currently don't support A-PHY. */
3617 have_aphy = 0;
3618
3619 phy->possible_phymodes = 0;
3620 for (; 1; cnt++) {
3621 if (have_aphy) {
3622 B43_WARN_ON(cnt >= B43_MAX_PHYHWMODES);
3623 mode = &phy->hwmodes[cnt];
3624
3625 mode->mode = MODE_IEEE80211A;
3626 mode->num_channels = b43_a_chantable_size;
3627 mode->channels = b43_a_chantable;
3628 mode->num_rates = b43_a_ratetable_size;
3629 mode->rates = b43_a_ratetable;
3630 err = ieee80211_register_hwmode(hw, mode);
3631 if (err)
3632 return err;
3633
3634 phy->possible_phymodes |= B43_PHYMODE_A;
3635 have_aphy = 0;
3636 continue;
3637 }
3638 if (have_bphy) {
3639 B43_WARN_ON(cnt >= B43_MAX_PHYHWMODES);
3640 mode = &phy->hwmodes[cnt];
3641
3642 mode->mode = MODE_IEEE80211B;
3643 mode->num_channels = b43_bg_chantable_size;
3644 mode->channels = b43_bg_chantable;
3645 mode->num_rates = b43_b_ratetable_size;
3646 mode->rates = b43_b_ratetable;
3647 err = ieee80211_register_hwmode(hw, mode);
3648 if (err)
3649 return err;
3650
3651 phy->possible_phymodes |= B43_PHYMODE_B;
3652 have_bphy = 0;
3653 continue;
3654 }
3655 if (have_gphy) {
3656 B43_WARN_ON(cnt >= B43_MAX_PHYHWMODES);
3657 mode = &phy->hwmodes[cnt];
3658
3659 mode->mode = MODE_IEEE80211G;
3660 mode->num_channels = b43_bg_chantable_size;
3661 mode->channels = b43_bg_chantable;
3662 mode->num_rates = b43_g_ratetable_size;
3663 mode->rates = b43_g_ratetable;
3664 err = ieee80211_register_hwmode(hw, mode);
3665 if (err)
3666 return err;
3667
3668 phy->possible_phymodes |= B43_PHYMODE_G;
3669 have_gphy = 0;
3670 continue;
3671 }
3672 break;
3673 }
3674
3675 return 0;
3676}
3677
3678static void b43_wireless_core_detach(struct b43_wldev *dev)
3679{
3680 /* We release firmware that late to not be required to re-request
3681 * is all the time when we reinit the core. */
3682 b43_release_firmware(dev);
3683}
3684
3685static int b43_wireless_core_attach(struct b43_wldev *dev)
3686{
3687 struct b43_wl *wl = dev->wl;
3688 struct ssb_bus *bus = dev->dev->bus;
3689 struct pci_dev *pdev = bus->host_pci;
3690 int err;
3691 int have_aphy = 0, have_bphy = 0, have_gphy = 0;
3692 u32 tmp;
3693
3694 /* Do NOT do any device initialization here.
3695 * Do it in wireless_core_init() instead.
3696 * This function is for gathering basic information about the HW, only.
3697 * Also some structs may be set up here. But most likely you want to have
3698 * that in core_init(), too.
3699 */
3700
3701 err = ssb_bus_powerup(bus, 0);
3702 if (err) {
3703 b43err(wl, "Bus powerup failed\n");
3704 goto out;
3705 }
3706 /* Get the PHY type. */
3707 if (dev->dev->id.revision >= 5) {
3708 u32 tmshigh;
3709
3710 tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
3711 have_aphy = !!(tmshigh & B43_TMSHIGH_APHY);
3712 have_gphy = !!(tmshigh & B43_TMSHIGH_GPHY);
3713 if (!have_aphy && !have_gphy)
3714 have_bphy = 1;
3715 } else if (dev->dev->id.revision == 4) {
3716 have_gphy = 1;
3717 have_aphy = 1;
3718 } else
3719 have_bphy = 1;
3720
3721 /* Initialize LEDs structs. */
3722 err = b43_leds_init(dev);
3723 if (err)
3724 goto err_powerdown;
3725
3726 dev->phy.gmode = (have_gphy || have_bphy);
3727 tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
3728 b43_wireless_core_reset(dev, tmp);
3729
3730 err = b43_phy_versioning(dev);
3731 if (err)
3732 goto err_leds_exit;
3733 /* Check if this device supports multiband. */
3734 if (!pdev ||
3735 (pdev->device != 0x4312 &&
3736 pdev->device != 0x4319 && pdev->device != 0x4324)) {
3737 /* No multiband support. */
3738 have_aphy = 0;
3739 have_bphy = 0;
3740 have_gphy = 0;
3741 switch (dev->phy.type) {
3742 case B43_PHYTYPE_A:
3743 have_aphy = 1;
3744 break;
3745 case B43_PHYTYPE_B:
3746 have_bphy = 1;
3747 break;
3748 case B43_PHYTYPE_G:
3749 have_gphy = 1;
3750 break;
3751 default:
3752 B43_WARN_ON(1);
3753 }
3754 }
3755 dev->phy.gmode = (have_gphy || have_bphy);
3756 tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
3757 b43_wireless_core_reset(dev, tmp);
3758
3759 err = b43_validate_chipaccess(dev);
3760 if (err)
3761 goto err_leds_exit;
3762 err = b43_setup_modes(dev, have_aphy, have_bphy, have_gphy);
3763 if (err)
3764 goto err_leds_exit;
3765
3766 /* Now set some default "current_dev" */
3767 if (!wl->current_dev)
3768 wl->current_dev = dev;
3769 INIT_WORK(&dev->restart_work, b43_chip_reset);
3770
3771 b43_radio_turn_off(dev);
3772 b43_switch_analog(dev, 0);
3773 ssb_device_disable(dev->dev, 0);
3774 ssb_bus_may_powerdown(bus);
3775
3776out:
3777 return err;
3778
3779err_leds_exit:
3780 b43_leds_exit(dev);
3781err_powerdown:
3782 ssb_bus_may_powerdown(bus);
3783 return err;
3784}
3785
3786static void b43_one_core_detach(struct ssb_device *dev)
3787{
3788 struct b43_wldev *wldev;
3789 struct b43_wl *wl;
3790
3791 wldev = ssb_get_drvdata(dev);
3792 wl = wldev->wl;
3793 cancel_work_sync(&wldev->restart_work);
3794 b43_debugfs_remove_device(wldev);
3795 b43_wireless_core_detach(wldev);
3796 list_del(&wldev->list);
3797 wl->nr_devs--;
3798 ssb_set_drvdata(dev, NULL);
3799 kfree(wldev);
3800}
3801
3802static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
3803{
3804 struct b43_wldev *wldev;
3805 struct pci_dev *pdev;
3806 int err = -ENOMEM;
3807
3808 if (!list_empty(&wl->devlist)) {
3809 /* We are not the first core on this chip. */
3810 pdev = dev->bus->host_pci;
3811 /* Only special chips support more than one wireless
3812 * core, although some of the other chips have more than
3813 * one wireless core as well. Check for this and
3814 * bail out early.
3815 */
3816 if (!pdev ||
3817 ((pdev->device != 0x4321) &&
3818 (pdev->device != 0x4313) && (pdev->device != 0x431A))) {
3819 b43dbg(wl, "Ignoring unconnected 802.11 core\n");
3820 return -ENODEV;
3821 }
3822 }
3823
3824 wldev = kzalloc(sizeof(*wldev), GFP_KERNEL);
3825 if (!wldev)
3826 goto out;
3827
3828 wldev->dev = dev;
3829 wldev->wl = wl;
3830 b43_set_status(wldev, B43_STAT_UNINIT);
3831 wldev->bad_frames_preempt = modparam_bad_frames_preempt;
3832 tasklet_init(&wldev->isr_tasklet,
3833 (void (*)(unsigned long))b43_interrupt_tasklet,
3834 (unsigned long)wldev);
3835 if (modparam_pio)
3836 wldev->__using_pio = 1;
3837 INIT_LIST_HEAD(&wldev->list);
3838
3839 err = b43_wireless_core_attach(wldev);
3840 if (err)
3841 goto err_kfree_wldev;
3842
3843 list_add(&wldev->list, &wl->devlist);
3844 wl->nr_devs++;
3845 ssb_set_drvdata(dev, wldev);
3846 b43_debugfs_add_device(wldev);
3847
3848 out:
3849 return err;
3850
3851 err_kfree_wldev:
3852 kfree(wldev);
3853 return err;
3854}
3855
3856static void b43_sprom_fixup(struct ssb_bus *bus)
3857{
3858 /* boardflags workarounds */
3859 if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
3860 bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
3861 bus->sprom.r1.boardflags_lo |= B43_BFL_BTCOEXIST;
3862 if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
3863 bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
3864 bus->sprom.r1.boardflags_lo |= B43_BFL_PACTRL;
3865
3866 /* Handle case when gain is not set in sprom */
3867 if (bus->sprom.r1.antenna_gain_a == 0xFF)
3868 bus->sprom.r1.antenna_gain_a = 2;
3869 if (bus->sprom.r1.antenna_gain_bg == 0xFF)
3870 bus->sprom.r1.antenna_gain_bg = 2;
3871
3872 /* Convert Antennagain values to Q5.2 */
3873 bus->sprom.r1.antenna_gain_a <<= 2;
3874 bus->sprom.r1.antenna_gain_bg <<= 2;
3875}
3876
3877static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
3878{
3879 struct ieee80211_hw *hw = wl->hw;
3880
3881 ssb_set_devtypedata(dev, NULL);
3882 ieee80211_free_hw(hw);
3883}
3884
3885static int b43_wireless_init(struct ssb_device *dev)
3886{
3887 struct ssb_sprom *sprom = &dev->bus->sprom;
3888 struct ieee80211_hw *hw;
3889 struct b43_wl *wl;
3890 int err = -ENOMEM;
3891
3892 b43_sprom_fixup(dev->bus);
3893
3894 hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
3895 if (!hw) {
3896 b43err(NULL, "Could not allocate ieee80211 device\n");
3897 goto out;
3898 }
3899
3900 /* fill hw info */
3901 hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
3902 IEEE80211_HW_MONITOR_DURING_OPER;
3903 hw->max_signal = 100;
3904 hw->max_rssi = -110;
3905 hw->max_noise = -110;
3906 hw->queues = 1; /* FIXME: hardware has more queues */
3907 SET_IEEE80211_DEV(hw, dev->dev);
3908 if (is_valid_ether_addr(sprom->r1.et1mac))
3909 SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
3910 else
3911 SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
3912
3913 /* Get and initialize struct b43_wl */
3914 wl = hw_to_b43_wl(hw);
3915 memset(wl, 0, sizeof(*wl));
3916 wl->hw = hw;
3917 spin_lock_init(&wl->irq_lock);
3918 spin_lock_init(&wl->leds_lock);
3919 mutex_init(&wl->mutex);
3920 INIT_LIST_HEAD(&wl->devlist);
3921
3922 ssb_set_devtypedata(dev, wl);
3923 b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
3924 err = 0;
3925 out:
3926 return err;
3927}
3928
3929static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
3930{
3931 struct b43_wl *wl;
3932 int err;
3933 int first = 0;
3934
3935 wl = ssb_get_devtypedata(dev);
3936 if (!wl) {
3937 /* Probing the first core. Must setup common struct b43_wl */
3938 first = 1;
3939 err = b43_wireless_init(dev);
3940 if (err)
3941 goto out;
3942 wl = ssb_get_devtypedata(dev);
3943 B43_WARN_ON(!wl);
3944 }
3945 err = b43_one_core_attach(dev, wl);
3946 if (err)
3947 goto err_wireless_exit;
3948
3949 if (first) {
3950 err = ieee80211_register_hw(wl->hw);
3951 if (err)
3952 goto err_one_core_detach;
3953 }
3954
3955 out:
3956 return err;
3957
3958 err_one_core_detach:
3959 b43_one_core_detach(dev);
3960 err_wireless_exit:
3961 if (first)
3962 b43_wireless_exit(dev, wl);
3963 return err;
3964}
3965
3966static void b43_remove(struct ssb_device *dev)
3967{
3968 struct b43_wl *wl = ssb_get_devtypedata(dev);
3969 struct b43_wldev *wldev = ssb_get_drvdata(dev);
3970
3971 B43_WARN_ON(!wl);
3972 if (wl->current_dev == wldev)
3973 ieee80211_unregister_hw(wl->hw);
3974
3975 b43_one_core_detach(dev);
3976
3977 if (list_empty(&wl->devlist)) {
3978 /* Last core on the chip unregistered.
3979 * We can destroy common struct b43_wl.
3980 */
3981 b43_wireless_exit(dev, wl);
3982 }
3983}
3984
3985/* Perform a hardware reset. This can be called from any context. */
3986void b43_controller_restart(struct b43_wldev *dev, const char *reason)
3987{
3988 /* Must avoid requeueing, if we are in shutdown. */
3989 if (b43_status(dev) < B43_STAT_INITIALIZED)
3990 return;
3991 b43info(dev->wl, "Controller RESET (%s) ...\n", reason);
3992 queue_work(dev->wl->hw->workqueue, &dev->restart_work);
3993}
3994
3995#ifdef CONFIG_PM
3996
3997static int b43_suspend(struct ssb_device *dev, pm_message_t state)
3998{
3999 struct b43_wldev *wldev = ssb_get_drvdata(dev);
4000 struct b43_wl *wl = wldev->wl;
4001
4002 b43dbg(wl, "Suspending...\n");
4003
4004 mutex_lock(&wl->mutex);
4005 wldev->suspend_init_status = b43_status(wldev);
4006 if (wldev->suspend_init_status >= B43_STAT_STARTED)
4007 b43_wireless_core_stop(wldev);
4008 if (wldev->suspend_init_status >= B43_STAT_INITIALIZED)
4009 b43_wireless_core_exit(wldev);
4010 mutex_unlock(&wl->mutex);
4011
4012 b43dbg(wl, "Device suspended.\n");
4013
4014 return 0;
4015}
4016
4017static int b43_resume(struct ssb_device *dev)
4018{
4019 struct b43_wldev *wldev = ssb_get_drvdata(dev);
4020 struct b43_wl *wl = wldev->wl;
4021 int err = 0;
4022
4023 b43dbg(wl, "Resuming...\n");
4024
4025 mutex_lock(&wl->mutex);
4026 if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) {
4027 err = b43_wireless_core_init(wldev);
4028 if (err) {
4029 b43err(wl, "Resume failed at core init\n");
4030 goto out;
4031 }
4032 }
4033 if (wldev->suspend_init_status >= B43_STAT_STARTED) {
4034 err = b43_wireless_core_start(wldev);
4035 if (err) {
4036 b43_wireless_core_exit(wldev);
4037 b43err(wl, "Resume failed at core start\n");
4038 goto out;
4039 }
4040 }
4041 mutex_unlock(&wl->mutex);
4042
4043 b43dbg(wl, "Device resumed.\n");
4044 out:
4045 return err;
4046}
4047
4048#else /* CONFIG_PM */
4049# define b43_suspend NULL
4050# define b43_resume NULL
4051#endif /* CONFIG_PM */
4052
4053static struct ssb_driver b43_ssb_driver = {
4054 .name = KBUILD_MODNAME,
4055 .id_table = b43_ssb_tbl,
4056 .probe = b43_probe,
4057 .remove = b43_remove,
4058 .suspend = b43_suspend,
4059 .resume = b43_resume,
4060};
4061
4062static int __init b43_init(void)
4063{
4064 int err;
4065
4066 b43_debugfs_init();
4067 err = b43_pcmcia_init();
4068 if (err)
4069 goto err_dfs_exit;
4070 err = ssb_driver_register(&b43_ssb_driver);
4071 if (err)
4072 goto err_pcmcia_exit;
4073
4074 return err;
4075
4076err_pcmcia_exit:
4077 b43_pcmcia_exit();
4078err_dfs_exit:
4079 b43_debugfs_exit();
4080 return err;
4081}
4082
4083static void __exit b43_exit(void)
4084{
4085 ssb_driver_unregister(&b43_ssb_driver);
4086 b43_pcmcia_exit();
4087 b43_debugfs_exit();
4088}
4089
4090module_init(b43_init)
4091module_exit(b43_exit)
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
new file mode 100644
index 000000000000..bd8fcf72dc5d
--- /dev/null
+++ b/drivers/net/wireless/b43/main.h
@@ -0,0 +1,142 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mb@bu3sch.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 B43_MAIN_H_
32#define B43_MAIN_H_
33
34#include "b43.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/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
42static inline u8 b43_freq_to_channel_a(int freq)
43{
44 return ((freq - 5000) / 5);
45}
46static inline u8 b43_freq_to_channel_bg(int freq)
47{
48 u8 channel;
49
50 if (freq == 2484)
51 channel = 14;
52 else
53 channel = (freq - 2407) / 5;
54
55 return channel;
56}
57static inline u8 b43_freq_to_channel(struct b43_wldev *dev, int freq)
58{
59 if (dev->phy.type == B43_PHYTYPE_A)
60 return b43_freq_to_channel_a(freq);
61 return b43_freq_to_channel_bg(freq);
62}
63
64/* Lightweight function to convert a channel number to a frequency (in Mhz). */
65static inline int b43_channel_to_freq_a(u8 channel)
66{
67 return (5000 + (5 * channel));
68}
69static inline int b43_channel_to_freq_bg(u8 channel)
70{
71 int freq;
72
73 if (channel == 14)
74 freq = 2484;
75 else
76 freq = 2407 + (5 * channel);
77
78 return freq;
79}
80static inline int b43_channel_to_freq(struct b43_wldev *dev, u8 channel)
81{
82 if (dev->phy.type == B43_PHYTYPE_A)
83 return b43_channel_to_freq_a(channel);
84 return b43_channel_to_freq_bg(channel);
85}
86
87static inline int b43_is_cck_rate(int rate)
88{
89 return (rate == B43_CCK_RATE_1MB ||
90 rate == B43_CCK_RATE_2MB ||
91 rate == B43_CCK_RATE_5MB || rate == B43_CCK_RATE_11MB);
92}
93
94static inline int b43_is_ofdm_rate(int rate)
95{
96 return !b43_is_cck_rate(rate);
97}
98
99static inline int b43_is_hw_radio_enabled(struct b43_wldev *dev)
100{
101 /* function to return state of hardware enable of radio
102 * returns 0 if radio disabled, 1 if radio enabled
103 */
104 struct b43_phy *phy = &dev->phy;
105
106 if (phy->rev >= 3)
107 return ((b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
108 & B43_MMIO_RADIO_HWENABLED_HI_MASK)
109 == 0) ? 1 : 0;
110 else
111 return ((b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
112 & B43_MMIO_RADIO_HWENABLED_LO_MASK)
113 == 0) ? 0 : 1;
114}
115
116void b43_tsf_read(struct b43_wldev *dev, u64 * tsf);
117void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
118
119u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
120u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
121void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
122void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
123
124u32 b43_hf_read(struct b43_wldev *dev);
125void b43_hf_write(struct b43_wldev *dev, u32 value);
126
127void b43_dummy_transmission(struct b43_wldev *dev);
128
129void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
130
131void b43_mac_suspend(struct b43_wldev *dev);
132void b43_mac_enable(struct b43_wldev *dev);
133
134void b43_controller_restart(struct b43_wldev *dev, const char *reason);
135
136#define B43_PS_ENABLED (1 << 0) /* Force enable hardware power saving */
137#define B43_PS_DISABLED (1 << 1) /* Force disable hardware power saving */
138#define B43_PS_AWAKE (1 << 2) /* Force device awake */
139#define B43_PS_ASLEEP (1 << 3) /* Force device asleep */
140void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
141
142#endif /* B43_MAIN_H_ */
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
new file mode 100644
index 000000000000..3e75a8a12c96
--- /dev/null
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -0,0 +1,157 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22*/
23
24#include <linux/ssb/ssb.h>
25
26#include <pcmcia/cs_types.h>
27#include <pcmcia/cs.h>
28#include <pcmcia/cistpl.h>
29#include <pcmcia/ciscode.h>
30#include <pcmcia/ds.h>
31#include <pcmcia/cisreg.h>
32
33static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = {
34 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
35 PCMCIA_DEVICE_NULL,
36};
37
38MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
39
40#ifdef CONFIG_PM
41static int b43_pcmcia_suspend(struct pcmcia_device *dev)
42{
43 //TODO
44 return 0;
45}
46
47static int b43_pcmcia_resume(struct pcmcia_device *dev)
48{
49 //TODO
50 return 0;
51}
52#else /* CONFIG_PM */
53# define b43_pcmcia_suspend NULL
54# define b43_pcmcia_resume NULL
55#endif /* CONFIG_PM */
56
57static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
58{
59 struct ssb_bus *ssb;
60 win_req_t win;
61 memreq_t mem;
62 tuple_t tuple;
63 cisparse_t parse;
64 int err = -ENOMEM;
65 int res;
66 unsigned char buf[64];
67
68 ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
69 if (!ssb)
70 goto out;
71
72 err = -ENODEV;
73 tuple.DesiredTuple = CISTPL_CONFIG;
74 tuple.Attributes = 0;
75 tuple.TupleData = buf;
76 tuple.TupleDataMax = sizeof(buf);
77 tuple.TupleOffset = 0;
78
79 res = pcmcia_get_first_tuple(dev, &tuple);
80 if (res != CS_SUCCESS)
81 goto err_kfree_ssb;
82 res = pcmcia_get_tuple_data(dev, &tuple);
83 if (res != CS_SUCCESS)
84 goto err_kfree_ssb;
85 res = pcmcia_parse_tuple(dev, &tuple, &parse);
86 if (res != CS_SUCCESS)
87 goto err_kfree_ssb;
88
89 dev->conf.ConfigBase = parse.config.base;
90 dev->conf.Present = parse.config.rmask[0];
91
92 dev->io.BasePort2 = 0;
93 dev->io.NumPorts2 = 0;
94 dev->io.Attributes2 = 0;
95
96 win.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
97 win.Base = 0;
98 win.Size = SSB_CORE_SIZE;
99 win.AccessSpeed = 1000;
100 res = pcmcia_request_window(&dev, &win, &dev->win);
101 if (res != CS_SUCCESS)
102 goto err_kfree_ssb;
103
104 mem.CardOffset = 0;
105 mem.Page = 0;
106 res = pcmcia_map_mem_page(dev->win, &mem);
107 if (res != CS_SUCCESS)
108 goto err_kfree_ssb;
109
110 res = pcmcia_request_configuration(dev, &dev->conf);
111 if (res != CS_SUCCESS)
112 goto err_disable;
113
114 err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
115 dev->priv = ssb;
116
117 out:
118 return err;
119 err_disable:
120 pcmcia_disable_device(dev);
121 err_kfree_ssb:
122 kfree(ssb);
123 return err;
124}
125
126static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
127{
128 struct ssb_bus *ssb = dev->priv;
129
130 ssb_bus_unregister(ssb);
131 pcmcia_release_window(dev->win);
132 pcmcia_disable_device(dev);
133 kfree(ssb);
134 dev->priv = NULL;
135}
136
137static struct pcmcia_driver b43_pcmcia_driver = {
138 .owner = THIS_MODULE,
139 .drv = {
140 .name = "b43-pcmcia",
141 },
142 .id_table = b43_pcmcia_tbl,
143 .probe = b43_pcmcia_probe,
144 .remove = b43_pcmcia_remove,
145 .suspend = b43_pcmcia_suspend,
146 .resume = b43_pcmcia_resume,
147};
148
149int b43_pcmcia_init(void)
150{
151 return pcmcia_register_driver(&b43_pcmcia_driver);
152}
153
154void b43_pcmcia_exit(void)
155{
156 pcmcia_unregister_driver(&b43_pcmcia_driver);
157}
diff --git a/drivers/net/wireless/b43/pcmcia.h b/drivers/net/wireless/b43/pcmcia.h
new file mode 100644
index 000000000000..85f120a67cbe
--- /dev/null
+++ b/drivers/net/wireless/b43/pcmcia.h
@@ -0,0 +1,20 @@
1#ifndef B43_PCMCIA_H_
2#define B43_PCMCIA_H_
3
4#ifdef CONFIG_B43_PCMCIA
5
6int b43_pcmcia_init(void);
7void b43_pcmcia_exit(void);
8
9#else /* CONFIG_B43_PCMCIA */
10
11static inline int b43_pcmcia_init(void)
12{
13 return 0;
14}
15static inline void b43_pcmcia_exit(void)
16{
17}
18
19#endif /* CONFIG_B43_PCMCIA */
20#endif /* B43_PCMCIA_H_ */
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
new file mode 100644
index 000000000000..3282893021b0
--- /dev/null
+++ b/drivers/net/wireless/b43/phy.c
@@ -0,0 +1,4351 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>
7 Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
8 Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
9 Copyright (c) 2005, 2006 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 <linux/delay.h>
29#include <linux/types.h>
30
31#include "b43.h"
32#include "phy.h"
33#include "main.h"
34#include "tables.h"
35#include "lo.h"
36
37static const s8 b43_tssi2dbm_b_table[] = {
38 0x4D, 0x4C, 0x4B, 0x4A,
39 0x4A, 0x49, 0x48, 0x47,
40 0x47, 0x46, 0x45, 0x45,
41 0x44, 0x43, 0x42, 0x42,
42 0x41, 0x40, 0x3F, 0x3E,
43 0x3D, 0x3C, 0x3B, 0x3A,
44 0x39, 0x38, 0x37, 0x36,
45 0x35, 0x34, 0x32, 0x31,
46 0x30, 0x2F, 0x2D, 0x2C,
47 0x2B, 0x29, 0x28, 0x26,
48 0x25, 0x23, 0x21, 0x1F,
49 0x1D, 0x1A, 0x17, 0x14,
50 0x10, 0x0C, 0x06, 0x00,
51 -7, -7, -7, -7,
52 -7, -7, -7, -7,
53 -7, -7, -7, -7,
54};
55
56static const s8 b43_tssi2dbm_g_table[] = {
57 77, 77, 77, 76,
58 76, 76, 75, 75,
59 74, 74, 73, 73,
60 73, 72, 72, 71,
61 71, 70, 70, 69,
62 68, 68, 67, 67,
63 66, 65, 65, 64,
64 63, 63, 62, 61,
65 60, 59, 58, 57,
66 56, 55, 54, 53,
67 52, 50, 49, 47,
68 45, 43, 40, 37,
69 33, 28, 22, 14,
70 5, -7, -20, -20,
71 -20, -20, -20, -20,
72 -20, -20, -20, -20,
73};
74
75const u8 b43_radio_channel_codes_bg[] = {
76 12, 17, 22, 27,
77 32, 37, 42, 47,
78 52, 57, 62, 67,
79 72, 84,
80};
81
82static void b43_phy_initg(struct b43_wldev *dev);
83
84/* Reverse the bits of a 4bit value.
85 * Example: 1101 is flipped 1011
86 */
87static u16 flip_4bit(u16 value)
88{
89 u16 flipped = 0x0000;
90
91 B43_WARN_ON(value & ~0x000F);
92
93 flipped |= (value & 0x0001) << 3;
94 flipped |= (value & 0x0002) << 1;
95 flipped |= (value & 0x0004) >> 1;
96 flipped |= (value & 0x0008) >> 3;
97
98 return flipped;
99}
100
101static void generate_rfatt_list(struct b43_wldev *dev,
102 struct b43_rfatt_list *list)
103{
104 struct b43_phy *phy = &dev->phy;
105
106 /* APHY.rev < 5 || GPHY.rev < 6 */
107 static const struct b43_rfatt rfatt_0[] = {
108 {.att = 3,.with_padmix = 0,},
109 {.att = 1,.with_padmix = 0,},
110 {.att = 5,.with_padmix = 0,},
111 {.att = 7,.with_padmix = 0,},
112 {.att = 9,.with_padmix = 0,},
113 {.att = 2,.with_padmix = 0,},
114 {.att = 0,.with_padmix = 0,},
115 {.att = 4,.with_padmix = 0,},
116 {.att = 6,.with_padmix = 0,},
117 {.att = 8,.with_padmix = 0,},
118 {.att = 1,.with_padmix = 1,},
119 {.att = 2,.with_padmix = 1,},
120 {.att = 3,.with_padmix = 1,},
121 {.att = 4,.with_padmix = 1,},
122 };
123 /* Radio.rev == 8 && Radio.version == 0x2050 */
124 static const struct b43_rfatt rfatt_1[] = {
125 {.att = 2,.with_padmix = 1,},
126 {.att = 4,.with_padmix = 1,},
127 {.att = 6,.with_padmix = 1,},
128 {.att = 8,.with_padmix = 1,},
129 {.att = 10,.with_padmix = 1,},
130 {.att = 12,.with_padmix = 1,},
131 {.att = 14,.with_padmix = 1,},
132 };
133 /* Otherwise */
134 static const struct b43_rfatt rfatt_2[] = {
135 {.att = 0,.with_padmix = 1,},
136 {.att = 2,.with_padmix = 1,},
137 {.att = 4,.with_padmix = 1,},
138 {.att = 6,.with_padmix = 1,},
139 {.att = 8,.with_padmix = 1,},
140 {.att = 9,.with_padmix = 1,},
141 {.att = 9,.with_padmix = 1,},
142 };
143
144 if ((phy->type == B43_PHYTYPE_A && phy->rev < 5) ||
145 (phy->type == B43_PHYTYPE_G && phy->rev < 6)) {
146 /* Software pctl */
147 list->list = rfatt_0;
148 list->len = ARRAY_SIZE(rfatt_0);
149 list->min_val = 0;
150 list->max_val = 9;
151 return;
152 }
153 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
154 /* Hardware pctl */
155 list->list = rfatt_1;
156 list->len = ARRAY_SIZE(rfatt_1);
157 list->min_val = 2;
158 list->max_val = 14;
159 return;
160 }
161 /* Hardware pctl */
162 list->list = rfatt_2;
163 list->len = ARRAY_SIZE(rfatt_2);
164 list->min_val = 0;
165 list->max_val = 9;
166}
167
168static void generate_bbatt_list(struct b43_wldev *dev,
169 struct b43_bbatt_list *list)
170{
171 static const struct b43_bbatt bbatt_0[] = {
172 {.att = 0,},
173 {.att = 1,},
174 {.att = 2,},
175 {.att = 3,},
176 {.att = 4,},
177 {.att = 5,},
178 {.att = 6,},
179 {.att = 7,},
180 {.att = 8,},
181 };
182
183 list->list = bbatt_0;
184 list->len = ARRAY_SIZE(bbatt_0);
185 list->min_val = 0;
186 list->max_val = 8;
187}
188
189bool b43_has_hardware_pctl(struct b43_phy *phy)
190{
191 if (!phy->hardware_power_control)
192 return 0;
193 switch (phy->type) {
194 case B43_PHYTYPE_A:
195 if (phy->rev >= 5)
196 return 1;
197 break;
198 case B43_PHYTYPE_G:
199 if (phy->rev >= 6)
200 return 1;
201 break;
202 default:
203 B43_WARN_ON(1);
204 }
205 return 0;
206}
207
208static void b43_shm_clear_tssi(struct b43_wldev *dev)
209{
210 struct b43_phy *phy = &dev->phy;
211
212 switch (phy->type) {
213 case B43_PHYTYPE_A:
214 b43_shm_write16(dev, B43_SHM_SHARED, 0x0068, 0x7F7F);
215 b43_shm_write16(dev, B43_SHM_SHARED, 0x006a, 0x7F7F);
216 break;
217 case B43_PHYTYPE_B:
218 case B43_PHYTYPE_G:
219 b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F);
220 b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F);
221 b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F);
222 b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F);
223 break;
224 }
225}
226
227void b43_raw_phy_lock(struct b43_wldev *dev)
228{
229 struct b43_phy *phy = &dev->phy;
230
231 B43_WARN_ON(!irqs_disabled());
232
233 /* We had a check for MACCTL==0 here, but I think that doesn't
234 * make sense, as MACCTL is never 0 when this is called.
235 * --mb */
236 B43_WARN_ON(b43_read32(dev, B43_MMIO_MACCTL) == 0);
237
238 if (dev->dev->id.revision < 3) {
239 b43_mac_suspend(dev);
240 spin_lock(&phy->lock);
241 } else {
242 if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
243 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
244 }
245 phy->locked = 1;
246}
247
248void b43_raw_phy_unlock(struct b43_wldev *dev)
249{
250 struct b43_phy *phy = &dev->phy;
251
252 B43_WARN_ON(!irqs_disabled());
253 if (dev->dev->id.revision < 3) {
254 if (phy->locked) {
255 spin_unlock(&phy->lock);
256 b43_mac_enable(dev);
257 }
258 } else {
259 if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
260 b43_power_saving_ctl_bits(dev, 0);
261 }
262 phy->locked = 0;
263}
264
265/* Different PHYs require different register routing flags.
266 * This adjusts (and does sanity checks on) the routing flags.
267 */
268static inline u16 adjust_phyreg_for_phytype(struct b43_phy *phy,
269 u16 offset, struct b43_wldev *dev)
270{
271 if (phy->type == B43_PHYTYPE_A) {
272 /* OFDM registers are base-registers for the A-PHY. */
273 offset &= ~B43_PHYROUTE_OFDM_GPHY;
274 }
275 if (offset & B43_PHYROUTE_EXT_GPHY) {
276 /* Ext-G registers are only available on G-PHYs */
277 if (phy->type != B43_PHYTYPE_G) {
278 b43dbg(dev->wl, "EXT-G PHY access at "
279 "0x%04X on %u type PHY\n", offset, phy->type);
280 }
281 }
282
283 return offset;
284}
285
286u16 b43_phy_read(struct b43_wldev * dev, u16 offset)
287{
288 struct b43_phy *phy = &dev->phy;
289
290 offset = adjust_phyreg_for_phytype(phy, offset, dev);
291 b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);
292 return b43_read16(dev, B43_MMIO_PHY_DATA);
293}
294
295void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val)
296{
297 struct b43_phy *phy = &dev->phy;
298
299 offset = adjust_phyreg_for_phytype(phy, offset, dev);
300 b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);
301 mmiowb();
302 b43_write16(dev, B43_MMIO_PHY_DATA, val);
303}
304
305static void b43_radio_set_txpower_a(struct b43_wldev *dev, u16 txpower);
306
307/* Adjust the transmission power output (G-PHY) */
308void b43_set_txpower_g(struct b43_wldev *dev,
309 const struct b43_bbatt *bbatt,
310 const struct b43_rfatt *rfatt, u8 tx_control)
311{
312 struct b43_phy *phy = &dev->phy;
313 struct b43_txpower_lo_control *lo = phy->lo_control;
314 u16 bb, rf;
315 u16 tx_bias, tx_magn;
316
317 bb = bbatt->att;
318 rf = rfatt->att;
319 tx_bias = lo->tx_bias;
320 tx_magn = lo->tx_magn;
321 if (unlikely(tx_bias == 0xFF))
322 tx_bias = 0;
323
324 /* Save the values for later */
325 phy->tx_control = tx_control;
326 memcpy(&phy->rfatt, rfatt, sizeof(*rfatt));
327 memcpy(&phy->bbatt, bbatt, sizeof(*bbatt));
328
329 if (b43_debug(dev, B43_DBG_XMITPOWER)) {
330 b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), "
331 "rfatt(%u), tx_control(0x%02X), "
332 "tx_bias(0x%02X), tx_magn(0x%02X)\n",
333 bb, rf, tx_control, tx_bias, tx_magn);
334 }
335
336 b43_phy_set_baseband_attenuation(dev, bb);
337 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf);
338 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
339 b43_radio_write16(dev, 0x43,
340 (rf & 0x000F) | (tx_control & 0x0070));
341 } else {
342 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
343 & 0xFFF0) | (rf & 0x000F));
344 b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)
345 & ~0x0070) | (tx_control &
346 0x0070));
347 }
348 if (has_tx_magnification(phy)) {
349 b43_radio_write16(dev, 0x52, tx_magn | tx_bias);
350 } else {
351 b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)
352 & 0xFFF0) | (tx_bias & 0x000F));
353 }
354 if (phy->type == B43_PHYTYPE_G)
355 b43_lo_g_adjust(dev);
356}
357
358static void default_baseband_attenuation(struct b43_wldev *dev,
359 struct b43_bbatt *bb)
360{
361 struct b43_phy *phy = &dev->phy;
362
363 if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
364 bb->att = 0;
365 else
366 bb->att = 2;
367}
368
369static void default_radio_attenuation(struct b43_wldev *dev,
370 struct b43_rfatt *rf)
371{
372 struct ssb_bus *bus = dev->dev->bus;
373 struct b43_phy *phy = &dev->phy;
374
375 rf->with_padmix = 0;
376
377 if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
378 bus->boardinfo.type == SSB_BOARD_BCM4309G) {
379 if (bus->boardinfo.rev < 0x43) {
380 rf->att = 2;
381 return;
382 } else if (bus->boardinfo.rev < 0x51) {
383 rf->att = 3;
384 return;
385 }
386 }
387
388 if (phy->type == B43_PHYTYPE_A) {
389 rf->att = 0x60;
390 return;
391 }
392
393 switch (phy->radio_ver) {
394 case 0x2053:
395 switch (phy->radio_rev) {
396 case 1:
397 rf->att = 6;
398 return;
399 }
400 break;
401 case 0x2050:
402 switch (phy->radio_rev) {
403 case 0:
404 rf->att = 5;
405 return;
406 case 1:
407 if (phy->type == B43_PHYTYPE_G) {
408 if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
409 && bus->boardinfo.type == SSB_BOARD_BCM4309G
410 && bus->boardinfo.rev >= 30)
411 rf->att = 3;
412 else if (bus->boardinfo.vendor ==
413 SSB_BOARDVENDOR_BCM
414 && bus->boardinfo.type ==
415 SSB_BOARD_BU4306)
416 rf->att = 3;
417 else
418 rf->att = 1;
419 } else {
420 if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
421 && bus->boardinfo.type == SSB_BOARD_BCM4309G
422 && bus->boardinfo.rev >= 30)
423 rf->att = 7;
424 else
425 rf->att = 6;
426 }
427 return;
428 case 2:
429 if (phy->type == B43_PHYTYPE_G) {
430 if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
431 && bus->boardinfo.type == SSB_BOARD_BCM4309G
432 && bus->boardinfo.rev >= 30)
433 rf->att = 3;
434 else if (bus->boardinfo.vendor ==
435 SSB_BOARDVENDOR_BCM
436 && bus->boardinfo.type ==
437 SSB_BOARD_BU4306)
438 rf->att = 5;
439 else if (bus->chip_id == 0x4320)
440 rf->att = 4;
441 else
442 rf->att = 3;
443 } else
444 rf->att = 6;
445 return;
446 case 3:
447 rf->att = 5;
448 return;
449 case 4:
450 case 5:
451 rf->att = 1;
452 return;
453 case 6:
454 case 7:
455 rf->att = 5;
456 return;
457 case 8:
458 rf->att = 0xA;
459 rf->with_padmix = 1;
460 return;
461 case 9:
462 default:
463 rf->att = 5;
464 return;
465 }
466 }
467 rf->att = 5;
468}
469
470static u16 default_tx_control(struct b43_wldev *dev)
471{
472 struct b43_phy *phy = &dev->phy;
473
474 if (phy->radio_ver != 0x2050)
475 return 0;
476 if (phy->radio_rev == 1)
477 return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX;
478 if (phy->radio_rev < 6)
479 return B43_TXCTL_PA2DB;
480 if (phy->radio_rev == 8)
481 return B43_TXCTL_TXMIX;
482 return 0;
483}
484
485/* This func is called "PHY calibrate" in the specs... */
486void b43_phy_early_init(struct b43_wldev *dev)
487{
488 struct b43_phy *phy = &dev->phy;
489 struct b43_txpower_lo_control *lo = phy->lo_control;
490
491 default_baseband_attenuation(dev, &phy->bbatt);
492 default_radio_attenuation(dev, &phy->rfatt);
493 phy->tx_control = (default_tx_control(dev) << 4);
494
495 /* Commit previous writes */
496 b43_read32(dev, B43_MMIO_MACCTL);
497
498 if (phy->type == B43_PHYTYPE_B || phy->type == B43_PHYTYPE_G) {
499 generate_rfatt_list(dev, &lo->rfatt_list);
500 generate_bbatt_list(dev, &lo->bbatt_list);
501 }
502 if (phy->type == B43_PHYTYPE_G && phy->rev == 1) {
503 /* Workaround: Temporarly disable gmode through the early init
504 * phase, as the gmode stuff is not needed for phy rev 1 */
505 phy->gmode = 0;
506 b43_wireless_core_reset(dev, 0);
507 b43_phy_initg(dev);
508 phy->gmode = 1;
509 b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
510 }
511}
512
513/* GPHY_TSSI_Power_Lookup_Table_Init */
514static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev)
515{
516 struct b43_phy *phy = &dev->phy;
517 int i;
518 u16 value;
519
520 for (i = 0; i < 32; i++)
521 b43_ofdmtab_write16(dev, 0x3C20, i, phy->tssi2dbm[i]);
522 for (i = 32; i < 64; i++)
523 b43_ofdmtab_write16(dev, 0x3C00, i - 32, phy->tssi2dbm[i]);
524 for (i = 0; i < 64; i += 2) {
525 value = (u16) phy->tssi2dbm[i];
526 value |= ((u16) phy->tssi2dbm[i + 1]) << 8;
527 b43_phy_write(dev, 0x380 + (i / 2), value);
528 }
529}
530
531/* GPHY_Gain_Lookup_Table_Init */
532static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
533{
534 struct b43_phy *phy = &dev->phy;
535 struct b43_txpower_lo_control *lo = phy->lo_control;
536 u16 nr_written = 0;
537 u16 tmp;
538 u8 rf, bb;
539
540 if (!lo->lo_measured) {
541 b43_phy_write(dev, 0x3FF, 0);
542 return;
543 }
544
545 for (rf = 0; rf < lo->rfatt_list.len; rf++) {
546 for (bb = 0; bb < lo->bbatt_list.len; bb++) {
547 if (nr_written >= 0x40)
548 return;
549 tmp = lo->bbatt_list.list[bb].att;
550 tmp <<= 8;
551 if (phy->radio_rev == 8)
552 tmp |= 0x50;
553 else
554 tmp |= 0x40;
555 tmp |= lo->rfatt_list.list[rf].att;
556 b43_phy_write(dev, 0x3C0 + nr_written, tmp);
557 nr_written++;
558 }
559 }
560}
561
562/* GPHY_DC_Lookup_Table */
563void b43_gphy_dc_lt_init(struct b43_wldev *dev)
564{
565 struct b43_phy *phy = &dev->phy;
566 struct b43_txpower_lo_control *lo = phy->lo_control;
567 struct b43_loctl *loctl0;
568 struct b43_loctl *loctl1;
569 int i;
570 int rf_offset, bb_offset;
571 u16 tmp;
572
573 for (i = 0; i < lo->rfatt_list.len + lo->bbatt_list.len; i += 2) {
574 rf_offset = i / lo->rfatt_list.len;
575 bb_offset = i % lo->rfatt_list.len;
576
577 loctl0 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset],
578 &lo->bbatt_list.list[bb_offset]);
579 if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) {
580 rf_offset = (i + 1) / lo->rfatt_list.len;
581 bb_offset = (i + 1) % lo->rfatt_list.len;
582
583 loctl1 =
584 b43_get_lo_g_ctl(dev,
585 &lo->rfatt_list.list[rf_offset],
586 &lo->bbatt_list.list[bb_offset]);
587 } else
588 loctl1 = loctl0;
589
590 tmp = ((u16) loctl0->q & 0xF);
591 tmp |= ((u16) loctl0->i & 0xF) << 4;
592 tmp |= ((u16) loctl1->q & 0xF) << 8;
593 tmp |= ((u16) loctl1->i & 0xF) << 12; //FIXME?
594 b43_phy_write(dev, 0x3A0 + (i / 2), tmp);
595 }
596}
597
598static void hardware_pctl_init_aphy(struct b43_wldev *dev)
599{
600 //TODO
601}
602
603static void hardware_pctl_init_gphy(struct b43_wldev *dev)
604{
605 struct b43_phy *phy = &dev->phy;
606
607 b43_phy_write(dev, 0x0036, (b43_phy_read(dev, 0x0036) & 0xFFC0)
608 | (phy->tgt_idle_tssi - phy->cur_idle_tssi));
609 b43_phy_write(dev, 0x0478, (b43_phy_read(dev, 0x0478) & 0xFF00)
610 | (phy->tgt_idle_tssi - phy->cur_idle_tssi));
611 b43_gphy_tssi_power_lt_init(dev);
612 b43_gphy_gain_lt_init(dev);
613 b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) & 0xFFBF);
614 b43_phy_write(dev, 0x0014, 0x0000);
615
616 B43_WARN_ON(phy->rev < 6);
617 b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478)
618 | 0x0800);
619 b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478)
620 & 0xFEFF);
621 b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801)
622 & 0xFFBF);
623
624 b43_gphy_dc_lt_init(dev);
625}
626
627/* HardwarePowerControl init for A and G PHY */
628static void b43_hardware_pctl_init(struct b43_wldev *dev)
629{
630 struct b43_phy *phy = &dev->phy;
631
632 if (!b43_has_hardware_pctl(phy)) {
633 /* No hardware power control */
634 b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL);
635 return;
636 }
637 /* Init the hwpctl related hardware */
638 switch (phy->type) {
639 case B43_PHYTYPE_A:
640 hardware_pctl_init_aphy(dev);
641 break;
642 case B43_PHYTYPE_G:
643 hardware_pctl_init_gphy(dev);
644 break;
645 default:
646 B43_WARN_ON(1);
647 }
648 /* Enable hardware pctl in firmware. */
649 b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);
650}
651
652static void b43_hardware_pctl_early_init(struct b43_wldev *dev)
653{
654 struct b43_phy *phy = &dev->phy;
655
656 if (!b43_has_hardware_pctl(phy)) {
657 b43_phy_write(dev, 0x047A, 0xC111);
658 return;
659 }
660
661 b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) & 0xFEFF);
662 b43_phy_write(dev, 0x002F, 0x0202);
663 b43_phy_write(dev, 0x047C, b43_phy_read(dev, 0x047C) | 0x0002);
664 b43_phy_write(dev, 0x047A, b43_phy_read(dev, 0x047A) | 0xF000);
665 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
666 b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A)
667 & 0xFF0F) | 0x0010);
668 b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D)
669 | 0x8000);
670 b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E)
671 & 0xFFC0) | 0x0010);
672 b43_phy_write(dev, 0x002E, 0xC07F);
673 b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
674 | 0x0400);
675 } else {
676 b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
677 | 0x0200);
678 b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
679 | 0x0400);
680 b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D)
681 & 0x7FFF);
682 b43_phy_write(dev, 0x004F, b43_phy_read(dev, 0x004F)
683 & 0xFFFE);
684 b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E)
685 & 0xFFC0) | 0x0010);
686 b43_phy_write(dev, 0x002E, 0xC07F);
687 b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A)
688 & 0xFF0F) | 0x0010);
689 }
690}
691
692/* Intialize B/G PHY power control
693 * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
694 */
695static void b43_phy_init_pctl(struct b43_wldev *dev)
696{
697 struct ssb_bus *bus = dev->dev->bus;
698 struct b43_phy *phy = &dev->phy;
699 struct b43_rfatt old_rfatt;
700 struct b43_bbatt old_bbatt;
701 u8 old_tx_control = 0;
702
703 if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
704 (bus->boardinfo.type == SSB_BOARD_BU4306))
705 return;
706
707 b43_phy_write(dev, 0x0028, 0x8018);
708
709 /* This does something with the Analog... */
710 b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0)
711 & 0xFFDF);
712
713 if (phy->type == B43_PHYTYPE_G && !phy->gmode)
714 return;
715 b43_hardware_pctl_early_init(dev);
716 if (phy->cur_idle_tssi == 0) {
717 if (phy->radio_ver == 0x2050 && phy->analog == 0) {
718 b43_radio_write16(dev, 0x0076,
719 (b43_radio_read16(dev, 0x0076)
720 & 0x00F7) | 0x0084);
721 } else {
722 struct b43_rfatt rfatt;
723 struct b43_bbatt bbatt;
724
725 memcpy(&old_rfatt, &phy->rfatt, sizeof(old_rfatt));
726 memcpy(&old_bbatt, &phy->bbatt, sizeof(old_bbatt));
727 old_tx_control = phy->tx_control;
728
729 bbatt.att = 11;
730 if (phy->radio_rev == 8) {
731 rfatt.att = 15;
732 rfatt.with_padmix = 1;
733 } else {
734 rfatt.att = 9;
735 rfatt.with_padmix = 0;
736 }
737 b43_set_txpower_g(dev, &bbatt, &rfatt, 0);
738 }
739 b43_dummy_transmission(dev);
740 phy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);
741 if (B43_DEBUG) {
742 /* Current-Idle-TSSI sanity check. */
743 if (abs(phy->cur_idle_tssi - phy->tgt_idle_tssi) >= 20) {
744 b43dbg(dev->wl,
745 "!WARNING! Idle-TSSI phy->cur_idle_tssi "
746 "measuring failed. (cur=%d, tgt=%d). Disabling TX power "
747 "adjustment.\n", phy->cur_idle_tssi,
748 phy->tgt_idle_tssi);
749 phy->cur_idle_tssi = 0;
750 }
751 }
752 if (phy->radio_ver == 0x2050 && phy->analog == 0) {
753 b43_radio_write16(dev, 0x0076,
754 b43_radio_read16(dev, 0x0076)
755 & 0xFF7B);
756 } else {
757 b43_set_txpower_g(dev, &old_bbatt,
758 &old_rfatt, old_tx_control);
759 }
760 }
761 b43_hardware_pctl_init(dev);
762 b43_shm_clear_tssi(dev);
763}
764
765static void b43_phy_agcsetup(struct b43_wldev *dev)
766{
767 struct b43_phy *phy = &dev->phy;
768 u16 offset = 0x0000;
769
770 if (phy->rev == 1)
771 offset = 0x4C00;
772
773 b43_ofdmtab_write16(dev, offset, 0, 0x00FE);
774 b43_ofdmtab_write16(dev, offset, 1, 0x000D);
775 b43_ofdmtab_write16(dev, offset, 2, 0x0013);
776 b43_ofdmtab_write16(dev, offset, 3, 0x0019);
777
778 if (phy->rev == 1) {
779 b43_ofdmtab_write16(dev, 0x1800, 0, 0x2710);
780 b43_ofdmtab_write16(dev, 0x1801, 0, 0x9B83);
781 b43_ofdmtab_write16(dev, 0x1802, 0, 0x9B83);
782 b43_ofdmtab_write16(dev, 0x1803, 0, 0x0F8D);
783 b43_phy_write(dev, 0x0455, 0x0004);
784 }
785
786 b43_phy_write(dev, 0x04A5, (b43_phy_read(dev, 0x04A5)
787 & 0x00FF) | 0x5700);
788 b43_phy_write(dev, 0x041A, (b43_phy_read(dev, 0x041A)
789 & 0xFF80) | 0x000F);
790 b43_phy_write(dev, 0x041A, (b43_phy_read(dev, 0x041A)
791 & 0xC07F) | 0x2B80);
792 b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C)
793 & 0xF0FF) | 0x0300);
794
795 b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A)
796 | 0x0008);
797
798 b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0)
799 & 0xFFF0) | 0x0008);
800 b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1)
801 & 0xF0FF) | 0x0600);
802 b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2)
803 & 0xF0FF) | 0x0700);
804 b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0)
805 & 0xF0FF) | 0x0100);
806
807 if (phy->rev == 1) {
808 b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2)
809 & 0xFFF0) | 0x0007);
810 }
811
812 b43_phy_write(dev, 0x0488, (b43_phy_read(dev, 0x0488)
813 & 0xFF00) | 0x001C);
814 b43_phy_write(dev, 0x0488, (b43_phy_read(dev, 0x0488)
815 & 0xC0FF) | 0x0200);
816 b43_phy_write(dev, 0x0496, (b43_phy_read(dev, 0x0496)
817 & 0xFF00) | 0x001C);
818 b43_phy_write(dev, 0x0489, (b43_phy_read(dev, 0x0489)
819 & 0xFF00) | 0x0020);
820 b43_phy_write(dev, 0x0489, (b43_phy_read(dev, 0x0489)
821 & 0xC0FF) | 0x0200);
822 b43_phy_write(dev, 0x0482, (b43_phy_read(dev, 0x0482)
823 & 0xFF00) | 0x002E);
824 b43_phy_write(dev, 0x0496, (b43_phy_read(dev, 0x0496)
825 & 0x00FF) | 0x1A00);
826 b43_phy_write(dev, 0x0481, (b43_phy_read(dev, 0x0481)
827 & 0xFF00) | 0x0028);
828 b43_phy_write(dev, 0x0481, (b43_phy_read(dev, 0x0481)
829 & 0x00FF) | 0x2C00);
830
831 if (phy->rev == 1) {
832 b43_phy_write(dev, 0x0430, 0x092B);
833 b43_phy_write(dev, 0x041B, (b43_phy_read(dev, 0x041B)
834 & 0xFFE1) | 0x0002);
835 } else {
836 b43_phy_write(dev, 0x041B, b43_phy_read(dev, 0x041B)
837 & 0xFFE1);
838 b43_phy_write(dev, 0x041F, 0x287A);
839 b43_phy_write(dev, 0x0420, (b43_phy_read(dev, 0x0420)
840 & 0xFFF0) | 0x0004);
841 }
842
843 if (phy->rev >= 6) {
844 b43_phy_write(dev, 0x0422, 0x287A);
845 b43_phy_write(dev, 0x0420, (b43_phy_read(dev, 0x0420)
846 & 0x0FFF) | 0x3000);
847 }
848
849 b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8)
850 & 0x8080) | 0x7874);
851 b43_phy_write(dev, 0x048E, 0x1C00);
852
853 offset = 0x0800;
854 if (phy->rev == 1) {
855 offset = 0x5400;
856 b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB)
857 & 0xF0FF) | 0x0600);
858 b43_phy_write(dev, 0x048B, 0x005E);
859 b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C)
860 & 0xFF00) | 0x001E);
861 b43_phy_write(dev, 0x048D, 0x0002);
862 }
863 b43_ofdmtab_write16(dev, offset, 0, 0x00);
864 b43_ofdmtab_write16(dev, offset, 1, 0x07);
865 b43_ofdmtab_write16(dev, offset, 2, 0x10);
866 b43_ofdmtab_write16(dev, offset, 3, 0x1C);
867
868 if (phy->rev >= 6) {
869 b43_phy_write(dev, 0x0426, b43_phy_read(dev, 0x0426)
870 & 0xFFFC);
871 b43_phy_write(dev, 0x0426, b43_phy_read(dev, 0x0426)
872 & 0xEFFF);
873 }
874}
875
876static void b43_phy_setupg(struct b43_wldev *dev)
877{
878 struct ssb_bus *bus = dev->dev->bus;
879 struct b43_phy *phy = &dev->phy;
880 u16 i;
881
882 B43_WARN_ON(phy->type != B43_PHYTYPE_G);
883 if (phy->rev == 1) {
884 b43_phy_write(dev, 0x0406, 0x4F19);
885 b43_phy_write(dev, B43_PHY_G_CRS,
886 (b43_phy_read(dev, B43_PHY_G_CRS) & 0xFC3F) |
887 0x0340);
888 b43_phy_write(dev, 0x042C, 0x005A);
889 b43_phy_write(dev, 0x0427, 0x001A);
890
891 for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++)
892 b43_ofdmtab_write16(dev, 0x5800, i,
893 b43_tab_finefreqg[i]);
894 for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++)
895 b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noiseg1[i]);
896 for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
897 b43_ofdmtab_write16(dev, 0x2000, i, b43_tab_rotor[i]);
898 } else {
899 /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
900 b43_nrssi_hw_write(dev, 0xBA98, (s16) 0x7654);
901
902 if (phy->rev == 2) {
903 b43_phy_write(dev, 0x04C0, 0x1861);
904 b43_phy_write(dev, 0x04C1, 0x0271);
905 } else if (phy->rev > 2) {
906 b43_phy_write(dev, 0x04C0, 0x0098);
907 b43_phy_write(dev, 0x04C1, 0x0070);
908 b43_phy_write(dev, 0x04C9, 0x0080);
909 }
910 b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x800);
911
912 for (i = 0; i < 64; i++)
913 b43_ofdmtab_write16(dev, 0x4000, i, i);
914 for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++)
915 b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noiseg2[i]);
916 }
917
918 if (phy->rev <= 2)
919 for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
920 b43_ofdmtab_write16(dev, 0x1400, i,
921 b43_tab_noisescaleg1[i]);
922 else if ((phy->rev >= 7) && (b43_phy_read(dev, 0x0449) & 0x0200))
923 for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
924 b43_ofdmtab_write16(dev, 0x1400, i,
925 b43_tab_noisescaleg3[i]);
926 else
927 for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
928 b43_ofdmtab_write16(dev, 0x1400, i,
929 b43_tab_noisescaleg2[i]);
930
931 if (phy->rev == 2)
932 for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++)
933 b43_ofdmtab_write16(dev, 0x5000, i,
934 b43_tab_sigmasqr1[i]);
935 else if ((phy->rev > 2) && (phy->rev <= 8))
936 for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++)
937 b43_ofdmtab_write16(dev, 0x5000, i,
938 b43_tab_sigmasqr2[i]);
939
940 if (phy->rev == 1) {
941 for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
942 b43_ofdmtab_write32(dev, 0x2400, i, b43_tab_retard[i]);
943 for (i = 4; i < 20; i++)
944 b43_ofdmtab_write16(dev, 0x5400, i, 0x0020);
945 b43_phy_agcsetup(dev);
946
947 if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
948 (bus->boardinfo.type == SSB_BOARD_BU4306) &&
949 (bus->boardinfo.rev == 0x17))
950 return;
951
952 b43_ofdmtab_write16(dev, 0x5001, 0, 0x0002);
953 b43_ofdmtab_write16(dev, 0x5002, 0, 0x0001);
954 } else {
955 for (i = 0; i < 0x20; i++)
956 b43_ofdmtab_write16(dev, 0x1000, i, 0x0820);
957 b43_phy_agcsetup(dev);
958 b43_phy_read(dev, 0x0400); /* dummy read */
959 b43_phy_write(dev, 0x0403, 0x1000);
960 b43_ofdmtab_write16(dev, 0x3C02, 0, 0x000F);
961 b43_ofdmtab_write16(dev, 0x3C03, 0, 0x0014);
962
963 if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
964 (bus->boardinfo.type == SSB_BOARD_BU4306) &&
965 (bus->boardinfo.rev == 0x17))
966 return;
967
968 b43_ofdmtab_write16(dev, 0x0401, 0, 0x0002);
969 b43_ofdmtab_write16(dev, 0x0402, 0, 0x0001);
970 }
971}
972
973/* Initialize the noisescaletable for APHY */
974static void b43_phy_init_noisescaletbl(struct b43_wldev *dev)
975{
976 struct b43_phy *phy = &dev->phy;
977 int i;
978
979 for (i = 0; i < 12; i++) {
980 if (phy->rev == 2)
981 b43_ofdmtab_write16(dev, 0x1400, i, 0x6767);
982 else
983 b43_ofdmtab_write16(dev, 0x1400, i, 0x2323);
984 }
985 if (phy->rev == 2)
986 b43_ofdmtab_write16(dev, 0x1400, i, 0x6700);
987 else
988 b43_ofdmtab_write16(dev, 0x1400, i, 0x2300);
989 for (i = 0; i < 11; i++) {
990 if (phy->rev == 2)
991 b43_ofdmtab_write16(dev, 0x1400, i, 0x6767);
992 else
993 b43_ofdmtab_write16(dev, 0x1400, i, 0x2323);
994 }
995 if (phy->rev == 2)
996 b43_ofdmtab_write16(dev, 0x1400, i, 0x0067);
997 else
998 b43_ofdmtab_write16(dev, 0x1400, i, 0x0023);
999}
1000
1001static void b43_phy_setupa(struct b43_wldev *dev)
1002{
1003 struct b43_phy *phy = &dev->phy;
1004 u16 i;
1005
1006 B43_WARN_ON(phy->type != B43_PHYTYPE_A);
1007 switch (phy->rev) {
1008 case 2:
1009 b43_phy_write(dev, 0x008E, 0x3800);
1010 b43_phy_write(dev, 0x0035, 0x03FF);
1011 b43_phy_write(dev, 0x0036, 0x0400);
1012
1013 b43_ofdmtab_write16(dev, 0x3807, 0, 0x0051);
1014
1015 b43_phy_write(dev, 0x001C, 0x0FF9);
1016 b43_phy_write(dev, 0x0020, b43_phy_read(dev, 0x0020) & 0xFF0F);
1017 b43_ofdmtab_write16(dev, 0x3C0C, 0, 0x07BF);
1018 b43_radio_write16(dev, 0x0002, 0x07BF);
1019
1020 b43_phy_write(dev, 0x0024, 0x4680);
1021 b43_phy_write(dev, 0x0020, 0x0003);
1022 b43_phy_write(dev, 0x001D, 0x0F40);
1023 b43_phy_write(dev, 0x001F, 0x1C00);
1024
1025 b43_phy_write(dev, 0x002A, (b43_phy_read(dev, 0x002A)
1026 & 0x00FF) | 0x0400);
1027 b43_phy_write(dev, 0x002B, b43_phy_read(dev, 0x002B)
1028 & 0xFBFF);
1029 b43_phy_write(dev, 0x008E, 0x58C1);
1030
1031 b43_ofdmtab_write16(dev, 0x0803, 0, 0x000F);
1032 b43_ofdmtab_write16(dev, 0x0804, 0, 0x001F);
1033 b43_ofdmtab_write16(dev, 0x0805, 0, 0x002A);
1034 b43_ofdmtab_write16(dev, 0x0805, 0, 0x0030);
1035 b43_ofdmtab_write16(dev, 0x0807, 0, 0x003A);
1036
1037 b43_ofdmtab_write16(dev, 0x0000, 0, 0x0013);
1038 b43_ofdmtab_write16(dev, 0x0000, 1, 0x0013);
1039 b43_ofdmtab_write16(dev, 0x0000, 2, 0x0013);
1040 b43_ofdmtab_write16(dev, 0x0000, 3, 0x0013);
1041 b43_ofdmtab_write16(dev, 0x0000, 4, 0x0015);
1042 b43_ofdmtab_write16(dev, 0x0000, 5, 0x0015);
1043 b43_ofdmtab_write16(dev, 0x0000, 6, 0x0019);
1044
1045 b43_ofdmtab_write16(dev, 0x0404, 0, 0x0003);
1046 b43_ofdmtab_write16(dev, 0x0405, 0, 0x0003);
1047 b43_ofdmtab_write16(dev, 0x0406, 0, 0x0007);
1048
1049 for (i = 0; i < 16; i++)
1050 b43_ofdmtab_write16(dev, 0x4000, i, (0x8 + i) & 0x000F);
1051
1052 b43_ofdmtab_write16(dev, 0x3003, 0, 0x1044);
1053 b43_ofdmtab_write16(dev, 0x3004, 0, 0x7201);
1054 b43_ofdmtab_write16(dev, 0x3006, 0, 0x0040);
1055 b43_ofdmtab_write16(dev, 0x3001, 0,
1056 (b43_ofdmtab_read16(dev, 0x3001, 0) &
1057 0x0010) | 0x0008);
1058
1059 for (i = 0; i < B43_TAB_FINEFREQA_SIZE; i++)
1060 b43_ofdmtab_write16(dev, 0x5800, i,
1061 b43_tab_finefreqa[i]);
1062 for (i = 0; i < B43_TAB_NOISEA2_SIZE; i++)
1063 b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noisea2[i]);
1064 for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
1065 b43_ofdmtab_write32(dev, 0x2000, i, b43_tab_rotor[i]);
1066 b43_phy_init_noisescaletbl(dev);
1067 for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
1068 b43_ofdmtab_write32(dev, 0x2400, i, b43_tab_retard[i]);
1069 break;
1070 case 3:
1071 for (i = 0; i < 64; i++)
1072 b43_ofdmtab_write16(dev, 0x4000, i, i);
1073
1074 b43_ofdmtab_write16(dev, 0x3807, 0, 0x0051);
1075
1076 b43_phy_write(dev, 0x001C, 0x0FF9);
1077 b43_phy_write(dev, 0x0020, b43_phy_read(dev, 0x0020) & 0xFF0F);
1078 b43_radio_write16(dev, 0x0002, 0x07BF);
1079
1080 b43_phy_write(dev, 0x0024, 0x4680);
1081 b43_phy_write(dev, 0x0020, 0x0003);
1082 b43_phy_write(dev, 0x001D, 0x0F40);
1083 b43_phy_write(dev, 0x001F, 0x1C00);
1084 b43_phy_write(dev, 0x002A, (b43_phy_read(dev, 0x002A)
1085 & 0x00FF) | 0x0400);
1086
1087 b43_ofdmtab_write16(dev, 0x3000, 1,
1088 (b43_ofdmtab_read16(dev, 0x3000, 1)
1089 & 0x0010) | 0x0008);
1090 for (i = 0; i < B43_TAB_NOISEA3_SIZE; i++) {
1091 b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noisea3[i]);
1092 }
1093 b43_phy_init_noisescaletbl(dev);
1094 for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) {
1095 b43_ofdmtab_write16(dev, 0x5000, i,
1096 b43_tab_sigmasqr1[i]);
1097 }
1098
1099 b43_phy_write(dev, 0x0003, 0x1808);
1100
1101 b43_ofdmtab_write16(dev, 0x0803, 0, 0x000F);
1102 b43_ofdmtab_write16(dev, 0x0804, 0, 0x001F);
1103 b43_ofdmtab_write16(dev, 0x0805, 0, 0x002A);
1104 b43_ofdmtab_write16(dev, 0x0805, 0, 0x0030);
1105 b43_ofdmtab_write16(dev, 0x0807, 0, 0x003A);
1106
1107 b43_ofdmtab_write16(dev, 0x0000, 0, 0x0013);
1108 b43_ofdmtab_write16(dev, 0x0001, 0, 0x0013);
1109 b43_ofdmtab_write16(dev, 0x0002, 0, 0x0013);
1110 b43_ofdmtab_write16(dev, 0x0003, 0, 0x0013);
1111 b43_ofdmtab_write16(dev, 0x0004, 0, 0x0015);
1112 b43_ofdmtab_write16(dev, 0x0005, 0, 0x0015);
1113 b43_ofdmtab_write16(dev, 0x0006, 0, 0x0019);
1114
1115 b43_ofdmtab_write16(dev, 0x0404, 0, 0x0003);
1116 b43_ofdmtab_write16(dev, 0x0405, 0, 0x0003);
1117 b43_ofdmtab_write16(dev, 0x0406, 0, 0x0007);
1118
1119 b43_ofdmtab_write16(dev, 0x3C02, 0, 0x000F);
1120 b43_ofdmtab_write16(dev, 0x3C03, 0, 0x0014);
1121 break;
1122 default:
1123 B43_WARN_ON(1);
1124 }
1125}
1126
1127/* Initialize APHY. This is also called for the GPHY in some cases. */
1128static void b43_phy_inita(struct b43_wldev *dev)
1129{
1130 struct ssb_bus *bus = dev->dev->bus;
1131 struct b43_phy *phy = &dev->phy;
1132 u16 tval;
1133
1134 might_sleep();
1135
1136 if (phy->type == B43_PHYTYPE_A) {
1137 b43_phy_setupa(dev);
1138 } else {
1139 b43_phy_setupg(dev);
1140 if (phy->gmode &&
1141 (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL))
1142 b43_phy_write(dev, 0x046E, 0x03CF);
1143 return;
1144 }
1145
1146 b43_phy_write(dev, B43_PHY_A_CRS,
1147 (b43_phy_read(dev, B43_PHY_A_CRS) & 0xF83C) | 0x0340);
1148 b43_phy_write(dev, 0x0034, 0x0001);
1149
1150 //TODO: RSSI AGC
1151 b43_phy_write(dev, B43_PHY_A_CRS,
1152 b43_phy_read(dev, B43_PHY_A_CRS) | (1 << 14));
1153 b43_radio_init2060(dev);
1154
1155 if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
1156 ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
1157 (bus->boardinfo.type == SSB_BOARD_BU4309))) {
1158 if (phy->lofcal == 0xFFFF) {
1159 //TODO: LOF Cal
1160 b43_radio_set_tx_iq(dev);
1161 } else
1162 b43_radio_write16(dev, 0x001E, phy->lofcal);
1163 }
1164
1165 b43_phy_write(dev, 0x007A, 0xF111);
1166
1167 if (phy->cur_idle_tssi == 0) {
1168 b43_radio_write16(dev, 0x0019, 0x0000);
1169 b43_radio_write16(dev, 0x0017, 0x0020);
1170
1171 tval = b43_ofdmtab_read16(dev, 0x3001, 0);
1172 if (phy->rev == 1) {
1173 b43_ofdmtab_write16(dev, 0x3001, 0,
1174 (b43_ofdmtab_read16(dev, 0x3001, 0)
1175 & 0xFF87)
1176 | 0x0058);
1177 } else {
1178 b43_ofdmtab_write16(dev, 0x3001, 0,
1179 (b43_ofdmtab_read16(dev, 0x3001, 0)
1180 & 0xFFC3)
1181 | 0x002C);
1182 }
1183 b43_dummy_transmission(dev);
1184 phy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_A_PCTL);
1185 b43_ofdmtab_write16(dev, 0x3001, 0, tval);
1186
1187 b43_radio_set_txpower_a(dev, 0x0018);
1188 }
1189 b43_shm_clear_tssi(dev);
1190}
1191
1192static void b43_phy_initb2(struct b43_wldev *dev)
1193{
1194 struct b43_phy *phy = &dev->phy;
1195 u16 offset, val;
1196
1197 b43_write16(dev, 0x03EC, 0x3F22);
1198 b43_phy_write(dev, 0x0020, 0x301C);
1199 b43_phy_write(dev, 0x0026, 0x0000);
1200 b43_phy_write(dev, 0x0030, 0x00C6);
1201 b43_phy_write(dev, 0x0088, 0x3E00);
1202 val = 0x3C3D;
1203 for (offset = 0x0089; offset < 0x00A7; offset++) {
1204 b43_phy_write(dev, offset, val);
1205 val -= 0x0202;
1206 }
1207 b43_phy_write(dev, 0x03E4, 0x3000);
1208 if (phy->channel == 0xFF)
1209 b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 0);
1210 else
1211 b43_radio_selectchannel(dev, phy->channel, 0);
1212 if (phy->radio_ver != 0x2050) {
1213 b43_radio_write16(dev, 0x0075, 0x0080);
1214 b43_radio_write16(dev, 0x0079, 0x0081);
1215 }
1216 b43_radio_write16(dev, 0x0050, 0x0020);
1217 b43_radio_write16(dev, 0x0050, 0x0023);
1218 if (phy->radio_ver == 0x2050) {
1219 b43_radio_write16(dev, 0x0050, 0x0020);
1220 b43_radio_write16(dev, 0x005A, 0x0070);
1221 b43_radio_write16(dev, 0x005B, 0x007B);
1222 b43_radio_write16(dev, 0x005C, 0x00B0);
1223 b43_radio_write16(dev, 0x007A, 0x000F);
1224 b43_phy_write(dev, 0x0038, 0x0677);
1225 b43_radio_init2050(dev);
1226 }
1227 b43_phy_write(dev, 0x0014, 0x0080);
1228 b43_phy_write(dev, 0x0032, 0x00CA);
1229 b43_phy_write(dev, 0x0032, 0x00CC);
1230 b43_phy_write(dev, 0x0035, 0x07C2);
1231 b43_lo_b_measure(dev);
1232 b43_phy_write(dev, 0x0026, 0xCC00);
1233 if (phy->radio_ver != 0x2050)
1234 b43_phy_write(dev, 0x0026, 0xCE00);
1235 b43_write16(dev, B43_MMIO_CHANNEL_EXT, 0x1000);
1236 b43_phy_write(dev, 0x002A, 0x88A3);
1237 if (phy->radio_ver != 0x2050)
1238 b43_phy_write(dev, 0x002A, 0x88C2);
1239 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
1240 b43_phy_init_pctl(dev);
1241}
1242
1243static void b43_phy_initb4(struct b43_wldev *dev)
1244{
1245 struct b43_phy *phy = &dev->phy;
1246 u16 offset, val;
1247
1248 b43_write16(dev, 0x03EC, 0x3F22);
1249 b43_phy_write(dev, 0x0020, 0x301C);
1250 b43_phy_write(dev, 0x0026, 0x0000);
1251 b43_phy_write(dev, 0x0030, 0x00C6);
1252 b43_phy_write(dev, 0x0088, 0x3E00);
1253 val = 0x3C3D;
1254 for (offset = 0x0089; offset < 0x00A7; offset++) {
1255 b43_phy_write(dev, offset, val);
1256 val -= 0x0202;
1257 }
1258 b43_phy_write(dev, 0x03E4, 0x3000);
1259 if (phy->channel == 0xFF)
1260 b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 0);
1261 else
1262 b43_radio_selectchannel(dev, phy->channel, 0);
1263 if (phy->radio_ver != 0x2050) {
1264 b43_radio_write16(dev, 0x0075, 0x0080);
1265 b43_radio_write16(dev, 0x0079, 0x0081);
1266 }
1267 b43_radio_write16(dev, 0x0050, 0x0020);
1268 b43_radio_write16(dev, 0x0050, 0x0023);
1269 if (phy->radio_ver == 0x2050) {
1270 b43_radio_write16(dev, 0x0050, 0x0020);
1271 b43_radio_write16(dev, 0x005A, 0x0070);
1272 b43_radio_write16(dev, 0x005B, 0x007B);
1273 b43_radio_write16(dev, 0x005C, 0x00B0);
1274 b43_radio_write16(dev, 0x007A, 0x000F);
1275 b43_phy_write(dev, 0x0038, 0x0677);
1276 b43_radio_init2050(dev);
1277 }
1278 b43_phy_write(dev, 0x0014, 0x0080);
1279 b43_phy_write(dev, 0x0032, 0x00CA);
1280 if (phy->radio_ver == 0x2050)
1281 b43_phy_write(dev, 0x0032, 0x00E0);
1282 b43_phy_write(dev, 0x0035, 0x07C2);
1283
1284 b43_lo_b_measure(dev);
1285
1286 b43_phy_write(dev, 0x0026, 0xCC00);
1287 if (phy->radio_ver == 0x2050)
1288 b43_phy_write(dev, 0x0026, 0xCE00);
1289 b43_write16(dev, B43_MMIO_CHANNEL_EXT, 0x1100);
1290 b43_phy_write(dev, 0x002A, 0x88A3);
1291 if (phy->radio_ver == 0x2050)
1292 b43_phy_write(dev, 0x002A, 0x88C2);
1293 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
1294 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
1295 b43_calc_nrssi_slope(dev);
1296 b43_calc_nrssi_threshold(dev);
1297 }
1298 b43_phy_init_pctl(dev);
1299}
1300
1301static void b43_phy_initb5(struct b43_wldev *dev)
1302{
1303 struct ssb_bus *bus = dev->dev->bus;
1304 struct b43_phy *phy = &dev->phy;
1305 u16 offset, value;
1306 u8 old_channel;
1307
1308 if (phy->analog == 1) {
1309 b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A)
1310 | 0x0050);
1311 }
1312 if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
1313 (bus->boardinfo.type != SSB_BOARD_BU4306)) {
1314 value = 0x2120;
1315 for (offset = 0x00A8; offset < 0x00C7; offset++) {
1316 b43_phy_write(dev, offset, value);
1317 value += 0x202;
1318 }
1319 }
1320 b43_phy_write(dev, 0x0035, (b43_phy_read(dev, 0x0035) & 0xF0FF)
1321 | 0x0700);
1322 if (phy->radio_ver == 0x2050)
1323 b43_phy_write(dev, 0x0038, 0x0667);
1324
1325 if (phy->gmode || phy->rev >= 2) {
1326 if (phy->radio_ver == 0x2050) {
1327 b43_radio_write16(dev, 0x007A,
1328 b43_radio_read16(dev, 0x007A)
1329 | 0x0020);
1330 b43_radio_write16(dev, 0x0051,
1331 b43_radio_read16(dev, 0x0051)
1332 | 0x0004);
1333 }
1334 b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000);
1335
1336 b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100);
1337 b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000);
1338
1339 b43_phy_write(dev, 0x001C, 0x186A);
1340
1341 b43_phy_write(dev, 0x0013,
1342 (b43_phy_read(dev, 0x0013) & 0x00FF) | 0x1900);
1343 b43_phy_write(dev, 0x0035,
1344 (b43_phy_read(dev, 0x0035) & 0xFFC0) | 0x0064);
1345 b43_phy_write(dev, 0x005D,
1346 (b43_phy_read(dev, 0x005D) & 0xFF80) | 0x000A);
1347 }
1348
1349 if (dev->bad_frames_preempt) {
1350 b43_phy_write(dev, B43_PHY_RADIO_BITFIELD,
1351 b43_phy_read(dev,
1352 B43_PHY_RADIO_BITFIELD) | (1 << 11));
1353 }
1354
1355 if (phy->analog == 1) {
1356 b43_phy_write(dev, 0x0026, 0xCE00);
1357 b43_phy_write(dev, 0x0021, 0x3763);
1358 b43_phy_write(dev, 0x0022, 0x1BC3);
1359 b43_phy_write(dev, 0x0023, 0x06F9);
1360 b43_phy_write(dev, 0x0024, 0x037E);
1361 } else
1362 b43_phy_write(dev, 0x0026, 0xCC00);
1363 b43_phy_write(dev, 0x0030, 0x00C6);
1364 b43_write16(dev, 0x03EC, 0x3F22);
1365
1366 if (phy->analog == 1)
1367 b43_phy_write(dev, 0x0020, 0x3E1C);
1368 else
1369 b43_phy_write(dev, 0x0020, 0x301C);
1370
1371 if (phy->analog == 0)
1372 b43_write16(dev, 0x03E4, 0x3000);
1373
1374 old_channel = phy->channel;
1375 /* Force to channel 7, even if not supported. */
1376 b43_radio_selectchannel(dev, 7, 0);
1377
1378 if (phy->radio_ver != 0x2050) {
1379 b43_radio_write16(dev, 0x0075, 0x0080);
1380 b43_radio_write16(dev, 0x0079, 0x0081);
1381 }
1382
1383 b43_radio_write16(dev, 0x0050, 0x0020);
1384 b43_radio_write16(dev, 0x0050, 0x0023);
1385
1386 if (phy->radio_ver == 0x2050) {
1387 b43_radio_write16(dev, 0x0050, 0x0020);
1388 b43_radio_write16(dev, 0x005A, 0x0070);
1389 }
1390
1391 b43_radio_write16(dev, 0x005B, 0x007B);
1392 b43_radio_write16(dev, 0x005C, 0x00B0);
1393
1394 b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0007);
1395
1396 b43_radio_selectchannel(dev, old_channel, 0);
1397
1398 b43_phy_write(dev, 0x0014, 0x0080);
1399 b43_phy_write(dev, 0x0032, 0x00CA);
1400 b43_phy_write(dev, 0x002A, 0x88A3);
1401
1402 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
1403
1404 if (phy->radio_ver == 0x2050)
1405 b43_radio_write16(dev, 0x005D, 0x000D);
1406
1407 b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004);
1408}
1409
1410static void b43_phy_initb6(struct b43_wldev *dev)
1411{
1412 struct b43_phy *phy = &dev->phy;
1413 u16 offset, val;
1414 u8 old_channel;
1415
1416 b43_phy_write(dev, 0x003E, 0x817A);
1417 b43_radio_write16(dev, 0x007A,
1418 (b43_radio_read16(dev, 0x007A) | 0x0058));
1419 if (phy->radio_rev == 4 || phy->radio_rev == 5) {
1420 b43_radio_write16(dev, 0x51, 0x37);
1421 b43_radio_write16(dev, 0x52, 0x70);
1422 b43_radio_write16(dev, 0x53, 0xB3);
1423 b43_radio_write16(dev, 0x54, 0x9B);
1424 b43_radio_write16(dev, 0x5A, 0x88);
1425 b43_radio_write16(dev, 0x5B, 0x88);
1426 b43_radio_write16(dev, 0x5D, 0x88);
1427 b43_radio_write16(dev, 0x5E, 0x88);
1428 b43_radio_write16(dev, 0x7D, 0x88);
1429 b43_hf_write(dev, b43_hf_read(dev)
1430 | B43_HF_TSSIRPSMW);
1431 }
1432 B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7); /* We had code for these revs here... */
1433 if (phy->radio_rev == 8) {
1434 b43_radio_write16(dev, 0x51, 0);
1435 b43_radio_write16(dev, 0x52, 0x40);
1436 b43_radio_write16(dev, 0x53, 0xB7);
1437 b43_radio_write16(dev, 0x54, 0x98);
1438 b43_radio_write16(dev, 0x5A, 0x88);
1439 b43_radio_write16(dev, 0x5B, 0x6B);
1440 b43_radio_write16(dev, 0x5C, 0x0F);
1441 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_ALTIQ) {
1442 b43_radio_write16(dev, 0x5D, 0xFA);
1443 b43_radio_write16(dev, 0x5E, 0xD8);
1444 } else {
1445 b43_radio_write16(dev, 0x5D, 0xF5);
1446 b43_radio_write16(dev, 0x5E, 0xB8);
1447 }
1448 b43_radio_write16(dev, 0x0073, 0x0003);
1449 b43_radio_write16(dev, 0x007D, 0x00A8);
1450 b43_radio_write16(dev, 0x007C, 0x0001);
1451 b43_radio_write16(dev, 0x007E, 0x0008);
1452 }
1453 val = 0x1E1F;
1454 for (offset = 0x0088; offset < 0x0098; offset++) {
1455 b43_phy_write(dev, offset, val);
1456 val -= 0x0202;
1457 }
1458 val = 0x3E3F;
1459 for (offset = 0x0098; offset < 0x00A8; offset++) {
1460 b43_phy_write(dev, offset, val);
1461 val -= 0x0202;
1462 }
1463 val = 0x2120;
1464 for (offset = 0x00A8; offset < 0x00C8; offset++) {
1465 b43_phy_write(dev, offset, (val & 0x3F3F));
1466 val += 0x0202;
1467 }
1468 if (phy->type == B43_PHYTYPE_G) {
1469 b43_radio_write16(dev, 0x007A,
1470 b43_radio_read16(dev, 0x007A) | 0x0020);
1471 b43_radio_write16(dev, 0x0051,
1472 b43_radio_read16(dev, 0x0051) | 0x0004);
1473 b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100);
1474 b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000);
1475 b43_phy_write(dev, 0x5B, 0);
1476 b43_phy_write(dev, 0x5C, 0);
1477 }
1478
1479 old_channel = phy->channel;
1480 if (old_channel >= 8)
1481 b43_radio_selectchannel(dev, 1, 0);
1482 else
1483 b43_radio_selectchannel(dev, 13, 0);
1484
1485 b43_radio_write16(dev, 0x0050, 0x0020);
1486 b43_radio_write16(dev, 0x0050, 0x0023);
1487 udelay(40);
1488 if (phy->radio_rev < 6 || phy->radio_rev == 8) {
1489 b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C)
1490 | 0x0002));
1491 b43_radio_write16(dev, 0x50, 0x20);
1492 }
1493 if (phy->radio_rev <= 2) {
1494 b43_radio_write16(dev, 0x7C, 0x20);
1495 b43_radio_write16(dev, 0x5A, 0x70);
1496 b43_radio_write16(dev, 0x5B, 0x7B);
1497 b43_radio_write16(dev, 0x5C, 0xB0);
1498 }
1499 b43_radio_write16(dev, 0x007A,
1500 (b43_radio_read16(dev, 0x007A) & 0x00F8) | 0x0007);
1501
1502 b43_radio_selectchannel(dev, old_channel, 0);
1503
1504 b43_phy_write(dev, 0x0014, 0x0200);
1505 if (phy->radio_rev >= 6)
1506 b43_phy_write(dev, 0x2A, 0x88C2);
1507 else
1508 b43_phy_write(dev, 0x2A, 0x8AC0);
1509 b43_phy_write(dev, 0x0038, 0x0668);
1510 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
1511 if (phy->radio_rev <= 5) {
1512 b43_phy_write(dev, 0x5D, (b43_phy_read(dev, 0x5D)
1513 & 0xFF80) | 0x0003);
1514 }
1515 if (phy->radio_rev <= 2)
1516 b43_radio_write16(dev, 0x005D, 0x000D);
1517
1518 if (phy->analog == 4) {
1519 b43_write16(dev, 0x3E4, 9);
1520 b43_phy_write(dev, 0x61, b43_phy_read(dev, 0x61)
1521 & 0x0FFF);
1522 } else {
1523 b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0)
1524 | 0x0004);
1525 }
1526 if (phy->type == B43_PHYTYPE_B) {
1527 b43_write16(dev, 0x03E6, 0x8140);
1528 b43_phy_write(dev, 0x0016, 0x0410);
1529 b43_phy_write(dev, 0x0017, 0x0820);
1530 b43_phy_write(dev, 0x0062, 0x0007);
1531 b43_radio_init2050(dev);
1532 b43_lo_g_measure(dev);
1533 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
1534 b43_calc_nrssi_slope(dev);
1535 b43_calc_nrssi_threshold(dev);
1536 }
1537 b43_phy_init_pctl(dev);
1538 } else if (phy->type == B43_PHYTYPE_G)
1539 b43_write16(dev, 0x03E6, 0x0);
1540}
1541
1542static void b43_calc_loopback_gain(struct b43_wldev *dev)
1543{
1544 struct b43_phy *phy = &dev->phy;
1545 u16 backup_phy[16] = { 0 };
1546 u16 backup_radio[3];
1547 u16 backup_bband;
1548 u16 i, j, loop_i_max;
1549 u16 trsw_rx;
1550 u16 loop1_outer_done, loop1_inner_done;
1551
1552 backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0);
1553 backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);
1554 backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER);
1555 backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL);
1556 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1557 backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER);
1558 backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
1559 }
1560 backup_phy[6] = b43_phy_read(dev, B43_PHY_BASE(0x5A));
1561 backup_phy[7] = b43_phy_read(dev, B43_PHY_BASE(0x59));
1562 backup_phy[8] = b43_phy_read(dev, B43_PHY_BASE(0x58));
1563 backup_phy[9] = b43_phy_read(dev, B43_PHY_BASE(0x0A));
1564 backup_phy[10] = b43_phy_read(dev, B43_PHY_BASE(0x03));
1565 backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK);
1566 backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL);
1567 backup_phy[13] = b43_phy_read(dev, B43_PHY_BASE(0x2B));
1568 backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL);
1569 backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
1570 backup_bband = phy->bbatt.att;
1571 backup_radio[0] = b43_radio_read16(dev, 0x52);
1572 backup_radio[1] = b43_radio_read16(dev, 0x43);
1573 backup_radio[2] = b43_radio_read16(dev, 0x7A);
1574
1575 b43_phy_write(dev, B43_PHY_CRS0,
1576 b43_phy_read(dev, B43_PHY_CRS0) & 0x3FFF);
1577 b43_phy_write(dev, B43_PHY_CCKBBANDCFG,
1578 b43_phy_read(dev, B43_PHY_CCKBBANDCFG) | 0x8000);
1579 b43_phy_write(dev, B43_PHY_RFOVER,
1580 b43_phy_read(dev, B43_PHY_RFOVER) | 0x0002);
1581 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1582 b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFD);
1583 b43_phy_write(dev, B43_PHY_RFOVER,
1584 b43_phy_read(dev, B43_PHY_RFOVER) | 0x0001);
1585 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1586 b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFE);
1587 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1588 b43_phy_write(dev, B43_PHY_ANALOGOVER,
1589 b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0001);
1590 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
1591 b43_phy_read(dev,
1592 B43_PHY_ANALOGOVERVAL) & 0xFFFE);
1593 b43_phy_write(dev, B43_PHY_ANALOGOVER,
1594 b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0002);
1595 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
1596 b43_phy_read(dev,
1597 B43_PHY_ANALOGOVERVAL) & 0xFFFD);
1598 }
1599 b43_phy_write(dev, B43_PHY_RFOVER,
1600 b43_phy_read(dev, B43_PHY_RFOVER) | 0x000C);
1601 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1602 b43_phy_read(dev, B43_PHY_RFOVERVAL) | 0x000C);
1603 b43_phy_write(dev, B43_PHY_RFOVER,
1604 b43_phy_read(dev, B43_PHY_RFOVER) | 0x0030);
1605 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1606 (b43_phy_read(dev, B43_PHY_RFOVERVAL)
1607 & 0xFFCF) | 0x10);
1608
1609 b43_phy_write(dev, B43_PHY_BASE(0x5A), 0x0780);
1610 b43_phy_write(dev, B43_PHY_BASE(0x59), 0xC810);
1611 b43_phy_write(dev, B43_PHY_BASE(0x58), 0x000D);
1612
1613 b43_phy_write(dev, B43_PHY_BASE(0x0A),
1614 b43_phy_read(dev, B43_PHY_BASE(0x0A)) | 0x2000);
1615 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1616 b43_phy_write(dev, B43_PHY_ANALOGOVER,
1617 b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0004);
1618 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
1619 b43_phy_read(dev,
1620 B43_PHY_ANALOGOVERVAL) & 0xFFFB);
1621 }
1622 b43_phy_write(dev, B43_PHY_BASE(0x03),
1623 (b43_phy_read(dev, B43_PHY_BASE(0x03))
1624 & 0xFF9F) | 0x40);
1625
1626 if (phy->radio_rev == 8) {
1627 b43_radio_write16(dev, 0x43, 0x000F);
1628 } else {
1629 b43_radio_write16(dev, 0x52, 0);
1630 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
1631 & 0xFFF0) | 0x9);
1632 }
1633 b43_phy_set_baseband_attenuation(dev, 11);
1634
1635 if (phy->rev >= 3)
1636 b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);
1637 else
1638 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
1639 b43_phy_write(dev, B43_PHY_LO_CTL, 0);
1640
1641 b43_phy_write(dev, B43_PHY_BASE(0x2B),
1642 (b43_phy_read(dev, B43_PHY_BASE(0x2B))
1643 & 0xFFC0) | 0x01);
1644 b43_phy_write(dev, B43_PHY_BASE(0x2B),
1645 (b43_phy_read(dev, B43_PHY_BASE(0x2B))
1646 & 0xC0FF) | 0x800);
1647
1648 b43_phy_write(dev, B43_PHY_RFOVER,
1649 b43_phy_read(dev, B43_PHY_RFOVER) | 0x0100);
1650 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1651 b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF);
1652
1653 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_EXTLNA) {
1654 if (phy->rev >= 7) {
1655 b43_phy_write(dev, B43_PHY_RFOVER,
1656 b43_phy_read(dev, B43_PHY_RFOVER)
1657 | 0x0800);
1658 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1659 b43_phy_read(dev, B43_PHY_RFOVERVAL)
1660 | 0x8000);
1661 }
1662 }
1663 b43_radio_write16(dev, 0x7A, b43_radio_read16(dev, 0x7A)
1664 & 0x00F7);
1665
1666 j = 0;
1667 loop_i_max = (phy->radio_rev == 8) ? 15 : 9;
1668 for (i = 0; i < loop_i_max; i++) {
1669 for (j = 0; j < 16; j++) {
1670 b43_radio_write16(dev, 0x43, i);
1671 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1672 (b43_phy_read(dev, B43_PHY_RFOVERVAL)
1673 & 0xF0FF) | (j << 8));
1674 b43_phy_write(dev, B43_PHY_PGACTL,
1675 (b43_phy_read(dev, B43_PHY_PGACTL)
1676 & 0x0FFF) | 0xA000);
1677 b43_phy_write(dev, B43_PHY_PGACTL,
1678 b43_phy_read(dev, B43_PHY_PGACTL)
1679 | 0xF000);
1680 udelay(20);
1681 if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
1682 goto exit_loop1;
1683 }
1684 }
1685 exit_loop1:
1686 loop1_outer_done = i;
1687 loop1_inner_done = j;
1688 if (j >= 8) {
1689 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1690 b43_phy_read(dev, B43_PHY_RFOVERVAL)
1691 | 0x30);
1692 trsw_rx = 0x1B;
1693 for (j = j - 8; j < 16; j++) {
1694 b43_phy_write(dev, B43_PHY_RFOVERVAL,
1695 (b43_phy_read(dev, B43_PHY_RFOVERVAL)
1696 & 0xF0FF) | (j << 8));
1697 b43_phy_write(dev, B43_PHY_PGACTL,
1698 (b43_phy_read(dev, B43_PHY_PGACTL)
1699 & 0x0FFF) | 0xA000);
1700 b43_phy_write(dev, B43_PHY_PGACTL,
1701 b43_phy_read(dev, B43_PHY_PGACTL)
1702 | 0xF000);
1703 udelay(20);
1704 trsw_rx -= 3;
1705 if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
1706 goto exit_loop2;
1707 }
1708 } else
1709 trsw_rx = 0x18;
1710 exit_loop2:
1711
1712 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1713 b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]);
1714 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]);
1715 }
1716 b43_phy_write(dev, B43_PHY_BASE(0x5A), backup_phy[6]);
1717 b43_phy_write(dev, B43_PHY_BASE(0x59), backup_phy[7]);
1718 b43_phy_write(dev, B43_PHY_BASE(0x58), backup_phy[8]);
1719 b43_phy_write(dev, B43_PHY_BASE(0x0A), backup_phy[9]);
1720 b43_phy_write(dev, B43_PHY_BASE(0x03), backup_phy[10]);
1721 b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]);
1722 b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]);
1723 b43_phy_write(dev, B43_PHY_BASE(0x2B), backup_phy[13]);
1724 b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]);
1725
1726 b43_phy_set_baseband_attenuation(dev, backup_bband);
1727
1728 b43_radio_write16(dev, 0x52, backup_radio[0]);
1729 b43_radio_write16(dev, 0x43, backup_radio[1]);
1730 b43_radio_write16(dev, 0x7A, backup_radio[2]);
1731
1732 b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003);
1733 udelay(10);
1734 b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]);
1735 b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]);
1736 b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]);
1737 b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]);
1738
1739 phy->max_lb_gain =
1740 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
1741 phy->trsw_rx_gain = trsw_rx * 2;
1742}
1743
1744static void b43_phy_initg(struct b43_wldev *dev)
1745{
1746 struct b43_phy *phy = &dev->phy;
1747 u16 tmp;
1748
1749 if (phy->rev == 1)
1750 b43_phy_initb5(dev);
1751 else
1752 b43_phy_initb6(dev);
1753
1754 if (phy->rev >= 2 || phy->gmode)
1755 b43_phy_inita(dev);
1756
1757 if (phy->rev >= 2) {
1758 b43_phy_write(dev, B43_PHY_ANALOGOVER, 0);
1759 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0);
1760 }
1761 if (phy->rev == 2) {
1762 b43_phy_write(dev, B43_PHY_RFOVER, 0);
1763 b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
1764 }
1765 if (phy->rev > 5) {
1766 b43_phy_write(dev, B43_PHY_RFOVER, 0x400);
1767 b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
1768 }
1769 if (phy->gmode || phy->rev >= 2) {
1770 tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM);
1771 tmp &= B43_PHYVER_VERSION;
1772 if (tmp == 3 || tmp == 5) {
1773 b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816);
1774 b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006);
1775 }
1776 if (tmp == 5) {
1777 b43_phy_write(dev, B43_PHY_OFDM(0xCC),
1778 (b43_phy_read(dev, B43_PHY_OFDM(0xCC))
1779 & 0x00FF) | 0x1F00);
1780 }
1781 }
1782 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
1783 b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78);
1784 if (phy->radio_rev == 8) {
1785 b43_phy_write(dev, B43_PHY_EXTG(0x01),
1786 b43_phy_read(dev, B43_PHY_EXTG(0x01))
1787 | 0x80);
1788 b43_phy_write(dev, B43_PHY_OFDM(0x3E),
1789 b43_phy_read(dev, B43_PHY_OFDM(0x3E))
1790 | 0x4);
1791 }
1792 if (has_loopback_gain(phy))
1793 b43_calc_loopback_gain(dev);
1794
1795 if (phy->radio_rev != 8) {
1796 if (phy->initval == 0xFFFF)
1797 phy->initval = b43_radio_init2050(dev);
1798 else
1799 b43_radio_write16(dev, 0x0078, phy->initval);
1800 }
1801 if (phy->lo_control->tx_bias == 0xFF) {
1802 b43_lo_g_measure(dev);
1803 } else {
1804 if (has_tx_magnification(phy)) {
1805 b43_radio_write16(dev, 0x52,
1806 (b43_radio_read16(dev, 0x52) & 0xFF00)
1807 | phy->lo_control->tx_bias | phy->
1808 lo_control->tx_magn);
1809 } else {
1810 b43_radio_write16(dev, 0x52,
1811 (b43_radio_read16(dev, 0x52) & 0xFFF0)
1812 | phy->lo_control->tx_bias);
1813 }
1814 if (phy->rev >= 6) {
1815 b43_phy_write(dev, B43_PHY_BASE(0x36),
1816 (b43_phy_read(dev, B43_PHY_BASE(0x36))
1817 & 0x0FFF) | (phy->lo_control->
1818 tx_bias << 12));
1819 }
1820 if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL)
1821 b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8075);
1822 else
1823 b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x807F);
1824 if (phy->rev < 2)
1825 b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x101);
1826 else
1827 b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x202);
1828 }
1829 if (phy->gmode || phy->rev >= 2) {
1830 b43_lo_g_adjust(dev);
1831 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
1832 }
1833
1834 if (!(dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI)) {
1835 /* The specs state to update the NRSSI LT with
1836 * the value 0x7FFFFFFF here. I think that is some weird
1837 * compiler optimization in the original driver.
1838 * Essentially, what we do here is resetting all NRSSI LT
1839 * entries to -32 (see the limit_value() in nrssi_hw_update())
1840 */
1841 b43_nrssi_hw_update(dev, 0xFFFF); //FIXME?
1842 b43_calc_nrssi_threshold(dev);
1843 } else if (phy->gmode || phy->rev >= 2) {
1844 if (phy->nrssi[0] == -1000) {
1845 B43_WARN_ON(phy->nrssi[1] != -1000);
1846 b43_calc_nrssi_slope(dev);
1847 } else
1848 b43_calc_nrssi_threshold(dev);
1849 }
1850 if (phy->radio_rev == 8)
1851 b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230);
1852 b43_phy_init_pctl(dev);
1853 /* FIXME: The spec says in the following if, the 0 should be replaced
1854 'if OFDM may not be used in the current locale'
1855 but OFDM is legal everywhere */
1856 if ((dev->dev->bus->chip_id == 0x4306
1857 && dev->dev->bus->chip_package == 2) || 0) {
1858 b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0)
1859 & 0xBFFF);
1860 b43_phy_write(dev, B43_PHY_OFDM(0xC3),
1861 b43_phy_read(dev, B43_PHY_OFDM(0xC3))
1862 & 0x7FFF);
1863 }
1864}
1865
1866/* Set the baseband attenuation value on chip. */
1867void b43_phy_set_baseband_attenuation(struct b43_wldev *dev,
1868 u16 baseband_attenuation)
1869{
1870 struct b43_phy *phy = &dev->phy;
1871
1872 if (phy->analog == 0) {
1873 b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0)
1874 & 0xFFF0) |
1875 baseband_attenuation);
1876 } else if (phy->analog > 1) {
1877 b43_phy_write(dev, B43_PHY_DACCTL,
1878 (b43_phy_read(dev, B43_PHY_DACCTL)
1879 & 0xFFC3) | (baseband_attenuation << 2));
1880 } else {
1881 b43_phy_write(dev, B43_PHY_DACCTL,
1882 (b43_phy_read(dev, B43_PHY_DACCTL)
1883 & 0xFF87) | (baseband_attenuation << 3));
1884 }
1885}
1886
1887/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
1888 * This function converts a TSSI value to dBm in Q5.2
1889 */
1890static s8 b43_phy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
1891{
1892 struct b43_phy *phy = &dev->phy;
1893 s8 dbm = 0;
1894 s32 tmp;
1895
1896 tmp = (phy->tgt_idle_tssi - phy->cur_idle_tssi + tssi);
1897
1898 switch (phy->type) {
1899 case B43_PHYTYPE_A:
1900 tmp += 0x80;
1901 tmp = limit_value(tmp, 0x00, 0xFF);
1902 dbm = phy->tssi2dbm[tmp];
1903 //TODO: There's a FIXME on the specs
1904 break;
1905 case B43_PHYTYPE_B:
1906 case B43_PHYTYPE_G:
1907 tmp = limit_value(tmp, 0x00, 0x3F);
1908 dbm = phy->tssi2dbm[tmp];
1909 break;
1910 default:
1911 B43_WARN_ON(1);
1912 }
1913
1914 return dbm;
1915}
1916
1917void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
1918 int *_bbatt, int *_rfatt)
1919{
1920 int rfatt = *_rfatt;
1921 int bbatt = *_bbatt;
1922 struct b43_txpower_lo_control *lo = dev->phy.lo_control;
1923
1924 /* Get baseband and radio attenuation values into their permitted ranges.
1925 * Radio attenuation affects power level 4 times as much as baseband. */
1926
1927 /* Range constants */
1928 const int rf_min = lo->rfatt_list.min_val;
1929 const int rf_max = lo->rfatt_list.max_val;
1930 const int bb_min = lo->bbatt_list.min_val;
1931 const int bb_max = lo->bbatt_list.max_val;
1932
1933 while (1) {
1934 if (rfatt > rf_max && bbatt > bb_max - 4)
1935 break; /* Can not get it into ranges */
1936 if (rfatt < rf_min && bbatt < bb_min + 4)
1937 break; /* Can not get it into ranges */
1938 if (bbatt > bb_max && rfatt > rf_max - 1)
1939 break; /* Can not get it into ranges */
1940 if (bbatt < bb_min && rfatt < rf_min + 1)
1941 break; /* Can not get it into ranges */
1942
1943 if (bbatt > bb_max) {
1944 bbatt -= 4;
1945 rfatt += 1;
1946 continue;
1947 }
1948 if (bbatt < bb_min) {
1949 bbatt += 4;
1950 rfatt -= 1;
1951 continue;
1952 }
1953 if (rfatt > rf_max) {
1954 rfatt -= 1;
1955 bbatt += 4;
1956 continue;
1957 }
1958 if (rfatt < rf_min) {
1959 rfatt += 1;
1960 bbatt -= 4;
1961 continue;
1962 }
1963 break;
1964 }
1965
1966 *_rfatt = limit_value(rfatt, rf_min, rf_max);
1967 *_bbatt = limit_value(bbatt, bb_min, bb_max);
1968}
1969
1970/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
1971void b43_phy_xmitpower(struct b43_wldev *dev)
1972{
1973 struct ssb_bus *bus = dev->dev->bus;
1974 struct b43_phy *phy = &dev->phy;
1975
1976 if (phy->cur_idle_tssi == 0)
1977 return;
1978 if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
1979 (bus->boardinfo.type == SSB_BOARD_BU4306))
1980 return;
1981#ifdef CONFIG_B43_DEBUG
1982 if (phy->manual_txpower_control)
1983 return;
1984#endif
1985
1986 switch (phy->type) {
1987 case B43_PHYTYPE_A:{
1988
1989 //TODO: Nothing for A PHYs yet :-/
1990
1991 break;
1992 }
1993 case B43_PHYTYPE_B:
1994 case B43_PHYTYPE_G:{
1995 u16 tmp;
1996 s8 v0, v1, v2, v3;
1997 s8 average;
1998 int max_pwr;
1999 int desired_pwr, estimated_pwr, pwr_adjust;
2000 int rfatt_delta, bbatt_delta;
2001 int rfatt, bbatt;
2002 u8 tx_control;
2003 unsigned long phylock_flags;
2004
2005 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x0058);
2006 v0 = (s8) (tmp & 0x00FF);
2007 v1 = (s8) ((tmp & 0xFF00) >> 8);
2008 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x005A);
2009 v2 = (s8) (tmp & 0x00FF);
2010 v3 = (s8) ((tmp & 0xFF00) >> 8);
2011 tmp = 0;
2012
2013 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F
2014 || v3 == 0x7F) {
2015 tmp =
2016 b43_shm_read16(dev, B43_SHM_SHARED, 0x0070);
2017 v0 = (s8) (tmp & 0x00FF);
2018 v1 = (s8) ((tmp & 0xFF00) >> 8);
2019 tmp =
2020 b43_shm_read16(dev, B43_SHM_SHARED, 0x0072);
2021 v2 = (s8) (tmp & 0x00FF);
2022 v3 = (s8) ((tmp & 0xFF00) >> 8);
2023 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F
2024 || v3 == 0x7F)
2025 return;
2026 v0 = (v0 + 0x20) & 0x3F;
2027 v1 = (v1 + 0x20) & 0x3F;
2028 v2 = (v2 + 0x20) & 0x3F;
2029 v3 = (v3 + 0x20) & 0x3F;
2030 tmp = 1;
2031 }
2032 b43_shm_clear_tssi(dev);
2033
2034 average = (v0 + v1 + v2 + v3 + 2) / 4;
2035
2036 if (tmp
2037 && (b43_shm_read16(dev, B43_SHM_SHARED, 0x005E) &
2038 0x8))
2039 average -= 13;
2040
2041 estimated_pwr =
2042 b43_phy_estimate_power_out(dev, average);
2043
2044 max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
2045 if ((dev->dev->bus->sprom.r1.
2046 boardflags_lo & B43_BFL_PACTRL)
2047 && (phy->type == B43_PHYTYPE_G))
2048 max_pwr -= 0x3;
2049 if (unlikely(max_pwr <= 0)) {
2050 b43warn(dev->wl,
2051 "Invalid max-TX-power value in SPROM.\n");
2052 max_pwr = 60; /* fake it */
2053 dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr;
2054 }
2055
2056 /*TODO:
2057 max_pwr = min(REG - dev->dev->bus->sprom.antennagain_bgphy - 0x6, max_pwr)
2058 where REG is the max power as per the regulatory domain
2059 */
2060
2061 /* Get desired power (in Q5.2) */
2062 desired_pwr = INT_TO_Q52(phy->power_level);
2063 /* And limit it. max_pwr already is Q5.2 */
2064 desired_pwr = limit_value(desired_pwr, 0, max_pwr);
2065 if (b43_debug(dev, B43_DBG_XMITPOWER)) {
2066 b43dbg(dev->wl,
2067 "Current TX power output: " Q52_FMT
2068 " dBm, " "Desired TX power output: "
2069 Q52_FMT " dBm\n", Q52_ARG(estimated_pwr),
2070 Q52_ARG(desired_pwr));
2071 }
2072
2073 /* Calculate the adjustment delta. */
2074 pwr_adjust = desired_pwr - estimated_pwr;
2075
2076 /* RF attenuation delta. */
2077 rfatt_delta = ((pwr_adjust + 7) / 8);
2078 /* Lower attenuation => Bigger power output. Negate it. */
2079 rfatt_delta = -rfatt_delta;
2080
2081 /* Baseband attenuation delta. */
2082 bbatt_delta = pwr_adjust / 2;
2083 /* Lower attenuation => Bigger power output. Negate it. */
2084 bbatt_delta = -bbatt_delta;
2085 /* RF att affects power level 4 times as much as
2086 * Baseband attennuation. Subtract it. */
2087 bbatt_delta -= 4 * rfatt_delta;
2088
2089 /* So do we finally need to adjust something? */
2090 if ((rfatt_delta == 0) && (bbatt_delta == 0)) {
2091 b43_lo_g_ctl_mark_cur_used(dev);
2092 return;
2093 }
2094
2095 /* Calculate the new attenuation values. */
2096 bbatt = phy->bbatt.att;
2097 bbatt += bbatt_delta;
2098 rfatt = phy->rfatt.att;
2099 rfatt += rfatt_delta;
2100
2101 b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
2102 tx_control = phy->tx_control;
2103 if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
2104 if (rfatt <= 1) {
2105 if (tx_control == 0) {
2106 tx_control =
2107 B43_TXCTL_PA2DB |
2108 B43_TXCTL_TXMIX;
2109 rfatt += 2;
2110 bbatt += 2;
2111 } else if (dev->dev->bus->sprom.r1.
2112 boardflags_lo &
2113 B43_BFL_PACTRL) {
2114 bbatt += 4 * (rfatt - 2);
2115 rfatt = 2;
2116 }
2117 } else if (rfatt > 4 && tx_control) {
2118 tx_control = 0;
2119 if (bbatt < 3) {
2120 rfatt -= 3;
2121 bbatt += 2;
2122 } else {
2123 rfatt -= 2;
2124 bbatt -= 2;
2125 }
2126 }
2127 }
2128 /* Save the control values */
2129 phy->tx_control = tx_control;
2130 b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
2131 phy->rfatt.att = rfatt;
2132 phy->bbatt.att = bbatt;
2133
2134 /* Adjust the hardware */
2135 b43_phy_lock(dev, phylock_flags);
2136 b43_radio_lock(dev);
2137 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt,
2138 phy->tx_control);
2139 b43_lo_g_ctl_mark_cur_used(dev);
2140 b43_radio_unlock(dev);
2141 b43_phy_unlock(dev, phylock_flags);
2142 break;
2143 }
2144 default:
2145 B43_WARN_ON(1);
2146 }
2147}
2148
2149static inline s32 b43_tssi2dbm_ad(s32 num, s32 den)
2150{
2151 if (num < 0)
2152 return num / den;
2153 else
2154 return (num + den / 2) / den;
2155}
2156
2157static inline
2158 s8 b43_tssi2dbm_entry(s8 entry[], u8 index, s16 pab0, s16 pab1, s16 pab2)
2159{
2160 s32 m1, m2, f = 256, q, delta;
2161 s8 i = 0;
2162
2163 m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
2164 m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1);
2165 do {
2166 if (i > 15)
2167 return -EINVAL;
2168 q = b43_tssi2dbm_ad(f * 4096 -
2169 b43_tssi2dbm_ad(m2 * f, 16) * f, 2048);
2170 delta = abs(q - f);
2171 f = q;
2172 i++;
2173 } while (delta >= 2);
2174 entry[index] = limit_value(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);
2175 return 0;
2176}
2177
2178/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
2179int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
2180{
2181 struct b43_phy *phy = &dev->phy;
2182 s16 pab0, pab1, pab2;
2183 u8 idx;
2184 s8 *dyn_tssi2dbm;
2185
2186 if (phy->type == B43_PHYTYPE_A) {
2187 pab0 = (s16) (dev->dev->bus->sprom.r1.pa1b0);
2188 pab1 = (s16) (dev->dev->bus->sprom.r1.pa1b1);
2189 pab2 = (s16) (dev->dev->bus->sprom.r1.pa1b2);
2190 } else {
2191 pab0 = (s16) (dev->dev->bus->sprom.r1.pa0b0);
2192 pab1 = (s16) (dev->dev->bus->sprom.r1.pa0b1);
2193 pab2 = (s16) (dev->dev->bus->sprom.r1.pa0b2);
2194 }
2195
2196 if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
2197 phy->tgt_idle_tssi = 0x34;
2198 phy->tssi2dbm = b43_tssi2dbm_b_table;
2199 return 0;
2200 }
2201
2202 if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
2203 pab0 != -1 && pab1 != -1 && pab2 != -1) {
2204 /* The pabX values are set in SPROM. Use them. */
2205 if (phy->type == B43_PHYTYPE_A) {
2206 if ((s8) dev->dev->bus->sprom.r1.itssi_a != 0 &&
2207 (s8) dev->dev->bus->sprom.r1.itssi_a != -1)
2208 phy->tgt_idle_tssi =
2209 (s8) (dev->dev->bus->sprom.r1.itssi_a);
2210 else
2211 phy->tgt_idle_tssi = 62;
2212 } else {
2213 if ((s8) dev->dev->bus->sprom.r1.itssi_bg != 0 &&
2214 (s8) dev->dev->bus->sprom.r1.itssi_bg != -1)
2215 phy->tgt_idle_tssi =
2216 (s8) (dev->dev->bus->sprom.r1.itssi_bg);
2217 else
2218 phy->tgt_idle_tssi = 62;
2219 }
2220 dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
2221 if (dyn_tssi2dbm == NULL) {
2222 b43err(dev->wl, "Could not allocate memory"
2223 "for tssi2dbm table\n");
2224 return -ENOMEM;
2225 }
2226 for (idx = 0; idx < 64; idx++)
2227 if (b43_tssi2dbm_entry
2228 (dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
2229 phy->tssi2dbm = NULL;
2230 b43err(dev->wl, "Could not generate "
2231 "tssi2dBm table\n");
2232 kfree(dyn_tssi2dbm);
2233 return -ENODEV;
2234 }
2235 phy->tssi2dbm = dyn_tssi2dbm;
2236 phy->dyn_tssi_tbl = 1;
2237 } else {
2238 /* pabX values not set in SPROM. */
2239 switch (phy->type) {
2240 case B43_PHYTYPE_A:
2241 /* APHY needs a generated table. */
2242 phy->tssi2dbm = NULL;
2243 b43err(dev->wl, "Could not generate tssi2dBm "
2244 "table (wrong SPROM info)!\n");
2245 return -ENODEV;
2246 case B43_PHYTYPE_B:
2247 phy->tgt_idle_tssi = 0x34;
2248 phy->tssi2dbm = b43_tssi2dbm_b_table;
2249 break;
2250 case B43_PHYTYPE_G:
2251 phy->tgt_idle_tssi = 0x34;
2252 phy->tssi2dbm = b43_tssi2dbm_g_table;
2253 break;
2254 }
2255 }
2256
2257 return 0;
2258}
2259
2260int b43_phy_init(struct b43_wldev *dev)
2261{
2262 struct b43_phy *phy = &dev->phy;
2263 int err = -ENODEV;
2264
2265 switch (phy->type) {
2266 case B43_PHYTYPE_A:
2267 if (phy->rev == 2 || phy->rev == 3) {
2268 b43_phy_inita(dev);
2269 err = 0;
2270 }
2271 break;
2272 case B43_PHYTYPE_B:
2273 switch (phy->rev) {
2274 case 2:
2275 b43_phy_initb2(dev);
2276 err = 0;
2277 break;
2278 case 4:
2279 b43_phy_initb4(dev);
2280 err = 0;
2281 break;
2282 case 5:
2283 b43_phy_initb5(dev);
2284 err = 0;
2285 break;
2286 case 6:
2287 b43_phy_initb6(dev);
2288 err = 0;
2289 break;
2290 }
2291 break;
2292 case B43_PHYTYPE_G:
2293 b43_phy_initg(dev);
2294 err = 0;
2295 break;
2296 }
2297 if (err)
2298 b43err(dev->wl, "Unknown PHYTYPE found\n");
2299
2300 return err;
2301}
2302
2303void b43_set_rx_antenna(struct b43_wldev *dev, int antenna)
2304{
2305 struct b43_phy *phy = &dev->phy;
2306 u32 hf;
2307 u16 tmp;
2308 int autodiv = 0;
2309
2310 if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
2311 autodiv = 1;
2312
2313 hf = b43_hf_read(dev);
2314 hf &= ~B43_HF_ANTDIVHELP;
2315 b43_hf_write(dev, hf);
2316
2317 switch (phy->type) {
2318 case B43_PHYTYPE_A:
2319 case B43_PHYTYPE_G:
2320 tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
2321 tmp &= ~B43_PHY_BBANDCFG_RXANT;
2322 tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
2323 << B43_PHY_BBANDCFG_RXANT_SHIFT;
2324 b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
2325
2326 if (autodiv) {
2327 tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
2328 if (antenna == B43_ANTENNA_AUTO0)
2329 tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
2330 else
2331 tmp |= B43_PHY_ANTDWELL_AUTODIV1;
2332 b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
2333 }
2334 if (phy->type == B43_PHYTYPE_G) {
2335 tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT);
2336 if (autodiv)
2337 tmp |= B43_PHY_ANTWRSETT_ARXDIV;
2338 else
2339 tmp &= ~B43_PHY_ANTWRSETT_ARXDIV;
2340 b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp);
2341 if (phy->rev >= 2) {
2342 tmp = b43_phy_read(dev, B43_PHY_OFDM61);
2343 tmp |= B43_PHY_OFDM61_10;
2344 b43_phy_write(dev, B43_PHY_OFDM61, tmp);
2345
2346 tmp =
2347 b43_phy_read(dev, B43_PHY_DIVSRCHGAINBACK);
2348 tmp = (tmp & 0xFF00) | 0x15;
2349 b43_phy_write(dev, B43_PHY_DIVSRCHGAINBACK,
2350 tmp);
2351
2352 if (phy->rev == 2) {
2353 b43_phy_write(dev, B43_PHY_ADIVRELATED,
2354 8);
2355 } else {
2356 tmp =
2357 b43_phy_read(dev,
2358 B43_PHY_ADIVRELATED);
2359 tmp = (tmp & 0xFF00) | 8;
2360 b43_phy_write(dev, B43_PHY_ADIVRELATED,
2361 tmp);
2362 }
2363 }
2364 if (phy->rev >= 6)
2365 b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC);
2366 } else {
2367 if (phy->rev < 3) {
2368 tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
2369 tmp = (tmp & 0xFF00) | 0x24;
2370 b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
2371 } else {
2372 tmp = b43_phy_read(dev, B43_PHY_OFDM61);
2373 tmp |= 0x10;
2374 b43_phy_write(dev, B43_PHY_OFDM61, tmp);
2375 if (phy->analog == 3) {
2376 b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
2377 0x1D);
2378 b43_phy_write(dev, B43_PHY_ADIVRELATED,
2379 8);
2380 } else {
2381 b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
2382 0x3A);
2383 tmp =
2384 b43_phy_read(dev,
2385 B43_PHY_ADIVRELATED);
2386 tmp = (tmp & 0xFF00) | 8;
2387 b43_phy_write(dev, B43_PHY_ADIVRELATED,
2388 tmp);
2389 }
2390 }
2391 }
2392 break;
2393 case B43_PHYTYPE_B:
2394 tmp = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);
2395 tmp &= ~B43_PHY_BBANDCFG_RXANT;
2396 tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
2397 << B43_PHY_BBANDCFG_RXANT_SHIFT;
2398 b43_phy_write(dev, B43_PHY_CCKBBANDCFG, tmp);
2399 break;
2400 default:
2401 B43_WARN_ON(1);
2402 }
2403
2404 hf |= B43_HF_ANTDIVHELP;
2405 b43_hf_write(dev, hf);
2406}
2407
2408/* Get the freq, as it has to be written to the device. */
2409static inline u16 channel2freq_bg(u8 channel)
2410{
2411 B43_WARN_ON(!(channel >= 1 && channel <= 14));
2412
2413 return b43_radio_channel_codes_bg[channel - 1];
2414}
2415
2416/* Get the freq, as it has to be written to the device. */
2417static inline u16 channel2freq_a(u8 channel)
2418{
2419 B43_WARN_ON(channel > 200);
2420
2421 return (5000 + 5 * channel);
2422}
2423
2424void b43_radio_lock(struct b43_wldev *dev)
2425{
2426 u32 macctl;
2427
2428 macctl = b43_read32(dev, B43_MMIO_MACCTL);
2429 macctl |= B43_MACCTL_RADIOLOCK;
2430 b43_write32(dev, B43_MMIO_MACCTL, macctl);
2431 /* Commit the write and wait for the device
2432 * to exit any radio register access. */
2433 b43_read32(dev, B43_MMIO_MACCTL);
2434 udelay(10);
2435}
2436
2437void b43_radio_unlock(struct b43_wldev *dev)
2438{
2439 u32 macctl;
2440
2441 /* Commit any write */
2442 b43_read16(dev, B43_MMIO_PHY_VER);
2443 /* unlock */
2444 macctl = b43_read32(dev, B43_MMIO_MACCTL);
2445 macctl &= ~B43_MACCTL_RADIOLOCK;
2446 b43_write32(dev, B43_MMIO_MACCTL, macctl);
2447}
2448
2449u16 b43_radio_read16(struct b43_wldev *dev, u16 offset)
2450{
2451 struct b43_phy *phy = &dev->phy;
2452
2453 switch (phy->type) {
2454 case B43_PHYTYPE_A:
2455 offset |= 0x0040;
2456 break;
2457 case B43_PHYTYPE_B:
2458 if (phy->radio_ver == 0x2053) {
2459 if (offset < 0x70)
2460 offset += 0x80;
2461 else if (offset < 0x80)
2462 offset += 0x70;
2463 } else if (phy->radio_ver == 0x2050) {
2464 offset |= 0x80;
2465 } else
2466 B43_WARN_ON(1);
2467 break;
2468 case B43_PHYTYPE_G:
2469 offset |= 0x80;
2470 break;
2471 }
2472
2473 b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset);
2474 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
2475}
2476
2477void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val)
2478{
2479 b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset);
2480 mmiowb();
2481 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, val);
2482}
2483
2484static void b43_set_all_gains(struct b43_wldev *dev,
2485 s16 first, s16 second, s16 third)
2486{
2487 struct b43_phy *phy = &dev->phy;
2488 u16 i;
2489 u16 start = 0x08, end = 0x18;
2490 u16 tmp;
2491 u16 table;
2492
2493 if (phy->rev <= 1) {
2494 start = 0x10;
2495 end = 0x20;
2496 }
2497
2498 table = B43_OFDMTAB_GAINX;
2499 if (phy->rev <= 1)
2500 table = B43_OFDMTAB_GAINX_R1;
2501 for (i = 0; i < 4; i++)
2502 b43_ofdmtab_write16(dev, table, i, first);
2503
2504 for (i = start; i < end; i++)
2505 b43_ofdmtab_write16(dev, table, i, second);
2506
2507 if (third != -1) {
2508 tmp = ((u16) third << 14) | ((u16) third << 6);
2509 b43_phy_write(dev, 0x04A0,
2510 (b43_phy_read(dev, 0x04A0) & 0xBFBF) | tmp);
2511 b43_phy_write(dev, 0x04A1,
2512 (b43_phy_read(dev, 0x04A1) & 0xBFBF) | tmp);
2513 b43_phy_write(dev, 0x04A2,
2514 (b43_phy_read(dev, 0x04A2) & 0xBFBF) | tmp);
2515 }
2516 b43_dummy_transmission(dev);
2517}
2518
2519static void b43_set_original_gains(struct b43_wldev *dev)
2520{
2521 struct b43_phy *phy = &dev->phy;
2522 u16 i, tmp;
2523 u16 table;
2524 u16 start = 0x0008, end = 0x0018;
2525
2526 if (phy->rev <= 1) {
2527 start = 0x0010;
2528 end = 0x0020;
2529 }
2530
2531 table = B43_OFDMTAB_GAINX;
2532 if (phy->rev <= 1)
2533 table = B43_OFDMTAB_GAINX_R1;
2534 for (i = 0; i < 4; i++) {
2535 tmp = (i & 0xFFFC);
2536 tmp |= (i & 0x0001) << 1;
2537 tmp |= (i & 0x0002) >> 1;
2538
2539 b43_ofdmtab_write16(dev, table, i, tmp);
2540 }
2541
2542 for (i = start; i < end; i++)
2543 b43_ofdmtab_write16(dev, table, i, i - start);
2544
2545 b43_phy_write(dev, 0x04A0,
2546 (b43_phy_read(dev, 0x04A0) & 0xBFBF) | 0x4040);
2547 b43_phy_write(dev, 0x04A1,
2548 (b43_phy_read(dev, 0x04A1) & 0xBFBF) | 0x4040);
2549 b43_phy_write(dev, 0x04A2,
2550 (b43_phy_read(dev, 0x04A2) & 0xBFBF) | 0x4000);
2551 b43_dummy_transmission(dev);
2552}
2553
2554/* Synthetic PU workaround */
2555static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel)
2556{
2557 struct b43_phy *phy = &dev->phy;
2558
2559 might_sleep();
2560
2561 if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) {
2562 /* We do not need the workaround. */
2563 return;
2564 }
2565
2566 if (channel <= 10) {
2567 b43_write16(dev, B43_MMIO_CHANNEL,
2568 channel2freq_bg(channel + 4));
2569 } else {
2570 b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1));
2571 }
2572 msleep(1);
2573 b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
2574}
2575
2576u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel)
2577{
2578 struct b43_phy *phy = &dev->phy;
2579 u8 ret = 0;
2580 u16 saved, rssi, temp;
2581 int i, j = 0;
2582
2583 saved = b43_phy_read(dev, 0x0403);
2584 b43_radio_selectchannel(dev, channel, 0);
2585 b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
2586 if (phy->aci_hw_rssi)
2587 rssi = b43_phy_read(dev, 0x048A) & 0x3F;
2588 else
2589 rssi = saved & 0x3F;
2590 /* clamp temp to signed 5bit */
2591 if (rssi > 32)
2592 rssi -= 64;
2593 for (i = 0; i < 100; i++) {
2594 temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F;
2595 if (temp > 32)
2596 temp -= 64;
2597 if (temp < rssi)
2598 j++;
2599 if (j >= 20)
2600 ret = 1;
2601 }
2602 b43_phy_write(dev, 0x0403, saved);
2603
2604 return ret;
2605}
2606
2607u8 b43_radio_aci_scan(struct b43_wldev * dev)
2608{
2609 struct b43_phy *phy = &dev->phy;
2610 u8 ret[13];
2611 unsigned int channel = phy->channel;
2612 unsigned int i, j, start, end;
2613 unsigned long phylock_flags;
2614
2615 if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0)))
2616 return 0;
2617
2618 b43_phy_lock(dev, phylock_flags);
2619 b43_radio_lock(dev);
2620 b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
2621 b43_phy_write(dev, B43_PHY_G_CRS,
2622 b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF);
2623 b43_set_all_gains(dev, 3, 8, 1);
2624
2625 start = (channel - 5 > 0) ? channel - 5 : 1;
2626 end = (channel + 5 < 14) ? channel + 5 : 13;
2627
2628 for (i = start; i <= end; i++) {
2629 if (abs(channel - i) > 2)
2630 ret[i - 1] = b43_radio_aci_detect(dev, i);
2631 }
2632 b43_radio_selectchannel(dev, channel, 0);
2633 b43_phy_write(dev, 0x0802,
2634 (b43_phy_read(dev, 0x0802) & 0xFFFC) | 0x0003);
2635 b43_phy_write(dev, 0x0403, b43_phy_read(dev, 0x0403) & 0xFFF8);
2636 b43_phy_write(dev, B43_PHY_G_CRS,
2637 b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000);
2638 b43_set_original_gains(dev);
2639 for (i = 0; i < 13; i++) {
2640 if (!ret[i])
2641 continue;
2642 end = (i + 5 < 13) ? i + 5 : 13;
2643 for (j = i; j < end; j++)
2644 ret[j] = 1;
2645 }
2646 b43_radio_unlock(dev);
2647 b43_phy_unlock(dev, phylock_flags);
2648
2649 return ret[channel - 1];
2650}
2651
2652/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2653void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)
2654{
2655 b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
2656 mmiowb();
2657 b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val);
2658}
2659
2660/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2661s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
2662{
2663 u16 val;
2664
2665 b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
2666 val = b43_phy_read(dev, B43_PHY_NRSSILT_DATA);
2667
2668 return (s16) val;
2669}
2670
2671/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2672void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
2673{
2674 u16 i;
2675 s16 tmp;
2676
2677 for (i = 0; i < 64; i++) {
2678 tmp = b43_nrssi_hw_read(dev, i);
2679 tmp -= val;
2680 tmp = limit_value(tmp, -32, 31);
2681 b43_nrssi_hw_write(dev, i, tmp);
2682 }
2683}
2684
2685/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2686void b43_nrssi_mem_update(struct b43_wldev *dev)
2687{
2688 struct b43_phy *phy = &dev->phy;
2689 s16 i, delta;
2690 s32 tmp;
2691
2692 delta = 0x1F - phy->nrssi[0];
2693 for (i = 0; i < 64; i++) {
2694 tmp = (i - delta) * phy->nrssislope;
2695 tmp /= 0x10000;
2696 tmp += 0x3A;
2697 tmp = limit_value(tmp, 0, 0x3F);
2698 phy->nrssi_lt[i] = tmp;
2699 }
2700}
2701
2702static void b43_calc_nrssi_offset(struct b43_wldev *dev)
2703{
2704 struct b43_phy *phy = &dev->phy;
2705 u16 backup[20] = { 0 };
2706 s16 v47F;
2707 u16 i;
2708 u16 saved = 0xFFFF;
2709
2710 backup[0] = b43_phy_read(dev, 0x0001);
2711 backup[1] = b43_phy_read(dev, 0x0811);
2712 backup[2] = b43_phy_read(dev, 0x0812);
2713 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2714 backup[3] = b43_phy_read(dev, 0x0814);
2715 backup[4] = b43_phy_read(dev, 0x0815);
2716 }
2717 backup[5] = b43_phy_read(dev, 0x005A);
2718 backup[6] = b43_phy_read(dev, 0x0059);
2719 backup[7] = b43_phy_read(dev, 0x0058);
2720 backup[8] = b43_phy_read(dev, 0x000A);
2721 backup[9] = b43_phy_read(dev, 0x0003);
2722 backup[10] = b43_radio_read16(dev, 0x007A);
2723 backup[11] = b43_radio_read16(dev, 0x0043);
2724
2725 b43_phy_write(dev, 0x0429, b43_phy_read(dev, 0x0429) & 0x7FFF);
2726 b43_phy_write(dev, 0x0001,
2727 (b43_phy_read(dev, 0x0001) & 0x3FFF) | 0x4000);
2728 b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x000C);
2729 b43_phy_write(dev, 0x0812,
2730 (b43_phy_read(dev, 0x0812) & 0xFFF3) | 0x0004);
2731 b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & ~(0x1 | 0x2));
2732 if (phy->rev >= 6) {
2733 backup[12] = b43_phy_read(dev, 0x002E);
2734 backup[13] = b43_phy_read(dev, 0x002F);
2735 backup[14] = b43_phy_read(dev, 0x080F);
2736 backup[15] = b43_phy_read(dev, 0x0810);
2737 backup[16] = b43_phy_read(dev, 0x0801);
2738 backup[17] = b43_phy_read(dev, 0x0060);
2739 backup[18] = b43_phy_read(dev, 0x0014);
2740 backup[19] = b43_phy_read(dev, 0x0478);
2741
2742 b43_phy_write(dev, 0x002E, 0);
2743 b43_phy_write(dev, 0x002F, 0);
2744 b43_phy_write(dev, 0x080F, 0);
2745 b43_phy_write(dev, 0x0810, 0);
2746 b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | 0x0100);
2747 b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) | 0x0040);
2748 b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) | 0x0040);
2749 b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014) | 0x0200);
2750 }
2751 b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0070);
2752 b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0080);
2753 udelay(30);
2754
2755 v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
2756 if (v47F >= 0x20)
2757 v47F -= 0x40;
2758 if (v47F == 31) {
2759 for (i = 7; i >= 4; i--) {
2760 b43_radio_write16(dev, 0x007B, i);
2761 udelay(20);
2762 v47F =
2763 (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
2764 if (v47F >= 0x20)
2765 v47F -= 0x40;
2766 if (v47F < 31 && saved == 0xFFFF)
2767 saved = i;
2768 }
2769 if (saved == 0xFFFF)
2770 saved = 4;
2771 } else {
2772 b43_radio_write16(dev, 0x007A,
2773 b43_radio_read16(dev, 0x007A) & 0x007F);
2774 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2775 b43_phy_write(dev, 0x0814,
2776 b43_phy_read(dev, 0x0814) | 0x0001);
2777 b43_phy_write(dev, 0x0815,
2778 b43_phy_read(dev, 0x0815) & 0xFFFE);
2779 }
2780 b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x000C);
2781 b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) | 0x000C);
2782 b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x0030);
2783 b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) | 0x0030);
2784 b43_phy_write(dev, 0x005A, 0x0480);
2785 b43_phy_write(dev, 0x0059, 0x0810);
2786 b43_phy_write(dev, 0x0058, 0x000D);
2787 if (phy->rev == 0) {
2788 b43_phy_write(dev, 0x0003, 0x0122);
2789 } else {
2790 b43_phy_write(dev, 0x000A, b43_phy_read(dev, 0x000A)
2791 | 0x2000);
2792 }
2793 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2794 b43_phy_write(dev, 0x0814,
2795 b43_phy_read(dev, 0x0814) | 0x0004);
2796 b43_phy_write(dev, 0x0815,
2797 b43_phy_read(dev, 0x0815) & 0xFFFB);
2798 }
2799 b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003) & 0xFF9F)
2800 | 0x0040);
2801 b43_radio_write16(dev, 0x007A,
2802 b43_radio_read16(dev, 0x007A) | 0x000F);
2803 b43_set_all_gains(dev, 3, 0, 1);
2804 b43_radio_write16(dev, 0x0043, (b43_radio_read16(dev, 0x0043)
2805 & 0x00F0) | 0x000F);
2806 udelay(30);
2807 v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
2808 if (v47F >= 0x20)
2809 v47F -= 0x40;
2810 if (v47F == -32) {
2811 for (i = 0; i < 4; i++) {
2812 b43_radio_write16(dev, 0x007B, i);
2813 udelay(20);
2814 v47F =
2815 (s16) ((b43_phy_read(dev, 0x047F) >> 8) &
2816 0x003F);
2817 if (v47F >= 0x20)
2818 v47F -= 0x40;
2819 if (v47F > -31 && saved == 0xFFFF)
2820 saved = i;
2821 }
2822 if (saved == 0xFFFF)
2823 saved = 3;
2824 } else
2825 saved = 0;
2826 }
2827 b43_radio_write16(dev, 0x007B, saved);
2828
2829 if (phy->rev >= 6) {
2830 b43_phy_write(dev, 0x002E, backup[12]);
2831 b43_phy_write(dev, 0x002F, backup[13]);
2832 b43_phy_write(dev, 0x080F, backup[14]);
2833 b43_phy_write(dev, 0x0810, backup[15]);
2834 }
2835 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2836 b43_phy_write(dev, 0x0814, backup[3]);
2837 b43_phy_write(dev, 0x0815, backup[4]);
2838 }
2839 b43_phy_write(dev, 0x005A, backup[5]);
2840 b43_phy_write(dev, 0x0059, backup[6]);
2841 b43_phy_write(dev, 0x0058, backup[7]);
2842 b43_phy_write(dev, 0x000A, backup[8]);
2843 b43_phy_write(dev, 0x0003, backup[9]);
2844 b43_radio_write16(dev, 0x0043, backup[11]);
2845 b43_radio_write16(dev, 0x007A, backup[10]);
2846 b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x1 | 0x2);
2847 b43_phy_write(dev, 0x0429, b43_phy_read(dev, 0x0429) | 0x8000);
2848 b43_set_original_gains(dev);
2849 if (phy->rev >= 6) {
2850 b43_phy_write(dev, 0x0801, backup[16]);
2851 b43_phy_write(dev, 0x0060, backup[17]);
2852 b43_phy_write(dev, 0x0014, backup[18]);
2853 b43_phy_write(dev, 0x0478, backup[19]);
2854 }
2855 b43_phy_write(dev, 0x0001, backup[0]);
2856 b43_phy_write(dev, 0x0812, backup[2]);
2857 b43_phy_write(dev, 0x0811, backup[1]);
2858}
2859
2860void b43_calc_nrssi_slope(struct b43_wldev *dev)
2861{
2862 struct b43_phy *phy = &dev->phy;
2863 u16 backup[18] = { 0 };
2864 u16 tmp;
2865 s16 nrssi0, nrssi1;
2866
2867 switch (phy->type) {
2868 case B43_PHYTYPE_B:
2869 backup[0] = b43_radio_read16(dev, 0x007A);
2870 backup[1] = b43_radio_read16(dev, 0x0052);
2871 backup[2] = b43_radio_read16(dev, 0x0043);
2872 backup[3] = b43_phy_read(dev, 0x0030);
2873 backup[4] = b43_phy_read(dev, 0x0026);
2874 backup[5] = b43_phy_read(dev, 0x0015);
2875 backup[6] = b43_phy_read(dev, 0x002A);
2876 backup[7] = b43_phy_read(dev, 0x0020);
2877 backup[8] = b43_phy_read(dev, 0x005A);
2878 backup[9] = b43_phy_read(dev, 0x0059);
2879 backup[10] = b43_phy_read(dev, 0x0058);
2880 backup[11] = b43_read16(dev, 0x03E2);
2881 backup[12] = b43_read16(dev, 0x03E6);
2882 backup[13] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);
2883
2884 tmp = b43_radio_read16(dev, 0x007A);
2885 tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
2886 b43_radio_write16(dev, 0x007A, tmp);
2887 b43_phy_write(dev, 0x0030, 0x00FF);
2888 b43_write16(dev, 0x03EC, 0x7F7F);
2889 b43_phy_write(dev, 0x0026, 0x0000);
2890 b43_phy_write(dev, 0x0015, b43_phy_read(dev, 0x0015) | 0x0020);
2891 b43_phy_write(dev, 0x002A, 0x08A3);
2892 b43_radio_write16(dev, 0x007A,
2893 b43_radio_read16(dev, 0x007A) | 0x0080);
2894
2895 nrssi0 = (s16) b43_phy_read(dev, 0x0027);
2896 b43_radio_write16(dev, 0x007A,
2897 b43_radio_read16(dev, 0x007A) & 0x007F);
2898 if (phy->rev >= 2) {
2899 b43_write16(dev, 0x03E6, 0x0040);
2900 } else if (phy->rev == 0) {
2901 b43_write16(dev, 0x03E6, 0x0122);
2902 } else {
2903 b43_write16(dev, B43_MMIO_CHANNEL_EXT,
2904 b43_read16(dev,
2905 B43_MMIO_CHANNEL_EXT) & 0x2000);
2906 }
2907 b43_phy_write(dev, 0x0020, 0x3F3F);
2908 b43_phy_write(dev, 0x0015, 0xF330);
2909 b43_radio_write16(dev, 0x005A, 0x0060);
2910 b43_radio_write16(dev, 0x0043,
2911 b43_radio_read16(dev, 0x0043) & 0x00F0);
2912 b43_phy_write(dev, 0x005A, 0x0480);
2913 b43_phy_write(dev, 0x0059, 0x0810);
2914 b43_phy_write(dev, 0x0058, 0x000D);
2915 udelay(20);
2916
2917 nrssi1 = (s16) b43_phy_read(dev, 0x0027);
2918 b43_phy_write(dev, 0x0030, backup[3]);
2919 b43_radio_write16(dev, 0x007A, backup[0]);
2920 b43_write16(dev, 0x03E2, backup[11]);
2921 b43_phy_write(dev, 0x0026, backup[4]);
2922 b43_phy_write(dev, 0x0015, backup[5]);
2923 b43_phy_write(dev, 0x002A, backup[6]);
2924 b43_synth_pu_workaround(dev, phy->channel);
2925 if (phy->rev != 0)
2926 b43_write16(dev, 0x03F4, backup[13]);
2927
2928 b43_phy_write(dev, 0x0020, backup[7]);
2929 b43_phy_write(dev, 0x005A, backup[8]);
2930 b43_phy_write(dev, 0x0059, backup[9]);
2931 b43_phy_write(dev, 0x0058, backup[10]);
2932 b43_radio_write16(dev, 0x0052, backup[1]);
2933 b43_radio_write16(dev, 0x0043, backup[2]);
2934
2935 if (nrssi0 == nrssi1)
2936 phy->nrssislope = 0x00010000;
2937 else
2938 phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
2939
2940 if (nrssi0 <= -4) {
2941 phy->nrssi[0] = nrssi0;
2942 phy->nrssi[1] = nrssi1;
2943 }
2944 break;
2945 case B43_PHYTYPE_G:
2946 if (phy->radio_rev >= 9)
2947 return;
2948 if (phy->radio_rev == 8)
2949 b43_calc_nrssi_offset(dev);
2950
2951 b43_phy_write(dev, B43_PHY_G_CRS,
2952 b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF);
2953 b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
2954 backup[7] = b43_read16(dev, 0x03E2);
2955 b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000);
2956 backup[0] = b43_radio_read16(dev, 0x007A);
2957 backup[1] = b43_radio_read16(dev, 0x0052);
2958 backup[2] = b43_radio_read16(dev, 0x0043);
2959 backup[3] = b43_phy_read(dev, 0x0015);
2960 backup[4] = b43_phy_read(dev, 0x005A);
2961 backup[5] = b43_phy_read(dev, 0x0059);
2962 backup[6] = b43_phy_read(dev, 0x0058);
2963 backup[8] = b43_read16(dev, 0x03E6);
2964 backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);
2965 if (phy->rev >= 3) {
2966 backup[10] = b43_phy_read(dev, 0x002E);
2967 backup[11] = b43_phy_read(dev, 0x002F);
2968 backup[12] = b43_phy_read(dev, 0x080F);
2969 backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL);
2970 backup[14] = b43_phy_read(dev, 0x0801);
2971 backup[15] = b43_phy_read(dev, 0x0060);
2972 backup[16] = b43_phy_read(dev, 0x0014);
2973 backup[17] = b43_phy_read(dev, 0x0478);
2974 b43_phy_write(dev, 0x002E, 0);
2975 b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0);
2976 switch (phy->rev) {
2977 case 4:
2978 case 6:
2979 case 7:
2980 b43_phy_write(dev, 0x0478,
2981 b43_phy_read(dev, 0x0478)
2982 | 0x0100);
2983 b43_phy_write(dev, 0x0801,
2984 b43_phy_read(dev, 0x0801)
2985 | 0x0040);
2986 break;
2987 case 3:
2988 case 5:
2989 b43_phy_write(dev, 0x0801,
2990 b43_phy_read(dev, 0x0801)
2991 & 0xFFBF);
2992 break;
2993 }
2994 b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060)
2995 | 0x0040);
2996 b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014)
2997 | 0x0200);
2998 }
2999 b43_radio_write16(dev, 0x007A,
3000 b43_radio_read16(dev, 0x007A) | 0x0070);
3001 b43_set_all_gains(dev, 0, 8, 0);
3002 b43_radio_write16(dev, 0x007A,
3003 b43_radio_read16(dev, 0x007A) & 0x00F7);
3004 if (phy->rev >= 2) {
3005 b43_phy_write(dev, 0x0811,
3006 (b43_phy_read(dev, 0x0811) & 0xFFCF) |
3007 0x0030);
3008 b43_phy_write(dev, 0x0812,
3009 (b43_phy_read(dev, 0x0812) & 0xFFCF) |
3010 0x0010);
3011 }
3012 b43_radio_write16(dev, 0x007A,
3013 b43_radio_read16(dev, 0x007A) | 0x0080);
3014 udelay(20);
3015
3016 nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
3017 if (nrssi0 >= 0x0020)
3018 nrssi0 -= 0x0040;
3019
3020 b43_radio_write16(dev, 0x007A,
3021 b43_radio_read16(dev, 0x007A) & 0x007F);
3022 if (phy->rev >= 2) {
3023 b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003)
3024 & 0xFF9F) | 0x0040);
3025 }
3026
3027 b43_write16(dev, B43_MMIO_CHANNEL_EXT,
3028 b43_read16(dev, B43_MMIO_CHANNEL_EXT)
3029 | 0x2000);
3030 b43_radio_write16(dev, 0x007A,
3031 b43_radio_read16(dev, 0x007A) | 0x000F);
3032 b43_phy_write(dev, 0x0015, 0xF330);
3033 if (phy->rev >= 2) {
3034 b43_phy_write(dev, 0x0812,
3035 (b43_phy_read(dev, 0x0812) & 0xFFCF) |
3036 0x0020);
3037 b43_phy_write(dev, 0x0811,
3038 (b43_phy_read(dev, 0x0811) & 0xFFCF) |
3039 0x0020);
3040 }
3041
3042 b43_set_all_gains(dev, 3, 0, 1);
3043 if (phy->radio_rev == 8) {
3044 b43_radio_write16(dev, 0x0043, 0x001F);
3045 } else {
3046 tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F;
3047 b43_radio_write16(dev, 0x0052, tmp | 0x0060);
3048 tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0;
3049 b43_radio_write16(dev, 0x0043, tmp | 0x0009);
3050 }
3051 b43_phy_write(dev, 0x005A, 0x0480);
3052 b43_phy_write(dev, 0x0059, 0x0810);
3053 b43_phy_write(dev, 0x0058, 0x000D);
3054 udelay(20);
3055 nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
3056 if (nrssi1 >= 0x0020)
3057 nrssi1 -= 0x0040;
3058 if (nrssi0 == nrssi1)
3059 phy->nrssislope = 0x00010000;
3060 else
3061 phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
3062 if (nrssi0 >= -4) {
3063 phy->nrssi[0] = nrssi1;
3064 phy->nrssi[1] = nrssi0;
3065 }
3066 if (phy->rev >= 3) {
3067 b43_phy_write(dev, 0x002E, backup[10]);
3068 b43_phy_write(dev, 0x002F, backup[11]);
3069 b43_phy_write(dev, 0x080F, backup[12]);
3070 b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]);
3071 }
3072 if (phy->rev >= 2) {
3073 b43_phy_write(dev, 0x0812,
3074 b43_phy_read(dev, 0x0812) & 0xFFCF);
3075 b43_phy_write(dev, 0x0811,
3076 b43_phy_read(dev, 0x0811) & 0xFFCF);
3077 }
3078
3079 b43_radio_write16(dev, 0x007A, backup[0]);
3080 b43_radio_write16(dev, 0x0052, backup[1]);
3081 b43_radio_write16(dev, 0x0043, backup[2]);
3082 b43_write16(dev, 0x03E2, backup[7]);
3083 b43_write16(dev, 0x03E6, backup[8]);
3084 b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]);
3085 b43_phy_write(dev, 0x0015, backup[3]);
3086 b43_phy_write(dev, 0x005A, backup[4]);
3087 b43_phy_write(dev, 0x0059, backup[5]);
3088 b43_phy_write(dev, 0x0058, backup[6]);
3089 b43_synth_pu_workaround(dev, phy->channel);
3090 b43_phy_write(dev, 0x0802,
3091 b43_phy_read(dev, 0x0802) | (0x0001 | 0x0002));
3092 b43_set_original_gains(dev);
3093 b43_phy_write(dev, B43_PHY_G_CRS,
3094 b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000);
3095 if (phy->rev >= 3) {
3096 b43_phy_write(dev, 0x0801, backup[14]);
3097 b43_phy_write(dev, 0x0060, backup[15]);
3098 b43_phy_write(dev, 0x0014, backup[16]);
3099 b43_phy_write(dev, 0x0478, backup[17]);
3100 }
3101 b43_nrssi_mem_update(dev);
3102 b43_calc_nrssi_threshold(dev);
3103 break;
3104 default:
3105 B43_WARN_ON(1);
3106 }
3107}
3108
3109void b43_calc_nrssi_threshold(struct b43_wldev *dev)
3110{
3111 struct b43_phy *phy = &dev->phy;
3112 s32 threshold;
3113 s32 a, b;
3114 s16 tmp16;
3115 u16 tmp_u16;
3116
3117 switch (phy->type) {
3118 case B43_PHYTYPE_B:{
3119 if (phy->radio_ver != 0x2050)
3120 return;
3121 if (!
3122 (dev->dev->bus->sprom.r1.
3123 boardflags_lo & B43_BFL_RSSI))
3124 return;
3125
3126 if (phy->radio_rev >= 6) {
3127 threshold =
3128 (phy->nrssi[1] - phy->nrssi[0]) * 32;
3129 threshold += 20 * (phy->nrssi[0] + 1);
3130 threshold /= 40;
3131 } else
3132 threshold = phy->nrssi[1] - 5;
3133
3134 threshold = limit_value(threshold, 0, 0x3E);
3135 b43_phy_read(dev, 0x0020); /* dummy read */
3136 b43_phy_write(dev, 0x0020,
3137 (((u16) threshold) << 8) | 0x001C);
3138
3139 if (phy->radio_rev >= 6) {
3140 b43_phy_write(dev, 0x0087, 0x0E0D);
3141 b43_phy_write(dev, 0x0086, 0x0C0B);
3142 b43_phy_write(dev, 0x0085, 0x0A09);
3143 b43_phy_write(dev, 0x0084, 0x0808);
3144 b43_phy_write(dev, 0x0083, 0x0808);
3145 b43_phy_write(dev, 0x0082, 0x0604);
3146 b43_phy_write(dev, 0x0081, 0x0302);
3147 b43_phy_write(dev, 0x0080, 0x0100);
3148 }
3149 break;
3150 }
3151 case B43_PHYTYPE_G:
3152 if (!phy->gmode ||
3153 !(dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI)) {
3154 tmp16 = b43_nrssi_hw_read(dev, 0x20);
3155 if (tmp16 >= 0x20)
3156 tmp16 -= 0x40;
3157 if (tmp16 < 3) {
3158 b43_phy_write(dev, 0x048A,
3159 (b43_phy_read(dev, 0x048A)
3160 & 0xF000) | 0x09EB);
3161 } else {
3162 b43_phy_write(dev, 0x048A,
3163 (b43_phy_read(dev, 0x048A)
3164 & 0xF000) | 0x0AED);
3165 }
3166 } else {
3167 if (phy->interfmode == B43_INTERFMODE_NONWLAN) {
3168 a = 0xE;
3169 b = 0xA;
3170 } else if (!phy->aci_wlan_automatic && phy->aci_enable) {
3171 a = 0x13;
3172 b = 0x12;
3173 } else {
3174 a = 0xE;
3175 b = 0x11;
3176 }
3177
3178 a = a * (phy->nrssi[1] - phy->nrssi[0]);
3179 a += (phy->nrssi[0] << 6);
3180 if (a < 32)
3181 a += 31;
3182 else
3183 a += 32;
3184 a = a >> 6;
3185 a = limit_value(a, -31, 31);
3186
3187 b = b * (phy->nrssi[1] - phy->nrssi[0]);
3188 b += (phy->nrssi[0] << 6);
3189 if (b < 32)
3190 b += 31;
3191 else
3192 b += 32;
3193 b = b >> 6;
3194 b = limit_value(b, -31, 31);
3195
3196 tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000;
3197 tmp_u16 |= ((u32) b & 0x0000003F);
3198 tmp_u16 |= (((u32) a & 0x0000003F) << 6);
3199 b43_phy_write(dev, 0x048A, tmp_u16);
3200 }
3201 break;
3202 default:
3203 B43_WARN_ON(1);
3204 }
3205}
3206
3207/* Stack implementation to save/restore values from the
3208 * interference mitigation code.
3209 * It is save to restore values in random order.
3210 */
3211static void _stack_save(u32 * _stackptr, size_t * stackidx,
3212 u8 id, u16 offset, u16 value)
3213{
3214 u32 *stackptr = &(_stackptr[*stackidx]);
3215
3216 B43_WARN_ON(offset & 0xF000);
3217 B43_WARN_ON(id & 0xF0);
3218 *stackptr = offset;
3219 *stackptr |= ((u32) id) << 12;
3220 *stackptr |= ((u32) value) << 16;
3221 (*stackidx)++;
3222 B43_WARN_ON(*stackidx >= B43_INTERFSTACK_SIZE);
3223}
3224
3225static u16 _stack_restore(u32 * stackptr, u8 id, u16 offset)
3226{
3227 size_t i;
3228
3229 B43_WARN_ON(offset & 0xF000);
3230 B43_WARN_ON(id & 0xF0);
3231 for (i = 0; i < B43_INTERFSTACK_SIZE; i++, stackptr++) {
3232 if ((*stackptr & 0x00000FFF) != offset)
3233 continue;
3234 if (((*stackptr & 0x0000F000) >> 12) != id)
3235 continue;
3236 return ((*stackptr & 0xFFFF0000) >> 16);
3237 }
3238 B43_WARN_ON(1);
3239
3240 return 0;
3241}
3242
3243#define phy_stacksave(offset) \
3244 do { \
3245 _stack_save(stack, &stackidx, 0x1, (offset), \
3246 b43_phy_read(dev, (offset))); \
3247 } while (0)
3248#define phy_stackrestore(offset) \
3249 do { \
3250 b43_phy_write(dev, (offset), \
3251 _stack_restore(stack, 0x1, \
3252 (offset))); \
3253 } while (0)
3254#define radio_stacksave(offset) \
3255 do { \
3256 _stack_save(stack, &stackidx, 0x2, (offset), \
3257 b43_radio_read16(dev, (offset))); \
3258 } while (0)
3259#define radio_stackrestore(offset) \
3260 do { \
3261 b43_radio_write16(dev, (offset), \
3262 _stack_restore(stack, 0x2, \
3263 (offset))); \
3264 } while (0)
3265#define ofdmtab_stacksave(table, offset) \
3266 do { \
3267 _stack_save(stack, &stackidx, 0x3, (offset)|(table), \
3268 b43_ofdmtab_read16(dev, (table), (offset))); \
3269 } while (0)
3270#define ofdmtab_stackrestore(table, offset) \
3271 do { \
3272 b43_ofdmtab_write16(dev, (table), (offset), \
3273 _stack_restore(stack, 0x3, \
3274 (offset)|(table))); \
3275 } while (0)
3276
3277static void
3278b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
3279{
3280 struct b43_phy *phy = &dev->phy;
3281 u16 tmp, flipped;
3282 size_t stackidx = 0;
3283 u32 *stack = phy->interfstack;
3284
3285 switch (mode) {
3286 case B43_INTERFMODE_NONWLAN:
3287 if (phy->rev != 1) {
3288 b43_phy_write(dev, 0x042B,
3289 b43_phy_read(dev, 0x042B) | 0x0800);
3290 b43_phy_write(dev, B43_PHY_G_CRS,
3291 b43_phy_read(dev,
3292 B43_PHY_G_CRS) & ~0x4000);
3293 break;
3294 }
3295 radio_stacksave(0x0078);
3296 tmp = (b43_radio_read16(dev, 0x0078) & 0x001E);
3297 flipped = flip_4bit(tmp);
3298 if (flipped < 10 && flipped >= 8)
3299 flipped = 7;
3300 else if (flipped >= 10)
3301 flipped -= 3;
3302 flipped = flip_4bit(flipped);
3303 flipped = (flipped << 1) | 0x0020;
3304 b43_radio_write16(dev, 0x0078, flipped);
3305
3306 b43_calc_nrssi_threshold(dev);
3307
3308 phy_stacksave(0x0406);
3309 b43_phy_write(dev, 0x0406, 0x7E28);
3310
3311 b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x0800);
3312 b43_phy_write(dev, B43_PHY_RADIO_BITFIELD,
3313 b43_phy_read(dev,
3314 B43_PHY_RADIO_BITFIELD) | 0x1000);
3315
3316 phy_stacksave(0x04A0);
3317 b43_phy_write(dev, 0x04A0,
3318 (b43_phy_read(dev, 0x04A0) & 0xC0C0) | 0x0008);
3319 phy_stacksave(0x04A1);
3320 b43_phy_write(dev, 0x04A1,
3321 (b43_phy_read(dev, 0x04A1) & 0xC0C0) | 0x0605);
3322 phy_stacksave(0x04A2);
3323 b43_phy_write(dev, 0x04A2,
3324 (b43_phy_read(dev, 0x04A2) & 0xC0C0) | 0x0204);
3325 phy_stacksave(0x04A8);
3326 b43_phy_write(dev, 0x04A8,
3327 (b43_phy_read(dev, 0x04A8) & 0xC0C0) | 0x0803);
3328 phy_stacksave(0x04AB);
3329 b43_phy_write(dev, 0x04AB,
3330 (b43_phy_read(dev, 0x04AB) & 0xC0C0) | 0x0605);
3331
3332 phy_stacksave(0x04A7);
3333 b43_phy_write(dev, 0x04A7, 0x0002);
3334 phy_stacksave(0x04A3);
3335 b43_phy_write(dev, 0x04A3, 0x287A);
3336 phy_stacksave(0x04A9);
3337 b43_phy_write(dev, 0x04A9, 0x2027);
3338 phy_stacksave(0x0493);
3339 b43_phy_write(dev, 0x0493, 0x32F5);
3340 phy_stacksave(0x04AA);
3341 b43_phy_write(dev, 0x04AA, 0x2027);
3342 phy_stacksave(0x04AC);
3343 b43_phy_write(dev, 0x04AC, 0x32F5);
3344 break;
3345 case B43_INTERFMODE_MANUALWLAN:
3346 if (b43_phy_read(dev, 0x0033) & 0x0800)
3347 break;
3348
3349 phy->aci_enable = 1;
3350
3351 phy_stacksave(B43_PHY_RADIO_BITFIELD);
3352 phy_stacksave(B43_PHY_G_CRS);
3353 if (phy->rev < 2) {
3354 phy_stacksave(0x0406);
3355 } else {
3356 phy_stacksave(0x04C0);
3357 phy_stacksave(0x04C1);
3358 }
3359 phy_stacksave(0x0033);
3360 phy_stacksave(0x04A7);
3361 phy_stacksave(0x04A3);
3362 phy_stacksave(0x04A9);
3363 phy_stacksave(0x04AA);
3364 phy_stacksave(0x04AC);
3365 phy_stacksave(0x0493);
3366 phy_stacksave(0x04A1);
3367 phy_stacksave(0x04A0);
3368 phy_stacksave(0x04A2);
3369 phy_stacksave(0x048A);
3370 phy_stacksave(0x04A8);
3371 phy_stacksave(0x04AB);
3372 if (phy->rev == 2) {
3373 phy_stacksave(0x04AD);
3374 phy_stacksave(0x04AE);
3375 } else if (phy->rev >= 3) {
3376 phy_stacksave(0x04AD);
3377 phy_stacksave(0x0415);
3378 phy_stacksave(0x0416);
3379 phy_stacksave(0x0417);
3380 ofdmtab_stacksave(0x1A00, 0x2);
3381 ofdmtab_stacksave(0x1A00, 0x3);
3382 }
3383 phy_stacksave(0x042B);
3384 phy_stacksave(0x048C);
3385
3386 b43_phy_write(dev, B43_PHY_RADIO_BITFIELD,
3387 b43_phy_read(dev, B43_PHY_RADIO_BITFIELD)
3388 & ~0x1000);
3389 b43_phy_write(dev, B43_PHY_G_CRS,
3390 (b43_phy_read(dev, B43_PHY_G_CRS)
3391 & 0xFFFC) | 0x0002);
3392
3393 b43_phy_write(dev, 0x0033, 0x0800);
3394 b43_phy_write(dev, 0x04A3, 0x2027);
3395 b43_phy_write(dev, 0x04A9, 0x1CA8);
3396 b43_phy_write(dev, 0x0493, 0x287A);
3397 b43_phy_write(dev, 0x04AA, 0x1CA8);
3398 b43_phy_write(dev, 0x04AC, 0x287A);
3399
3400 b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0)
3401 & 0xFFC0) | 0x001A);
3402 b43_phy_write(dev, 0x04A7, 0x000D);
3403
3404 if (phy->rev < 2) {
3405 b43_phy_write(dev, 0x0406, 0xFF0D);
3406 } else if (phy->rev == 2) {
3407 b43_phy_write(dev, 0x04C0, 0xFFFF);
3408 b43_phy_write(dev, 0x04C1, 0x00A9);
3409 } else {
3410 b43_phy_write(dev, 0x04C0, 0x00C1);
3411 b43_phy_write(dev, 0x04C1, 0x0059);
3412 }
3413
3414 b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1)
3415 & 0xC0FF) | 0x1800);
3416 b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1)
3417 & 0xFFC0) | 0x0015);
3418 b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8)
3419 & 0xCFFF) | 0x1000);
3420 b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8)
3421 & 0xF0FF) | 0x0A00);
3422 b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB)
3423 & 0xCFFF) | 0x1000);
3424 b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB)
3425 & 0xF0FF) | 0x0800);
3426 b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB)
3427 & 0xFFCF) | 0x0010);
3428 b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB)
3429 & 0xFFF0) | 0x0005);
3430 b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8)
3431 & 0xFFCF) | 0x0010);
3432 b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8)
3433 & 0xFFF0) | 0x0006);
3434 b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2)
3435 & 0xF0FF) | 0x0800);
3436 b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0)
3437 & 0xF0FF) | 0x0500);
3438 b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2)
3439 & 0xFFF0) | 0x000B);
3440
3441 if (phy->rev >= 3) {
3442 b43_phy_write(dev, 0x048A, b43_phy_read(dev, 0x048A)
3443 & ~0x8000);
3444 b43_phy_write(dev, 0x0415, (b43_phy_read(dev, 0x0415)
3445 & 0x8000) | 0x36D8);
3446 b43_phy_write(dev, 0x0416, (b43_phy_read(dev, 0x0416)
3447 & 0x8000) | 0x36D8);
3448 b43_phy_write(dev, 0x0417, (b43_phy_read(dev, 0x0417)
3449 & 0xFE00) | 0x016D);
3450 } else {
3451 b43_phy_write(dev, 0x048A, b43_phy_read(dev, 0x048A)
3452 | 0x1000);
3453 b43_phy_write(dev, 0x048A, (b43_phy_read(dev, 0x048A)
3454 & 0x9FFF) | 0x2000);
3455 b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ACIW);
3456 }
3457 if (phy->rev >= 2) {
3458 b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B)
3459 | 0x0800);
3460 }
3461 b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C)
3462 & 0xF0FF) | 0x0200);
3463 if (phy->rev == 2) {
3464 b43_phy_write(dev, 0x04AE, (b43_phy_read(dev, 0x04AE)
3465 & 0xFF00) | 0x007F);
3466 b43_phy_write(dev, 0x04AD, (b43_phy_read(dev, 0x04AD)
3467 & 0x00FF) | 0x1300);
3468 } else if (phy->rev >= 6) {
3469 b43_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F);
3470 b43_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F);
3471 b43_phy_write(dev, 0x04AD, b43_phy_read(dev, 0x04AD)
3472 & 0x00FF);
3473 }
3474 b43_calc_nrssi_slope(dev);
3475 break;
3476 default:
3477 B43_WARN_ON(1);
3478 }
3479}
3480
3481static void
3482b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)
3483{
3484 struct b43_phy *phy = &dev->phy;
3485 u32 *stack = phy->interfstack;
3486
3487 switch (mode) {
3488 case B43_INTERFMODE_NONWLAN:
3489 if (phy->rev != 1) {
3490 b43_phy_write(dev, 0x042B,
3491 b43_phy_read(dev, 0x042B) & ~0x0800);
3492 b43_phy_write(dev, B43_PHY_G_CRS,
3493 b43_phy_read(dev,
3494 B43_PHY_G_CRS) | 0x4000);
3495 break;
3496 }
3497 radio_stackrestore(0x0078);
3498 b43_calc_nrssi_threshold(dev);
3499 phy_stackrestore(0x0406);
3500 b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) & ~0x0800);
3501 if (!dev->bad_frames_preempt) {
3502 b43_phy_write(dev, B43_PHY_RADIO_BITFIELD,
3503 b43_phy_read(dev, B43_PHY_RADIO_BITFIELD)
3504 & ~(1 << 11));
3505 }
3506 b43_phy_write(dev, B43_PHY_G_CRS,
3507 b43_phy_read(dev, B43_PHY_G_CRS) | 0x4000);
3508 phy_stackrestore(0x04A0);
3509 phy_stackrestore(0x04A1);
3510 phy_stackrestore(0x04A2);
3511 phy_stackrestore(0x04A8);
3512 phy_stackrestore(0x04AB);
3513 phy_stackrestore(0x04A7);
3514 phy_stackrestore(0x04A3);
3515 phy_stackrestore(0x04A9);
3516 phy_stackrestore(0x0493);
3517 phy_stackrestore(0x04AA);
3518 phy_stackrestore(0x04AC);
3519 break;
3520 case B43_INTERFMODE_MANUALWLAN:
3521 if (!(b43_phy_read(dev, 0x0033) & 0x0800))
3522 break;
3523
3524 phy->aci_enable = 0;
3525
3526 phy_stackrestore(B43_PHY_RADIO_BITFIELD);
3527 phy_stackrestore(B43_PHY_G_CRS);
3528 phy_stackrestore(0x0033);
3529 phy_stackrestore(0x04A3);
3530 phy_stackrestore(0x04A9);
3531 phy_stackrestore(0x0493);
3532 phy_stackrestore(0x04AA);
3533 phy_stackrestore(0x04AC);
3534 phy_stackrestore(0x04A0);
3535 phy_stackrestore(0x04A7);
3536 if (phy->rev >= 2) {
3537 phy_stackrestore(0x04C0);
3538 phy_stackrestore(0x04C1);
3539 } else
3540 phy_stackrestore(0x0406);
3541 phy_stackrestore(0x04A1);
3542 phy_stackrestore(0x04AB);
3543 phy_stackrestore(0x04A8);
3544 if (phy->rev == 2) {
3545 phy_stackrestore(0x04AD);
3546 phy_stackrestore(0x04AE);
3547 } else if (phy->rev >= 3) {
3548 phy_stackrestore(0x04AD);
3549 phy_stackrestore(0x0415);
3550 phy_stackrestore(0x0416);
3551 phy_stackrestore(0x0417);
3552 ofdmtab_stackrestore(0x1A00, 0x2);
3553 ofdmtab_stackrestore(0x1A00, 0x3);
3554 }
3555 phy_stackrestore(0x04A2);
3556 phy_stackrestore(0x048A);
3557 phy_stackrestore(0x042B);
3558 phy_stackrestore(0x048C);
3559 b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACIW);
3560 b43_calc_nrssi_slope(dev);
3561 break;
3562 default:
3563 B43_WARN_ON(1);
3564 }
3565}
3566
3567#undef phy_stacksave
3568#undef phy_stackrestore
3569#undef radio_stacksave
3570#undef radio_stackrestore
3571#undef ofdmtab_stacksave
3572#undef ofdmtab_stackrestore
3573
3574int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode)
3575{
3576 struct b43_phy *phy = &dev->phy;
3577 int currentmode;
3578
3579 if ((phy->type != B43_PHYTYPE_G) || (phy->rev == 0) || (!phy->gmode))
3580 return -ENODEV;
3581
3582 phy->aci_wlan_automatic = 0;
3583 switch (mode) {
3584 case B43_INTERFMODE_AUTOWLAN:
3585 phy->aci_wlan_automatic = 1;
3586 if (phy->aci_enable)
3587 mode = B43_INTERFMODE_MANUALWLAN;
3588 else
3589 mode = B43_INTERFMODE_NONE;
3590 break;
3591 case B43_INTERFMODE_NONE:
3592 case B43_INTERFMODE_NONWLAN:
3593 case B43_INTERFMODE_MANUALWLAN:
3594 break;
3595 default:
3596 return -EINVAL;
3597 }
3598
3599 currentmode = phy->interfmode;
3600 if (currentmode == mode)
3601 return 0;
3602 if (currentmode != B43_INTERFMODE_NONE)
3603 b43_radio_interference_mitigation_disable(dev, currentmode);
3604
3605 if (mode == B43_INTERFMODE_NONE) {
3606 phy->aci_enable = 0;
3607 phy->aci_hw_rssi = 0;
3608 } else
3609 b43_radio_interference_mitigation_enable(dev, mode);
3610 phy->interfmode = mode;
3611
3612 return 0;
3613}
3614
3615static u16 b43_radio_core_calibration_value(struct b43_wldev *dev)
3616{
3617 u16 reg, index, ret;
3618
3619 static const u8 rcc_table[] = {
3620 0x02, 0x03, 0x01, 0x0F,
3621 0x06, 0x07, 0x05, 0x0F,
3622 0x0A, 0x0B, 0x09, 0x0F,
3623 0x0E, 0x0F, 0x0D, 0x0F,
3624 };
3625
3626 reg = b43_radio_read16(dev, 0x60);
3627 index = (reg & 0x001E) >> 1;
3628 ret = rcc_table[index] << 1;
3629 ret |= (reg & 0x0001);
3630 ret |= 0x0020;
3631
3632 return ret;
3633}
3634
3635#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
3636static u16 radio2050_rfover_val(struct b43_wldev *dev,
3637 u16 phy_register, unsigned int lpd)
3638{
3639 struct b43_phy *phy = &dev->phy;
3640 struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
3641
3642 if (!phy->gmode)
3643 return 0;
3644
3645 if (has_loopback_gain(phy)) {
3646 int max_lb_gain = phy->max_lb_gain;
3647 u16 extlna;
3648 u16 i;
3649
3650 if (phy->radio_rev == 8)
3651 max_lb_gain += 0x3E;
3652 else
3653 max_lb_gain += 0x26;
3654 if (max_lb_gain >= 0x46) {
3655 extlna = 0x3000;
3656 max_lb_gain -= 0x46;
3657 } else if (max_lb_gain >= 0x3A) {
3658 extlna = 0x1000;
3659 max_lb_gain -= 0x3A;
3660 } else if (max_lb_gain >= 0x2E) {
3661 extlna = 0x2000;
3662 max_lb_gain -= 0x2E;
3663 } else {
3664 extlna = 0;
3665 max_lb_gain -= 0x10;
3666 }
3667
3668 for (i = 0; i < 16; i++) {
3669 max_lb_gain -= (i * 6);
3670 if (max_lb_gain < 6)
3671 break;
3672 }
3673
3674 if ((phy->rev < 7) ||
3675 !(sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
3676 if (phy_register == B43_PHY_RFOVER) {
3677 return 0x1B3;
3678 } else if (phy_register == B43_PHY_RFOVERVAL) {
3679 extlna |= (i << 8);
3680 switch (lpd) {
3681 case LPD(0, 1, 1):
3682 return 0x0F92;
3683 case LPD(0, 0, 1):
3684 case LPD(1, 0, 1):
3685 return (0x0092 | extlna);
3686 case LPD(1, 0, 0):
3687 return (0x0093 | extlna);
3688 }
3689 B43_WARN_ON(1);
3690 }
3691 B43_WARN_ON(1);
3692 } else {
3693 if (phy_register == B43_PHY_RFOVER) {
3694 return 0x9B3;
3695 } else if (phy_register == B43_PHY_RFOVERVAL) {
3696 if (extlna)
3697 extlna |= 0x8000;
3698 extlna |= (i << 8);
3699 switch (lpd) {
3700 case LPD(0, 1, 1):
3701 return 0x8F92;
3702 case LPD(0, 0, 1):
3703 return (0x8092 | extlna);
3704 case LPD(1, 0, 1):
3705 return (0x2092 | extlna);
3706 case LPD(1, 0, 0):
3707 return (0x2093 | extlna);
3708 }
3709 B43_WARN_ON(1);
3710 }
3711 B43_WARN_ON(1);
3712 }
3713 } else {
3714 if ((phy->rev < 7) ||
3715 !(sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
3716 if (phy_register == B43_PHY_RFOVER) {
3717 return 0x1B3;
3718 } else if (phy_register == B43_PHY_RFOVERVAL) {
3719 switch (lpd) {
3720 case LPD(0, 1, 1):
3721 return 0x0FB2;
3722 case LPD(0, 0, 1):
3723 return 0x00B2;
3724 case LPD(1, 0, 1):
3725 return 0x30B2;
3726 case LPD(1, 0, 0):
3727 return 0x30B3;
3728 }
3729 B43_WARN_ON(1);
3730 }
3731 B43_WARN_ON(1);
3732 } else {
3733 if (phy_register == B43_PHY_RFOVER) {
3734 return 0x9B3;
3735 } else if (phy_register == B43_PHY_RFOVERVAL) {
3736 switch (lpd) {
3737 case LPD(0, 1, 1):
3738 return 0x8FB2;
3739 case LPD(0, 0, 1):
3740 return 0x80B2;
3741 case LPD(1, 0, 1):
3742 return 0x20B2;
3743 case LPD(1, 0, 0):
3744 return 0x20B3;
3745 }
3746 B43_WARN_ON(1);
3747 }
3748 B43_WARN_ON(1);
3749 }
3750 }
3751 return 0;
3752}
3753
3754struct init2050_saved_values {
3755 /* Core registers */
3756 u16 reg_3EC;
3757 u16 reg_3E6;
3758 u16 reg_3F4;
3759 /* Radio registers */
3760 u16 radio_43;
3761 u16 radio_51;
3762 u16 radio_52;
3763 /* PHY registers */
3764 u16 phy_pgactl;
3765 u16 phy_base_5A;
3766 u16 phy_base_59;
3767 u16 phy_base_58;
3768 u16 phy_base_30;
3769 u16 phy_rfover;
3770 u16 phy_rfoverval;
3771 u16 phy_analogover;
3772 u16 phy_analogoverval;
3773 u16 phy_crs0;
3774 u16 phy_classctl;
3775 u16 phy_lo_mask;
3776 u16 phy_lo_ctl;
3777 u16 phy_syncctl;
3778};
3779
3780u16 b43_radio_init2050(struct b43_wldev *dev)
3781{
3782 struct b43_phy *phy = &dev->phy;
3783 struct init2050_saved_values sav;
3784 u16 rcc;
3785 u16 radio78;
3786 u16 ret;
3787 u16 i, j;
3788 u32 tmp1 = 0, tmp2 = 0;
3789
3790 memset(&sav, 0, sizeof(sav)); /* get rid of "may be used uninitialized..." */
3791
3792 sav.radio_43 = b43_radio_read16(dev, 0x43);
3793 sav.radio_51 = b43_radio_read16(dev, 0x51);
3794 sav.radio_52 = b43_radio_read16(dev, 0x52);
3795 sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);
3796 sav.phy_base_5A = b43_phy_read(dev, B43_PHY_BASE(0x5A));
3797 sav.phy_base_59 = b43_phy_read(dev, B43_PHY_BASE(0x59));
3798 sav.phy_base_58 = b43_phy_read(dev, B43_PHY_BASE(0x58));
3799
3800 if (phy->type == B43_PHYTYPE_B) {
3801 sav.phy_base_30 = b43_phy_read(dev, B43_PHY_BASE(0x30));
3802 sav.reg_3EC = b43_read16(dev, 0x3EC);
3803
3804 b43_phy_write(dev, B43_PHY_BASE(0x30), 0xFF);
3805 b43_write16(dev, 0x3EC, 0x3F3F);
3806 } else if (phy->gmode || phy->rev >= 2) {
3807 sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);
3808 sav.phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
3809 sav.phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER);
3810 sav.phy_analogoverval =
3811 b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
3812 sav.phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);
3813 sav.phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL);
3814
3815 b43_phy_write(dev, B43_PHY_ANALOGOVER,
3816 b43_phy_read(dev, B43_PHY_ANALOGOVER)
3817 | 0x0003);
3818 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
3819 b43_phy_read(dev, B43_PHY_ANALOGOVERVAL)
3820 & 0xFFFC);
3821 b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0)
3822 & 0x7FFF);
3823 b43_phy_write(dev, B43_PHY_CLASSCTL,
3824 b43_phy_read(dev, B43_PHY_CLASSCTL)
3825 & 0xFFFC);
3826 if (has_loopback_gain(phy)) {
3827 sav.phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
3828 sav.phy_lo_ctl = b43_phy_read(dev, B43_PHY_LO_CTL);
3829
3830 if (phy->rev >= 3)
3831 b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);
3832 else
3833 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
3834 b43_phy_write(dev, B43_PHY_LO_CTL, 0);
3835 }
3836
3837 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3838 radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
3839 LPD(0, 1, 1)));
3840 b43_phy_write(dev, B43_PHY_RFOVER,
3841 radio2050_rfover_val(dev, B43_PHY_RFOVER, 0));
3842 }
3843 b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000);
3844
3845 sav.phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL);
3846 b43_phy_write(dev, B43_PHY_SYNCCTL, b43_phy_read(dev, B43_PHY_SYNCCTL)
3847 & 0xFF7F);
3848 sav.reg_3E6 = b43_read16(dev, 0x3E6);
3849 sav.reg_3F4 = b43_read16(dev, 0x3F4);
3850
3851 if (phy->analog == 0) {
3852 b43_write16(dev, 0x03E6, 0x0122);
3853 } else {
3854 if (phy->analog >= 2) {
3855 b43_phy_write(dev, B43_PHY_BASE(0x03),
3856 (b43_phy_read(dev, B43_PHY_BASE(0x03))
3857 & 0xFFBF) | 0x40);
3858 }
3859 b43_write16(dev, B43_MMIO_CHANNEL_EXT,
3860 (b43_read16(dev, B43_MMIO_CHANNEL_EXT) | 0x2000));
3861 }
3862
3863 rcc = b43_radio_core_calibration_value(dev);
3864
3865 if (phy->type == B43_PHYTYPE_B)
3866 b43_radio_write16(dev, 0x78, 0x26);
3867 if (phy->gmode || phy->rev >= 2) {
3868 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3869 radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
3870 LPD(0, 1, 1)));
3871 }
3872 b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF);
3873 b43_phy_write(dev, B43_PHY_BASE(0x2B), 0x1403);
3874 if (phy->gmode || phy->rev >= 2) {
3875 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3876 radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
3877 LPD(0, 0, 1)));
3878 }
3879 b43_phy_write(dev, B43_PHY_PGACTL, 0xBFA0);
3880 b43_radio_write16(dev, 0x51, b43_radio_read16(dev, 0x51)
3881 | 0x0004);
3882 if (phy->radio_rev == 8) {
3883 b43_radio_write16(dev, 0x43, 0x1F);
3884 } else {
3885 b43_radio_write16(dev, 0x52, 0);
3886 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
3887 & 0xFFF0) | 0x0009);
3888 }
3889 b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
3890
3891 for (i = 0; i < 16; i++) {
3892 b43_phy_write(dev, B43_PHY_BASE(0x5A), 0x0480);
3893 b43_phy_write(dev, B43_PHY_BASE(0x59), 0xC810);
3894 b43_phy_write(dev, B43_PHY_BASE(0x58), 0x000D);
3895 if (phy->gmode || phy->rev >= 2) {
3896 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3897 radio2050_rfover_val(dev,
3898 B43_PHY_RFOVERVAL,
3899 LPD(1, 0, 1)));
3900 }
3901 b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
3902 udelay(10);
3903 if (phy->gmode || phy->rev >= 2) {
3904 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3905 radio2050_rfover_val(dev,
3906 B43_PHY_RFOVERVAL,
3907 LPD(1, 0, 1)));
3908 }
3909 b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0);
3910 udelay(10);
3911 if (phy->gmode || phy->rev >= 2) {
3912 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3913 radio2050_rfover_val(dev,
3914 B43_PHY_RFOVERVAL,
3915 LPD(1, 0, 0)));
3916 }
3917 b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);
3918 udelay(20);
3919 tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
3920 b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
3921 if (phy->gmode || phy->rev >= 2) {
3922 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3923 radio2050_rfover_val(dev,
3924 B43_PHY_RFOVERVAL,
3925 LPD(1, 0, 1)));
3926 }
3927 b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
3928 }
3929 udelay(10);
3930
3931 b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
3932 tmp1++;
3933 tmp1 >>= 9;
3934
3935 for (i = 0; i < 16; i++) {
3936 radio78 = ((flip_4bit(i) << 1) | 0x20);
3937 b43_radio_write16(dev, 0x78, radio78);
3938 udelay(10);
3939 for (j = 0; j < 16; j++) {
3940 b43_phy_write(dev, B43_PHY_BASE(0x5A), 0x0D80);
3941 b43_phy_write(dev, B43_PHY_BASE(0x59), 0xC810);
3942 b43_phy_write(dev, B43_PHY_BASE(0x58), 0x000D);
3943 if (phy->gmode || phy->rev >= 2) {
3944 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3945 radio2050_rfover_val(dev,
3946 B43_PHY_RFOVERVAL,
3947 LPD(1, 0,
3948 1)));
3949 }
3950 b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
3951 udelay(10);
3952 if (phy->gmode || phy->rev >= 2) {
3953 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3954 radio2050_rfover_val(dev,
3955 B43_PHY_RFOVERVAL,
3956 LPD(1, 0,
3957 1)));
3958 }
3959 b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0);
3960 udelay(10);
3961 if (phy->gmode || phy->rev >= 2) {
3962 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3963 radio2050_rfover_val(dev,
3964 B43_PHY_RFOVERVAL,
3965 LPD(1, 0,
3966 0)));
3967 }
3968 b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);
3969 udelay(10);
3970 tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
3971 b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
3972 if (phy->gmode || phy->rev >= 2) {
3973 b43_phy_write(dev, B43_PHY_RFOVERVAL,
3974 radio2050_rfover_val(dev,
3975 B43_PHY_RFOVERVAL,
3976 LPD(1, 0,
3977 1)));
3978 }
3979 b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
3980 }
3981 tmp2++;
3982 tmp2 >>= 8;
3983 if (tmp1 < tmp2)
3984 break;
3985 }
3986
3987 /* Restore the registers */
3988 b43_phy_write(dev, B43_PHY_PGACTL, sav.phy_pgactl);
3989 b43_radio_write16(dev, 0x51, sav.radio_51);
3990 b43_radio_write16(dev, 0x52, sav.radio_52);
3991 b43_radio_write16(dev, 0x43, sav.radio_43);
3992 b43_phy_write(dev, B43_PHY_BASE(0x5A), sav.phy_base_5A);
3993 b43_phy_write(dev, B43_PHY_BASE(0x59), sav.phy_base_59);
3994 b43_phy_write(dev, B43_PHY_BASE(0x58), sav.phy_base_58);
3995 b43_write16(dev, 0x3E6, sav.reg_3E6);
3996 if (phy->analog != 0)
3997 b43_write16(dev, 0x3F4, sav.reg_3F4);
3998 b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl);
3999 b43_synth_pu_workaround(dev, phy->channel);
4000 if (phy->type == B43_PHYTYPE_B) {
4001 b43_phy_write(dev, B43_PHY_BASE(0x30), sav.phy_base_30);
4002 b43_write16(dev, 0x3EC, sav.reg_3EC);
4003 } else if (phy->gmode) {
4004 b43_write16(dev, B43_MMIO_PHY_RADIO,
4005 b43_read16(dev, B43_MMIO_PHY_RADIO)
4006 & 0x7FFF);
4007 b43_phy_write(dev, B43_PHY_RFOVER, sav.phy_rfover);
4008 b43_phy_write(dev, B43_PHY_RFOVERVAL, sav.phy_rfoverval);
4009 b43_phy_write(dev, B43_PHY_ANALOGOVER, sav.phy_analogover);
4010 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
4011 sav.phy_analogoverval);
4012 b43_phy_write(dev, B43_PHY_CRS0, sav.phy_crs0);
4013 b43_phy_write(dev, B43_PHY_CLASSCTL, sav.phy_classctl);
4014 if (has_loopback_gain(phy)) {
4015 b43_phy_write(dev, B43_PHY_LO_MASK, sav.phy_lo_mask);
4016 b43_phy_write(dev, B43_PHY_LO_CTL, sav.phy_lo_ctl);
4017 }
4018 }
4019 if (i > 15)
4020 ret = radio78;
4021 else
4022 ret = rcc;
4023
4024 return ret;
4025}
4026
4027void b43_radio_init2060(struct b43_wldev *dev)
4028{
4029 int err;
4030
4031 b43_radio_write16(dev, 0x0004, 0x00C0);
4032 b43_radio_write16(dev, 0x0005, 0x0008);
4033 b43_radio_write16(dev, 0x0009, 0x0040);
4034 b43_radio_write16(dev, 0x0005, 0x00AA);
4035 b43_radio_write16(dev, 0x0032, 0x008F);
4036 b43_radio_write16(dev, 0x0006, 0x008F);
4037 b43_radio_write16(dev, 0x0034, 0x008F);
4038 b43_radio_write16(dev, 0x002C, 0x0007);
4039 b43_radio_write16(dev, 0x0082, 0x0080);
4040 b43_radio_write16(dev, 0x0080, 0x0000);
4041 b43_radio_write16(dev, 0x003F, 0x00DA);
4042 b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
4043 b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010);
4044 b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
4045 b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
4046 msleep(1); /* delay 400usec */
4047
4048 b43_radio_write16(dev, 0x0081,
4049 (b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010);
4050 msleep(1); /* delay 400usec */
4051
4052 b43_radio_write16(dev, 0x0005,
4053 (b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008);
4054 b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010);
4055 b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
4056 b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040);
4057 b43_radio_write16(dev, 0x0081,
4058 (b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040);
4059 b43_radio_write16(dev, 0x0005,
4060 (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
4061 b43_phy_write(dev, 0x0063, 0xDDC6);
4062 b43_phy_write(dev, 0x0069, 0x07BE);
4063 b43_phy_write(dev, 0x006A, 0x0000);
4064
4065 err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_A, 0);
4066 B43_WARN_ON(err);
4067
4068 msleep(1);
4069}
4070
4071static inline u16 freq_r3A_value(u16 frequency)
4072{
4073 u16 value;
4074
4075 if (frequency < 5091)
4076 value = 0x0040;
4077 else if (frequency < 5321)
4078 value = 0x0000;
4079 else if (frequency < 5806)
4080 value = 0x0080;
4081 else
4082 value = 0x0040;
4083
4084 return value;
4085}
4086
4087void b43_radio_set_tx_iq(struct b43_wldev *dev)
4088{
4089 static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
4090 static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
4091 u16 tmp = b43_radio_read16(dev, 0x001E);
4092 int i, j;
4093
4094 for (i = 0; i < 5; i++) {
4095 for (j = 0; j < 5; j++) {
4096 if (tmp == (data_high[i] << 4 | data_low[j])) {
4097 b43_phy_write(dev, 0x0069,
4098 (i - j) << 8 | 0x00C0);
4099 return;
4100 }
4101 }
4102 }
4103}
4104
4105int b43_radio_selectchannel(struct b43_wldev *dev,
4106 u8 channel, int synthetic_pu_workaround)
4107{
4108 struct b43_phy *phy = &dev->phy;
4109 u16 r8, tmp;
4110 u16 freq;
4111 u16 channelcookie;
4112
4113 /* First we set the channel radio code to prevent the
4114 * firmware from sending ghost packets.
4115 */
4116 channelcookie = channel;
4117 if (phy->type == B43_PHYTYPE_A)
4118 channelcookie |= 0x100;
4119 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
4120
4121 if (phy->type == B43_PHYTYPE_A) {
4122 if (channel > 200)
4123 return -EINVAL;
4124 freq = channel2freq_a(channel);
4125
4126 r8 = b43_radio_read16(dev, 0x0008);
4127 b43_write16(dev, 0x03F0, freq);
4128 b43_radio_write16(dev, 0x0008, r8);
4129
4130 //TODO: write max channel TX power? to Radio 0x2D
4131 tmp = b43_radio_read16(dev, 0x002E);
4132 tmp &= 0x0080;
4133 //TODO: OR tmp with the Power out estimation for this channel?
4134 b43_radio_write16(dev, 0x002E, tmp);
4135
4136 if (freq >= 4920 && freq <= 5500) {
4137 /*
4138 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
4139 * = (freq * 0.025862069
4140 */
4141 r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
4142 }
4143 b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
4144 b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
4145 b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
4146 b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022)
4147 & 0x000F) | (r8 << 4));
4148 b43_radio_write16(dev, 0x002A, (r8 << 4));
4149 b43_radio_write16(dev, 0x002B, (r8 << 4));
4150 b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008)
4151 & 0x00F0) | (r8 << 4));
4152 b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029)
4153 & 0xFF0F) | 0x00B0);
4154 b43_radio_write16(dev, 0x0035, 0x00AA);
4155 b43_radio_write16(dev, 0x0036, 0x0085);
4156 b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A)
4157 & 0xFF20) |
4158 freq_r3A_value(freq));
4159 b43_radio_write16(dev, 0x003D,
4160 b43_radio_read16(dev, 0x003D) & 0x00FF);
4161 b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081)
4162 & 0xFF7F) | 0x0080);
4163 b43_radio_write16(dev, 0x0035,
4164 b43_radio_read16(dev, 0x0035) & 0xFFEF);
4165 b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035)
4166 & 0xFFEF) | 0x0010);
4167 b43_radio_set_tx_iq(dev);
4168 //TODO: TSSI2dbm workaround
4169 b43_phy_xmitpower(dev); //FIXME correct?
4170 } else {
4171 if ((channel < 1) || (channel > 14))
4172 return -EINVAL;
4173
4174 if (synthetic_pu_workaround)
4175 b43_synth_pu_workaround(dev, channel);
4176
4177 b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
4178
4179 if (channel == 14) {
4180 if (dev->dev->bus->sprom.r1.country_code ==
4181 SSB_SPROM1CCODE_JAPAN)
4182 b43_hf_write(dev,
4183 b43_hf_read(dev) & ~B43_HF_ACPR);
4184 else
4185 b43_hf_write(dev,
4186 b43_hf_read(dev) | B43_HF_ACPR);
4187 b43_write16(dev, B43_MMIO_CHANNEL_EXT,
4188 b43_read16(dev, B43_MMIO_CHANNEL_EXT)
4189 | (1 << 11));
4190 } else {
4191 b43_write16(dev, B43_MMIO_CHANNEL_EXT,
4192 b43_read16(dev, B43_MMIO_CHANNEL_EXT)
4193 & 0xF7BF);
4194 }
4195 }
4196
4197 phy->channel = channel;
4198 /* Wait for the radio to tune to the channel and stabilize. */
4199 msleep(8);
4200
4201 return 0;
4202}
4203
4204/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
4205static u16 b43_get_txgain_base_band(u16 txpower)
4206{
4207 u16 ret;
4208
4209 B43_WARN_ON(txpower > 63);
4210
4211 if (txpower >= 54)
4212 ret = 2;
4213 else if (txpower >= 49)
4214 ret = 4;
4215 else if (txpower >= 44)
4216 ret = 5;
4217 else
4218 ret = 6;
4219
4220 return ret;
4221}
4222
4223/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
4224static u16 b43_get_txgain_freq_power_amp(u16 txpower)
4225{
4226 u16 ret;
4227
4228 B43_WARN_ON(txpower > 63);
4229
4230 if (txpower >= 32)
4231 ret = 0;
4232 else if (txpower >= 25)
4233 ret = 1;
4234 else if (txpower >= 20)
4235 ret = 2;
4236 else if (txpower >= 12)
4237 ret = 3;
4238 else
4239 ret = 4;
4240
4241 return ret;
4242}
4243
4244/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
4245static u16 b43_get_txgain_dac(u16 txpower)
4246{
4247 u16 ret;
4248
4249 B43_WARN_ON(txpower > 63);
4250
4251 if (txpower >= 54)
4252 ret = txpower - 53;
4253 else if (txpower >= 49)
4254 ret = txpower - 42;
4255 else if (txpower >= 44)
4256 ret = txpower - 37;
4257 else if (txpower >= 32)
4258 ret = txpower - 32;
4259 else if (txpower >= 25)
4260 ret = txpower - 20;
4261 else if (txpower >= 20)
4262 ret = txpower - 13;
4263 else if (txpower >= 12)
4264 ret = txpower - 8;
4265 else
4266 ret = txpower;
4267
4268 return ret;
4269}
4270
4271static void b43_radio_set_txpower_a(struct b43_wldev *dev, u16 txpower)
4272{
4273 struct b43_phy *phy = &dev->phy;
4274 u16 pamp, base, dac, t;
4275
4276 txpower = limit_value(txpower, 0, 63);
4277
4278 pamp = b43_get_txgain_freq_power_amp(txpower);
4279 pamp <<= 5;
4280 pamp &= 0x00E0;
4281 b43_phy_write(dev, 0x0019, pamp);
4282
4283 base = b43_get_txgain_base_band(txpower);
4284 base &= 0x000F;
4285 b43_phy_write(dev, 0x0017, base | 0x0020);
4286
4287 t = b43_ofdmtab_read16(dev, 0x3000, 1);
4288 t &= 0x0007;
4289
4290 dac = b43_get_txgain_dac(txpower);
4291 dac <<= 3;
4292 dac |= t;
4293
4294 b43_ofdmtab_write16(dev, 0x3000, 1, dac);
4295
4296 phy->txpwr_offset = txpower;
4297
4298 //TODO: FuncPlaceholder (Adjust BB loft cancel)
4299}
4300
4301void b43_radio_turn_on(struct b43_wldev *dev)
4302{
4303 struct b43_phy *phy = &dev->phy;
4304 int err;
4305
4306 might_sleep();
4307
4308 if (phy->radio_on)
4309 return;
4310
4311 switch (phy->type) {
4312 case B43_PHYTYPE_A:
4313 b43_radio_write16(dev, 0x0004, 0x00C0);
4314 b43_radio_write16(dev, 0x0005, 0x0008);
4315 b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) & 0xFFF7);
4316 b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) & 0xFFF7);
4317 b43_radio_init2060(dev);
4318 break;
4319 case B43_PHYTYPE_B:
4320 case B43_PHYTYPE_G:
4321 b43_phy_write(dev, 0x0015, 0x8000);
4322 b43_phy_write(dev, 0x0015, 0xCC00);
4323 b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));
4324 err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 1);
4325 B43_WARN_ON(err);
4326 break;
4327 default:
4328 B43_WARN_ON(1);
4329 }
4330 phy->radio_on = 1;
4331 b43dbg(dev->wl, "Radio turned on\n");
4332}
4333
4334void b43_radio_turn_off(struct b43_wldev *dev)
4335{
4336 struct b43_phy *phy = &dev->phy;
4337
4338 if (phy->type == B43_PHYTYPE_A) {
4339 b43_radio_write16(dev, 0x0004, 0x00FF);
4340 b43_radio_write16(dev, 0x0005, 0x00FB);
4341 b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) | 0x0008);
4342 b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
4343 }
4344 if (phy->type == B43_PHYTYPE_G && dev->dev->id.revision >= 5) {
4345 b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x008C);
4346 b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) & 0xFF73);
4347 } else
4348 b43_phy_write(dev, 0x0015, 0xAA00);
4349 phy->radio_on = 0;
4350 b43dbg(dev->wl, "Radio turned off\n");
4351}
diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h
new file mode 100644
index 000000000000..d1f623cb9b34
--- /dev/null
+++ b/drivers/net/wireless/b43/phy.h
@@ -0,0 +1,297 @@
1#ifndef B43_PHY_H_
2#define B43_PHY_H_
3
4#include <linux/types.h>
5
6struct b43_wldev;
7struct b43_phy;
8
9/*** PHY Registers ***/
10
11/* Routing */
12#define B43_PHYROUTE_OFDM_GPHY 0x400
13#define B43_PHYROUTE_EXT_GPHY 0x800
14
15/* Base registers. */
16#define B43_PHY_BASE(reg) (reg)
17/* OFDM (A) registers of a G-PHY */
18#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
19/* Extended G-PHY registers */
20#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
21
22/* OFDM (A) PHY Registers */
23#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */
24#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */
25#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
26#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
27#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
28#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 */
29#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
30#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
31#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
32#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
33#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
34#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
35#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */
36#define B43_PHY_LMS B43_PHY_OFDM(0x55)
37#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
38#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
39#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
40#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
41#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
42#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
43#define B43_PHY_OTABLENR_SHIFT 10
44#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
45#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
46#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
47#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
48#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
49#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
50#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */
51#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */
52#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0)
53#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1)
54#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
55#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
56#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
57#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
58#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
59#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
60#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
61#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
62#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
63#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (rev 1 only) */
64#define B43_PHY_CRSTHRES2_R1 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (rev 1 only) */
65#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
66#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
67#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
68
69/* CCK (B) PHY Registers */
70#define B43_PHY_VERSION_CCK B43_PHY_BASE(0x00) /* Versioning register for B-PHY */
71#define B43_PHY_CCKBBANDCFG B43_PHY_BASE(0x01) /* Contains antenna 0/1 control bit */
72#define B43_PHY_PGACTL B43_PHY_BASE(0x15) /* PGA control */
73#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
74#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
75#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
76#define B43_PHY_FBCTL1 B43_PHY_BASE(0x18) /* Frequency bandwidth control 1 */
77#define B43_PHY_ITSSI B43_PHY_BASE(0x29) /* Idle TSSI */
78#define B43_PHY_LO_LEAKAGE B43_PHY_BASE(0x2D) /* Measured LO leakage */
79#define B43_PHY_ENERGY B43_PHY_BASE(0x33) /* Energy */
80#define B43_PHY_SYNCCTL B43_PHY_BASE(0x35)
81#define B43_PHY_FBCTL2 B43_PHY_BASE(0x38) /* Frequency bandwidth control 2 */
82#define B43_PHY_DACCTL B43_PHY_BASE(0x60) /* DAC control */
83#define B43_PHY_RCCALOVER B43_PHY_BASE(0x78) /* RC calibration override */
84
85/* Extended G-PHY Registers */
86#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
87#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */
88#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */
89#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */
90#define B43_PHY_GTABNR_SHIFT 10
91#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */
92#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */
93#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */
94#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */
95#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */
96#define B43_PHY_RFOVERVAL_EXTLNA 0x8000
97#define B43_PHY_RFOVERVAL_LNA 0x7000
98#define B43_PHY_RFOVERVAL_LNA_SHIFT 12
99#define B43_PHY_RFOVERVAL_PGA 0x0F00
100#define B43_PHY_RFOVERVAL_PGA_SHIFT 8
101#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */
102#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0
103#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */
104#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */
105#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */
106#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */
107#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */
108
109/*** OFDM table numbers ***/
110#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
111#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0)
112#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0)
113#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename
114#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4)
115#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0)
116#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3)
117#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0)
118#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0)
119#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0)
120#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0)
121#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0)
122#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0)
123#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0)
124#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0)
125#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
126#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
127#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
128//TODO
129#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
130#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
131//TODO
132#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
133#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO rename
134#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 1)
135#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
136#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
137#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
138#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0)
139#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0)
140#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0)
141
142u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
143void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
144 u16 offset, u16 value);
145u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
146void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
147 u16 offset, u32 value);
148
149/*** G-PHY table numbers */
150#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset))
151#define B43_GTAB_NRSSI B43_GTAB(0x00, 0)
152#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120)
153#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298)
154
155u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); //TODO implement
156void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); //TODO implement
157
158#define B43_DEFAULT_CHANNEL_A 36
159#define B43_DEFAULT_CHANNEL_BG 6
160
161enum {
162 B43_ANTENNA0, /* Antenna 0 */
163 B43_ANTENNA1, /* Antenna 0 */
164 B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
165 B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
166
167 B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
168 B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
169};
170
171enum {
172 B43_INTERFMODE_NONE,
173 B43_INTERFMODE_NONWLAN,
174 B43_INTERFMODE_MANUALWLAN,
175 B43_INTERFMODE_AUTOWLAN,
176};
177
178/* Masks for the different PHY versioning registers. */
179#define B43_PHYVER_ANALOG 0xF000
180#define B43_PHYVER_ANALOG_SHIFT 12
181#define B43_PHYVER_TYPE 0x0F00
182#define B43_PHYVER_TYPE_SHIFT 8
183#define B43_PHYVER_VERSION 0x00FF
184
185void b43_raw_phy_lock(struct b43_wldev *dev);
186#define b43_phy_lock(dev, flags) \
187 do { \
188 local_irq_save(flags); \
189 b43_raw_phy_lock(dev); \
190 } while (0)
191void b43_raw_phy_unlock(struct b43_wldev *dev);
192#define b43_phy_unlock(dev, flags) \
193 do { \
194 b43_raw_phy_unlock(dev); \
195 local_irq_restore(flags); \
196 } while (0)
197
198u16 b43_phy_read(struct b43_wldev *dev, u16 offset);
199void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val);
200
201int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev);
202
203void b43_phy_early_init(struct b43_wldev *dev);
204int b43_phy_init(struct b43_wldev *dev);
205
206void b43_set_rx_antenna(struct b43_wldev *dev, int antenna);
207
208void b43_phy_xmitpower(struct b43_wldev *dev);
209void b43_gphy_dc_lt_init(struct b43_wldev *dev);
210
211/* Returns the boolean whether the board has HardwarePowerControl */
212bool b43_has_hardware_pctl(struct b43_phy *phy);
213/* Returns the boolean whether "TX Magnification" is enabled. */
214#define has_tx_magnification(phy) \
215 (((phy)->rev >= 2) && \
216 ((phy)->radio_ver == 0x2050) && \
217 ((phy)->radio_rev == 8))
218/* Card uses the loopback gain stuff */
219#define has_loopback_gain(phy) \
220 (((phy)->rev > 1) || ((phy)->gmode))
221
222/* Radio Attenuation (RF Attenuation) */
223struct b43_rfatt {
224 u8 att; /* Attenuation value */
225 bool with_padmix; /* Flag, PAD Mixer enabled. */
226};
227struct b43_rfatt_list {
228 /* Attenuation values list */
229 const struct b43_rfatt *list;
230 u8 len;
231 /* Minimum/Maximum attenuation values */
232 u8 min_val;
233 u8 max_val;
234};
235
236/* Baseband Attenuation */
237struct b43_bbatt {
238 u8 att; /* Attenuation value */
239};
240struct b43_bbatt_list {
241 /* Attenuation values list */
242 const struct b43_bbatt *list;
243 u8 len;
244 /* Minimum/Maximum attenuation values */
245 u8 min_val;
246 u8 max_val;
247};
248
249/* tx_control bits. */
250#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
251#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
252#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */
253
254/* Write BasebandAttenuation value to the device. */
255void b43_phy_set_baseband_attenuation(struct b43_wldev *dev,
256 u16 baseband_attenuation);
257
258extern const u8 b43_radio_channel_codes_bg[];
259
260void b43_radio_lock(struct b43_wldev *dev);
261void b43_radio_unlock(struct b43_wldev *dev);
262
263u16 b43_radio_read16(struct b43_wldev *dev, u16 offset);
264void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val);
265
266u16 b43_radio_init2050(struct b43_wldev *dev);
267void b43_radio_init2060(struct b43_wldev *dev);
268
269void b43_radio_turn_on(struct b43_wldev *dev);
270void b43_radio_turn_off(struct b43_wldev *dev);
271
272int b43_radio_selectchannel(struct b43_wldev *dev, u8 channel,
273 int synthetic_pu_workaround);
274
275u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel);
276u8 b43_radio_aci_scan(struct b43_wldev *dev);
277
278int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode);
279
280void b43_calc_nrssi_slope(struct b43_wldev *dev);
281void b43_calc_nrssi_threshold(struct b43_wldev *dev);
282s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset);
283void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val);
284void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val);
285void b43_nrssi_mem_update(struct b43_wldev *dev);
286
287void b43_radio_set_tx_iq(struct b43_wldev *dev);
288u16 b43_radio_calibrationvalue(struct b43_wldev *dev);
289
290void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
291 int *_bbatt, int *_rfatt);
292
293void b43_set_txpower_g(struct b43_wldev *dev,
294 const struct b43_bbatt *bbatt,
295 const struct b43_rfatt *rfatt, u8 tx_control);
296
297#endif /* B43_PHY_H_ */
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
new file mode 100644
index 000000000000..4ac91fdd356e
--- /dev/null
+++ b/drivers/net/wireless/b43/pio.c
@@ -0,0 +1,650 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 PIO Transmission
6
7 Copyright (c) 2005 Michael Buesch <mb@bu3sch.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 "b43.h"
27#include "pio.h"
28#include "main.h"
29#include "xmit.h"
30
31#include <linux/delay.h>
32
33static void tx_start(struct b43_pioqueue *queue)
34{
35 b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_INIT);
36}
37
38static void tx_octet(struct b43_pioqueue *queue, u8 octet)
39{
40 if (queue->need_workarounds) {
41 b43_pio_write(queue, B43_PIO_TXDATA, octet);
42 b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_WRITELO);
43 } else {
44 b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_WRITELO);
45 b43_pio_write(queue, B43_PIO_TXDATA, octet);
46 }
47}
48
49static u16 tx_get_next_word(const u8 * txhdr,
50 const u8 * packet,
51 size_t txhdr_size, unsigned int *pos)
52{
53 const u8 *source;
54 unsigned int i = *pos;
55 u16 ret;
56
57 if (i < txhdr_size) {
58 source = txhdr;
59 } else {
60 source = packet;
61 i -= txhdr_size;
62 }
63 ret = le16_to_cpu(*((u16 *) (source + i)));
64 *pos += 2;
65
66 return ret;
67}
68
69static void tx_data(struct b43_pioqueue *queue,
70 u8 * txhdr, const u8 * packet, unsigned int octets)
71{
72 u16 data;
73 unsigned int i = 0;
74
75 if (queue->need_workarounds) {
76 data = tx_get_next_word(txhdr, packet,
77 sizeof(struct b43_txhdr_fw4), &i);
78 b43_pio_write(queue, B43_PIO_TXDATA, data);
79 }
80 b43_pio_write(queue, B43_PIO_TXCTL,
81 B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI);
82 while (i < octets - 1) {
83 data = tx_get_next_word(txhdr, packet,
84 sizeof(struct b43_txhdr_fw4), &i);
85 b43_pio_write(queue, B43_PIO_TXDATA, data);
86 }
87 if (octets % 2)
88 tx_octet(queue,
89 packet[octets - sizeof(struct b43_txhdr_fw4) - 1]);
90}
91
92static void tx_complete(struct b43_pioqueue *queue, struct sk_buff *skb)
93{
94 if (queue->need_workarounds) {
95 b43_pio_write(queue, B43_PIO_TXDATA, skb->data[skb->len - 1]);
96 b43_pio_write(queue, B43_PIO_TXCTL,
97 B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_COMPLETE);
98 } else {
99 b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_COMPLETE);
100 }
101}
102
103static u16 generate_cookie(struct b43_pioqueue *queue,
104 struct b43_pio_txpacket *packet)
105{
106 u16 cookie = 0x0000;
107 int packetindex;
108
109 /* We use the upper 4 bits for the PIO
110 * controller ID and the lower 12 bits
111 * for the packet index (in the cache).
112 */
113 switch (queue->mmio_base) {
114 case B43_MMIO_PIO1_BASE:
115 break;
116 case B43_MMIO_PIO2_BASE:
117 cookie = 0x1000;
118 break;
119 case B43_MMIO_PIO3_BASE:
120 cookie = 0x2000;
121 break;
122 case B43_MMIO_PIO4_BASE:
123 cookie = 0x3000;
124 break;
125 default:
126 B43_WARN_ON(1);
127 }
128 packetindex = pio_txpacket_getindex(packet);
129 B43_WARN_ON(packetindex & ~0x0FFF);
130 cookie |= (u16) packetindex;
131
132 return cookie;
133}
134
135static
136struct b43_pioqueue *parse_cookie(struct b43_wldev *dev,
137 u16 cookie, struct b43_pio_txpacket **packet)
138{
139 struct b43_pio *pio = &dev->pio;
140 struct b43_pioqueue *queue = NULL;
141 int packetindex;
142
143 switch (cookie & 0xF000) {
144 case 0x0000:
145 queue = pio->queue0;
146 break;
147 case 0x1000:
148 queue = pio->queue1;
149 break;
150 case 0x2000:
151 queue = pio->queue2;
152 break;
153 case 0x3000:
154 queue = pio->queue3;
155 break;
156 default:
157 B43_WARN_ON(1);
158 }
159 packetindex = (cookie & 0x0FFF);
160 B43_WARN_ON(!(packetindex >= 0 && packetindex < B43_PIO_MAXTXPACKETS));
161 *packet = &(queue->tx_packets_cache[packetindex]);
162
163 return queue;
164}
165
166union txhdr_union {
167 struct b43_txhdr_fw4 txhdr_fw4;
168};
169
170static void pio_tx_write_fragment(struct b43_pioqueue *queue,
171 struct sk_buff *skb,
172 struct b43_pio_txpacket *packet,
173 size_t txhdr_size)
174{
175 union txhdr_union txhdr_data;
176 u8 *txhdr = NULL;
177 unsigned int octets;
178
179 txhdr = (u8 *) (&txhdr_data.txhdr_fw4);
180
181 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
182 b43_generate_txhdr(queue->dev,
183 txhdr, skb->data, skb->len,
184 &packet->txstat.control,
185 generate_cookie(queue, packet));
186
187 tx_start(queue);
188 octets = skb->len + txhdr_size;
189 if (queue->need_workarounds)
190 octets--;
191 tx_data(queue, txhdr, (u8 *) skb->data, octets);
192 tx_complete(queue, skb);
193}
194
195static void free_txpacket(struct b43_pio_txpacket *packet)
196{
197 struct b43_pioqueue *queue = packet->queue;
198
199 if (packet->skb)
200 dev_kfree_skb_any(packet->skb);
201 list_move(&packet->list, &queue->txfree);
202 queue->nr_txfree++;
203}
204
205static int pio_tx_packet(struct b43_pio_txpacket *packet)
206{
207 struct b43_pioqueue *queue = packet->queue;
208 struct sk_buff *skb = packet->skb;
209 u16 octets;
210
211 octets = (u16) skb->len + sizeof(struct b43_txhdr_fw4);
212 if (queue->tx_devq_size < octets) {
213 b43warn(queue->dev->wl, "PIO queue too small. "
214 "Dropping packet.\n");
215 /* Drop it silently (return success) */
216 free_txpacket(packet);
217 return 0;
218 }
219 B43_WARN_ON(queue->tx_devq_packets > B43_PIO_MAXTXDEVQPACKETS);
220 B43_WARN_ON(queue->tx_devq_used > queue->tx_devq_size);
221 /* Check if there is sufficient free space on the device
222 * TX queue. If not, return and let the TX tasklet
223 * retry later.
224 */
225 if (queue->tx_devq_packets == B43_PIO_MAXTXDEVQPACKETS)
226 return -EBUSY;
227 if (queue->tx_devq_used + octets > queue->tx_devq_size)
228 return -EBUSY;
229 /* Now poke the device. */
230 pio_tx_write_fragment(queue, skb, packet, sizeof(struct b43_txhdr_fw4));
231
232 /* Account for the packet size.
233 * (We must not overflow the device TX queue)
234 */
235 queue->tx_devq_packets++;
236 queue->tx_devq_used += octets;
237
238 /* Transmission started, everything ok, move the
239 * packet to the txrunning list.
240 */
241 list_move_tail(&packet->list, &queue->txrunning);
242
243 return 0;
244}
245
246static void tx_tasklet(unsigned long d)
247{
248 struct b43_pioqueue *queue = (struct b43_pioqueue *)d;
249 struct b43_wldev *dev = queue->dev;
250 unsigned long flags;
251 struct b43_pio_txpacket *packet, *tmp_packet;
252 int err;
253 u16 txctl;
254
255 spin_lock_irqsave(&dev->wl->irq_lock, flags);
256 if (queue->tx_frozen)
257 goto out_unlock;
258 txctl = b43_pio_read(queue, B43_PIO_TXCTL);
259 if (txctl & B43_PIO_TXCTL_SUSPEND)
260 goto out_unlock;
261
262 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
263 /* Try to transmit the packet. This can fail, if
264 * the device queue is full. In case of failure, the
265 * packet is left in the txqueue.
266 * If transmission succeed, the packet is moved to txrunning.
267 * If it is impossible to transmit the packet, it
268 * is dropped.
269 */
270 err = pio_tx_packet(packet);
271 if (err)
272 break;
273 }
274 out_unlock:
275 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
276}
277
278static void setup_txqueues(struct b43_pioqueue *queue)
279{
280 struct b43_pio_txpacket *packet;
281 int i;
282
283 queue->nr_txfree = B43_PIO_MAXTXPACKETS;
284 for (i = 0; i < B43_PIO_MAXTXPACKETS; i++) {
285 packet = &(queue->tx_packets_cache[i]);
286
287 packet->queue = queue;
288 INIT_LIST_HEAD(&packet->list);
289
290 list_add(&packet->list, &queue->txfree);
291 }
292}
293
294static
295struct b43_pioqueue *b43_setup_pioqueue(struct b43_wldev *dev,
296 u16 pio_mmio_base)
297{
298 struct b43_pioqueue *queue;
299 u16 qsize;
300
301 queue = kzalloc(sizeof(*queue), GFP_KERNEL);
302 if (!queue)
303 goto out;
304
305 queue->dev = dev;
306 queue->mmio_base = pio_mmio_base;
307 queue->need_workarounds = (dev->dev->id.revision < 3);
308
309 INIT_LIST_HEAD(&queue->txfree);
310 INIT_LIST_HEAD(&queue->txqueue);
311 INIT_LIST_HEAD(&queue->txrunning);
312 tasklet_init(&queue->txtask, tx_tasklet, (unsigned long)queue);
313
314 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
315 & ~B43_MACCTL_BE);
316
317 qsize = b43_read16(dev, queue->mmio_base + B43_PIO_TXQBUFSIZE);
318 if (qsize == 0) {
319 b43err(dev->wl, "This card does not support PIO "
320 "operation mode. Please use DMA mode "
321 "(module parameter pio=0).\n");
322 goto err_freequeue;
323 }
324 if (qsize <= B43_PIO_TXQADJUST) {
325 b43err(dev->wl, "PIO tx device-queue too small (%u)\n", qsize);
326 goto err_freequeue;
327 }
328 qsize -= B43_PIO_TXQADJUST;
329 queue->tx_devq_size = qsize;
330
331 setup_txqueues(queue);
332
333 out:
334 return queue;
335
336 err_freequeue:
337 kfree(queue);
338 queue = NULL;
339 goto out;
340}
341
342static void cancel_transfers(struct b43_pioqueue *queue)
343{
344 struct b43_pio_txpacket *packet, *tmp_packet;
345
346 tasklet_disable(&queue->txtask);
347
348 list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
349 free_txpacket(packet);
350 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
351 free_txpacket(packet);
352}
353
354static void b43_destroy_pioqueue(struct b43_pioqueue *queue)
355{
356 if (!queue)
357 return;
358
359 cancel_transfers(queue);
360 kfree(queue);
361}
362
363void b43_pio_free(struct b43_wldev *dev)
364{
365 struct b43_pio *pio;
366
367 if (!b43_using_pio(dev))
368 return;
369 pio = &dev->pio;
370
371 b43_destroy_pioqueue(pio->queue3);
372 pio->queue3 = NULL;
373 b43_destroy_pioqueue(pio->queue2);
374 pio->queue2 = NULL;
375 b43_destroy_pioqueue(pio->queue1);
376 pio->queue1 = NULL;
377 b43_destroy_pioqueue(pio->queue0);
378 pio->queue0 = NULL;
379}
380
381int b43_pio_init(struct b43_wldev *dev)
382{
383 struct b43_pio *pio = &dev->pio;
384 struct b43_pioqueue *queue;
385 int err = -ENOMEM;
386
387 queue = b43_setup_pioqueue(dev, B43_MMIO_PIO1_BASE);
388 if (!queue)
389 goto out;
390 pio->queue0 = queue;
391
392 queue = b43_setup_pioqueue(dev, B43_MMIO_PIO2_BASE);
393 if (!queue)
394 goto err_destroy0;
395 pio->queue1 = queue;
396
397 queue = b43_setup_pioqueue(dev, B43_MMIO_PIO3_BASE);
398 if (!queue)
399 goto err_destroy1;
400 pio->queue2 = queue;
401
402 queue = b43_setup_pioqueue(dev, B43_MMIO_PIO4_BASE);
403 if (!queue)
404 goto err_destroy2;
405 pio->queue3 = queue;
406
407 if (dev->dev->id.revision < 3)
408 dev->irq_savedstate |= B43_IRQ_PIO_WORKAROUND;
409
410 b43dbg(dev->wl, "PIO initialized\n");
411 err = 0;
412 out:
413 return err;
414
415 err_destroy2:
416 b43_destroy_pioqueue(pio->queue2);
417 pio->queue2 = NULL;
418 err_destroy1:
419 b43_destroy_pioqueue(pio->queue1);
420 pio->queue1 = NULL;
421 err_destroy0:
422 b43_destroy_pioqueue(pio->queue0);
423 pio->queue0 = NULL;
424 goto out;
425}
426
427int b43_pio_tx(struct b43_wldev *dev,
428 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
429{
430 struct b43_pioqueue *queue = dev->pio.queue1;
431 struct b43_pio_txpacket *packet;
432
433 B43_WARN_ON(queue->tx_suspended);
434 B43_WARN_ON(list_empty(&queue->txfree));
435
436 packet = list_entry(queue->txfree.next, struct b43_pio_txpacket, list);
437 packet->skb = skb;
438
439 memset(&packet->txstat, 0, sizeof(packet->txstat));
440 memcpy(&packet->txstat.control, ctl, sizeof(*ctl));
441
442 list_move_tail(&packet->list, &queue->txqueue);
443 queue->nr_txfree--;
444 queue->nr_tx_packets++;
445 B43_WARN_ON(queue->nr_txfree >= B43_PIO_MAXTXPACKETS);
446
447 tasklet_schedule(&queue->txtask);
448
449 return 0;
450}
451
452void b43_pio_handle_txstatus(struct b43_wldev *dev,
453 const struct b43_txstatus *status)
454{
455 struct b43_pioqueue *queue;
456 struct b43_pio_txpacket *packet;
457
458 queue = parse_cookie(dev, status->cookie, &packet);
459 if (B43_WARN_ON(!queue))
460 return;
461
462 queue->tx_devq_packets--;
463 queue->tx_devq_used -=
464 (packet->skb->len + sizeof(struct b43_txhdr_fw4));
465
466 if (status->acked) {
467 packet->txstat.flags |= IEEE80211_TX_STATUS_ACK;
468 } else {
469 if (!(packet->txstat.control.flags & IEEE80211_TXCTL_NO_ACK))
470 packet->txstat.excessive_retries = 1;
471 }
472 if (status->frame_count == 0) {
473 /* The frame was not transmitted at all. */
474 packet->txstat.retry_count = 0;
475 } else
476 packet->txstat.retry_count = status->frame_count - 1;
477 ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb,
478 &(packet->txstat));
479 packet->skb = NULL;
480
481 free_txpacket(packet);
482 /* If there are packets on the txqueue, poke the tasklet
483 * to transmit them.
484 */
485 if (!list_empty(&queue->txqueue))
486 tasklet_schedule(&queue->txtask);
487}
488
489void b43_pio_get_tx_stats(struct b43_wldev *dev,
490 struct ieee80211_tx_queue_stats *stats)
491{
492 struct b43_pio *pio = &dev->pio;
493 struct b43_pioqueue *queue;
494 struct ieee80211_tx_queue_stats_data *data;
495
496 queue = pio->queue1;
497 data = &(stats->data[0]);
498 data->len = B43_PIO_MAXTXPACKETS - queue->nr_txfree;
499 data->limit = B43_PIO_MAXTXPACKETS;
500 data->count = queue->nr_tx_packets;
501}
502
503static void pio_rx_error(struct b43_pioqueue *queue,
504 int clear_buffers, const char *error)
505{
506 int i;
507
508 b43err(queue->dev->wl, "PIO RX error: %s\n", error);
509 b43_pio_write(queue, B43_PIO_RXCTL, B43_PIO_RXCTL_READY);
510 if (clear_buffers) {
511 B43_WARN_ON(queue->mmio_base != B43_MMIO_PIO1_BASE);
512 for (i = 0; i < 15; i++) {
513 /* Dummy read. */
514 b43_pio_read(queue, B43_PIO_RXDATA);
515 }
516 }
517}
518
519void b43_pio_rx(struct b43_pioqueue *queue)
520{
521 u16 preamble[21] = { 0 };
522 struct b43_rxhdr_fw4 *rxhdr;
523 u16 tmp, len, macstat;
524 int i, preamble_readwords;
525 struct sk_buff *skb;
526
527 tmp = b43_pio_read(queue, B43_PIO_RXCTL);
528 if (!(tmp & B43_PIO_RXCTL_DATAAVAILABLE))
529 return;
530 b43_pio_write(queue, B43_PIO_RXCTL, B43_PIO_RXCTL_DATAAVAILABLE);
531
532 for (i = 0; i < 10; i++) {
533 tmp = b43_pio_read(queue, B43_PIO_RXCTL);
534 if (tmp & B43_PIO_RXCTL_READY)
535 goto data_ready;
536 udelay(10);
537 }
538 b43dbg(queue->dev->wl, "PIO RX timed out\n");
539 return;
540 data_ready:
541
542 len = b43_pio_read(queue, B43_PIO_RXDATA);
543 if (unlikely(len > 0x700)) {
544 pio_rx_error(queue, 0, "len > 0x700");
545 return;
546 }
547 if (unlikely(len == 0 && queue->mmio_base != B43_MMIO_PIO4_BASE)) {
548 pio_rx_error(queue, 0, "len == 0");
549 return;
550 }
551 preamble[0] = cpu_to_le16(len);
552 if (queue->mmio_base == B43_MMIO_PIO4_BASE)
553 preamble_readwords = 14 / sizeof(u16);
554 else
555 preamble_readwords = 18 / sizeof(u16);
556 for (i = 0; i < preamble_readwords; i++) {
557 tmp = b43_pio_read(queue, B43_PIO_RXDATA);
558 preamble[i + 1] = cpu_to_le16(tmp);
559 }
560 rxhdr = (struct b43_rxhdr_fw4 *)preamble;
561 macstat = le16_to_cpu(rxhdr->mac_status);
562 if (macstat & B43_RX_MAC_FCSERR) {
563 pio_rx_error(queue,
564 (queue->mmio_base == B43_MMIO_PIO1_BASE),
565 "Frame FCS error");
566 return;
567 }
568 if (queue->mmio_base == B43_MMIO_PIO4_BASE) {
569 /* We received an xmit status. */
570 struct b43_hwtxstatus *hw;
571
572 hw = (struct b43_hwtxstatus *)(preamble + 1);
573 b43_handle_hwtxstatus(queue->dev, hw);
574
575 return;
576 }
577
578 skb = dev_alloc_skb(len);
579 if (unlikely(!skb)) {
580 pio_rx_error(queue, 1, "OOM");
581 return;
582 }
583 skb_put(skb, len);
584 for (i = 0; i < len - 1; i += 2) {
585 tmp = b43_pio_read(queue, B43_PIO_RXDATA);
586 *((u16 *) (skb->data + i)) = cpu_to_le16(tmp);
587 }
588 if (len % 2) {
589 tmp = b43_pio_read(queue, B43_PIO_RXDATA);
590 skb->data[len - 1] = (tmp & 0x00FF);
591/* The specs say the following is required, but
592 * it is wrong and corrupts the PLCP. If we don't do
593 * this, the PLCP seems to be correct. So ifdef it out for now.
594 */
595#if 0
596 if (rxflags2 & B43_RXHDR_FLAGS2_TYPE2FRAME)
597 skb->data[2] = (tmp & 0xFF00) >> 8;
598 else
599 skb->data[0] = (tmp & 0xFF00) >> 8;
600#endif
601 }
602 b43_rx(queue->dev, skb, rxhdr);
603}
604
605void b43_pio_tx_suspend(struct b43_pioqueue *queue)
606{
607 b43_power_saving_ctl_bits(queue->dev, B43_PS_AWAKE);
608 b43_pio_write(queue, B43_PIO_TXCTL, b43_pio_read(queue, B43_PIO_TXCTL)
609 | B43_PIO_TXCTL_SUSPEND);
610}
611
612void b43_pio_tx_resume(struct b43_pioqueue *queue)
613{
614 b43_pio_write(queue, B43_PIO_TXCTL, b43_pio_read(queue, B43_PIO_TXCTL)
615 & ~B43_PIO_TXCTL_SUSPEND);
616 b43_power_saving_ctl_bits(queue->dev, 0);
617 tasklet_schedule(&queue->txtask);
618}
619
620void b43_pio_freeze_txqueues(struct b43_wldev *dev)
621{
622 struct b43_pio *pio;
623
624 B43_WARN_ON(!b43_using_pio(dev));
625 pio = &dev->pio;
626 pio->queue0->tx_frozen = 1;
627 pio->queue1->tx_frozen = 1;
628 pio->queue2->tx_frozen = 1;
629 pio->queue3->tx_frozen = 1;
630}
631
632void b43_pio_thaw_txqueues(struct b43_wldev *dev)
633{
634 struct b43_pio *pio;
635
636 B43_WARN_ON(!b43_using_pio(dev));
637 pio = &dev->pio;
638 pio->queue0->tx_frozen = 0;
639 pio->queue1->tx_frozen = 0;
640 pio->queue2->tx_frozen = 0;
641 pio->queue3->tx_frozen = 0;
642 if (!list_empty(&pio->queue0->txqueue))
643 tasklet_schedule(&pio->queue0->txtask);
644 if (!list_empty(&pio->queue1->txqueue))
645 tasklet_schedule(&pio->queue1->txtask);
646 if (!list_empty(&pio->queue2->txqueue))
647 tasklet_schedule(&pio->queue2->txtask);
648 if (!list_empty(&pio->queue3->txqueue))
649 tasklet_schedule(&pio->queue3->txtask);
650}
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h
new file mode 100644
index 000000000000..46d6d2ea9b5f
--- /dev/null
+++ b/drivers/net/wireless/b43/pio.h
@@ -0,0 +1,153 @@
1#ifndef B43_PIO_H_
2#define B43_PIO_H_
3
4#include "b43.h"
5
6#include <linux/interrupt.h>
7#include <linux/list.h>
8#include <linux/skbuff.h>
9
10#define B43_PIO_TXCTL 0x00
11#define B43_PIO_TXDATA 0x02
12#define B43_PIO_TXQBUFSIZE 0x04
13#define B43_PIO_RXCTL 0x08
14#define B43_PIO_RXDATA 0x0A
15
16#define B43_PIO_TXCTL_WRITELO (1 << 0)
17#define B43_PIO_TXCTL_WRITEHI (1 << 1)
18#define B43_PIO_TXCTL_COMPLETE (1 << 2)
19#define B43_PIO_TXCTL_INIT (1 << 3)
20#define B43_PIO_TXCTL_SUSPEND (1 << 7)
21
22#define B43_PIO_RXCTL_DATAAVAILABLE (1 << 0)
23#define B43_PIO_RXCTL_READY (1 << 1)
24
25/* PIO constants */
26#define B43_PIO_MAXTXDEVQPACKETS 31
27#define B43_PIO_TXQADJUST 80
28
29/* PIO tuning knobs */
30#define B43_PIO_MAXTXPACKETS 256
31
32#ifdef CONFIG_B43_PIO
33
34struct b43_pioqueue;
35struct b43_xmitstatus;
36
37struct b43_pio_txpacket {
38 struct b43_pioqueue *queue;
39 struct sk_buff *skb;
40 struct ieee80211_tx_status txstat;
41 struct list_head list;
42};
43
44#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
45
46struct b43_pioqueue {
47 struct b43_wldev *dev;
48 u16 mmio_base;
49
50 bool tx_suspended;
51 bool tx_frozen;
52 bool need_workarounds; /* Workarounds needed for core.rev < 3 */
53
54 /* Adjusted size of the device internal TX buffer. */
55 u16 tx_devq_size;
56 /* Used octets of the device internal TX buffer. */
57 u16 tx_devq_used;
58 /* Used packet slots in the device internal TX buffer. */
59 u8 tx_devq_packets;
60 /* Packets from the txfree list can
61 * be taken on incoming TX requests.
62 */
63 struct list_head txfree;
64 unsigned int nr_txfree;
65 /* Packets on the txqueue are queued,
66 * but not completely written to the chip, yet.
67 */
68 struct list_head txqueue;
69 /* Packets on the txrunning queue are completely
70 * posted to the device. We are waiting for the txstatus.
71 */
72 struct list_head txrunning;
73 /* Total number or packets sent.
74 * (This counter can obviously wrap).
75 */
76 unsigned int nr_tx_packets;
77 struct tasklet_struct txtask;
78 struct b43_pio_txpacket tx_packets_cache[B43_PIO_MAXTXPACKETS];
79};
80
81static inline u16 b43_pio_read(struct b43_pioqueue *queue, u16 offset)
82{
83 return b43_read16(queue->dev, queue->mmio_base + offset);
84}
85
86static inline
87 void b43_pio_write(struct b43_pioqueue *queue, u16 offset, u16 value)
88{
89 b43_write16(queue->dev, queue->mmio_base + offset, value);
90 mmiowb();
91}
92
93int b43_pio_init(struct b43_wldev *dev);
94void b43_pio_free(struct b43_wldev *dev);
95
96int b43_pio_tx(struct b43_wldev *dev,
97 struct sk_buff *skb, struct ieee80211_tx_control *ctl);
98void b43_pio_handle_txstatus(struct b43_wldev *dev,
99 const struct b43_txstatus *status);
100void b43_pio_get_tx_stats(struct b43_wldev *dev,
101 struct ieee80211_tx_queue_stats *stats);
102void b43_pio_rx(struct b43_pioqueue *queue);
103
104/* Suspend TX queue in hardware. */
105void b43_pio_tx_suspend(struct b43_pioqueue *queue);
106void b43_pio_tx_resume(struct b43_pioqueue *queue);
107/* Suspend (freeze) the TX tasklet (software level). */
108void b43_pio_freeze_txqueues(struct b43_wldev *dev);
109void b43_pio_thaw_txqueues(struct b43_wldev *dev);
110
111#else /* CONFIG_B43_PIO */
112
113static inline int b43_pio_init(struct b43_wldev *dev)
114{
115 return 0;
116}
117static inline void b43_pio_free(struct b43_wldev *dev)
118{
119}
120static inline
121 int b43_pio_tx(struct b43_wldev *dev,
122 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
123{
124 return 0;
125}
126static inline
127 void b43_pio_handle_txstatus(struct b43_wldev *dev,
128 const struct b43_txstatus *status)
129{
130}
131static inline
132 void b43_pio_get_tx_stats(struct b43_wldev *dev,
133 struct ieee80211_tx_queue_stats *stats)
134{
135}
136static inline void b43_pio_rx(struct b43_pioqueue *queue)
137{
138}
139static inline void b43_pio_tx_suspend(struct b43_pioqueue *queue)
140{
141}
142static inline void b43_pio_tx_resume(struct b43_pioqueue *queue)
143{
144}
145static inline void b43_pio_freeze_txqueues(struct b43_wldev *dev)
146{
147}
148static inline void b43_pio_thaw_txqueues(struct b43_wldev *dev)
149{
150}
151
152#endif /* CONFIG_B43_PIO */
153#endif /* B43_PIO_H_ */
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
new file mode 100644
index 000000000000..fcb777383e70
--- /dev/null
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -0,0 +1,235 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 SYSFS support routines
6
7 Copyright (c) 2006 Michael Buesch <mb@bu3sch.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 "b43.h"
27#include "sysfs.h"
28#include "main.h"
29#include "phy.h"
30
31#include <linux/capability.h>
32
33#define GENERIC_FILESIZE 64
34
35static int get_integer(const char *buf, size_t count)
36{
37 char tmp[10 + 1] = { 0 };
38 int ret = -EINVAL;
39
40 if (count == 0)
41 goto out;
42 count = min(count, (size_t) 10);
43 memcpy(tmp, buf, count);
44 ret = simple_strtol(tmp, NULL, 10);
45 out:
46 return ret;
47}
48
49static int get_boolean(const char *buf, size_t count)
50{
51 if (count != 0) {
52 if (buf[0] == '1')
53 return 1;
54 if (buf[0] == '0')
55 return 0;
56 if (count >= 4 && memcmp(buf, "true", 4) == 0)
57 return 1;
58 if (count >= 5 && memcmp(buf, "false", 5) == 0)
59 return 0;
60 if (count >= 3 && memcmp(buf, "yes", 3) == 0)
61 return 1;
62 if (count >= 2 && memcmp(buf, "no", 2) == 0)
63 return 0;
64 if (count >= 2 && memcmp(buf, "on", 2) == 0)
65 return 1;
66 if (count >= 3 && memcmp(buf, "off", 3) == 0)
67 return 0;
68 }
69 return -EINVAL;
70}
71
72static ssize_t b43_attr_interfmode_show(struct device *dev,
73 struct device_attribute *attr,
74 char *buf)
75{
76 struct b43_wldev *wldev = dev_to_b43_wldev(dev);
77 ssize_t count = 0;
78
79 if (!capable(CAP_NET_ADMIN))
80 return -EPERM;
81
82 mutex_lock(&wldev->wl->mutex);
83
84 switch (wldev->phy.interfmode) {
85 case B43_INTERFMODE_NONE:
86 count =
87 snprintf(buf, PAGE_SIZE,
88 "0 (No Interference Mitigation)\n");
89 break;
90 case B43_INTERFMODE_NONWLAN:
91 count =
92 snprintf(buf, PAGE_SIZE,
93 "1 (Non-WLAN Interference Mitigation)\n");
94 break;
95 case B43_INTERFMODE_MANUALWLAN:
96 count =
97 snprintf(buf, PAGE_SIZE,
98 "2 (WLAN Interference Mitigation)\n");
99 break;
100 default:
101 B43_WARN_ON(1);
102 }
103
104 mutex_unlock(&wldev->wl->mutex);
105
106 return count;
107}
108
109static ssize_t b43_attr_interfmode_store(struct device *dev,
110 struct device_attribute *attr,
111 const char *buf, size_t count)
112{
113 struct b43_wldev *wldev = dev_to_b43_wldev(dev);
114 unsigned long flags;
115 int err;
116 int mode;
117
118 if (!capable(CAP_NET_ADMIN))
119 return -EPERM;
120
121 mode = get_integer(buf, count);
122 switch (mode) {
123 case 0:
124 mode = B43_INTERFMODE_NONE;
125 break;
126 case 1:
127 mode = B43_INTERFMODE_NONWLAN;
128 break;
129 case 2:
130 mode = B43_INTERFMODE_MANUALWLAN;
131 break;
132 case 3:
133 mode = B43_INTERFMODE_AUTOWLAN;
134 break;
135 default:
136 return -EINVAL;
137 }
138
139 mutex_lock(&wldev->wl->mutex);
140 spin_lock_irqsave(&wldev->wl->irq_lock, flags);
141
142 err = b43_radio_set_interference_mitigation(wldev, mode);
143 if (err) {
144 b43err(wldev->wl, "Interference Mitigation not "
145 "supported by device\n");
146 }
147 mmiowb();
148 spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
149 mutex_unlock(&wldev->wl->mutex);
150
151 return err ? err : count;
152}
153
154static DEVICE_ATTR(interference, 0644,
155 b43_attr_interfmode_show, b43_attr_interfmode_store);
156
157static ssize_t b43_attr_preamble_show(struct device *dev,
158 struct device_attribute *attr, char *buf)
159{
160 struct b43_wldev *wldev = dev_to_b43_wldev(dev);
161 ssize_t count;
162
163 if (!capable(CAP_NET_ADMIN))
164 return -EPERM;
165
166 mutex_lock(&wldev->wl->mutex);
167
168 if (wldev->short_preamble)
169 count =
170 snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
171 else
172 count =
173 snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
174
175 mutex_unlock(&wldev->wl->mutex);
176
177 return count;
178}
179
180static ssize_t b43_attr_preamble_store(struct device *dev,
181 struct device_attribute *attr,
182 const char *buf, size_t count)
183{
184 struct b43_wldev *wldev = dev_to_b43_wldev(dev);
185 unsigned long flags;
186 int value;
187
188 if (!capable(CAP_NET_ADMIN))
189 return -EPERM;
190
191 value = get_boolean(buf, count);
192 if (value < 0)
193 return value;
194 mutex_lock(&wldev->wl->mutex);
195 spin_lock_irqsave(&wldev->wl->irq_lock, flags);
196
197 wldev->short_preamble = !!value;
198
199 spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
200 mutex_unlock(&wldev->wl->mutex);
201
202 return count;
203}
204
205static DEVICE_ATTR(shortpreamble, 0644,
206 b43_attr_preamble_show, b43_attr_preamble_store);
207
208int b43_sysfs_register(struct b43_wldev *wldev)
209{
210 struct device *dev = wldev->dev->dev;
211 int err;
212
213 B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
214
215 err = device_create_file(dev, &dev_attr_interference);
216 if (err)
217 goto out;
218 err = device_create_file(dev, &dev_attr_shortpreamble);
219 if (err)
220 goto err_remove_interfmode;
221
222 out:
223 return err;
224 err_remove_interfmode:
225 device_remove_file(dev, &dev_attr_interference);
226 goto out;
227}
228
229void b43_sysfs_unregister(struct b43_wldev *wldev)
230{
231 struct device *dev = wldev->dev->dev;
232
233 device_remove_file(dev, &dev_attr_shortpreamble);
234 device_remove_file(dev, &dev_attr_interference);
235}
diff --git a/drivers/net/wireless/b43/sysfs.h b/drivers/net/wireless/b43/sysfs.h
new file mode 100644
index 000000000000..12bda9ef1a85
--- /dev/null
+++ b/drivers/net/wireless/b43/sysfs.h
@@ -0,0 +1,9 @@
1#ifndef B43_SYSFS_H_
2#define B43_SYSFS_H_
3
4struct b43_wldev;
5
6int b43_sysfs_register(struct b43_wldev *dev);
7void b43_sysfs_unregister(struct b43_wldev *dev);
8
9#endif /* B43_SYSFS_H_ */
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
new file mode 100644
index 000000000000..15a87183a572
--- /dev/null
+++ b/drivers/net/wireless/b43/tables.c
@@ -0,0 +1,375 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
7 Copyright (c) 2006, 2006 Michael Buesch <mb@bu3sch.de>
8 Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
9 Copyright (c) 2005 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 "b43.h"
29#include "tables.h"
30#include "phy.h"
31
32const u32 b43_tab_rotor[] = {
33 0xFEB93FFD, 0xFEC63FFD, /* 0 */
34 0xFED23FFD, 0xFEDF3FFD,
35 0xFEEC3FFE, 0xFEF83FFE,
36 0xFF053FFE, 0xFF113FFE,
37 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
38 0xFF373FFF, 0xFF443FFF,
39 0xFF503FFF, 0xFF5D3FFF,
40 0xFF693FFF, 0xFF763FFF,
41 0xFF824000, 0xFF8F4000, /* 16 */
42 0xFF9B4000, 0xFFA84000,
43 0xFFB54000, 0xFFC14000,
44 0xFFCE4000, 0xFFDA4000,
45 0xFFE74000, 0xFFF34000, /* 24 */
46 0x00004000, 0x000D4000,
47 0x00194000, 0x00264000,
48 0x00324000, 0x003F4000,
49 0x004B4000, 0x00584000, /* 32 */
50 0x00654000, 0x00714000,
51 0x007E4000, 0x008A3FFF,
52 0x00973FFF, 0x00A33FFF,
53 0x00B03FFF, 0x00BC3FFF, /* 40 */
54 0x00C93FFF, 0x00D63FFF,
55 0x00E23FFE, 0x00EF3FFE,
56 0x00FB3FFE, 0x01083FFE,
57 0x01143FFE, 0x01213FFD, /* 48 */
58 0x012E3FFD, 0x013A3FFD,
59 0x01473FFD,
60};
61
62const u32 b43_tab_retard[] = {
63 0xDB93CB87, 0xD666CF64, /* 0 */
64 0xD1FDD358, 0xCDA6D826,
65 0xCA38DD9F, 0xC729E2B4,
66 0xC469E88E, 0xC26AEE2B,
67 0xC0DEF46C, 0xC073FA62, /* 8 */
68 0xC01D00D5, 0xC0760743,
69 0xC1560D1E, 0xC2E51369,
70 0xC4ED18FF, 0xC7AC1ED7,
71 0xCB2823B2, 0xCEFA28D9, /* 16 */
72 0xD2F62D3F, 0xD7BB3197,
73 0xDCE53568, 0xE1FE3875,
74 0xE7D13B35, 0xED663D35,
75 0xF39B3EC4, 0xF98E3FA7, /* 24 */
76 0x00004000, 0x06723FA7,
77 0x0C653EC4, 0x129A3D35,
78 0x182F3B35, 0x1E023875,
79 0x231B3568, 0x28453197, /* 32 */
80 0x2D0A2D3F, 0x310628D9,
81 0x34D823B2, 0x38541ED7,
82 0x3B1318FF, 0x3D1B1369,
83 0x3EAA0D1E, 0x3F8A0743, /* 40 */
84 0x3FE300D5, 0x3F8DFA62,
85 0x3F22F46C, 0x3D96EE2B,
86 0x3B97E88E, 0x38D7E2B4,
87 0x35C8DD9F, 0x325AD826, /* 48 */
88 0x2E03D358, 0x299ACF64,
89 0x246DCB87,
90};
91
92const u16 b43_tab_finefreqa[] = {
93 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
94 0x0202, 0x0282, 0x0302, 0x0382,
95 0x0402, 0x0482, 0x0502, 0x0582,
96 0x05E2, 0x0662, 0x06E2, 0x0762,
97 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
98 0x09C2, 0x0A22, 0x0AA2, 0x0B02,
99 0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
100 0x0D42, 0x0DA2, 0x0E02, 0x0E62,
101 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
102 0x1062, 0x10C2, 0x1122, 0x1182,
103 0x11E2, 0x1242, 0x12A2, 0x12E2,
104 0x1342, 0x13A2, 0x1402, 0x1442,
105 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
106 0x15E2, 0x1622, 0x1662, 0x16C1,
107 0x1701, 0x1741, 0x1781, 0x17E1,
108 0x1821, 0x1861, 0x18A1, 0x18E1,
109 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
110 0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
111 0x1B01, 0x1B41, 0x1B81, 0x1BA1,
112 0x1BE1, 0x1C21, 0x1C41, 0x1C81,
113 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
114 0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
115 0x1E21, 0x1E61, 0x1E81, 0x1EA1,
116 0x1EE1, 0x1F01, 0x1F21, 0x1F41,
117 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
118 0x2001, 0x2041, 0x2061, 0x2081,
119 0x20A1, 0x20C1, 0x20E1, 0x2101,
120 0x2121, 0x2141, 0x2161, 0x2181,
121 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
122 0x2221, 0x2241, 0x2261, 0x2281,
123 0x22A1, 0x22C1, 0x22C1, 0x22E1,
124 0x2301, 0x2321, 0x2341, 0x2361,
125 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
126 0x23E1, 0x23E1, 0x2401, 0x2421,
127 0x2441, 0x2441, 0x2461, 0x2481,
128 0x2481, 0x24A1, 0x24C1, 0x24C1,
129 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
130 0x2541, 0x2541, 0x2561, 0x2561,
131 0x2581, 0x25A1, 0x25A1, 0x25C1,
132 0x25C1, 0x25E1, 0x2601, 0x2601,
133 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
134 0x2661, 0x2661, 0x2681, 0x2681,
135 0x26A1, 0x26A1, 0x26C1, 0x26C1,
136 0x26E1, 0x26E1, 0x2701, 0x2701,
137 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
138 0x2760, 0x2760, 0x2780, 0x2780,
139 0x2780, 0x27A0, 0x27A0, 0x27C0,
140 0x27C0, 0x27E0, 0x27E0, 0x27E0,
141 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
142 0x2820, 0x2840, 0x2840, 0x2840,
143 0x2860, 0x2860, 0x2880, 0x2880,
144 0x2880, 0x28A0, 0x28A0, 0x28A0,
145 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
146 0x28E0, 0x28E0, 0x2900, 0x2900,
147 0x2900, 0x2920, 0x2920, 0x2920,
148 0x2940, 0x2940, 0x2940, 0x2960,
149 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
150 0x2980, 0x2980, 0x29A0, 0x29A0,
151 0x29A0, 0x29A0, 0x29C0, 0x29C0,
152 0x29C0, 0x29E0, 0x29E0, 0x29E0,
153 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
154 0x2A00, 0x2A20, 0x2A20, 0x2A20,
155 0x2A20, 0x2A40, 0x2A40, 0x2A40,
156 0x2A40, 0x2A60, 0x2A60, 0x2A60,
157};
158
159const u16 b43_tab_finefreqg[] = {
160 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
161 0x05A9, 0x0669, 0x0709, 0x0789,
162 0x0829, 0x08A9, 0x0929, 0x0989,
163 0x0A09, 0x0A69, 0x0AC9, 0x0B29,
164 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
165 0x0D09, 0x0D69, 0x0DA9, 0x0E09,
166 0x0E69, 0x0EA9, 0x0F09, 0x0F49,
167 0x0FA9, 0x0FE9, 0x1029, 0x1089,
168 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
169 0x11E9, 0x1229, 0x1289, 0x12C9,
170 0x1309, 0x1349, 0x1389, 0x13C9,
171 0x1409, 0x1449, 0x14A9, 0x14E9,
172 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
173 0x1629, 0x1669, 0x16A9, 0x16E8,
174 0x1728, 0x1768, 0x17A8, 0x17E8,
175 0x1828, 0x1868, 0x18A8, 0x18E8,
176 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
177 0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
178 0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
179 0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
180 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
181 0x1E48, 0x1E88, 0x1EC8, 0x1F08,
182 0x1F48, 0x1F88, 0x1FE8, 0x2028,
183 0x2068, 0x20A8, 0x2108, 0x2148,
184 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
185 0x22C8, 0x2308, 0x2348, 0x23A8,
186 0x23E8, 0x2448, 0x24A8, 0x24E8,
187 0x2548, 0x25A8, 0x2608, 0x2668,
188 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
189 0x2847, 0x28C7, 0x2947, 0x29A7,
190 0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
191 0x2CA7, 0x2D67, 0x2E47, 0x2F67,
192 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
193 0x3806, 0x38A6, 0x3946, 0x39E6,
194 0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
195 0x3C45, 0x3CA5, 0x3D05, 0x3D85,
196 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
197 0x3F45, 0x3FA5, 0x4005, 0x4045,
198 0x40A5, 0x40E5, 0x4145, 0x4185,
199 0x41E5, 0x4225, 0x4265, 0x42C5,
200 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
201 0x4424, 0x4464, 0x44C4, 0x4504,
202 0x4544, 0x4584, 0x45C4, 0x4604,
203 0x4644, 0x46A4, 0x46E4, 0x4724,
204 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
205 0x4864, 0x48A4, 0x48E4, 0x4924,
206 0x4964, 0x49A4, 0x49E4, 0x4A24,
207 0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
208 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
209 0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
210 0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
211 0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
212 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
213 0x5083, 0x50C3, 0x5103, 0x5143,
214 0x5183, 0x51E2, 0x5222, 0x5262,
215 0x52A2, 0x52E2, 0x5342, 0x5382,
216 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
217 0x5502, 0x5542, 0x55A2, 0x55E2,
218 0x5642, 0x5682, 0x56E2, 0x5722,
219 0x5782, 0x57E1, 0x5841, 0x58A1,
220 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
221 0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
222 0x5C61, 0x5D01, 0x5D80, 0x5E20,
223 0x5EE0, 0x5FA0, 0x6080, 0x61C0,
224};
225
226const u16 b43_tab_noisea2[] = {
227 0x0001, 0x0001, 0x0001, 0xFFFE,
228 0xFFFE, 0x3FFF, 0x1000, 0x0393,
229};
230
231const u16 b43_tab_noisea3[] = {
232 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
233 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
234};
235
236const u16 b43_tab_noiseg1[] = {
237 0x013C, 0x01F5, 0x031A, 0x0631,
238 0x0001, 0x0001, 0x0001, 0x0001,
239};
240
241const u16 b43_tab_noiseg2[] = {
242 0x5484, 0x3C40, 0x0000, 0x0000,
243 0x0000, 0x0000, 0x0000, 0x0000,
244};
245
246const u16 b43_tab_noisescaleg1[] = {
247 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
248 0x2F2D, 0x2A2A, 0x2527, 0x1F21,
249 0x1A1D, 0x1719, 0x1616, 0x1414,
250 0x1414, 0x1400, 0x1414, 0x1614,
251 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
252 0x2A27, 0x2F2A, 0x332D, 0x3B35,
253 0x5140, 0x6C62, 0x0077,
254};
255
256const u16 b43_tab_noisescaleg2[] = {
257 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
258 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
259 0x969B, 0x9195, 0x8F8F, 0x8A8A,
260 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
261 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
262 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
263 0xCBC0, 0xD8D4, 0x00DD,
264};
265
266const u16 b43_tab_noisescaleg3[] = {
267 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
268 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
269 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
270 0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
271 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
272 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
273 0xA4A4, 0xA4A4, 0x00A4,
274};
275
276const u16 b43_tab_sigmasqr1[] = {
277 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
278 0x0067, 0x0063, 0x005E, 0x0059,
279 0x0054, 0x0050, 0x004B, 0x0046,
280 0x0042, 0x003D, 0x003D, 0x003D,
281 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
282 0x003D, 0x003D, 0x003D, 0x003D,
283 0x003D, 0x003D, 0x0000, 0x003D,
284 0x003D, 0x003D, 0x003D, 0x003D,
285 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
286 0x003D, 0x003D, 0x003D, 0x003D,
287 0x0042, 0x0046, 0x004B, 0x0050,
288 0x0054, 0x0059, 0x005E, 0x0063,
289 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
290 0x007A,
291};
292
293const u16 b43_tab_sigmasqr2[] = {
294 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
295 0x00D6, 0x00D4, 0x00D2, 0x00CF,
296 0x00CD, 0x00CA, 0x00C7, 0x00C4,
297 0x00C1, 0x00BE, 0x00BE, 0x00BE,
298 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
299 0x00BE, 0x00BE, 0x00BE, 0x00BE,
300 0x00BE, 0x00BE, 0x0000, 0x00BE,
301 0x00BE, 0x00BE, 0x00BE, 0x00BE,
302 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
303 0x00BE, 0x00BE, 0x00BE, 0x00BE,
304 0x00C1, 0x00C4, 0x00C7, 0x00CA,
305 0x00CD, 0x00CF, 0x00D2, 0x00D4,
306 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
307 0x00DE,
308};
309
310static inline void assert_sizes(void)
311{
312 BUILD_BUG_ON(B43_TAB_ROTOR_SIZE != ARRAY_SIZE(b43_tab_rotor));
313 BUILD_BUG_ON(B43_TAB_RETARD_SIZE != ARRAY_SIZE(b43_tab_retard));
314 BUILD_BUG_ON(B43_TAB_FINEFREQA_SIZE != ARRAY_SIZE(b43_tab_finefreqa));
315 BUILD_BUG_ON(B43_TAB_FINEFREQG_SIZE != ARRAY_SIZE(b43_tab_finefreqg));
316 BUILD_BUG_ON(B43_TAB_NOISEA2_SIZE != ARRAY_SIZE(b43_tab_noisea2));
317 BUILD_BUG_ON(B43_TAB_NOISEA3_SIZE != ARRAY_SIZE(b43_tab_noisea3));
318 BUILD_BUG_ON(B43_TAB_NOISEG1_SIZE != ARRAY_SIZE(b43_tab_noiseg1));
319 BUILD_BUG_ON(B43_TAB_NOISEG2_SIZE != ARRAY_SIZE(b43_tab_noiseg2));
320 BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
321 ARRAY_SIZE(b43_tab_noisescaleg1));
322 BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
323 ARRAY_SIZE(b43_tab_noisescaleg2));
324 BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
325 ARRAY_SIZE(b43_tab_noisescaleg3));
326 BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr1));
327 BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr2));
328}
329
330u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
331{
332 assert_sizes();
333
334 b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
335 return b43_phy_read(dev, B43_PHY_OTABLEI);
336}
337
338void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
339 u16 offset, u16 value)
340{
341 b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
342 b43_phy_write(dev, B43_PHY_OTABLEI, value);
343}
344
345u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
346{
347 u32 ret;
348
349 b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
350 ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
351 ret <<= 16;
352 ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
353
354 return ret;
355}
356
357void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
358 u16 offset, u32 value)
359{
360 b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
361 b43_phy_write(dev, B43_PHY_OTABLEI, value);
362 b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
363}
364
365u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset)
366{
367 b43_phy_write(dev, B43_PHY_GTABCTL, table + offset);
368 return b43_phy_read(dev, B43_PHY_GTABDATA);
369}
370
371void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value)
372{
373 b43_phy_write(dev, B43_PHY_GTABCTL, table + offset);
374 b43_phy_write(dev, B43_PHY_GTABDATA, value);
375}
diff --git a/drivers/net/wireless/b43/tables.h b/drivers/net/wireless/b43/tables.h
new file mode 100644
index 000000000000..64635d7b518c
--- /dev/null
+++ b/drivers/net/wireless/b43/tables.h
@@ -0,0 +1,28 @@
1#ifndef B43_TABLES_H_
2#define B43_TABLES_H_
3
4#define B43_TAB_ROTOR_SIZE 53
5extern const u32 b43_tab_rotor[];
6#define B43_TAB_RETARD_SIZE 53
7extern const u32 b43_tab_retard[];
8#define B43_TAB_FINEFREQA_SIZE 256
9extern const u16 b43_tab_finefreqa[];
10#define B43_TAB_FINEFREQG_SIZE 256
11extern const u16 b43_tab_finefreqg[];
12#define B43_TAB_NOISEA2_SIZE 8
13extern const u16 b43_tab_noisea2[];
14#define B43_TAB_NOISEA3_SIZE 8
15extern const u16 b43_tab_noisea3[];
16#define B43_TAB_NOISEG1_SIZE 8
17extern const u16 b43_tab_noiseg1[];
18#define B43_TAB_NOISEG2_SIZE 8
19extern const u16 b43_tab_noiseg2[];
20#define B43_TAB_NOISESCALEG_SIZE 27
21extern const u16 b43_tab_noisescaleg1[];
22extern const u16 b43_tab_noisescaleg2[];
23extern const u16 b43_tab_noisescaleg3[];
24#define B43_TAB_SIGMASQR_SIZE 53
25extern const u16 b43_tab_sigmasqr1[];
26extern const u16 b43_tab_sigmasqr2[];
27
28#endif /* B43_TABLES_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
new file mode 100644
index 000000000000..e6174b6f11fb
--- /dev/null
+++ b/drivers/net/wireless/b43/xmit.c
@@ -0,0 +1,648 @@
1/*
2
3 Broadcom B43 wireless driver
4
5 Transmission (TX/RX) related functions.
6
7 Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
8 Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
9 Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
10 Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
11 Copyright (C) 2005 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 "xmit.h"
31#include "phy.h"
32#include "dma.h"
33#include "pio.h"
34
35/* Extract the bitrate out of a CCK PLCP header. */
36static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
37{
38 switch (plcp->raw[0]) {
39 case 0x0A:
40 return B43_CCK_RATE_1MB;
41 case 0x14:
42 return B43_CCK_RATE_2MB;
43 case 0x37:
44 return B43_CCK_RATE_5MB;
45 case 0x6E:
46 return B43_CCK_RATE_11MB;
47 }
48 B43_WARN_ON(1);
49 return 0;
50}
51
52/* Extract the bitrate out of an OFDM PLCP header. */
53static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp)
54{
55 switch (plcp->raw[0] & 0xF) {
56 case 0xB:
57 return B43_OFDM_RATE_6MB;
58 case 0xF:
59 return B43_OFDM_RATE_9MB;
60 case 0xA:
61 return B43_OFDM_RATE_12MB;
62 case 0xE:
63 return B43_OFDM_RATE_18MB;
64 case 0x9:
65 return B43_OFDM_RATE_24MB;
66 case 0xD:
67 return B43_OFDM_RATE_36MB;
68 case 0x8:
69 return B43_OFDM_RATE_48MB;
70 case 0xC:
71 return B43_OFDM_RATE_54MB;
72 }
73 B43_WARN_ON(1);
74 return 0;
75}
76
77u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
78{
79 switch (bitrate) {
80 case B43_CCK_RATE_1MB:
81 return 0x0A;
82 case B43_CCK_RATE_2MB:
83 return 0x14;
84 case B43_CCK_RATE_5MB:
85 return 0x37;
86 case B43_CCK_RATE_11MB:
87 return 0x6E;
88 }
89 B43_WARN_ON(1);
90 return 0;
91}
92
93u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
94{
95 switch (bitrate) {
96 case B43_OFDM_RATE_6MB:
97 return 0xB;
98 case B43_OFDM_RATE_9MB:
99 return 0xF;
100 case B43_OFDM_RATE_12MB:
101 return 0xA;
102 case B43_OFDM_RATE_18MB:
103 return 0xE;
104 case B43_OFDM_RATE_24MB:
105 return 0x9;
106 case B43_OFDM_RATE_36MB:
107 return 0xD;
108 case B43_OFDM_RATE_48MB:
109 return 0x8;
110 case B43_OFDM_RATE_54MB:
111 return 0xC;
112 }
113 B43_WARN_ON(1);
114 return 0;
115}
116
117void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
118 const u16 octets, const u8 bitrate)
119{
120 __le32 *data = &(plcp->data);
121 __u8 *raw = plcp->raw;
122
123 if (b43_is_ofdm_rate(bitrate)) {
124 *data = b43_plcp_get_ratecode_ofdm(bitrate);
125 B43_WARN_ON(octets & 0xF000);
126 *data |= (octets << 5);
127 *data = cpu_to_le32(*data);
128 } else {
129 u32 plen;
130
131 plen = octets * 16 / bitrate;
132 if ((octets * 16 % bitrate) > 0) {
133 plen++;
134 if ((bitrate == B43_CCK_RATE_11MB)
135 && ((octets * 8 % 11) < 4)) {
136 raw[1] = 0x84;
137 } else
138 raw[1] = 0x04;
139 } else
140 raw[1] = 0x04;
141 *data |= cpu_to_le32(plen << 16);
142 raw[0] = b43_plcp_get_ratecode_cck(bitrate);
143 }
144}
145
146static u8 b43_calc_fallback_rate(u8 bitrate)
147{
148 switch (bitrate) {
149 case B43_CCK_RATE_1MB:
150 return B43_CCK_RATE_1MB;
151 case B43_CCK_RATE_2MB:
152 return B43_CCK_RATE_1MB;
153 case B43_CCK_RATE_5MB:
154 return B43_CCK_RATE_2MB;
155 case B43_CCK_RATE_11MB:
156 return B43_CCK_RATE_5MB;
157 case B43_OFDM_RATE_6MB:
158 return B43_CCK_RATE_5MB;
159 case B43_OFDM_RATE_9MB:
160 return B43_OFDM_RATE_6MB;
161 case B43_OFDM_RATE_12MB:
162 return B43_OFDM_RATE_9MB;
163 case B43_OFDM_RATE_18MB:
164 return B43_OFDM_RATE_12MB;
165 case B43_OFDM_RATE_24MB:
166 return B43_OFDM_RATE_18MB;
167 case B43_OFDM_RATE_36MB:
168 return B43_OFDM_RATE_24MB;
169 case B43_OFDM_RATE_48MB:
170 return B43_OFDM_RATE_36MB;
171 case B43_OFDM_RATE_54MB:
172 return B43_OFDM_RATE_48MB;
173 }
174 B43_WARN_ON(1);
175 return 0;
176}
177
178static void generate_txhdr_fw4(struct b43_wldev *dev,
179 struct b43_txhdr_fw4 *txhdr,
180 const unsigned char *fragment_data,
181 unsigned int fragment_len,
182 const struct ieee80211_tx_control *txctl,
183 u16 cookie)
184{
185 const struct b43_phy *phy = &dev->phy;
186 const struct ieee80211_hdr *wlhdr =
187 (const struct ieee80211_hdr *)fragment_data;
188 int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
189 u16 fctl = le16_to_cpu(wlhdr->frame_control);
190 u8 rate, rate_fb;
191 int rate_ofdm, rate_fb_ofdm;
192 unsigned int plcp_fragment_len;
193 u32 mac_ctl = 0;
194 u16 phy_ctl = 0;
195 u8 extra_ft = 0;
196
197 memset(txhdr, 0, sizeof(*txhdr));
198
199 rate = txctl->tx_rate;
200 rate_ofdm = b43_is_ofdm_rate(rate);
201 rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
202 rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
203
204 if (rate_ofdm)
205 txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
206 else
207 txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
208 txhdr->mac_frame_ctl = wlhdr->frame_control;
209 memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
210
211 /* Calculate duration for fallback rate */
212 if ((rate_fb == rate) ||
213 (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
214 (wlhdr->duration_id == cpu_to_le16(0))) {
215 /* If the fallback rate equals the normal rate or the
216 * dur_id field contains an AID, CFP magic or 0,
217 * use the original dur_id field. */
218 txhdr->dur_fb = wlhdr->duration_id;
219 } else {
220 int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
221 txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
222 dev->wl->if_id,
223 fragment_len,
224 fbrate_base100kbps);
225 }
226
227 plcp_fragment_len = fragment_len + FCS_LEN;
228 if (use_encryption) {
229 u8 key_idx = (u16) (txctl->key_idx);
230 struct b43_key *key;
231 int wlhdr_len;
232 size_t iv_len;
233
234 B43_WARN_ON(key_idx >= dev->max_nr_keys);
235 key = &(dev->key[key_idx]);
236 B43_WARN_ON(!key->keyconf);
237
238 /* Hardware appends ICV. */
239 plcp_fragment_len += txctl->icv_len;
240
241 key_idx = b43_kidx_to_fw(dev, key_idx);
242 mac_ctl |= (key_idx << B43_TX4_MAC_KEYIDX_SHIFT) &
243 B43_TX4_MAC_KEYIDX;
244 mac_ctl |= (key->algorithm << B43_TX4_MAC_KEYALG_SHIFT) &
245 B43_TX4_MAC_KEYALG;
246 wlhdr_len = ieee80211_get_hdrlen(fctl);
247 iv_len = min((size_t) txctl->iv_len,
248 ARRAY_SIZE(txhdr->iv));
249 memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
250 }
251 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp),
252 plcp_fragment_len, rate);
253 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
254 plcp_fragment_len, rate_fb);
255
256 /* Extra Frame Types */
257 if (rate_fb_ofdm)
258 extra_ft |= B43_TX4_EFT_FBOFDM;
259
260 /* Set channel radio code. Note that the micrcode ORs 0x100 to
261 * this value before comparing it to the value in SHM, if this
262 * is a 5Ghz packet.
263 */
264 txhdr->chan_radio_code = phy->channel;
265
266 /* PHY TX Control word */
267 if (rate_ofdm)
268 phy_ctl |= B43_TX4_PHY_OFDM;
269 if (dev->short_preamble)
270 phy_ctl |= B43_TX4_PHY_SHORTPRMBL;
271 switch (txctl->antenna_sel_tx) {
272 case 0:
273 phy_ctl |= B43_TX4_PHY_ANTLAST;
274 break;
275 case 1:
276 phy_ctl |= B43_TX4_PHY_ANT0;
277 break;
278 case 2:
279 phy_ctl |= B43_TX4_PHY_ANT1;
280 break;
281 default:
282 B43_WARN_ON(1);
283 }
284
285 /* MAC control */
286 if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
287 mac_ctl |= B43_TX4_MAC_ACK;
288 if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
289 ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
290 mac_ctl |= B43_TX4_MAC_HWSEQ;
291 if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
292 mac_ctl |= B43_TX4_MAC_STMSDU;
293 if (phy->type == B43_PHYTYPE_A)
294 mac_ctl |= B43_TX4_MAC_5GHZ;
295
296 /* Generate the RTS or CTS-to-self frame */
297 if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
298 (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
299 unsigned int len;
300 struct ieee80211_hdr *hdr;
301 int rts_rate, rts_rate_fb;
302 int rts_rate_ofdm, rts_rate_fb_ofdm;
303
304 rts_rate = txctl->rts_cts_rate;
305 rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
306 rts_rate_fb = b43_calc_fallback_rate(rts_rate);
307 rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
308
309 if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
310 ieee80211_ctstoself_get(dev->wl->hw, dev->wl->if_id,
311 fragment_data, fragment_len,
312 txctl,
313 (struct ieee80211_cts *)(txhdr->
314 rts_frame));
315 mac_ctl |= B43_TX4_MAC_SENDCTS;
316 len = sizeof(struct ieee80211_cts);
317 } else {
318 ieee80211_rts_get(dev->wl->hw, dev->wl->if_id,
319 fragment_data, fragment_len, txctl,
320 (struct ieee80211_rts *)(txhdr->
321 rts_frame));
322 mac_ctl |= B43_TX4_MAC_SENDRTS;
323 len = sizeof(struct ieee80211_rts);
324 }
325 len += FCS_LEN;
326 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->
327 rts_plcp), len,
328 rts_rate);
329 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->
330 rts_plcp_fb),
331 len, rts_rate_fb);
332 hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
333 txhdr->rts_dur_fb = hdr->duration_id;
334 if (rts_rate_ofdm) {
335 extra_ft |= B43_TX4_EFT_RTSOFDM;
336 txhdr->phy_rate_rts =
337 b43_plcp_get_ratecode_ofdm(rts_rate);
338 } else
339 txhdr->phy_rate_rts =
340 b43_plcp_get_ratecode_cck(rts_rate);
341 if (rts_rate_fb_ofdm)
342 extra_ft |= B43_TX4_EFT_RTSFBOFDM;
343 mac_ctl |= B43_TX4_MAC_LONGFRAME;
344 }
345
346 /* Magic cookie */
347 txhdr->cookie = cpu_to_le16(cookie);
348
349 /* Apply the bitfields */
350 txhdr->mac_ctl = cpu_to_le32(mac_ctl);
351 txhdr->phy_ctl = cpu_to_le16(phy_ctl);
352 txhdr->extra_ft = extra_ft;
353}
354
355void b43_generate_txhdr(struct b43_wldev *dev,
356 u8 * txhdr,
357 const unsigned char *fragment_data,
358 unsigned int fragment_len,
359 const struct ieee80211_tx_control *txctl, u16 cookie)
360{
361 generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr,
362 fragment_data, fragment_len, txctl, cookie);
363}
364
365static s8 b43_rssi_postprocess(struct b43_wldev *dev,
366 u8 in_rssi, int ofdm,
367 int adjust_2053, int adjust_2050)
368{
369 struct b43_phy *phy = &dev->phy;
370 s32 tmp;
371
372 switch (phy->radio_ver) {
373 case 0x2050:
374 if (ofdm) {
375 tmp = in_rssi;
376 if (tmp > 127)
377 tmp -= 256;
378 tmp *= 73;
379 tmp /= 64;
380 if (adjust_2050)
381 tmp += 25;
382 else
383 tmp -= 3;
384 } else {
385 if (dev->dev->bus->sprom.r1.
386 boardflags_lo & B43_BFL_RSSI) {
387 if (in_rssi > 63)
388 in_rssi = 63;
389 tmp = phy->nrssi_lt[in_rssi];
390 tmp = 31 - tmp;
391 tmp *= -131;
392 tmp /= 128;
393 tmp -= 57;
394 } else {
395 tmp = in_rssi;
396 tmp = 31 - tmp;
397 tmp *= -149;
398 tmp /= 128;
399 tmp -= 68;
400 }
401 if (phy->type == B43_PHYTYPE_G && adjust_2050)
402 tmp += 25;
403 }
404 break;
405 case 0x2060:
406 if (in_rssi > 127)
407 tmp = in_rssi - 256;
408 else
409 tmp = in_rssi;
410 break;
411 default:
412 tmp = in_rssi;
413 tmp -= 11;
414 tmp *= 103;
415 tmp /= 64;
416 if (adjust_2053)
417 tmp -= 109;
418 else
419 tmp -= 83;
420 }
421
422 return (s8) tmp;
423}
424
425//TODO
426#if 0
427static s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
428{
429 struct b43_phy *phy = &dev->phy;
430 s8 ret;
431
432 if (phy->type == B43_PHYTYPE_A) {
433 //TODO: Incomplete specs.
434 ret = 0;
435 } else
436 ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
437
438 return ret;
439}
440#endif
441
442void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
443{
444 struct ieee80211_rx_status status;
445 struct b43_plcp_hdr6 *plcp;
446 struct ieee80211_hdr *wlhdr;
447 const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
448 u16 fctl;
449 u16 phystat0, phystat3, chanstat, mactime;
450 u32 macstat;
451 u16 chanid;
452 u8 jssi;
453 int padding;
454
455 memset(&status, 0, sizeof(status));
456
457 /* Get metadata about the frame from the header. */
458 phystat0 = le16_to_cpu(rxhdr->phy_status0);
459 phystat3 = le16_to_cpu(rxhdr->phy_status3);
460 jssi = rxhdr->jssi;
461 macstat = le32_to_cpu(rxhdr->mac_status);
462 mactime = le16_to_cpu(rxhdr->mac_time);
463 chanstat = le16_to_cpu(rxhdr->channel);
464
465 if (macstat & B43_RX_MAC_FCSERR)
466 dev->wl->ieee_stats.dot11FCSErrorCount++;
467 if (macstat & B43_RX_MAC_DECERR) {
468 /* Decryption with the given key failed.
469 * Drop the packet. We also won't be able to decrypt it with
470 * the key in software. */
471 goto drop;
472 }
473
474 /* Skip PLCP and padding */
475 padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
476 if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
477 b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
478 goto drop;
479 }
480 plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
481 skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
482 /* The skb contains the Wireless Header + payload data now */
483 if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) {
484 b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
485 goto drop;
486 }
487 wlhdr = (struct ieee80211_hdr *)(skb->data);
488 fctl = le16_to_cpu(wlhdr->frame_control);
489 skb_trim(skb, skb->len - FCS_LEN);
490
491 if (macstat & B43_RX_MAC_DEC) {
492 unsigned int keyidx;
493 int wlhdr_len;
494
495 keyidx = ((macstat & B43_RX_MAC_KEYIDX)
496 >> B43_RX_MAC_KEYIDX_SHIFT);
497 /* We must adjust the key index here. We want the "physical"
498 * key index, but the ucode passed it slightly different.
499 */
500 keyidx = b43_kidx_to_raw(dev, keyidx);
501 B43_WARN_ON(keyidx >= dev->max_nr_keys);
502
503 if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
504 wlhdr_len = ieee80211_get_hdrlen(fctl);
505 if (unlikely(skb->len < (wlhdr_len + 3))) {
506 b43dbg(dev->wl,
507 "RX: Packet size underrun (3)\n");
508 goto drop;
509 }
510 status.flag |= RX_FLAG_DECRYPTED;
511 }
512 }
513
514 status.ssi = b43_rssi_postprocess(dev, jssi,
515 (phystat0 & B43_RX_PHYST0_OFDM),
516 (phystat0 & B43_RX_PHYST0_GAINCTL),
517 (phystat3 & B43_RX_PHYST3_TRSTATE));
518 status.noise = dev->stats.link_noise;
519 /* the next line looks wrong, but is what mac80211 wants */
520 status.signal = (jssi * 100) / B43_RX_MAX_SSI;
521 if (phystat0 & B43_RX_PHYST0_OFDM)
522 status.rate = b43_plcp_get_bitrate_ofdm(plcp);
523 else
524 status.rate = b43_plcp_get_bitrate_cck(plcp);
525 status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
526 status.mactime = mactime;
527
528 chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
529 switch (chanstat & B43_RX_CHAN_PHYTYPE) {
530 case B43_PHYTYPE_A:
531 status.phymode = MODE_IEEE80211A;
532 status.freq = chanid;
533 status.channel = b43_freq_to_channel_a(chanid);
534 break;
535 case B43_PHYTYPE_B:
536 status.phymode = MODE_IEEE80211B;
537 status.freq = chanid + 2400;
538 status.channel = b43_freq_to_channel_bg(chanid + 2400);
539 break;
540 case B43_PHYTYPE_G:
541 status.phymode = MODE_IEEE80211G;
542 status.freq = chanid + 2400;
543 status.channel = b43_freq_to_channel_bg(chanid + 2400);
544 break;
545 default:
546 B43_WARN_ON(1);
547 }
548
549 dev->stats.last_rx = jiffies;
550 ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
551
552 return;
553drop:
554 b43dbg(dev->wl, "RX: Packet dropped\n");
555 dev_kfree_skb_any(skb);
556}
557
558void b43_handle_txstatus(struct b43_wldev *dev,
559 const struct b43_txstatus *status)
560{
561 b43_debugfs_log_txstat(dev, status);
562
563 if (status->intermediate)
564 return;
565 if (status->for_ampdu)
566 return;
567 if (!status->acked)
568 dev->wl->ieee_stats.dot11ACKFailureCount++;
569 if (status->rts_count) {
570 if (status->rts_count == 0xF) //FIXME
571 dev->wl->ieee_stats.dot11RTSFailureCount++;
572 else
573 dev->wl->ieee_stats.dot11RTSSuccessCount++;
574 }
575
576 if (b43_using_pio(dev))
577 b43_pio_handle_txstatus(dev, status);
578 else
579 b43_dma_handle_txstatus(dev, status);
580}
581
582/* Handle TX status report as received through DMA/PIO queues */
583void b43_handle_hwtxstatus(struct b43_wldev *dev,
584 const struct b43_hwtxstatus *hw)
585{
586 struct b43_txstatus status;
587 u8 tmp;
588
589 status.cookie = le16_to_cpu(hw->cookie);
590 status.seq = le16_to_cpu(hw->seq);
591 status.phy_stat = hw->phy_stat;
592 tmp = hw->count;
593 status.frame_count = (tmp >> 4);
594 status.rts_count = (tmp & 0x0F);
595 tmp = hw->flags;
596 status.supp_reason = ((tmp & 0x1C) >> 2);
597 status.pm_indicated = !!(tmp & 0x80);
598 status.intermediate = !!(tmp & 0x40);
599 status.for_ampdu = !!(tmp & 0x20);
600 status.acked = !!(tmp & 0x02);
601
602 b43_handle_txstatus(dev, &status);
603}
604
605/* Stop any TX operation on the device (suspend the hardware queues) */
606void b43_tx_suspend(struct b43_wldev *dev)
607{
608 if (b43_using_pio(dev))
609 b43_pio_freeze_txqueues(dev);
610 else
611 b43_dma_tx_suspend(dev);
612}
613
614/* Resume any TX operation on the device (resume the hardware queues) */
615void b43_tx_resume(struct b43_wldev *dev)
616{
617 if (b43_using_pio(dev))
618 b43_pio_thaw_txqueues(dev);
619 else
620 b43_dma_tx_resume(dev);
621}
622
623#if 0
624static void upload_qos_parms(struct b43_wldev *dev,
625 const u16 * parms, u16 offset)
626{
627 int i;
628
629 for (i = 0; i < B43_NR_QOSPARMS; i++) {
630 b43_shm_write16(dev, B43_SHM_SHARED,
631 offset + (i * 2), parms[i]);
632 }
633}
634#endif
635
636/* Initialize the QoS parameters */
637void b43_qos_init(struct b43_wldev *dev)
638{
639 /* FIXME: This function must probably be called from the mac80211
640 * config callback. */
641 return;
642
643 b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
644 //FIXME kill magic
645 b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
646
647 /*TODO: We might need some stack support here to get the values. */
648}
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
new file mode 100644
index 000000000000..03bddd251618
--- /dev/null
+++ b/drivers/net/wireless/b43/xmit.h
@@ -0,0 +1,250 @@
1#ifndef B43_XMIT_H_
2#define B43_XMIT_H_
3
4#include "main.h"
5
6#define _b43_declare_plcp_hdr(size) \
7 struct b43_plcp_hdr##size { \
8 union { \
9 __le32 data; \
10 __u8 raw[size]; \
11 } __attribute__((__packed__)); \
12 } __attribute__((__packed__))
13
14/* struct b43_plcp_hdr4 */
15_b43_declare_plcp_hdr(4);
16/* struct b43_plcp_hdr6 */
17_b43_declare_plcp_hdr(6);
18
19#undef _b43_declare_plcp_hdr
20
21/* TX header for v4 firmware */
22struct b43_txhdr_fw4 {
23 __le32 mac_ctl; /* MAC TX control */
24 __le16 mac_frame_ctl; /* Copy of the FrameControl field */
25 __le16 tx_fes_time_norm; /* TX FES Time Normal */
26 __le16 phy_ctl; /* PHY TX control */
27 __le16 phy_ctl_0; /* Unused */
28 __le16 phy_ctl_1; /* Unused */
29 __le16 phy_ctl_rts_0; /* Unused */
30 __le16 phy_ctl_rts_1; /* Unused */
31 __u8 phy_rate; /* PHY rate */
32 __u8 phy_rate_rts; /* PHY rate for RTS/CTS */
33 __u8 extra_ft; /* Extra Frame Types */
34 __u8 chan_radio_code; /* Channel Radio Code */
35 __u8 iv[16]; /* Encryption IV */
36 __u8 tx_receiver[6]; /* TX Frame Receiver address */
37 __le16 tx_fes_time_fb; /* TX FES Time Fallback */
38 struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP */
39 __le16 rts_dur_fb; /* RTS fallback duration */
40 struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP */
41 __le16 dur_fb; /* Fallback duration */
42 __le16 mm_dur_time; /* Unused */
43 __le16 mm_dur_time_fb; /* Unused */
44 __le32 time_stamp; /* Timestamp */
45 PAD_BYTES(2);
46 __le16 cookie; /* TX frame cookie */
47 __le16 tx_status; /* TX status */
48 struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP */
49 __u8 rts_frame[16]; /* The RTS frame (if used) */
50 PAD_BYTES(2);
51 struct b43_plcp_hdr6 plcp; /* Main PLCP */
52} __attribute__ ((__packed__));
53
54/* MAC TX control */
55#define B43_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */
56#define B43_TX4_MAC_KEYIDX_SHIFT 20
57#define B43_TX4_MAC_KEYALG 0x00070000 /* Security key algorithm */
58#define B43_TX4_MAC_KEYALG_SHIFT 16
59#define B43_TX4_MAC_LIFETIME 0x00001000
60#define B43_TX4_MAC_FRAMEBURST 0x00000800
61#define B43_TX4_MAC_SENDCTS 0x00000400
62#define B43_TX4_MAC_AMPDU 0x00000300
63#define B43_TX4_MAC_AMPDU_SHIFT 8
64#define B43_TX4_MAC_5GHZ 0x00000080
65#define B43_TX4_MAC_IGNPMQ 0x00000020
66#define B43_TX4_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */
67#define B43_TX4_MAC_STMSDU 0x00000008 /* Start MSDU */
68#define B43_TX4_MAC_SENDRTS 0x00000004
69#define B43_TX4_MAC_LONGFRAME 0x00000002
70#define B43_TX4_MAC_ACK 0x00000001
71
72/* Extra Frame Types */
73#define B43_TX4_EFT_FBOFDM 0x0001 /* Data frame fallback rate type */
74#define B43_TX4_EFT_RTSOFDM 0x0004 /* RTS/CTS rate type */
75#define B43_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */
76
77/* PHY TX control word */
78#define B43_TX4_PHY_OFDM 0x0001 /* Data frame rate type */
79#define B43_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
80#define B43_TX4_PHY_ANT 0x03C0 /* Antenna selection */
81#define B43_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */
82#define B43_TX4_PHY_ANT1 0x0100 /* Use antenna 1 */
83#define B43_TX4_PHY_ANTLAST 0x0300 /* Use last used antenna */
84
85void b43_generate_txhdr(struct b43_wldev *dev,
86 u8 * txhdr,
87 const unsigned char *fragment_data,
88 unsigned int fragment_len,
89 const struct ieee80211_tx_control *txctl, u16 cookie);
90
91/* Transmit Status */
92struct b43_txstatus {
93 u16 cookie; /* The cookie from the txhdr */
94 u16 seq; /* Sequence number */
95 u8 phy_stat; /* PHY TX status */
96 u8 frame_count; /* Frame transmit count */
97 u8 rts_count; /* RTS transmit count */
98 u8 supp_reason; /* Suppression reason */
99 /* flags */
100 u8 pm_indicated; /* PM mode indicated to AP */
101 u8 intermediate; /* Intermediate status notification (not final) */
102 u8 for_ampdu; /* Status is for an AMPDU (afterburner) */
103 u8 acked; /* Wireless ACK received */
104};
105
106/* txstatus supp_reason values */
107enum {
108 B43_TXST_SUPP_NONE, /* Not suppressed */
109 B43_TXST_SUPP_PMQ, /* Suppressed due to PMQ entry */
110 B43_TXST_SUPP_FLUSH, /* Suppressed due to flush request */
111 B43_TXST_SUPP_PREV, /* Previous fragment failed */
112 B43_TXST_SUPP_CHAN, /* Channel mismatch */
113 B43_TXST_SUPP_LIFE, /* Lifetime expired */
114 B43_TXST_SUPP_UNDER, /* Buffer underflow */
115 B43_TXST_SUPP_ABNACK, /* Afterburner NACK */
116};
117
118/* Transmit Status as received through DMA/PIO on old chips */
119struct b43_hwtxstatus {
120 PAD_BYTES(4);
121 __le16 cookie;
122 u8 flags;
123 u8 count;
124 PAD_BYTES(2);
125 __le16 seq;
126 u8 phy_stat;
127 PAD_BYTES(1);
128} __attribute__ ((__packed__));
129
130/* Receive header for v4 firmware. */
131struct b43_rxhdr_fw4 {
132 __le16 frame_len; /* Frame length */
133 PAD_BYTES(2);
134 __le16 phy_status0; /* PHY RX Status 0 */
135 __u8 jssi; /* PHY RX Status 1: JSSI */
136 __u8 sig_qual; /* PHY RX Status 1: Signal Quality */
137 __le16 phy_status2; /* PHY RX Status 2 */
138 __le16 phy_status3; /* PHY RX Status 3 */
139 __le32 mac_status; /* MAC RX status */
140 __le16 mac_time;
141 __le16 channel;
142} __attribute__ ((__packed__));
143
144/* PHY RX Status 0 */
145#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */
146#define B43_RX_PHYST0_PLCPHCF 0x0200
147#define B43_RX_PHYST0_PLCPFV 0x0100
148#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */
149#define B43_RX_PHYST0_LCRS 0x0040
150#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */
151#define B43_RX_PHYST0_UNSRATE 0x0010
152#define B43_RX_PHYST0_CLIP 0x000C
153#define B43_RX_PHYST0_CLIP_SHIFT 2
154#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */
155#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */
156#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */
157#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */
158#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */
159
160/* PHY RX Status 2 */
161#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */
162#define B43_RX_PHYST2_LNAG_SHIFT 14
163#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */
164#define B43_RX_PHYST2_PNAG_SHIFT 10
165#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */
166
167/* PHY RX Status 3 */
168#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */
169#define B43_RX_PHYST3_DIGG_SHIFT 11
170#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */
171
172/* MAC RX Status */
173#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon send flag */
174#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */
175#define B43_RX_MAC_KEYIDX_SHIFT 5
176#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */
177#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */
178#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */
179#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */
180#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */
181
182/* RX channel */
183#define B43_RX_CHAN_GAIN 0xFC00 /* Gain */
184#define B43_RX_CHAN_GAIN_SHIFT 10
185#define B43_RX_CHAN_ID 0x03FC /* Channel ID */
186#define B43_RX_CHAN_ID_SHIFT 2
187#define B43_RX_CHAN_PHYTYPE 0x0003 /* PHY type */
188
189u8 b43_plcp_get_ratecode_cck(const u8 bitrate);
190u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate);
191
192void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
193 const u16 octets, const u8 bitrate);
194
195void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
196
197void b43_handle_txstatus(struct b43_wldev *dev,
198 const struct b43_txstatus *status);
199
200void b43_handle_hwtxstatus(struct b43_wldev *dev,
201 const struct b43_hwtxstatus *hw);
202
203void b43_tx_suspend(struct b43_wldev *dev);
204void b43_tx_resume(struct b43_wldev *dev);
205
206#define B43_NR_QOSPARMS 22
207enum {
208 B43_QOSPARM_TXOP = 0,
209 B43_QOSPARM_CWMIN,
210 B43_QOSPARM_CWMAX,
211 B43_QOSPARM_CWCUR,
212 B43_QOSPARM_AIFS,
213 B43_QOSPARM_BSLOTS,
214 B43_QOSPARM_REGGAP,
215 B43_QOSPARM_STATUS,
216};
217void b43_qos_init(struct b43_wldev *dev);
218
219/* Helper functions for converting the key-table index from "firmware-format"
220 * to "raw-format" and back. The firmware API changed for this at some revision.
221 * We need to account for that here. */
222static inline int b43_new_kidx_api(struct b43_wldev *dev)
223{
224 /* FIXME: Not sure the change was at rev 351 */
225 return (dev->fw.rev >= 351);
226}
227static inline u8 b43_kidx_to_fw(struct b43_wldev *dev, u8 raw_kidx)
228{
229 u8 firmware_kidx;
230 if (b43_new_kidx_api(dev)) {
231 firmware_kidx = raw_kidx;
232 } else {
233 if (raw_kidx >= 4) /* Is per STA key? */
234 firmware_kidx = raw_kidx - 4;
235 else
236 firmware_kidx = raw_kidx; /* TX default key */
237 }
238 return firmware_kidx;
239}
240static inline u8 b43_kidx_to_raw(struct b43_wldev *dev, u8 firmware_kidx)
241{
242 u8 raw_kidx;
243 if (b43_new_kidx_api(dev))
244 raw_kidx = firmware_kidx;
245 else
246 raw_kidx = firmware_kidx + 4; /* RX default keys or per STA keys */
247 return raw_kidx;
248}
249
250#endif /* B43_XMIT_H_ */